Require Import Clight.
Require Import AST.
Require Import Integers.
Require Import Ctypes.
Require Import Maps.
Require Import Cop.
Require Import Coqlib.
Require Import Smallstep.
Require Import Errors.
Require Import Globalenvs.
Require Import Values.
Require Import Memory.
Require Import Events.
Require Import ControlFlowGraphFlattening.
Open Scope error_monad_scope.
Semantics preservation proof for the Control Flow Graph Flattening transformation
Shorthand definition for the type of unsigned 32 bits integers
Definition tint :=
Tint I32 Unsigned noattr.
Section Utils.
phi is the numerotation function
Variable phi:
Z ->
Int.int.
not_in_expr id e indicates that identifier id doesn't appear in expression e
Inductive not_in_expr (
id:
ident):
expr ->
Prop :=
|
not_in_int:
forall i t,
not_in_expr id (
Econst_int i t)
|
not_in_float:
forall f t,
not_in_expr id (
Econst_float f t)
|
not_in_single:
forall s t,
not_in_expr id (
Econst_single s t)
|
not_in_long:
forall l t,
not_in_expr id (
Econst_long l t)
|
not_in_var:
forall v t,
id <>
v ->
not_in_expr id (
Evar v t)
|
not_in_tempvar:
forall v t,
id <>
v ->
not_in_expr id (
Etempvar v t)
|
not_in_deref:
forall e t,
not_in_expr id e ->
not_in_expr id (
Ederef e t)
|
not_in_addrof:
forall e t,
not_in_expr id e ->
not_in_expr id (
Eaddrof e t)
|
not_in_unop:
forall op e t,
not_in_expr id e ->
not_in_expr id (
Eunop op e t)
|
not_in_binop:
forall op e1 e2 t,
not_in_expr id e1 ->
not_in_expr id e2 ->
not_in_expr id (
Ebinop op e1 e2 t)
|
not_in_cast:
forall e t,
not_in_expr id e ->
not_in_expr id (
Ecast e t)
|
not_in_field:
forall e f t,
not_in_expr id e ->
id <>
f ->
not_in_expr id (
Efield e f t)
|
not_in_sizeof:
forall t1 t2,
not_in_expr id (
Esizeof t1 t2)
|
not_in_alignof:
forall t1 t2,
not_in_expr id (
Ealignof t1 t2).
not_in_stmt id s indicates that identifier id doesn't appear in statement s
Inductive not_in_stmt (
id:
ident):
statement ->
Prop :=
|
not_in_skip:
not_in_stmt id Sskip
|
not_in_assign:
forall e1 e2,
not_in_expr id e1 ->
not_in_expr id e2 ->
not_in_stmt id (
Sassign e1 e2)
|
not_in_set:
forall i e,
i <>
id ->
not_in_expr id e ->
not_in_stmt id (
Sset i e)
|
not_in_call_some:
forall v e el,
v <>
id ->
not_in_expr id e ->
(
forall e',
In e'
el ->
not_in_expr id e') ->
not_in_stmt id (
Scall (
Some v)
e el)
|
not_in_call_none:
forall e el,
not_in_expr id e ->
(
forall e',
In e'
el ->
not_in_expr id e') ->
not_in_stmt id (
Scall None e el)
|
not_in_builtin_some:
forall v ef tl el,
v <>
id ->
(
forall e,
In e el ->
not_in_expr id e) ->
not_in_stmt id (
Sbuiltin (
Some v)
ef tl el)
|
not_in_builtin_none:
forall ef tl el,
(
forall e,
In e el ->
not_in_expr id e) ->
not_in_stmt id (
Sbuiltin None ef tl el)
|
not_in_sequence:
forall s1 s2,
not_in_stmt id s1 ->
not_in_stmt id s2 ->
not_in_stmt id (
Ssequence s1 s2)
|
not_in_ifthenelse:
forall e s1 s2,
not_in_expr id e ->
not_in_stmt id s1 ->
not_in_stmt id s2 ->
not_in_stmt id (
Sifthenelse e s1 s2)
|
not_in_loop:
forall s1 s2,
not_in_stmt id s1 ->
not_in_stmt id s2 ->
not_in_stmt id (
Sloop s1 s2)
|
not_in_break:
not_in_stmt id Sbreak
|
not_in_continue:
not_in_stmt id Scontinue
|
not_in_return_some:
forall e,
not_in_expr id e ->
not_in_stmt id (
Sreturn (
Some e))
|
not_in_return_none:
not_in_stmt id (
Sreturn None)
|
not_in_switch:
forall e ls,
not_in_expr id e ->
not_in_lstmt id ls ->
not_in_stmt id (
Sswitch e ls)
|
not_in_label:
forall l s,
not_in_stmt id s ->
not_in_stmt id (
Slabel l s)
|
not_in_goto_some:
forall l,
not_in_stmt id (
Sgoto l)
not_in_lstmt id ls indicates that identifier id doesn't appear in labeled statement ls
with not_in_lstmt (
id:
ident):
labeled_statements ->
Prop :=
|
not_in_nil:
not_in_lstmt id LSnil
|
not_in_cons:
forall l s ls,
not_in_stmt id s ->
not_in_lstmt id ls ->
not_in_lstmt id (
LScons l s ls).
Lemma ple_max_ident:
forall e id,
Ple id (
max_ident_in_expr e id).
Proof.
induction e;
intros;
try (
simpl;
auto;
xomega;
fail).
-
simpl;
destruct (
plt id i);
xomega.
-
simpl;
destruct (
plt id i);
xomega.
-
simpl;
apply Ple_trans with (
max_ident_in_expr e1 id);
auto.
-
simpl;
destruct (
plt id i);
auto.
apply Ple_trans with i;
auto;
xomega.
Qed.
Lemma max_ident_in_expr_monotone:
forall e id1 id2,
Ple id1 id2 ->
Ple (
max_ident_in_expr e id1) (
max_ident_in_expr e id2).
Proof.
induction e;
intros;
try (
simpl;
auto;
xomega;
fail).
-
simpl;
destruct (
plt id1 i);
destruct (
plt id2 i);
xomega.
-
simpl;
destruct (
plt id1 i);
destruct (
plt id2 i);
xomega.
-
simpl;
destruct (
plt id1 i);
destruct (
plt id2 i);
try xomega.
+
apply IHe;
xomega.
+
apply IHe;
auto.
Qed.
Lemma ple_fold_max_ident:
forall l i,
Ple i (
fold_right max_ident_in_expr i l).
Proof.
Lemma max_ident_in_expr_fold_monotone:
forall l id1 id2,
Ple id1 id2 ->
Ple (
fold_right max_ident_in_expr id1 l) (
fold_right max_ident_in_expr id2 l).
Proof.
Any identifier strictly greater than max_ident_in_expr e 1%positive doesn't appear in e
Theorem not_in_expr_trans:
forall e id,
Plt (
max_ident_in_expr e 1%
positive)
id ->
not_in_expr id e.
Proof.
Theorem not_in_expr_trans_fold:
forall l i id,
Plt (
fold_right max_ident_in_expr i l)
id ->
forall e,
In e l ->
not_in_expr id e.
Proof.
Lemma ple_max_ident_stmt:
forall s id,
Ple id (
max_ident_in_stmt s id)
with ple_max_ident_lstmt:
forall ls id,
Ple id (
max_ident_in_lstmt ls id).
Proof.
Lemma max_ident_in_stmt_monotone:
forall s id1 id2,
Ple id1 id2 ->
Ple (
max_ident_in_stmt s id1) (
max_ident_in_stmt s id2)
with max_ident_in_lstmt_monotone:
forall ls id1 id2,
Ple id1 id2 ->
Ple (
max_ident_in_lstmt ls id1) (
max_ident_in_lstmt ls id2).
Proof.
Any identifier strictly greater than max_ident_in_stmt s 1%positive doesn't appear in s
Theorem max_ident_not_in_stmt:
forall s id,
Plt (
max_ident_in_stmt s 1%
positive)
id ->
not_in_stmt id s
Any identifier strictly greater than max_ident_in_lstmt ls 1%positive doesn't appear in ls
with max_ident_not_in_lstmt:
forall ls id,
Plt (
max_ident_in_lstmt ls 1%
positive)
id ->
not_in_lstmt id ls.
Proof.
Currently unused, but will be useful when Sgotos are supported
Lemma find_label_not_in:
forall s k s'
k'
lbl id,
not_in_stmt id s ->
find_label lbl s k =
Some (
s',
k') ->
not_in_stmt id s'
with find_label_ls_not_in:
forall ls k s'
k'
lbl id,
not_in_lstmt id ls ->
find_label_ls lbl ls k =
Some (
s',
k') ->
not_in_stmt id s'.
Proof.
{
destruct s;
intros;
try (
simpl in H0;
inv H0;
fail).
-
simpl in H0.
case_eq (
find_label lbl s1 (
Kseq s2 k)).
+
intros;
rewrite H1 in H0;
rewrite <-
H1 in H0;
clear H1.
inv H;
eapply find_label_not_in.
exact H3.
exact H0.
+
intros;
rewrite H1 in H0.
inv H;
eapply find_label_not_in.
exact H5.
exact H0.
-
simpl in H0.
case_eq (
find_label lbl s1 k);
intros;
rewrite H1 in H0.
+
rewrite <-
H1 in H0.
inv H;
eapply find_label_not_in.
exact H6.
exact H0.
+
inv H;
eapply find_label_not_in.
exact H7.
exact H0.
-
simpl in H0.
case_eq (
find_label lbl s1 (
Kloop1 s1 s2 k));
intros;
rewrite H1 in H0.
+
rewrite <-
H1 in H0;
inv H;
eapply find_label_not_in.
exact H4.
exact H0.
+
inv H;
eapply find_label_not_in.
exact H5.
exact H0.
-
simpl in H0.
eapply find_label_ls_not_in;
eauto.
inv H;
auto.
-
simpl in H0.
destruct (
ident_eq lbl l).
+
inv H0;
inv H;
auto.
+
inv H;
eapply find_label_not_in;
eauto. }
{
destruct ls;
intros.
-
simpl in H0;
inv H0.
-
simpl in H0;
case_eq (
find_label lbl s (
Kseq (
seq_of_labeled_statement ls)
k));
intros;
rewrite H1 in H0.
+
rewrite <-
H1 in H0;
inv H;
eapply find_label_not_in;
eauto.
+
inv H;
eapply find_label_ls_not_in;
eauto. }
Qed.
Lemma max_list_is_max:
forall l x,
In x l ->
Ple x (
fold_right (
fun x y =>
if plt x y then y else x) (1%
positive)
l).
Proof.
induction l;
intros.
-
inv H.
-
simpl;
destruct H.
+
subst x.
destruct (
plt a (
fold_right (
fun x0 y :
positive =>
if plt x0 y then y else x0) 1%
positive l));
xomega.
+
destruct (
plt a (
fold_right (
fun x0 y :
positive =>
if plt x0 y then y else x0) 1%
positive l)).
*
apply IHl;
auto.
*
generalize (
IHl x H);
intros;
xomega.
Qed.
new_ident_for_function f does return a fresh identifier for fn_body f
Theorem new_ident_not_in_body:
forall f,
not_in_stmt (
new_ident_for_function f) (
fn_body f).
Proof.
new_ident_for_function f is fresh for f
Theorem new_ident_no_repet:
forall f x,
In x (
var_names (
fn_vars f) ++
var_names (
fn_params f) ++
var_names (
fn_temps f)) ->
Plt x (
new_ident_for_function f).
Proof.
not_in_cont id k indicates the id doesn't appear in continuation k
Inductive not_in_cont (
id:
ident):
cont ->
Prop :=
|
not_in_Kstop:
not_in_cont id Kstop
|
not_in_Kseq:
forall s k,
not_in_stmt id s ->
not_in_cont id k ->
not_in_cont id (
Kseq s k)
|
not_in_Kloop1:
forall s1 s2 k,
not_in_stmt id s1 ->
not_in_stmt id s2 ->
not_in_cont id k ->
not_in_cont id (
Kloop1 s1 s2 k)
|
not_in_Kloop2:
forall s1 s2 k,
not_in_stmt id s1 ->
not_in_stmt id s2 ->
not_in_cont id k ->
not_in_cont id (
Kloop2 s1 s2 k)
|
not_in_Kswitch:
forall k,
not_in_cont id k ->
not_in_cont id (
Kswitch k)
|
not_in_Kcall_some:
forall f e le k id',
id' <>
new_ident_for_function f ->
not_in_cont (
new_ident_for_function f)
k ->
not_in_cont id (
Kcall (
Some id')
f e le k)
|
not_in_Kcall_none:
forall f e le k,
not_in_cont (
new_ident_for_function f)
k ->
not_in_cont id (
Kcall None f e le k).
not_in_cont is preserved by call_cont
Theorem not_in_cont_call_cont:
forall id k,
not_in_cont id k ->
forall id',
not_in_cont id' (
call_cont k).
Proof.
induction k; intros; simpl.
- econstructor.
- inv H; eapply IHk; auto.
- inv H; eapply IHk; auto.
- inv H; eapply IHk; auto.
- inv H; eapply IHk; auto.
- inv H; econstructor; eauto.
Qed.
sizeof_stmt s is always strictly positive
Lemma sizeof_stmt_pos:
forall s,
sizeof_stmt s > 0.
Proof.
no_switch_label_goto_in_stmt s indicates that there is no Sswitch nor Slabel nor Sgoto in s
Inductive no_switch_label_goto_in_stmt:
statement ->
Prop :=
|
no_switch_label_goto_in_skip:
no_switch_label_goto_in_stmt Sskip
|
no_switch_label_goto_in_assign:
forall e1 e2,
no_switch_label_goto_in_stmt (
Sassign e1 e2)
|
no_switch_label_goto_in_set:
forall id e,
no_switch_label_goto_in_stmt (
Sset id e)
|
no_switch_label_goto_in_call:
forall optid f args,
no_switch_label_goto_in_stmt (
Scall optid f args)
|
no_switch_label_goto_in_builtin:
forall optid ef tyl args,
no_switch_label_goto_in_stmt (
Sbuiltin optid ef tyl args)
|
no_switch_label_goto_in_sequence:
forall s1 s2,
no_switch_label_goto_in_stmt s1 ->
no_switch_label_goto_in_stmt s2 ->
no_switch_label_goto_in_stmt (
Ssequence s1 s2)
|
no_switch_label_goto_in_ifthenelse:
forall e s1 s2,
no_switch_label_goto_in_stmt s1 ->
no_switch_label_goto_in_stmt s2 ->
no_switch_label_goto_in_stmt (
Sifthenelse e s1 s2)
|
no_switch_label_goto_in_loop:
forall s1 s2,
no_switch_label_goto_in_stmt s1 ->
no_switch_label_goto_in_stmt s2 ->
no_switch_label_goto_in_stmt (
Sloop s1 s2)
|
no_switch_label_goto_in_break:
no_switch_label_goto_in_stmt Sbreak
|
no_switch_label_goto_in_continue:
no_switch_label_goto_in_stmt Scontinue
|
no_switch_label_goto_in_return:
forall e,
no_switch_label_goto_in_stmt (
Sreturn e).
Lemma no_switch_label_goto_loop1:
forall id_t s counter k to_continue to_break ls,
flatten_loop1 phi id_t s counter k to_continue to_break =
OK ls ->
no_switch_label_goto_in_stmt s
with no_switch_label_goto_loop2:
forall id_t s counter k to_break ls,
flatten_loop2 phi id_t s counter k to_break =
OK ls ->
no_switch_label_goto_in_stmt s.
Proof.
- destruct s; intros; try (econstructor; fail).
+ simpl in H; monadInv H.
econstructor; eauto.
+ simpl in H; monadInv H.
econstructor; eauto.
+ simpl in H; monadInv H.
econstructor; eauto.
+ simpl in H; monadInv H.
+ simpl in H; monadInv H.
+ simpl in H; monadInv H.
- destruct s; intros; try (econstructor; fail).
+ simpl in H; monadInv H.
econstructor; eauto.
+ simpl in H; monadInv H.
econstructor; eauto.
+ simpl in H; monadInv H.
econstructor; eauto.
+ simpl in H; monadInv H.
+ simpl in H; monadInv H.
+ simpl in H; monadInv H.
Qed.
Lemma no_switch_label_goto_stmt:
forall id_t s counter k ls,
flatten phi id_t s counter k =
OK ls ->
no_switch_label_goto_in_stmt s.
Proof.
induction s;
intros;
try (
econstructor;
fail).
-
simpl in H;
monadInv H.
econstructor;
eauto.
-
simpl in H;
monadInv H.
econstructor;
eauto.
-
unfold flatten in H;
fold flatten in H.
monadInv H.
econstructor;
eauto.
+
eapply no_switch_label_goto_loop1;
eauto.
+
eapply no_switch_label_goto_loop2;
eauto.
-
simpl in H;
monadInv H.
-
simpl in H;
monadInv H.
-
simpl in H;
monadInv H.
Qed.
Lemma no_switch_label_goto_body:
forall id_t s s',
obf_body phi id_t s =
OK s' ->
no_switch_label_goto_in_stmt s.
Proof.
If the function can be obfuscated, then there is no Sswitch nor Slabel nor Sgoto
Theorem no_switch_label_goto_function:
forall f f',
transf_function phi f =
OK f' ->
no_switch_label_goto_in_stmt (
fn_body f).
Proof.
no_switch_label_goto_in_cont k indicates that there is no Sswitch nor Slabel nor Sgoto in the continuation k
Inductive no_switch_label_goto_in_cont:
cont ->
Prop :=
|
no_switch_label_goto_in_stop:
no_switch_label_goto_in_cont Kstop
|
no_switch_label_goto_in_seq:
forall s k,
no_switch_label_goto_in_stmt s ->
no_switch_label_goto_in_cont k ->
no_switch_label_goto_in_cont (
Kseq s k)
|
no_switch_label_goto_in_loop1:
forall s1 s2 k,
no_switch_label_goto_in_stmt s1 ->
no_switch_label_goto_in_stmt s2 ->
no_switch_label_goto_in_cont k ->
no_switch_label_goto_in_cont (
Kloop1 s1 s2 k)
|
no_switch_label_goto_in_loop2:
forall s1 s2 k,
no_switch_label_goto_in_stmt s1 ->
no_switch_label_goto_in_stmt s2 ->
no_switch_label_goto_in_cont k ->
no_switch_label_goto_in_cont (
Kloop2 s1 s2 k)
|
no_switch_label_goto_in_Kcall:
forall optid f e le k,
no_switch_label_goto_in_stmt (
fn_body f) ->
no_switch_label_goto_in_cont k ->
no_switch_label_goto_in_cont (
Kcall optid f e le k).
End Utils.
Section PRESERVATION.
phi is the numerotation function
Variable phi:
Z ->
Int.int.
We assume that phi is an injective function of 0, 2^32 - 1 -> 0, 2^32 - 1
Variable phi_injective:
forall x y,
0 <=
x <=
Int.max_unsigned ->
0 <=
y <=
Int.max_unsigned ->
phi x =
phi y ->
x =
y.
Variable prog:
Clight.program.
Variable tprog:
Clight.program.
Hypothesis TRANSF:
transf_program phi prog =
OK tprog.
Let ge :=
Clight.globalenv prog.
Let tge :=
Clight.globalenv tprog.
Lemma comp_env_preserved:
Clight.genv_cenv tge =
Clight.genv_cenv ge.
Proof.
monadInv TRANSF.
unfold tge;
rewrite <-
H0;
auto.
Qed.
Lemma transf_programs:
AST.transform_partial_program (
transf_fundef phi) (
program_of_program prog) =
OK (
program_of_program tprog).
Proof.
monadInv TRANSF.
rewrite EQ.
destruct x;
reflexivity.
Qed.
Lemma symbols_preserved:
forall (
s:
ident),
Genv.find_symbol tge s =
Genv.find_symbol ge s.
Proof.
Lemma varinfo_preserved:
forall b,
Genv.find_var_info tge b =
Genv.find_var_info ge b.
Proof.
Lemma functions_translated:
forall (
v:
val) (
f:
Clight.fundef),
Genv.find_funct ge v =
Some f ->
exists tf,
Genv.find_funct tge v =
Some tf /\
transf_fundef phi f =
OK tf.
Proof.
Lemma function_ptr_translated:
forall (
b:
block) (
f:
Clight.fundef),
Genv.find_funct_ptr ge b =
Some f ->
exists tf,
Genv.find_funct_ptr tge b =
Some tf /\
transf_fundef phi f =
OK tf.
Proof.
Lemma type_of_fundef_preserved:
forall fd tfd,
transf_fundef phi fd =
OK tfd ->
type_of_fundef tfd =
type_of_fundef fd.
Proof.
intros.
destruct fd;
monadInv H;
auto.
monadInv EQ.
simpl;
unfold type_of_function;
simpl.
auto.
Qed.
Section EXPR_PRESERVATION.
Evaluation of expressions is preserved
id is assumed to be the identifier of the pseudo ``program counter''
Variable (
id:
ident).
Variable (
e:
env).
Variables (
le tle:
temp_env).
Variable (
m:
mem).
The values of all variables different from id are preserved
Hypothesis LENV:
forall id',
id' <>
id ->
le!
id' =
tle!
id'.
Evaluation of expressions is preserved
Theorem eval_expr_preserved:
forall a v,
eval_expr ge e le m a v ->
not_in_expr id a ->
eval_expr tge e tle m a v
Evaluation of l-values is preserved
with eval_lvalue_preserved:
forall a loc ofs,
eval_lvalue ge e le m a loc ofs ->
not_in_expr id a ->
eval_lvalue tge e tle m a loc ofs.
Proof.
{
destruct 1;
intros;
try (
econstructor;
fail).
-
econstructor.
inv H0;
rewrite <-
LENV;
auto.
-
econstructor.
inv H0;
eapply eval_lvalue_preserved;
eauto.
-
econstructor.
+
inv H1;
eapply eval_expr_preserved;
eauto.
+
exact H0.
-
econstructor.
+
inv H2;
eapply eval_expr_preserved;
eauto.
+
inv H2;
eapply eval_expr_preserved;
eauto.
+
rewrite comp_env_preserved.
exact H1.
-
econstructor.
+
inv H1;
eapply eval_expr_preserved;
eauto.
+
exact H0.
-
rewrite <-
comp_env_preserved.
eapply eval_Esizeof.
-
rewrite <-
comp_env_preserved.
eapply eval_Ealignof.
-
econstructor.
+
eapply eval_lvalue_preserved;
eauto.
+
exact H0. }
{
destruct 1;
intros;
try (
econstructor;
eauto;
fail).
-
eapply eval_Evar_global;
eauto.
rewrite symbols_preserved;
auto.
-
econstructor.
inv H0;
eapply eval_expr_preserved;
eauto.
-
rewrite <-
comp_env_preserved in *.
econstructor;
eauto.
inv H3;
eapply eval_expr_preserved;
eauto.
-
rewrite <-
comp_env_preserved in *.
econstructor;
eauto.
inv H2;
eapply eval_expr_preserved;
eauto. }
Qed.
Evaluation of expression lists is preserved
Theorem eval_exprlist_preserved:
forall al tyl v,
eval_exprlist ge e le m al tyl v ->
(
forall a,
In a al ->
not_in_expr id a) ->
eval_exprlist tge e tle m al tyl v.
Proof.
induction 1;
intros.
-
constructor.
-
econstructor;
eauto.
+
eapply eval_expr_preserved;
eauto.
eapply H2;
eauto.
simpl;
left;
auto.
+
eapply IHeval_exprlist;
eauto.
intros;
eapply H2;
simpl;
right;
auto.
Qed.
End EXPR_PRESERVATION.
Context of a continuation, either Kloop1, Kloop2, Kcall (Kswitch unused)
Fixpoint context (
k:
cont):
cont :=
match k with
|
Kseq _ k' =>
context k'
|
_ =>
k
end.
match_stmt_cont_in_loop1 s ls id_t starts current next_instr to_continues to_breaks k indicates that the statements s corresponds to the case associated with the number current in the labeled_statements ls, the next statement that can be found in the continuation k is associated with the case corresponding to next_instr.
starts is a stack (list) of numbers corresponding to the start of each Sloop that were encountered, to_continues stores the numbers associated to the Scontinue of each already encountered Sloop, likewise for to_breaks
Inductive match_stmt_cont_in_loop1:
statement ->
labeled_statements -> (
ident *
type) ->
list Z ->
Z ->
Z ->
list Z ->
list Z ->
cont ->
Prop :=
|
match_skip_cont_seq_in_loop1:
forall start id_t ls n next_instr to_continue to_break ls'
s k,
(
exists s1 s2 k',
context (
Kseq s k) =
Kloop1 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
(
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence Sskip (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') /\
exists m,
match_stmt_cont_in_loop1 s ls id_t start next_instr m to_continue to_break k) \/
match_stmt_cont_in_loop1 s ls id_t start n next_instr to_continue to_break k ->
match_stmt_cont_in_loop1 Sskip ls id_t start n next_instr to_continue to_break (
Kseq s k)
|
match_skip_cont_loop1_in_loop1:
forall start id_t ls n next_instr to_continue to_break ls'
s1 s2 k,
0 <
n <=
Int.max_unsigned ->
(
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence Sskip (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') /\
exists m,
match_stmt_cont_in_loop2 s2 ls id_t start next_instr m to_continue to_break (
Kloop2 s1 s2 k)) \/
match_stmt_cont_in_loop2 s2 ls id_t start n next_instr to_continue to_break (
Kloop2 s1 s2 k) ->
match_stmt_cont_in_loop1 Sskip ls id_t start n next_instr to_continue to_break (
Kloop1 s1 s2 k)
|
match_assign_cont_in_loop1:
forall start id_t ls n next_instr to_continue to_break ls'
e1 e2 k,
(
exists s1 s2 k',
context k =
Kloop1 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sassign e1 e2) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont_in_loop1 Sskip ls id_t start next_instr m to_continue to_break k) ->
match_stmt_cont_in_loop1 (
Sassign e1 e2)
ls id_t start n next_instr to_continue to_break k
|
match_set_cont_in_loop1:
forall start id_t ls n next_instr to_continue to_break ls'
id e k,
(
exists s1 s2 k',
context k =
Kloop1 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sset id e) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont_in_loop1 Sskip ls id_t start next_instr m to_continue to_break k) ->
match_stmt_cont_in_loop1 (
Sset id e)
ls id_t start n next_instr to_continue to_break k
|
match_call_cont_in_loop1:
forall start id_t ls n next_instr to_continue to_break ls'
optid a al k,
(
exists s1 s2 k',
context k =
Kloop1 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Scall optid a al) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont_in_loop1 Sskip ls id_t start next_instr m to_continue to_break k) ->
match_stmt_cont_in_loop1 (
Scall optid a al)
ls id_t start n next_instr to_continue to_break k
|
match_builtin_cont_in_loop1:
forall start id_t ls n next_instr to_continue to_break ls'
optid ef tyargs al k,
(
exists s1 s2 k',
context k =
Kloop1 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sbuiltin optid ef tyargs al) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont_in_loop1 Sskip ls id_t start next_instr m to_continue to_break k) ->
match_stmt_cont_in_loop1 (
Sbuiltin optid ef tyargs al)
ls id_t start n next_instr to_continue to_break k
|
match_sequence_cont_in_loop1:
forall start id_t ls n next_instr to_continue to_break s1 s2 k,
(
exists s s'
k',
context k =
Kloop1 s s'
k') ->
0 <
n <=
Int.max_unsigned ->
match_stmt_cont_in_loop1 s1 ls id_t start (
n) (
n +
sizeof_stmt s1)
to_continue to_break (
Kseq s2 k) ->
match_stmt_cont_in_loop1 s2 ls id_t start (
n +
sizeof_stmt s1)
next_instr to_continue to_break k ->
match_stmt_cont_in_loop1 (
Ssequence s1 s2)
ls id_t start n next_instr to_continue to_break k
|
match_ifthenelse_cont_in_loop1:
forall start id_t ls ls'
n next_instr to_continue to_break b s1 s2 k,
(
exists s s'
k',
context k =
Kloop1 s s'
k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Sifthenelse b (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
n + 1)) (
snd id_t)))
Sbreak) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
n + 1 +
sizeof_stmt s1)) (
snd id_t)))
Sbreak))
ls') ->
match_stmt_cont_in_loop1 s1 ls id_t start (
n + 1)
next_instr to_continue to_break k ->
match_stmt_cont_in_loop1 s2 ls id_t start (
n + 1 +
sizeof_stmt s1)
next_instr to_continue to_break k ->
match_stmt_cont_in_loop1 (
Sifthenelse b s1 s2)
ls id_t start n next_instr to_continue to_break k
|
match_loop_cont_in_loop1:
forall start id_t ls ls'
n next_instr to_continue to_break s1 s2 k,
(
exists s s'
k',
context k =
Kloop1 s s'
k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
n + 1)) (
snd id_t)))
Sbreak)
ls') ->
match_stmt_cont_in_loop1 s1 ls id_t (
n::
start) (
n + 1) (
n + 1 +
sizeof_stmt s1) ((
n + 1 +
sizeof_stmt s1)::
to_continue) (
next_instr::
to_break) (
Kloop1 s1 s2 k) ->
match_stmt_cont_in_loop2 s2 ls id_t (
n::
start) (
n + 1 +
sizeof_stmt s1)
n ((
n + 1 +
sizeof_stmt s1)::
to_continue) (
next_instr::
to_break) (
Kloop2 s1 s2 k) ->
match_stmt_cont_in_loop1 (
Sloop s1 s2)
ls id_t start n next_instr to_continue to_break k
|
match_break_cont_seq_in_loop1:
forall start id_t ls n next_instr to_continue to_break s k,
(
exists s1 s2 k',
context (
Kseq s k) =
Kloop1 s1 s2 k') ->
match_stmt_cont_in_loop1 Sbreak ls id_t start n next_instr to_continue to_break k ->
match_stmt_cont_in_loop1 Sbreak ls id_t start n next_instr to_continue to_break (
Kseq s k)
|
match_break_cont_loop1_in_loop1:
forall start id_t ls n next_instr to_continue to_break ls'
s1 s2 k start'
p q,
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi to_break) (
snd id_t)))
Sbreak)
ls') ->
((
is_call_cont (
context k) /\
exists m,
match_stmt_cont Sskip ls id_t to_break m k /\
start' =
nil /\
p =
nil /\
q =
nil) \/
(
exists s s'
k',
context k =
Kloop1 s s'
k' /\
exists m,
match_stmt_cont_in_loop1 Sskip ls id_t start'
to_break m p q k) \/
(
exists s s'
k',
context k =
Kloop2 s s'
k' /\
exists m,
match_stmt_cont_in_loop2 Sskip ls id_t start'
to_break m p q k)) ->
match_stmt_cont_in_loop1 Sbreak ls id_t (
start::
start')
n next_instr (
to_continue::
p) (
to_break::
q) (
Kloop1 s1 s2 k)
|
match_continue_cont_seq_in_loop1:
forall start id_t ls n next_instr to_continue to_break s k,
(
exists s1 s2 k',
context (
Kseq s k) =
Kloop1 s1 s2 k') ->
match_stmt_cont_in_loop1 Scontinue ls id_t start n next_instr to_continue to_break k ->
match_stmt_cont_in_loop1 Scontinue ls id_t start n next_instr to_continue to_break (
Kseq s k)
|
match_continue_cont_loop1_in_loop1:
forall start id_t ls n next_instr to_continue to_continue'
to_break ls'
s1 s2 k,
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi to_continue) (
snd id_t)))
Sbreak)
ls') ->
(
exists m,
match_stmt_cont_in_loop2 s2 ls id_t start to_continue m (
to_continue::
to_continue')
to_break (
Kloop2 s1 s2 k)) ->
match_stmt_cont_in_loop1 Scontinue ls id_t start n next_instr (
to_continue::
to_continue')
to_break (
Kloop1 s1 s2 k)
|
match_return_cont_in_loop1:
forall start id_t ls n next_instr to_continue to_break ls'
v k,
(
exists s1 s2 k',
context k =
Kloop1 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sreturn v) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
match_stmt_cont_in_loop1 (
Sreturn v)
ls id_t start n next_instr to_continue to_break k
similar to match_stmt_cont_in_loop1 with the exception that there Scontinues are not associated
with match_stmt_cont_in_loop2:
statement ->
labeled_statements ->
ident *
type ->
list Z ->
Z ->
Z ->
list Z ->
list Z ->
cont ->
Prop :=
|
match_skip_cont_seq_in_loop2:
forall start id_t ls n next_instr to_continue to_break ls'
s k,
(
exists s1 s2 k',
context (
Kseq s k) =
Kloop2 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
(
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence Sskip (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') /\
exists m,
match_stmt_cont_in_loop2 s ls id_t start next_instr m to_continue to_break k) \/
match_stmt_cont_in_loop2 s ls id_t start n next_instr to_continue to_break k ->
match_stmt_cont_in_loop2 Sskip ls id_t start n next_instr to_continue to_break (
Kseq s k)
|
match_skip_cont_loop2_in_loop2:
forall start start'
id_t ls n next_instr to_continue to_break ls'
s1 s2 k,
0 <
n <=
Int.max_unsigned ->
(
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence Sskip (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') /\
next_instr =
start /\
(
exists ls'',
select_switch_case (
Int.unsigned (
phi next_instr))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi next_instr))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
start + 1)) (
snd id_t)))
Sbreak)
ls'')) \/
(
n =
start /\
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
start + 1)) (
snd id_t)))
Sbreak)
ls'))) ->
match_stmt_cont_in_loop2 Sskip ls id_t (
start::
start')
n next_instr to_continue to_break (
Kloop2 s1 s2 k)
|
match_assign_cont_in_loop2:
forall start id_t ls n next_instr to_continue to_break ls'
e1 e2 k,
(
exists s1 s2 k',
context k =
Kloop2 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sassign e1 e2) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont_in_loop2 Sskip ls id_t start next_instr m to_continue to_break k) ->
match_stmt_cont_in_loop2 (
Sassign e1 e2)
ls id_t start n next_instr to_continue to_break k
|
match_set_cont_in_loop2:
forall start id_t ls n next_instr to_continue to_break ls'
id e k,
(
exists s1 s2 k',
context k =
Kloop2 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sset id e) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont_in_loop2 Sskip ls id_t start next_instr m to_continue to_break k) ->
match_stmt_cont_in_loop2 (
Sset id e)
ls id_t start n next_instr to_continue to_break k
|
match_call_cont_in_loop2:
forall start id_t ls n next_instr to_continue to_break ls'
optid a al k,
(
exists s1 s2 k',
context k =
Kloop2 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Scall optid a al) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont_in_loop2 Sskip ls id_t start next_instr m to_continue to_break k) ->
match_stmt_cont_in_loop2 (
Scall optid a al)
ls id_t start n next_instr to_continue to_break k
|
match_builtin_cont_in_loop2:
forall start id_t ls n next_instr to_continue to_break ls'
optid ef tyargs al k,
(
exists s1 s2 k',
context k =
Kloop2 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sbuiltin optid ef tyargs al) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont_in_loop2 Sskip ls id_t start next_instr m to_continue to_break k) ->
match_stmt_cont_in_loop2 (
Sbuiltin optid ef tyargs al)
ls id_t start n next_instr to_continue to_break k
|
match_sequence_cont_in_loop2:
forall start id_t ls n next_instr to_continue to_break s1 s2 k,
(
exists s s'
k',
context k =
Kloop2 s s'
k') ->
0 <
n <=
Int.max_unsigned ->
match_stmt_cont_in_loop2 s1 ls id_t start (
n) (
n +
sizeof_stmt s1)
to_continue to_break (
Kseq s2 k) ->
match_stmt_cont_in_loop2 s2 ls id_t start (
n +
sizeof_stmt s1)
next_instr to_continue to_break k ->
match_stmt_cont_in_loop2 (
Ssequence s1 s2)
ls id_t start n next_instr to_continue to_break k
|
match_ifthenelse_cont_in_loop2:
forall start id_t ls ls'
n next_instr to_continue to_break b s1 s2 k,
(
exists s s'
k',
context k =
Kloop2 s s'
k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Sifthenelse b (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
n + 1)) (
snd id_t)))
Sbreak) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
n + 1 +
sizeof_stmt s1)) (
snd id_t)))
Sbreak))
ls') ->
match_stmt_cont_in_loop2 s1 ls id_t start (
n + 1)
next_instr to_continue to_break k ->
match_stmt_cont_in_loop2 s2 ls id_t start (
n + 1 +
sizeof_stmt s1)
next_instr to_continue to_break k ->
match_stmt_cont_in_loop2 (
Sifthenelse b s1 s2)
ls id_t start n next_instr to_continue to_break k
|
match_loop_cont_in_loop2:
forall start id_t ls ls'
n next_instr to_continue to_break s1 s2 k,
(
exists s s'
k',
context k =
Kloop2 s s'
k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
n + 1)) (
snd id_t)))
Sbreak)
ls') ->
match_stmt_cont_in_loop1 s1 ls id_t (
n::
start) (
n + 1) (
n + 1 +
sizeof_stmt s1) ((
n + 1 +
sizeof_stmt s1)::
to_continue) (
next_instr::
to_break) (
Kloop1 s1 s2 k) ->
match_stmt_cont_in_loop2 s2 ls id_t (
n::
start) (
n + 1 +
sizeof_stmt s1)
n ((
n + 1 +
sizeof_stmt s1)::
to_continue) (
next_instr::
to_break) (
Kloop2 s1 s2 k) ->
match_stmt_cont_in_loop2 (
Sloop s1 s2)
ls id_t start n next_instr to_continue to_break k
|
match_break_cont_seq_in_loop2:
forall start id_t ls n next_instr to_continue to_break s k,
(
exists s1 s2 k',
context (
Kseq s k) =
Kloop2 s1 s2 k') ->
match_stmt_cont_in_loop2 Sbreak ls id_t start n next_instr to_continue to_break k ->
match_stmt_cont_in_loop2 Sbreak ls id_t start n next_instr to_continue to_break (
Kseq s k)
|
match_break_cont_loop2_in_loop2:
forall start start'
id_t ls n next_instr to_continue to_break ls'
s1 s2 k p q,
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi to_break) (
snd id_t)))
Sbreak)
ls') ->
((
is_call_cont (
context k) /\
exists m,
match_stmt_cont Sskip ls id_t to_break m k /\
start' =
nil /\
p =
nil /\
q =
nil) \/
(
exists s s'
k',
context k =
Kloop1 s s'
k' /\
exists m,
match_stmt_cont_in_loop1 Sskip ls id_t start'
to_break m p q k) \/
(
exists s s'
k',
context k =
Kloop2 s s'
k' /\
exists m,
match_stmt_cont_in_loop2 Sskip ls id_t start'
to_break m p q k)) ->
match_stmt_cont_in_loop2 Sbreak ls id_t (
start::
start')
n next_instr (
to_continue::
p) (
to_break::
q) (
Kloop2 s1 s2 k)
|
match_return_cont_in_loop2:
forall start id_t ls n next_instr to_continue to_break ls'
v k,
(
exists s1 s2 k',
context k =
Kloop2 s1 s2 k') ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sreturn v) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
match_stmt_cont_in_loop2 (
Sreturn v)
ls id_t start n next_instr to_continue to_break k
similar to match_stmt_cont_in_loop1 with the exception that Scontinues and Sbreaks are not associated
with match_stmt_cont:
statement ->
labeled_statements ->
ident *
type ->
Z ->
Z ->
cont ->
Prop :=
|
match_skip_cont_seq:
forall id_t ls n next_instr ls'
s k,
is_call_cont (
context (
Kseq s k)) ->
0 <
n <=
Int.max_unsigned ->
(
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence Sskip (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') /\
exists m,
match_stmt_cont s ls id_t next_instr m k) \/
match_stmt_cont s ls id_t n next_instr k ->
match_stmt_cont Sskip ls id_t n next_instr (
Kseq s k)
|
match_skip_cont_call_cont:
forall id_t ls n next_instr ls'
k,
is_call_cont k ->
((
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence Sskip (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') /\
0 <
n <=
Int.max_unsigned /\
next_instr = 0 /\
select_switch (
Int.unsigned (
phi next_instr))
ls =
LSnil) \/
n = 0 /\
select_switch (
Int.unsigned (
phi n))
ls =
LSnil) ->
match_stmt_cont Sskip ls id_t n next_instr k
|
match_assign_cont:
forall id_t ls n next_instr ls'
e1 e2 k,
is_call_cont (
context k) ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sassign e1 e2) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont Sskip ls id_t next_instr m k) ->
match_stmt_cont (
Sassign e1 e2)
ls id_t n next_instr k
|
match_set_cont:
forall id_t ls n next_instr ls'
id e k,
is_call_cont (
context k) ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sset id e) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont Sskip ls id_t next_instr m k) ->
match_stmt_cont (
Sset id e)
ls id_t n next_instr k
|
match_scall_cont:
forall id_t ls n next_instr ls'
optid a al k,
is_call_cont (
context k) ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Scall optid a al) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont Sskip ls id_t next_instr m k) ->
match_stmt_cont (
Scall optid a al)
ls id_t n next_instr k
|
match_builtin_cont:
forall id_t ls n next_instr ls'
optid ef tyargs al k,
is_call_cont (
context k) ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sbuiltin optid ef tyargs al) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
(
exists m,
match_stmt_cont Sskip ls id_t next_instr m k) ->
match_stmt_cont (
Sbuiltin optid ef tyargs al)
ls id_t n next_instr k
|
match_sequence_cont:
forall id_t ls n next_instr s1 s2 k,
is_call_cont (
context k) ->
0 <
n <=
Int.max_unsigned ->
match_stmt_cont s1 ls id_t (
n) (
n +
sizeof_stmt s1) (
Kseq s2 k) ->
match_stmt_cont s2 ls id_t (
n +
sizeof_stmt s1)
next_instr k ->
match_stmt_cont (
Ssequence s1 s2)
ls id_t n next_instr k
|
match_ifthenelse_cont:
forall id_t ls ls'
n next_instr b s1 s2 k,
is_call_cont (
context k) ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Sifthenelse b (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
n + 1)) (
snd id_t)))
Sbreak) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
n + 1 +
sizeof_stmt s1)) (
snd id_t)))
Sbreak))
ls') ->
match_stmt_cont s1 ls id_t (
n + 1)
next_instr k ->
match_stmt_cont s2 ls id_t (
n + 1 +
sizeof_stmt s1)
next_instr k ->
match_stmt_cont (
Sifthenelse b s1 s2)
ls id_t n next_instr k
|
match_loop_cont:
forall id_t ls ls'
n next_instr s1 s2 k,
is_call_cont (
context k) ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
n + 1)) (
snd id_t)))
Sbreak)
ls') ->
match_stmt_cont_in_loop1 s1 ls id_t (
n::
nil) (
n + 1) (
n + 1 +
sizeof_stmt s1) ((
n + 1 +
sizeof_stmt s1)::
nil) (
next_instr::
nil) (
Kloop1 s1 s2 k) ->
match_stmt_cont_in_loop2 s2 ls id_t (
n::
nil) (
n + 1 +
sizeof_stmt s1)
n ((
n + 1 +
sizeof_stmt s1)::
nil) (
next_instr::
nil) (
Kloop2 s1 s2 k) ->
match_stmt_cont (
Sloop s1 s2)
ls id_t n next_instr k
|
match_return_cont:
forall id_t ls n next_instr ls'
v k,
is_call_cont (
context k) ->
0 <
n <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi n))
ls =
Some (
LScons (
Some (
Int.unsigned (
phi n))) (
Ssequence (
Sreturn v) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi next_instr) (
snd id_t)))
Sbreak))
ls') ->
match_stmt_cont (
Sreturn v)
ls id_t n next_instr k.
If the context of continuation k is either Kcall or Kstop then k is either Kcall or Kstop or Kseq
Lemma is_call_cont_context:
forall k,
is_call_cont (
context k) ->
is_call_cont k \/
exists s k',
k =
Kseq s k'.
Proof.
destruct k; intros; try (inv H; left; constructor; fail).
right; eauto.
Qed.
Helper lemma for selecting a case in appended labeled statements
Lemma select_switch_case_app_right:
forall ls1 ls2 pc,
select_switch_case pc ls1 =
None ->
select_switch_case pc (
app_lstmt ls1 ls2) =
select_switch_case pc ls2.
Proof.
induction ls1;
simpl;
intros;
auto.
destruct o;
try (
destruct (
zeq z pc);
try inv H;
eauto).
eauto.
Qed.
Helper lemma for selecting case
Lemma select_switch_nil_select_switch_case:
forall pc ls,
select_switch pc ls =
LSnil ->
select_switch_case pc ls =
None.
Proof.
induction ls;
simpl;
intros;
eauto.
unfold select_switch in H;
simpl in H.
destruct o.
destruct (
zeq z pc);
try inv H.
exploit IHls;
eauto.
exploit IHls;
eauto.
unfold select_switch.
destruct (
select_switch_case pc ls);
auto;
inv H.
Qed.
Helper lemma for selecting a case in appended labeled statements
Lemma select_switch_default_app_right:
forall ls1 ls2,
select_switch_default ls1 =
LSnil ->
select_switch_default (
app_lstmt ls1 ls2) =
select_switch_default ls2.
Proof.
induction ls1; simpl; intros; auto.
destruct o; eauto; inv H.
Qed.
Helper lemma for selecting a case in appended labeled statements
Lemma select_switch_app_right:
forall ls1 ls2 pc,
select_switch pc ls1 =
LSnil ->
select_switch pc (
app_lstmt ls1 ls2) =
select_switch pc ls2.
Proof.
app_lstmt is associative
Lemma app_lstmt_assoc:
forall ls1 ls2 ls3,
app_lstmt (
app_lstmt ls1 ls2)
ls3 =
app_lstmt ls1 (
app_lstmt ls2 ls3).
Proof.
induction ls1; simpl; intros; eauto.
rewrite IHls1; eauto.
Qed.
select_switch_case never returns Some LSnil
Lemma select_switch_case_not_nil:
forall n ls,
select_switch_case n ls <>
Some LSnil.
Proof.
induction ls;
simpl;
try congruence.
destruct o;
auto.
destruct (
zeq z n);
try congruence;
auto.
Qed.
If the case cannot be selected in ls1 ++ ls2, it can't be found in neither ls1 nor ls2
Lemma select_switch_app_nil:
forall n ls1 ls2,
select_switch n (
app_lstmt ls1 ls2) =
LSnil ->
select_switch n ls1 =
LSnil /\
select_switch n ls2 =
LSnil.
Proof.
The composition of Int.unsigned and phi is still injective
Lemma phi_injection:
forall n m,
0 <=
n <=
Int.max_unsigned ->
0 <=
m <=
Int.max_unsigned ->
Int.unsigned (
phi n) =
Int.unsigned (
phi m) ->
n =
m.
Proof.
If statement s has been successfully transformed into labeled_statements ls and if there are no case corresponding to Int.unsigned (phi pc) in ls then pc must be either too low (pc < n) or too high (n + sizeof_stmt s <= pc) and conversely
Lemma select_switch_in_loop1_flatten:
forall s id_t n m k l ls pc,
0 <=
n ->
(
n +
sizeof_stmt s) <=
Int.max_unsigned ->
0 <=
pc <=
Int.max_unsigned ->
flatten_loop1 phi id_t s n m k l =
OK ls ->
(
select_switch (
Int.unsigned (
phi pc))
ls =
LSnil <->
pc <
n \/
n +
sizeof_stmt s <=
pc)
with select_switch_in_loop2_flatten:
forall s id_t n m k ls pc,
0 <=
n ->
(
n +
sizeof_stmt s) <=
Int.max_unsigned ->
0 <=
pc <=
Int.max_unsigned ->
flatten_loop2 phi id_t s n m k =
OK ls ->
(
select_switch (
Int.unsigned (
phi pc))
ls =
LSnil <->
pc <
n \/
n +
sizeof_stmt s <=
pc).
Proof.
If statement s has been successfully transformed into labeled_statements ls and if there are no case corresponding to Int.unsigned (phi pc) in ls then pc must be either too low (pc < n) or too high (n + sizeof_stmt s <= pc) and conversely
Lemma select_switch_flatten:
forall s id_t n m ls pc,
0 <=
n ->
(
n +
sizeof_stmt s) <=
Int.max_unsigned ->
0 <=
pc <=
Int.max_unsigned ->
flatten phi id_t s n m =
OK ls ->
(
select_switch (
Int.unsigned (
phi pc))
ls =
LSnil <->
pc <
n \/
n +
sizeof_stmt s <=
pc).
Proof.
Helper lemma relating cons and append over labeled_statements
Lemma lscons_app_lstmt:
forall o s ls,
LScons o s ls =
app_lstmt (
LScons o s LSnil)
ls.
Proof.
simpl; auto. Qed.
Helper lemma relating cons and append over labeled_statements
Lemma app_lstmt_lscons:
forall o s ls1 ls2,
LScons o s (
app_lstmt ls1 ls2) =
app_lstmt (
LScons o s ls1)
ls2.
Proof.
simpl; auto. Qed.
LSnil is the identity element for appending labeled_statements
Lemma app_lstmt_lsnil:
forall ls,
app_lstmt ls LSnil =
ls.
Proof.
induction ls; simpl; eauto. rewrite IHls; auto. Qed.
If the context of continuation k is Kloop1 then k must either be Kloop1 or Kseq
Lemma context_loop1:
forall k s1 s2 k',
context k =
Kloop1 s1 s2 k' ->
k =
Kloop1 s1 s2 k' \/
exists s''
k'',
k =
Kseq s''
k''.
Proof.
induction k; intros; try (inv H). right; eauto. left; eauto. Qed.
If the context of continuation k is Kloop2 then k must either be Kloop2 or Kseq
Lemma context_loop2:
forall k s1 s2 k',
context k =
Kloop2 s1 s2 k' ->
k =
Kloop2 s1 s2 k' \/
exists s''
k'',
k =
Kseq s''
k''.
Proof.
induction k; intros; try (inv H). right; eauto. left; eauto. Qed.
Fast-forward to the context
Lemma break_continue_seq_match_stmt_cont_in_loop1:
forall k s s1 s2 k'
start pc next_instr to_continue to_break ls id_t,
context k =
Kloop1 s1 s2 k' ->
s =
Sbreak \/
s =
Scontinue ->
(
match_stmt_cont_in_loop1 s ls id_t start pc next_instr to_continue to_break (
Kloop1 s1 s2 k') <->
match_stmt_cont_in_loop1 s ls id_t start pc next_instr to_continue to_break k).
Proof.
intros; split.
- induction k; intros; try (simpl in H; inv H; fail).
+ destruct H0; subst s; econstructor; eauto.
+ simpl in H; inv H; eauto.
- induction k; intros; try (simpl in H; inv H; fail).
+ destruct H0; subst s; eapply IHk; inv H1; eauto.
+ simpl in H; inv H; eauto.
Qed.
Fast-forward to the context
Lemma break_seq_match_stmt_cont_in_loop2:
forall k s1 s2 k'
start pc next_instr to_continue to_break ls id_t,
context k =
Kloop2 s1 s2 k' ->
(
match_stmt_cont_in_loop2 Sbreak ls id_t start pc next_instr to_continue to_break (
Kloop2 s1 s2 k') <->
match_stmt_cont_in_loop2 Sbreak ls id_t start pc next_instr to_continue to_break k).
Proof.
intros; split.
- induction k; intros; try (simpl in H; inv H; fail).
+ econstructor; eauto.
+ simpl in H; inv H; eauto.
- induction k; intros; try (simpl in H; inv H; fail).
+ eapply IHk; inv H0; eauto.
+ simpl in H; inv H; eauto.
Qed.
Sbreak has the same semantics within a Kloop1 or a Kloop2 context
Lemma break_loop1_loop2:
forall s1 s2 k ls id_t start pc next_instr to_continue to_break,
match_stmt_cont_in_loop1 Sbreak ls id_t start pc next_instr to_continue to_break (
Kloop1 s1 s2 k) <->
match_stmt_cont_in_loop2 Sbreak ls id_t start pc next_instr to_continue to_break (
Kloop2 s1 s2 k).
Proof.
intros; split; intros; inv H; econstructor; eauto. Qed.
If statement s can be matched with a case in labeled_statements ls with number pc then pc must be 0 < pc <= Int.max_unsigned
Lemma match_stmt_cont_in_loop1_pos:
forall s ls id_t start pc next_instr to_continue to_break k,
match_stmt_cont_in_loop1 s ls id_t start pc next_instr to_continue to_break k ->
0 <
pc <=
Int.max_unsigned
with match_stmt_cont_in_loop2_pos:
forall s ls id_t start pc next_instr to_continue to_break k,
match_stmt_cont_in_loop2 s ls id_t start pc next_instr to_continue to_break k ->
0 <
pc <=
Int.max_unsigned.
Proof.
Obfuscating statement s through flatten returns a labeled_statements ls that can be matched with s
Fixpoint match_stmt_cont_flatten s {
struct s } :
forall k ls ls1 ls2 pc next_instr id_t,
is_call_cont (
context k) ->
flatten phi id_t s pc next_instr =
OK ls ->
(
forall s'
k',
k =
Kseq s'
k' ->
exists next_instr',
0 <
next_instr <=
Int.max_unsigned /\
match_stmt_cont s' (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t next_instr next_instr'
k') ->
(
is_call_cont k ->
next_instr = 0 /\
select_switch (
Int.unsigned (
phi next_instr)) (
app_lstmt ls1 (
app_lstmt ls ls2)) =
LSnil) ->
(
next_instr <
pc \/
next_instr >=
pc +
sizeof_stmt s) ->
(
forall n,
pc <=
n <=
Int.max_unsigned ->
select_switch (
Int.unsigned (
phi n))
ls1 =
LSnil) ->
0 <
pc ->
pc +
sizeof_stmt s <=
Int.max_unsigned ->
match_stmt_cont s (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t pc next_instr k
with match_stmt_cont_in_loop1_flatten_loop1 s {
struct s } :
forall k ls ls1 ls2 start start'
pc next_instr to_continue to_continue'
to_break to_break'
id_t,
(
exists s1 s2 k',
context k =
Kloop1 s1 s2 k' /\
(
forall counter ls'
next,
0 <
counter <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi counter)) (
app_lstmt ls1 (
app_lstmt ls ls2)) =
Some (
LScons (
Some (
Int.unsigned (
phi counter))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi to_break) (
snd id_t)))
Sbreak)
ls') ->
match_stmt_cont_in_loop1 Sbreak (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t (
start::
start')
counter next (
to_continue::
to_continue') (
to_break::
to_break') (
Kloop1 s1 s2 k')) /\
(
forall counter ls'
next,
0 <
counter <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi counter)) (
app_lstmt ls1 (
app_lstmt ls ls2)) =
Some (
LScons (
Some (
Int.unsigned (
phi counter))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi to_continue) (
snd id_t)))
Sbreak)
ls') ->
match_stmt_cont_in_loop1 Scontinue (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t (
start::
start')
counter next (
to_continue::
to_continue') (
to_break::
to_break') (
Kloop1 s1 s2 k'))) ->
flatten_loop1 phi id_t s pc next_instr to_continue to_break =
OK ls ->
(
forall s'
k',
k =
Kseq s'
k' ->
((
exists next_instr',
match_stmt_cont_in_loop1 s' (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t (
start::
start')
next_instr next_instr' (
to_continue::
to_continue') (
to_break::
to_break')
k'))) ->
(
forall s1'
s2'
k',
k =
Kloop1 s1'
s2'
k' ->
(
next_instr =
to_continue) /\
(
exists ls',
(
next_instr =
start + 1 +
sizeof_stmt s1') /\
(0 <
start /\
start + 1 +
sizeof_stmt s1' +
sizeof_stmt s2' <=
Int.max_unsigned) /\
match_stmt_cont_in_loop2 s2' (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t (
start::
start')
next_instr start (
to_continue::
to_continue') (
to_break::
to_break') (
Kloop2 s1'
s2'
k') /\
select_switch_case (
Int.unsigned (
phi start)) (
app_lstmt ls1 (
app_lstmt ls ls2)) =
Some (
LScons (
Some (
Int.unsigned (
phi start))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
start + 1)) (
snd id_t)))
Sbreak)
ls')) /\
((
is_call_cont (
context k') /\
start' =
nil /\
to_continue' =
nil /\
to_break' =
nil /\
exists next_instr',
match_stmt_cont Sskip (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t to_break next_instr'
k') \/
(
exists s1''
s2''
k'',
context k' =
Kloop1 s1''
s2''
k'' /\
exists next_instr',
match_stmt_cont_in_loop1 Sskip (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t start'
to_break next_instr'
to_continue'
to_break'
k') \/
(
exists s1''
s2''
k'',
context k' =
Kloop2 s1''
s2''
k'' /\
exists next_instr',
match_stmt_cont_in_loop2 Sskip (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t start'
to_break next_instr'
to_continue'
to_break'
k'))) ->
(
next_instr <
pc \/
next_instr >=
pc +
sizeof_stmt s) ->
(
forall n,
pc <=
n <=
Int.max_unsigned ->
select_switch (
Int.unsigned (
phi n))
ls1 =
LSnil) ->
0 <
pc ->
pc +
sizeof_stmt s <=
Int.max_unsigned ->
match_stmt_cont_in_loop1 s (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t (
start::
start')
pc next_instr (
to_continue::
to_continue') (
to_break::
to_break')
k
with match_stmt_cont_in_loop2_flatten_loop2 s {
struct s } :
forall k ls ls1 ls2 start start'
pc next_instr to_continue to_continue'
to_break to_break'
id_t,
(
exists s1 s2 k',
context k =
Kloop2 s1 s2 k' /\
(
forall counter ls'
next,
0 <
counter <=
Int.max_unsigned ->
select_switch_case (
Int.unsigned (
phi counter)) (
app_lstmt ls1 (
app_lstmt ls ls2)) =
Some (
LScons (
Some (
Int.unsigned (
phi counter))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi to_break) (
snd id_t)))
Sbreak)
ls') ->
match_stmt_cont_in_loop2 Sbreak (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t (
start::
start')
counter next (
to_continue::
to_continue') (
to_break::
to_break') (
Kloop2 s1 s2 k'))) ->
flatten_loop2 phi id_t s pc next_instr to_break =
OK ls ->
(
forall s'
k',
k =
Kseq s'
k' ->
((
exists next_instr',
match_stmt_cont_in_loop2 s' (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t (
start::
start')
next_instr next_instr' (
to_continue::
to_continue') (
to_break::
to_break')
k'))) ->
(
forall s1'
s2'
k',
k =
Kloop2 s1'
s2'
k' ->
(
exists ls',
next_instr =
start /\
(0 <
start /\
start + 1 +
sizeof_stmt s1' +
sizeof_stmt s2' <=
Int.max_unsigned) /\
select_switch_case (
Int.unsigned (
phi next_instr)) (
app_lstmt ls1 (
app_lstmt ls ls2)) =
Some (
LScons (
Some (
Int.unsigned (
phi next_instr))) (
Ssequence (
Sset (
fst id_t) (
Econst_int (
phi (
start + 1)) (
snd id_t)))
Sbreak)
ls')) /\
((
is_call_cont (
context k') /\
start' =
nil /\
to_continue' =
nil /\
to_break' =
nil /\
exists next_instr',
match_stmt_cont Sskip (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t to_break next_instr'
k') \/
(
exists s1''
s2''
k'',
context k' =
Kloop1 s1''
s2''
k'' /\
exists next_instr',
match_stmt_cont_in_loop1 Sskip (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t start'
to_break next_instr'
to_continue'
to_break'
k') \/
(
exists s1''
s2''
k'',
context k' =
Kloop2 s1''
s2''
k'' /\
exists next_instr',
match_stmt_cont_in_loop2 Sskip (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t start'
to_break next_instr'
to_continue'
to_break'
k'))) ->
(
next_instr <
pc \/
next_instr >=
pc +
sizeof_stmt s) ->
(
forall n,
pc <=
n <=
Int.max_unsigned ->
select_switch (
Int.unsigned (
phi n))
ls1 =
LSnil) ->
0 <
pc ->
pc +
sizeof_stmt s <=
Int.max_unsigned ->
match_stmt_cont_in_loop2 s (
app_lstmt ls1 (
app_lstmt ls ls2))
id_t (
start::
start')
pc next_instr (
to_continue::
to_continue') (
to_break::
to_break')
k.
Proof.
CompCert doesn't allow stuttering in their simulation diagram: infinitely many transitions in the source program must correspond to infinitely many transitions in the second program. Therefore, when one transition in the first program corresponds to zero in the second, there must be some measure that strictly decreases.
These transitions that correspond to no transition in the transformed program are the following ones:
- Sskip with a Kseq s k continuation
- Scontinue with a Kseq s k continuation
- Sbreak with a Kseq s k continuation
- Sskip with a Kloop1 s1 s2 k continuation
- Sskip with a Kloop2 s1 s2 k continuation
Hence, the measure m must respect the following properties:
m (s1, Kseq s2 k) < m (Ssequence s1 s2, k)
m (s, k) < m (Sskip, Kseq s k)
m (Scontinue, k) < m (Scontinue, Kseq s k)
m (Sbreak, k) < m (Sbreak, Kseq s k)
m (s2, Kloop2 s1 s2 k) < m (Sskip, Kloop1 s1 s2 k)
m (Sloop s1 s2, k) < m (Sskip, Kloop2 s1 s2 k)
Fixpoint num_stmt (
s:
statement):
nat :=
match s with
|
Ssequence s1 s2 =>
S (
S (
num_stmt s1 +
num_stmt s2))
|
_ =>
O
end.
Fixpoint num_cont (
k:
cont):
nat :=
match k with
|
Kseq s k =>
S (
num_cont k +
num_stmt s)
|
Kstop |
Kcall _ _ _ _ _ |
Kswitch _ =>
O
|
Kloop1 _ s2 k =>
S (
S (
num_cont k) +
num_stmt s2)
|
Kloop2 _ _ k =>
S (
num_cont k)
end.
The following measure can be used
Definition measure (
st:
Clight.state):
nat :=
match st with
|
State _ s k _ _ _ => (
num_stmt s +
num_cont k)%
nat
|
_ => 0%
nat
end.
matching loops according to the context given by the continuation k
Inductive match_loop (
ls:
labeled_statements) (
id_t:
ident *
type):
list Z ->
list Z ->
list Z ->
cont ->
Prop :=
|
match_loop_cont_loop1:
forall start start'
to_continue to_continue'
to_break to_break'
s1 s2 k,
0 <
start <=
Int.max_unsigned ->
start + 1 +
sizeof_stmt s1 =
to_continue ->
match_stmt_cont_in_loop1 s1 ls id_t (
start::
start') (
start + 1) (
start + 1 +
sizeof_stmt s1) (
to_continue::
to_continue') (
to_break::
to_break') (
Kloop1 s1 s2 k) ->
match_stmt_cont_in_loop2 s2 ls id_t (
start::
start') (
start + 1 +
sizeof_stmt s1)
start (
to_continue::
to_continue') (
to_break::
to_break') (
Kloop2 s1 s2 k) ->
match_loop ls id_t start'
to_continue'
to_break'
k ->
match_loop ls id_t (
start::
start') (
to_continue::
to_continue') (
to_break::
to_break') (
Kloop1 s1 s2 k)
|
match_loop_cont_loop2:
forall start start'
to_continue to_continue'
to_break to_break'
s1 s2 k,
0 <
start <=
Int.max_unsigned ->
start + 1 +
sizeof_stmt s1 =
to_continue ->
match_stmt_cont_in_loop1 s1 ls id_t (
start::
start') (
start + 1) (
start + 1 +
sizeof_stmt s1) (
to_continue::
to_continue') (
to_break::
to_break') (
Kloop1 s1 s2 k) ->
match_stmt_cont_in_loop2 s2 ls id_t (
start::
start') (
start + 1 +
sizeof_stmt s1)
start (
to_continue::
to_continue') (
to_break::
to_break') (
Kloop2 s1 s2 k) ->
match_loop ls id_t start'
to_continue'
to_break'
k ->
match_loop ls id_t (
start::
start') (
to_continue::
to_continue') (
to_break::
to_break') (
Kloop2 s1 s2 k)
|
match_loop_cont_call:
forall optid f e le k,
match_loop ls id_t nil nil nil (
Kcall optid f e le k)
|
match_loop_cont_stop:
match_loop ls id_t nil nil nil Kstop
|
match_loop_cont_seq:
forall start to_continue to_break s k,
match_loop ls id_t start to_continue to_break (
context (
Kseq s k)) ->
match_loop ls id_t start to_continue to_break (
Kseq s k).
Matching loops depends only on the context of continuation k
Lemma match_loop_context:
forall ls id_t start continue break k,
match_loop ls id_t start continue break k <->
match_loop ls id_t start continue break (
context k).
Proof.
intros; destruct k; simpl; try tauto.
split; intros.
- inv H; simpl in H4; auto.
- constructor; simpl; auto.
Qed.
Matching loops in a call_cont context
Lemma match_loop_call_cont_context:
forall ls id_t k,
is_call_cont (
context k) ->
match_loop ls id_t nil nil nil (
context k).
Proof.
induction k; intros; simpl; try econstructor; try (simpl in H; inv H; fail).
eapply IHk; simpl in H; auto.
Qed.
Matching loops in a Kloop1 context
Lemma match_loop_loop1_context:
forall ls id_t start continue break k s1 s2 k',
context k =
Kloop1 s1 s2 k' ->
match_loop ls id_t start continue break k ->
exists to_start to_start'
to_continue to_continue'
to_break to_break',
start =
to_start::
to_start' /\
continue =
to_continue::
to_continue' /\
break =
to_break::
to_break'.
Proof.
induction k;
intros;
try (
simpl in H;
inv H;
fail).
-
inv H0;
simpl in H;
eapply IHk;
eauto.
eapply match_loop_context;
simpl in H5;
auto.
-
inv H0.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
Qed.
Matching loops in a Kloop2 context
Lemma match_loop_loop2_context:
forall ls id_t start continue break k s1 s2 k',
context k =
Kloop2 s1 s2 k' ->
match_loop ls id_t start continue break k ->
exists to_start to_start'
to_continue to_continue'
to_break to_break',
start =
to_start::
to_start' /\
continue =
to_continue::
to_continue' /\
break =
to_break::
to_break'.
Proof.
induction k;
intros;
try (
simpl in H;
inv H;
fail).
-
inv H0;
simpl in H;
eapply IHk;
eauto.
eapply match_loop_context;
simpl in H5;
auto.
-
inv H0.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
Qed.
Characterisation of matching loops in a call_cont context
Lemma match_loop_call_cont_context_charact:
forall ls id_t start to_continue to_break k,
is_call_cont (
context k) ->
match_loop ls id_t start to_continue to_break k ->
start =
nil /\
to_continue =
nil /\
to_break =
nil.
Proof.
induction k;
intros;
try (
simpl in H;
inv H).
-
inv H0;
auto.
-
simpl in H;
eapply IHk;
eauto.
inv H0;
simpl in H5;
eapply match_loop_context in H5;
auto.
-
inv H0;
auto.
Qed.
Characterisation of context
Lemma context_charact:
forall k,
is_call_cont (
context k) \/
(
exists s1 s2 k',
context k =
Kloop1 s1 s2 k') \/
(
exists s1 s2 k',
context k =
Kloop2 s1 s2 k') \/
(
exists k',
context k =
Kswitch k').
Proof.
induction k; try (simpl; tauto).
- simpl; right; left; eauto.
- simpl; right; right; left; eauto.
- simpl; right; right; right; eauto.
Qed.
If k doesn't contain a Kswitch then its context cannot be a Kswitch
Lemma no_switch_context:
forall k k',
no_switch_label_goto_in_cont k ->
context k <>
Kswitch k'.
Proof.
induction k; intros; try (simpl; congruence).
- inv H; simpl; apply IHk; auto.
- inv H.
Qed.
call_cont k doesn't contain a Kswitch if k doesn't
Lemma no_switch_label_goto_in_cont_call_cont:
forall k,
no_switch_label_goto_in_cont k ->
no_switch_label_goto_in_cont (
call_cont k).
Proof.
induction 1; simpl; eauto.
- econstructor.
- econstructor; eauto.
Qed.
Matching Kstop and Kcall continuations
Inductive match_call_cont:
cont ->
cont ->
Prop :=
|
match_call_cont_stop:
forall k tk,
call_cont k =
Kstop ->
call_cont tk =
Kstop ->
match_call_cont k tk
|
match_call_cont_call:
forall k tk optid f tf e le tle k'
tk'
ls,
call_cont k =
Kcall optid f e le k' ->
call_cont tk =
Kcall optid tf e tle tk' ->
transf_function phi f =
OK tf ->
flatten phi (
new_ident_for_function f,
tint) (
fn_body f) 1 0 =
OK ls ->
(
forall id,
id <>
new_ident_for_function f ->
le!
id =
tle!
id) ->
(
exists next_instr ls'
tk'',
tk' =
Kseq
(
Ssequence
(
Sset (
new_ident_for_function f)
(
Econst_int (
phi next_instr)
tint))
Sbreak)
(
Kseq (
seq_of_labeled_statement ls')
(
Kswitch
(
Kloop1
(
Ssequence
(
Sifthenelse
(
Ebinop One (
Etempvar (
new_ident_for_function f)
tint)
(
Econst_int (
phi 0)
tint)
tint)
Sskip Sbreak)
(
Sswitch (
Etempvar (
new_ident_for_function f)
tint)
ls))
Sskip tk''))) /\
(
is_call_cont tk'') /\
((
is_call_cont (
context k') /\
exists next_instr',
match_stmt_cont Sskip ls (
new_ident_for_function f,
tint)
next_instr next_instr'
k') \/
(
exists s1 s2 k'',
context k' =
Kloop1 s1 s2 k'' /\
exists start start'
next_instr'
to_continue to_continue'
to_break to_break',
match_stmt_cont_in_loop1 Sskip ls (
new_ident_for_function f,
tint) (
start::
start')
next_instr next_instr' (
to_continue::
to_continue') (
to_break::
to_break')
k' /\
match_loop ls (
new_ident_for_function f,
tint) (
start::
start') (
to_continue::
to_continue') (
to_break::
to_break')
k') \/
(
exists s1 s2 k'',
context k' =
Kloop2 s1 s2 k'' /\
exists start start'
next_instr'
to_continue to_continue'
to_break to_break',
match_stmt_cont_in_loop2 Sskip ls (
new_ident_for_function f,
tint) (
start::
start')
next_instr next_instr' (
to_continue::
to_continue') (
to_break::
to_break')
k' /\
match_loop ls (
new_ident_for_function f,
tint) (
start::
start') (
to_continue::
to_continue') (
to_break::
to_break')
k'))) ->
match_call_cont k'
tk' ->
match_call_cont k tk.
match_call_cont k tk depends only on the context of k and tk
Lemma match_call_cont_seq:
forall k tk,
match_call_cont k tk ->
forall s,
match_call_cont (
Kseq s k)
tk.
Proof.
induction 1; intros.
- econstructor 1; eauto.
- econstructor 2; eauto.
Qed.
match_call_cont k tk depends only on the context of k and tk
Lemma match_call_cont_seq_bis:
forall k tk,
match_call_cont k tk ->
forall s,
match_call_cont k (
Kseq s tk).
Proof.
induction 1; intros.
- econstructor 1; eauto.
- econstructor 2; eauto.
Qed.
match_call_cont k tk depends only on the context of k and tk
Lemma match_call_cont_loop1:
forall k tk,
match_call_cont k tk ->
forall s1 s2,
match_call_cont (
Kloop1 s1 s2 k)
tk.
Proof.
induction 1; intros.
- econstructor 1; eauto.
- econstructor 2; eauto.
Qed.
match_call_cont k tk depends only on the context of k and tk
Lemma match_call_cont_loop1_bis:
forall k tk,
match_call_cont k tk ->
forall s1 s2,
match_call_cont k (
Kloop1 s1 s2 tk).
Proof.
induction 1; intros.
- econstructor 1; eauto.
- econstructor 2; eauto.
Qed.
match_call_cont k tk depends only on the context of k and tk
Lemma match_call_cont_loop2:
forall k tk,
match_call_cont k tk ->
forall s1 s2,
match_call_cont (
Kloop2 s1 s2 k)
tk.
Proof.
induction 1; intros.
- econstructor 1; eauto.
- econstructor 2; eauto.
Qed.
match_call_cont k tk depends only on the context of k and tk
Lemma match_call_cont_loop2_bis:
forall k tk,
match_call_cont k tk ->
forall s1 s2,
match_call_cont k (
Kloop2 s1 s2 tk).
Proof.
induction 1; intros.
- econstructor 1; eauto.
- econstructor 2; eauto.
Qed.
match_call_cont k tk depends only on the context of k and tk
Lemma match_call_cont_switch_bis:
forall k tk,
match_call_cont k tk ->
match_call_cont k (
Kswitch tk).
Proof.
induction 1; intros.
- econstructor 1; eauto.
- econstructor 2; eauto.
Qed.
match_call_cont k tk depends only on the context of k and tk
Lemma match_call_cont_call_cont:
forall k tk,
match_call_cont k tk ->
match_call_cont (
call_cont k) (
call_cont tk).
Proof.
induction 1.
- rewrite H; rewrite H0; econstructor 1; eauto.
- rewrite H; rewrite H0; econstructor 2; simpl; eauto.
Qed.
Relating execution states
Inductive match_states:
Clight.state ->
Clight.state ->
Prop :=
|
match_regular_states:
forall f s k e le m tf tk tle ls n
(
TRF:
transf_function phi f =
OK tf)
(
TENV:
forall id,
id <>
new_ident_for_function f ->
le!
id =
tle!
id)
(
NSTMT:
not_in_stmt (
new_ident_for_function f)
s)
(
NCONT:
not_in_cont (
new_ident_for_function f)
k)
(
NSLG:
no_switch_label_goto_in_stmt s)
(
NSLGK:
no_switch_label_goto_in_cont k)
(
LS:
flatten phi (
new_ident_for_function f,
tint) (
fn_body f) 1 0 =
OK ls)
(
PC:
tle!(
new_ident_for_function f) =
Some (
Vint (
phi n)))
(
MSTMT: (
is_call_cont (
context k) /\
exists next_instr,
match_stmt_cont s ls (
new_ident_for_function f,
tint)
n next_instr k) \/
(
exists s1 s2 k',
context k =
Kloop1 s1 s2 k' /\
exists start start'
next_instr to_continue to_continue'
to_break to_break',
match_stmt_cont_in_loop1 s ls (
new_ident_for_function f,
tint) (
start::
start')
n next_instr (
to_continue::
to_continue') (
to_break::
to_break')
k /\
match_loop ls (
new_ident_for_function f,
tint) (
start::
start') (
to_continue::
to_continue') (
to_break::
to_break')
k) \/
(
exists s1 s2 k',
context k =
Kloop2 s1 s2 k' /\
exists start start'
next_instr to_continue to_continue'
to_break to_break',
match_stmt_cont_in_loop2 s ls (
new_ident_for_function f,
tint) (
start::
start')
n next_instr (
to_continue::
to_continue') (
to_break::
to_break')
k /\
match_loop ls (
new_ident_for_function f,
tint) (
start::
start') (
to_continue::
to_continue') (
to_break::
to_break')
k))
(
MCONT:
match_call_cont k tk)
(
CCONT:
is_call_cont tk),
match_states
(
State f s k e le m)
(
State tf
(
Sloop (
Ssequence
(
Sifthenelse
(
Ebinop One
(
Etempvar (
new_ident_for_function f)
tint)
(
Econst_int (
phi 0)
tint)
tint)
Sskip
Sbreak)
(
Sswitch (
Etempvar (
new_ident_for_function f)
tint)
ls))
Sskip)
tk e tle m)
|
match_call_states:
forall fd tfd args k tk m
(
TRFD:
transf_fundef phi fd =
OK tfd)
(
MCONT:
match_call_cont k tk)
(
NCONT:
forall id,
not_in_cont id k)
(
NSLGK:
no_switch_label_goto_in_cont k)
(
CCONT:
is_call_cont k)
(
TCONT:
is_call_cont tk),
match_states (
Callstate fd args k m) (
Callstate tfd args tk m)
|
match_return_states:
forall v k tk m
(
MCONT:
match_call_cont k tk)
(
NCONT:
forall id,
not_in_cont id k)
(
NSLGK:
no_switch_label_goto_in_cont k)
(
CCONT:
is_call_cont k)
(
TCONT:
is_call_cont tk),
match_states (
Returnstate v k m) (
Returnstate v tk m).
Lemma is_call_cont_call_cont:
forall k,
is_call_cont (
call_cont k).
Proof.
induction k; simpl; eauto.
Qed.
Lemma alloc_variables_preserved:
forall e m l e'
m',
alloc_variables ge e m l e'
m' ->
alloc_variables tge e m l e'
m'.
Proof.
Lemma bind_parameters_preserved:
forall e m params args m',
bind_parameters ge e m params args m' ->
bind_parameters tge e m params args m'.
Proof.
Simulation diagram
Theorem simulation:
forall S1 t S2,
step1 ge S1 t S2 ->
forall S1' (
MS:
match_states S1 S1'),
exists S2',
(
plus step1 tge S1'
t S2' \/
(
star step1 tge S1'
t S2' /\
measure S2 <
measure S1)%
nat)
/\
match_states S2 S2'.
Proof.
induction 1;
intros;
inv MS.
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H7;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_lvalue_preserved;
eauto.
inv NSTMT;
auto.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eauto.
rewrite comp_env_preserved.
eauto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
intros.
rewrite PTree.gso;
auto. }
{
constructor. }
{
constructor. }
{
rewrite PTree.gss;
auto. }
+
destruct MSTMT as [
s1 [
s2 [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break'
MSTMT]]]]]]].
destruct MSTMT as [
MSTMT MSTMT'].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H7;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_lvalue_preserved;
eauto.
inv NSTMT;
auto.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eauto.
rewrite comp_env_preserved.
eauto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
intros.
rewrite PTree.gso;
auto. }
{
constructor. }
{
constructor. }
{
rewrite PTree.gss;
auto. }
{
right.
left.
eexists.
eexists.
eexists.
split;
eauto.
destruct H16.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eauto. }
+
destruct MSTMT as [
s1 [
s2 [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break'
MSTMT]]]]]]].
destruct MSTMT as [
MSTMT MSTMT'].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H7;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_lvalue_preserved;
eauto.
inv NSTMT;
auto.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eauto.
rewrite comp_env_preserved.
eauto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
intros.
rewrite PTree.gso;
auto. }
{
constructor. }
{
constructor. }
{
rewrite PTree.gss;
auto. }
{
right.
right.
eexists.
eexists.
eexists.
split;
eauto.
destruct H16.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eauto. }
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H4;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
intros;
destruct (
ident_eq id id0).
-
subst id0;
rewrite PTree.gss.
rewrite PTree.gso;
auto.
rewrite PTree.gss;
auto.
-
repeat (
rewrite PTree.gso);
auto. }
{
constructor. }
{
constructor. }
{
rewrite PTree.gss;
auto. }
+
destruct MSTMT as [
s1 [
s2 [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H4;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
intros;
destruct (
ident_eq id id0).
-
subst id0;
rewrite PTree.gss.
rewrite PTree.gso;
auto.
rewrite PTree.gss;
auto.
-
repeat (
rewrite PTree.gso);
auto. }
{
constructor. }
{
constructor. }
{
rewrite PTree.gss;
auto. }
{
right.
left.
eexists.
eexists.
eexists.
destruct H13;
repeat split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto. }
+
destruct MSTMT as [
s1 [
s2 [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H4;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
intros;
destruct (
ident_eq id id0).
-
subst id0;
rewrite PTree.gss.
rewrite PTree.gso;
auto.
rewrite PTree.gss;
auto.
-
repeat (
rewrite PTree.gso);
auto. }
{
constructor. }
{
constructor. }
{
rewrite PTree.gss;
auto. }
{
right.
right.
eexists.
eexists.
eexists.
destruct H13;
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto. }
-
generalize (
functions_translated _ _ H2);
intros [
tf' [
A B]].
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H14;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eauto.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
eauto.
eapply eval_exprlist_preserved;
eauto.
inv NSTMT;
auto.
eauto.
rewrite (
type_of_fundef_preserved fd).
exact H3.
exact B.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
econstructor 2;
simpl;
eauto.
eexists.
eexists.
eexists.
split;
eauto.
eapply match_call_cont_seq_bis.
eapply match_call_cont_seq_bis.
eapply match_call_cont_switch_bis.
eapply match_call_cont_loop1_bis.
eauto. }
{
intros.
inv NSTMT;
econstructor;
eauto. }
{
inv NSLG;
econstructor;
eauto.
eapply no_switch_label_goto_function;
eauto. }
{
econstructor. }
{
econstructor. }
+
destruct MSTMT as [
s1 [
s2 [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H17;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eauto.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
eauto.
eapply eval_exprlist_preserved;
eauto.
inv NSTMT;
auto.
eauto.
rewrite (
type_of_fundef_preserved fd).
exact H3.
exact B.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
econstructor 2;
simpl;
eauto.
eexists.
eexists.
eexists.
repeat split;
eauto.
-
right.
left.
destruct H18 as [
next_instr'
H18].
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
split;
eauto.
-
eapply match_call_cont_seq_bis.
eapply match_call_cont_seq_bis.
eapply match_call_cont_switch_bis.
eapply match_call_cont_loop1_bis.
eauto. }
{
intros.
inv NSTMT;
econstructor;
eauto. }
{
inv NSLG;
econstructor;
eauto.
eapply no_switch_label_goto_function;
eauto. }
{
econstructor. }
{
econstructor. }
+
destruct MSTMT as [
s1 [
s2 [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H17;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eauto.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
eauto.
eapply eval_exprlist_preserved;
eauto.
inv NSTMT;
auto.
eauto.
rewrite (
type_of_fundef_preserved fd).
exact H3.
exact B.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
econstructor 2;
simpl;
eauto.
eexists.
eexists.
eexists.
repeat split;
eauto.
-
right.
right.
destruct H18 as [
next_instr'
H18].
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
split;
eauto.
-
eapply match_call_cont_seq_bis.
eapply match_call_cont_seq_bis.
eapply match_call_cont_switch_bis.
eapply match_call_cont_loop1_bis.
eauto. }
{
intros.
inv NSTMT;
econstructor;
eauto. }
{
inv NSLG;
econstructor;
eauto.
eapply no_switch_label_goto_function;
eauto. }
{
econstructor. }
{
econstructor. }
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H12;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_exprlist_preserved;
eauto.
inv NSTMT;
auto.
eapply external_call_symbols_preserved;
eauto.
exact symbols_preserved.
exact (
Genv.public_symbol_transf_partial _ _ transf_programs).
exact varinfo_preserved.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
repeat (
rewrite E0_left);
repeat (
rewrite E0_right);
eauto.
*
econstructor;
eauto.
{
intros;
rewrite PTree.gso;
auto.
unfold set_opttemp.
destruct optid.
-
destruct (
ident_eq i id).
+
subst i.
repeat (
rewrite PTree.gss);
auto.
+
repeat (
rewrite PTree.gso);
auto.
-
eauto. }
{
constructor. }
{
constructor. }
{
rewrite PTree.gss;
auto. }
+
destruct MSTMT as [
s1 [
s2 [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H15;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_exprlist_preserved;
eauto.
inv NSTMT;
auto.
eapply external_call_symbols_preserved;
eauto.
exact symbols_preserved.
exact (
Genv.public_symbol_transf_partial _ _ transf_programs).
exact varinfo_preserved.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
repeat (
rewrite E0_left);
repeat (
rewrite E0_right);
eauto.
*
econstructor;
eauto.
{
intros;
rewrite PTree.gso;
auto.
unfold set_opttemp.
destruct optid.
-
destruct (
ident_eq i id).
+
subst i.
repeat (
rewrite PTree.gss);
auto.
+
repeat (
rewrite PTree.gso);
auto.
-
eauto. }
{
constructor. }
{
constructor. }
{
rewrite PTree.gss;
auto. }
{
right.
left.
eexists.
eexists.
eexists.
destruct H16;
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto. }
+
destruct MSTMT as [
s1 [
s2 [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H15;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_exprlist_preserved;
eauto.
inv NSTMT;
auto.
eapply external_call_symbols_preserved;
eauto.
exact symbols_preserved.
exact (
Genv.public_symbol_transf_partial _ _ transf_programs).
exact varinfo_preserved.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
repeat (
rewrite E0_left);
repeat (
rewrite E0_right);
eauto.
*
econstructor;
eauto.
{
intros;
rewrite PTree.gso;
auto.
unfold set_opttemp.
destruct optid.
-
destruct (
ident_eq i id).
+
subst i.
repeat (
rewrite PTree.gss);
auto.
+
repeat (
rewrite PTree.gso);
auto.
-
eauto. }
{
constructor. }
{
constructor. }
{
rewrite PTree.gss;
auto. }
{
right.
right.
eexists.
eexists.
eexists.
destruct H16;
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto. }
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
eexists.
split.
*
right.
split.
econstructor.
simpl.
omega.
*
econstructor;
eauto.
{
inv NSTMT;
auto. }
{
inv NSTMT;
econstructor;
auto. }
{
inv NSLG;
auto. }
{
inv NSLG;
econstructor;
auto. }
{
eapply match_call_cont_seq;
eauto. }
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT.
eexists.
split.
*
right.
split.
econstructor.
simpl.
omega.
*
econstructor;
eauto.
{
inv NSTMT;
auto. }
{
inv NSTMT;
econstructor;
auto. }
{
inv NSLG;
auto. }
{
inv NSLG;
econstructor;
auto. }
{
right.
left.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
eapply match_loop_context in MSTMT'.
constructor;
simpl;
auto. }
{
eapply match_call_cont_seq;
eauto. }
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT.
eexists.
split.
*
right.
split.
econstructor.
simpl.
omega.
*
econstructor;
eauto.
{
inv NSTMT;
auto. }
{
inv NSTMT;
econstructor;
auto. }
{
inv NSLG;
auto. }
{
inv NSLG;
econstructor;
auto. }
{
right.
right.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
eapply match_loop_context in MSTMT'.
econstructor.
eauto. }
{
eapply match_call_cont_seq;
eauto. }
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT;
try (
inv H;
fail).
destruct H7 as [[
H7 [
next_instr'
H8]] |
H7].
*
eexists;
split.
{
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H7;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
econstructor;
eauto.
-
intros.
rewrite PTree.gso;
eauto.
-
inv NCONT;
auto.
-
inv NCONT;
auto.
-
inv NSLGK;
auto.
-
inv NSLGK;
auto.
-
rewrite PTree.gss;
auto.
-
inv MCONT;
simpl in H.
+
econstructor 1;
eauto.
+
econstructor 2;
eauto. }
*
eexists;
split.
{
right;
split.
-
econstructor.
-
simpl;
omega. }
{
econstructor;
eauto.
-
inv NCONT;
auto.
-
inv NCONT;
auto.
-
inv NSLGK;
auto.
-
inv NSLGK;
auto.
-
inv MCONT;
simpl in H.
+
econstructor 1;
eauto.
+
econstructor 2;
eauto. }
+
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT;
try (
inv H;
fail).
destruct H10 as [[
H10 [
next_instr'
H11]] |
H10].
*
eexists;
split.
{
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H10;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
econstructor;
eauto.
-
intros.
rewrite PTree.gso;
eauto.
-
inv NCONT;
auto.
-
inv NCONT;
auto.
-
inv NSLGK;
auto.
-
inv NSLGK;
auto.
-
rewrite PTree.gss;
auto.
-
right.
left.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
eapply match_loop_context in MSTMT';
eapply match_loop_context;
simpl in MSTMT';
auto.
-
inv MCONT;
simpl in H.
+
econstructor 1;
eauto.
+
econstructor 2;
eauto. }
*
eexists;
split.
{
right;
split.
-
econstructor.
-
simpl;
omega. }
{
econstructor;
eauto.
-
inv NCONT;
auto.
-
inv NCONT;
auto.
-
inv NSLGK;
auto.
-
inv NSLGK;
auto.
-
right.
left.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
eapply match_loop_context in MSTMT';
eapply match_loop_context;
simpl in MSTMT';
auto.
-
inv MCONT;
simpl in H.
+
econstructor 1;
eauto.
+
econstructor 2;
eauto. }
+
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT;
try (
inv H;
fail).
destruct H10 as [[
H10 [
next_instr'
H11]] |
H0].
*
eexists;
split.
{
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H10;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
econstructor;
eauto.
-
intros.
rewrite PTree.gso;
eauto.
-
inv NCONT;
auto.
-
inv NCONT;
auto.
-
inv NSLGK;
auto.
-
inv NSLGK;
auto.
-
rewrite PTree.gss;
auto.
-
right.
right.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
eapply match_loop_context in MSTMT';
eapply match_loop_context;
simpl in MSTMT';
auto.
-
inv MCONT;
simpl in H.
+
econstructor 1;
eauto.
+
econstructor 2;
eauto. }
*
eexists;
split.
{
right;
split.
-
econstructor.
-
simpl;
omega. }
{
econstructor;
eauto.
-
inv NCONT;
auto.
-
inv NCONT;
auto.
-
inv NSLGK;
auto.
-
inv NSLGK;
auto.
-
right.
right.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
eapply match_loop_context in MSTMT';
eapply match_loop_context;
simpl in MSTMT';
auto.
-
inv MCONT;
simpl in H.
+
econstructor 1;
eauto.
+
econstructor 2;
eauto. }
-
eexists;
split.
+
right;
split.
*
econstructor.
*
simpl;
omega.
+
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
*
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
*
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
econstructor;
eauto.
{
inv NCONT;
auto. }
{
inv NSLGK;
auto. }
{
right.
left.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
eapply match_loop_context in MSTMT';
eapply match_loop_context;
simpl in MSTMT';
auto. }
{
inv MCONT;
simpl in H.
-
econstructor 1;
eauto.
-
econstructor 2;
eauto. }
*
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
-
eexists;
split.
+
right;
split.
*
econstructor.
*
simpl;
omega.
+
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
*
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
*
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
econstructor;
eauto.
{
inv NCONT;
auto. }
{
inv NSLGK;
auto. }
{
right.
left.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
eapply match_loop_context in MSTMT';
eapply match_loop_context;
simpl in MSTMT';
auto. }
{
inv MCONT;
simpl in H.
-
econstructor 1;
eauto.
-
econstructor 2;
eauto. }
*
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
econstructor;
eauto.
{
inv NCONT;
auto. }
{
inv NSLGK;
auto. }
{
right.
right.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
eapply match_loop_context in MSTMT';
eapply match_loop_context;
simpl in MSTMT';
auto. }
{
inv MCONT;
simpl in H.
-
econstructor 1;
eauto.
-
econstructor 2;
eauto. }
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
destruct b.
*
eexists;
split.
{
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H6;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eauto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
econstructor;
eauto.
-
intros;
rewrite PTree.gso;
auto.
-
inv NSTMT;
auto.
-
inv NSLG;
auto.
-
rewrite PTree.gss;
auto. }
*
eexists;
split.
{
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H6;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eauto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
econstructor;
eauto.
-
intros;
rewrite PTree.gso;
auto.
-
inv NSTMT;
auto.
-
inv NSLG;
auto.
-
rewrite PTree.gss;
auto. }
+
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
destruct b.
*
eexists;
split.
{
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H6;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eauto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
econstructor;
eauto.
-
intros;
rewrite PTree.gso;
auto.
-
inv NSTMT;
auto.
-
inv NSLG;
auto.
-
rewrite PTree.gss;
auto.
-
right.
left.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto. }
*
eexists;
split.
{
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H6;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eauto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
econstructor;
eauto.
-
intros;
rewrite PTree.gso;
auto.
-
inv NSTMT;
auto.
-
inv NSLG;
auto.
-
rewrite PTree.gss;
auto.
-
right.
left.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto. }
+
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
destruct b.
*
eexists;
split.
{
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H6;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eauto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
econstructor;
eauto.
-
intros;
rewrite PTree.gso;
auto.
-
inv NSTMT;
auto.
-
inv NSLG;
auto.
-
rewrite PTree.gss;
auto.
-
right.
right.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto. }
*
eexists;
split.
{
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H6;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
auto.
eauto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
econstructor;
eauto.
-
intros;
rewrite PTree.gso;
auto.
-
inv NSTMT;
auto.
-
inv NSLG;
auto.
-
rewrite PTree.gss;
auto.
-
right.
right.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto. }
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H3;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
intros.
rewrite PTree.gso;
eauto. }
{
inv NSTMT;
auto. }
{
inv NSTMT;
econstructor;
auto. }
{
inv NSLG;
auto. }
{
inv NSLG;
econstructor;
auto. }
{
rewrite PTree.gss;
auto. }
{
right.
left.
eexists.
eexists.
eexists.
split;
simpl;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
econstructor;
eauto.
eapply match_loop_context.
eapply match_loop_call_cont_context;
eauto. }
{
inv MCONT;
simpl in H.
-
econstructor 1;
eauto.
-
econstructor 2;
eauto. }
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H3;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
intros.
rewrite PTree.gso;
eauto. }
{
inv NSTMT;
auto. }
{
inv NSTMT;
econstructor;
auto. }
{
inv NSLG;
auto. }
{
inv NSLG;
econstructor;
auto. }
{
rewrite PTree.gss;
auto. }
{
right.
left.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
econstructor;
eauto. }
{
inv MCONT;
simpl in H.
-
econstructor 1;
eauto.
-
econstructor 2;
eauto. }
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]].
inv MSTMT.
eexists.
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H3;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
intros.
rewrite PTree.gso;
eauto. }
{
inv NSTMT;
auto. }
{
inv NSTMT;
econstructor;
auto. }
{
inv NSLG;
auto. }
{
inv NSLG;
econstructor;
auto. }
{
rewrite PTree.gss;
auto. }
{
right.
left.
eexists.
eexists.
eexists.
split;
eauto.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
econstructor;
eauto. }
{
inv MCONT;
simpl in H.
-
econstructor 1;
eauto.
-
econstructor 2;
eauto. }
-
destruct H;
subst x.
+
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
*
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
inv H.
*
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
destruct H10 as [[
H10 [
next_instr'
H11]] |
H10].
{
eexists;
split.
-
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H10;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
-
econstructor;
eauto.
+
intros.
rewrite PTree.gso;
eauto.
+
inv NCONT;
auto.
+
inv NCONT;
econstructor;
eauto.
+
inv NSLGK;
auto.
+
inv NSLGK;
econstructor;
eauto.
+
rewrite PTree.gss;
auto.
+
right.
right.
eexists.
eexists.
eexists.
repeat split;
eauto.
simpl in Hcontext.
inv Hcontext.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
inv MSTMT';
econstructor;
eauto.
+
inv MCONT;
simpl in H.
*
econstructor 1;
eauto.
*
econstructor 2;
eauto. }
{
eexists;
split.
-
right;
split.
+
econstructor.
+
simpl;
omega.
-
econstructor;
eauto.
+
inv NCONT;
auto.
+
inv NCONT;
econstructor;
eauto.
+
inv NSLGK;
auto.
+
inv NSLGK;
econstructor;
eauto.
+
right.
right.
eexists.
eexists.
eexists.
repeat split;
eauto.
simpl in Hcontext.
inv Hcontext.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
inv MSTMT';
econstructor;
eauto.
+
inv MCONT;
simpl in H.
*
econstructor 1;
eauto.
*
econstructor 2;
eauto. }
*
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
simpl in Hcontext;
inv Hcontext.
+
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
*
destruct MSTMT as [
Hcontext MSTMT];
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
*
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
eexists;
split.
{
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H11;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
econstructor;
eauto.
-
intros.
rewrite PTree.gso;
eauto.
-
inv NCONT;
auto.
-
inv NCONT;
econstructor;
eauto.
-
inv NSLGK;
auto.
-
inv NSLGK;
econstructor;
eauto.
-
rewrite PTree.gss;
auto.
-
right.
right.
eexists.
eexists.
eexists.
repeat split;
eauto.
simpl in Hcontext.
inv Hcontext.
destruct H12 as [
next_instr'
H12].
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
repeat split;
eauto.
inv MSTMT';
econstructor;
eauto.
-
inv MCONT;
simpl in H.
+
econstructor 1;
eauto.
+
econstructor 2;
eauto. }
*
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
simpl in Hcontext;
inv Hcontext.
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT].
simpl in Hcontext;
inv Hcontext.
+
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
eexists;
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H13;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
intros.
rewrite PTree.gso;
eauto. }
{
econstructor. }
{
inv NCONT;
eauto. }
{
econstructor. }
{
inv NSLGK;
auto. }
{
rewrite PTree.gss;
auto. }
{
destruct H14 as [
H | [
H |
H]].
-
left;
destruct H.
destruct H0.
destruct H0.
split;
eauto.
-
right.
left.
destruct H as [
s [
s' [
k'' [
H [
next_instr'
H0]]]]].
eexists.
eexists.
eexists.
repeat split;
eauto.
inv MSTMT'.
generalize (
match_loop_loop1_context _ _ _ _ _ _ _ _ _ H H16).
intros [
to_start [
to_start' [
continue [
continue' [
break [
break' [
Hstart [
Hcontinue Hbreak]]]]]]]].
subst start'.
subst to_continue'.
subst to_break'.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
split;
eauto.
-
right.
right.
destruct H as [
s [
s' [
k'' [
H [
next_instr'
H0]]]]].
eexists.
eexists.
eexists.
repeat split;
eauto.
inv MSTMT'.
generalize (
match_loop_loop2_context _ _ _ _ _ _ _ _ _ H H16).
intros [
to_start [
to_start' [
continue [
continue' [
break [
break' [
Hstart [
Hcontinue Hbreak]]]]]]]].
subst start'.
subst to_continue'.
subst to_break'.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
split;
eauto. }
{
inv MCONT;
simpl in H.
-
econstructor 1;
eauto.
-
econstructor 2;
eauto. }
+
destruct MSTMT as [
s1' [
s2' [
k' [
Hcontext MSTMT]]]].
simpl in Hcontext;
inv Hcontext.
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT].
simpl in Hcontext;
inv Hcontext.
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
simpl in Hcontext;
inv Hcontext.
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
simpl in Hcontext;
inv Hcontext.
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
destruct H11.
*
destruct H as [
H [
H0 H1]].
subst next_instr.
eexists;
split.
{
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
econstructor;
eauto.
-
intros;
rewrite PTree.gso;
eauto.
-
inv NCONT.
econstructor;
eauto.
-
inv NCONT;
eauto.
-
inv NSLGK;
econstructor;
eauto.
-
inv NSLGK;
eauto.
-
rewrite PTree.gss;
eauto.
-
generalize (
context_charact k');
intros.
destruct H0 as [
H0 | [
H0 | [
H0 |
H0]]].
+
left.
split;
eauto.
destruct H1 as [
ls''
H1].
eexists.
inv MSTMT';
econstructor;
eauto.
*
generalize (
match_loop_call_cont_context_charact _ _ _ _ _ _ H0 H16).
intros [
A [
B C]].
subst start';
subst to_continue';
subst to_break';
eauto.
*
generalize (
match_loop_call_cont_context_charact _ _ _ _ _ _ H0 H16).
intros [
A [
B C]].
subst start';
subst to_continue';
subst to_break';
eauto.
+
right.
left.
destruct H0 as [
s1 [
s2 [
k''
H0]]].
eexists.
eexists.
eexists.
split;
eauto.
destruct H1 as [
ls''
H1].
inv MSTMT'.
generalize (
match_loop_loop1_context _ _ _ _ _ _ _ _ _ H0 H16).
intros [
to_start [
to_start' [
continue [
continue' [
break [
break' [
A [
B C]]]]]]]].
subst start';
subst to_continue';
subst to_break'.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
split;
eauto.
econstructor;
eauto.
+
right.
right.
destruct H0 as [
s1 [
s2 [
k''
H0]]].
eexists.
eexists.
eexists.
split;
eauto.
destruct H1 as [
ls''
H1].
inv MSTMT'.
generalize (
match_loop_loop2_context _ _ _ _ _ _ _ _ _ H0 H16).
intros [
to_start [
to_start' [
continue [
continue' [
break [
break' [
A [
B C]]]]]]]].
subst start';
subst to_continue';
subst to_break'.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
split;
eauto.
econstructor;
eauto.
+
destruct H0 as [
kk H0].
inv NSLGK.
generalize (
no_switch_context k'
kk H7);
intros.
contradiction.
-
inv MCONT;
simpl in H.
+
econstructor 1;
eauto.
+
econstructor 2;
eauto. }
*
destruct H as [
H0 H];
subst n.
eexists;
split.
{
right.
split.
-
econstructor.
-
simpl;
omega. }
{
econstructor;
eauto.
-
inv NCONT.
econstructor;
eauto.
-
inv NCONT;
eauto.
-
inv NSLGK;
econstructor;
eauto.
-
inv NSLGK;
eauto.
-
generalize (
context_charact k');
intros.
destruct H0 as [
H0 | [
H0 | [
H0 |
H0]]].
+
left.
split;
eauto.
eexists.
inv MSTMT';
econstructor;
eauto.
*
generalize (
match_loop_call_cont_context_charact _ _ _ _ _ _ H0 H15).
intros [
A [
B C]].
subst start';
subst to_continue';
subst to_break';
eauto.
*
generalize (
match_loop_call_cont_context_charact _ _ _ _ _ _ H0 H15).
intros [
A [
B C]].
subst start';
subst to_continue';
subst to_break';
eauto.
+
right.
left.
destruct H0 as [
s1 [
s2 [
k''
H0]]].
eexists.
eexists.
eexists.
split;
eauto.
inv MSTMT'.
generalize (
match_loop_loop1_context _ _ _ _ _ _ _ _ _ H0 H15).
intros [
to_start [
to_start' [
continue [
continue' [
break [
break' [
A [
B C]]]]]]]].
subst start';
subst to_continue';
subst to_break'.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
split;
eauto.
econstructor;
eauto.
+
right.
right.
destruct H0 as [
s1 [
s2 [
k''
H0]]].
eexists.
eexists.
eexists.
split;
eauto.
inv MSTMT'.
generalize (
match_loop_loop2_context _ _ _ _ _ _ _ _ _ H0 H15).
intros [
to_start [
to_start' [
continue [
continue' [
break [
break' [
A [
B C]]]]]]]].
subst start';
subst to_continue';
subst to_break'.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
split;
eauto.
econstructor;
eauto.
+
destruct H0 as [
kk H0].
inv NSLGK.
generalize (
no_switch_context k'
kk H6);
intros.
contradiction.
-
inv MCONT;
simpl in H.
+
econstructor 1;
eauto.
+
econstructor 2;
eauto. }
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT].
simpl in Hcontext;
inv Hcontext.
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
simpl in Hcontext;
inv Hcontext.
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
simpl in Hcontext;
inv Hcontext.
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
eexists;
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H13;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
auto.
eapply star_step.
econstructor.
left;
auto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
intros;
rewrite PTree.gso;
eauto. }
{
econstructor. }
{
inv NCONT;
eauto. }
{
econstructor. }
{
inv NSLGK;
eauto. }
{
rewrite PTree.gss;
eauto. }
{
destruct H14 as [
H14 | [
H14 |
H14]].
-
left.
destruct H14.
split;
eauto.
destruct H0 as [
next_instr' [
H0 A]].
eexists.
eauto.
-
right;
left.
destruct H14 as [
s1' [
s2' [
k'' [
H14 [
next_instr'
H15]]]]].
eexists.
eexists.
eexists.
split;
eauto.
inv MSTMT'.
generalize (
match_loop_loop1_context _ _ _ _ _ _ _ _ _ H14 H16).
intros [
to_start [
to_start' [
continue [
continue' [
break [
break' [
A [
B C]]]]]]]].
subst start';
subst to_continue';
subst to_break'.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
split;
eauto.
-
right;
right.
destruct H14 as [
s1' [
s2' [
k'' [
H14 [
next_instr'
H15]]]]].
eexists.
eexists.
eexists.
split;
eauto.
inv MSTMT'.
generalize (
match_loop_loop2_context _ _ _ _ _ _ _ _ _ H14 H16).
intros [
to_start [
to_start' [
continue [
continue' [
break [
break' [
A [
B C]]]]]]]].
subst start';
subst to_continue';
subst to_break'.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
eexists.
split;
eauto. }
{
inv MCONT;
simpl in H.
-
econstructor 1;
eauto.
-
econstructor 2;
eauto. }
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT].
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
eexists;
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H3;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
unfold blocks_of_env,
block_of_binding.
rewrite comp_env_preserved.
eauto.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
simpl;
eapply match_call_cont_call_cont;
eauto. }
{
intros.
eapply not_in_cont_call_cont;
eauto. }
{
eapply no_switch_label_goto_in_cont_call_cont;
eauto. }
{
eapply is_call_cont_call_cont. }
{
eapply is_call_cont_call_cont. }
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
simpl in Hcontext;
inv Hcontext.
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
eexists;
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H4;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
unfold blocks_of_env,
block_of_binding.
rewrite comp_env_preserved.
eauto.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
simpl;
eapply match_call_cont_call_cont;
eauto. }
{
intros.
eapply not_in_cont_call_cont;
eauto. }
{
eapply no_switch_label_goto_in_cont_call_cont;
eauto. }
{
eapply is_call_cont_call_cont. }
{
eapply is_call_cont_call_cont. }
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
simpl in Hcontext;
inv Hcontext.
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
eexists;
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H4;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
unfold blocks_of_env,
block_of_binding.
rewrite comp_env_preserved.
eauto.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
simpl;
eapply match_call_cont_call_cont;
eauto. }
{
intros.
eapply not_in_cont_call_cont;
eauto. }
{
eapply no_switch_label_goto_in_cont_call_cont;
eauto. }
{
eapply is_call_cont_call_cont. }
{
eapply is_call_cont_call_cont. }
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext MSTMT].
destruct MSTMT as [
next_instr MSTMT].
inv MSTMT.
eexists;
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H5;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
eauto.
monadInv TRF.
simpl;
eauto.
unfold blocks_of_env,
block_of_binding.
rewrite comp_env_preserved.
eauto.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
simpl;
eapply match_call_cont_call_cont;
eauto. }
{
intros.
eapply not_in_cont_call_cont;
eauto. }
{
eapply no_switch_label_goto_in_cont_call_cont;
eauto. }
{
eapply is_call_cont_call_cont. }
{
eapply is_call_cont_call_cont. }
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
simpl in Hcontext;
inv Hcontext.
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
eexists;
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H6;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
eauto.
monadInv TRF.
simpl;
eauto.
unfold blocks_of_env,
block_of_binding.
rewrite comp_env_preserved.
eauto.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
simpl;
eapply match_call_cont_call_cont;
eauto. }
{
intros.
eapply not_in_cont_call_cont;
eauto. }
{
eapply no_switch_label_goto_in_cont_call_cont;
eauto. }
{
eapply is_call_cont_call_cont. }
{
eapply is_call_cont_call_cont. }
+
destruct MSTMT as [
s [
s' [
k' [
Hcontext MSTMT]]]].
simpl in Hcontext;
inv Hcontext.
destruct MSTMT as [
start [
start' [
next_instr [
to_continue [
to_continue' [
to_break [
to_break' [
MSTMT MSTMT']]]]]]]];
inv MSTMT.
eexists;
split.
*
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H6;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply eval_expr_preserved;
eauto.
inv NSTMT;
eauto.
monadInv TRF.
simpl;
eauto.
unfold blocks_of_env,
block_of_binding.
rewrite comp_env_preserved.
eauto.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
*
econstructor;
eauto.
{
simpl;
eapply match_call_cont_call_cont;
eauto. }
{
intros.
eapply not_in_cont_call_cont;
eauto. }
{
eapply no_switch_label_goto_in_cont_call_cont;
eauto. }
{
eapply is_call_cont_call_cont. }
{
eapply is_call_cont_call_cont. }
-
destruct MSTMT as [
MSTMT | [
MSTMT |
MSTMT]].
+
destruct MSTMT as [
Hcontext [
next_instr MSTMT]].
inv MSTMT.
*
inv H.
*
destruct H2.
{
destruct H2 as [
H2 [
H3 [
H4 H5]]].
eexists.
split.
-
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try (
exploit (
phi_injection n 0);
omega;
fail).
simpl;
eauto.
rewrite Int.unsigned_zero.
rewrite Int.unsigned_one.
destruct (
zeq 1 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_switch.
econstructor.
eauto.
unfold sem_switch_arg;
simpl;
eauto.
unfold select_switch;
rewrite H2;
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
eauto.
eapply star_step.
econstructor.
left;
eauto.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
rewrite H4.
econstructor.
econstructor.
eauto.
rewrite PTree.gss;
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi next_instr)) (
Int.unsigned (
phi next_instr)));
try congruence.
simpl.
rewrite Int.unsigned_zero.
destruct (
zeq 0 0);
try omega;
simpl;
eauto.
simpl;
eapply star_step.
econstructor.
eapply star_step.
eapply step_break_loop1.
eapply star_step.
eapply step_skip_call.
eauto.
unfold blocks_of_env,
block_of_binding.
rewrite comp_env_preserved.
eauto.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
-
econstructor;
eauto.
intros.
destruct k;
try (
inv H1;
fail).
+
econstructor.
+
inv NCONT;
econstructor;
eauto. }
{
destruct H2.
eexists.
split.
-
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
econstructor.
eauto.
econstructor.
simpl;
unfold sem_cmp;
simpl;
unfold sem_binarith;
simpl;
eauto.
unfold bool_val;
simpl.
unfold Int.eq.
destruct (
zeq (
Int.unsigned (
phi n)) (
Int.unsigned (
phi 0)));
try congruence.
simpl;
eauto.
rewrite Int.unsigned_zero.
destruct (
zeq 0 0);
try omega;
simpl.
eapply star_step.
econstructor.
eapply star_step.
eapply step_break_loop1.
eapply star_step.
eapply step_skip_call.
eauto.
unfold blocks_of_env,
block_of_binding.
rewrite comp_env_preserved.
eauto.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
-
econstructor;
eauto.
intros.
destruct k;
try (
inv H1;
fail).
+
econstructor.
+
inv NCONT;
econstructor;
eauto. }
+
destruct MSTMT as [
s1 [
s2 [
k' [
Hcontext MSTMT]]]].
destruct k;
try (
inv H;
simpl in Hcontext;
inv Hcontext;
fail).
+
destruct MSTMT as [
s1 [
s2 [
k' [
Hcontext MSTMT]]]].
destruct k;
try (
inv H;
simpl in Hcontext;
inv Hcontext;
fail).
-
inv NSLG.
-
inv NSLGK.
-
inv NSLGK.
-
inv NSLG.
-
inv NSLG.
-
monadInv TRFD.
monadInv EQ.
unfold obf_body in EQ0.
destruct (
zlt (
sizeof_stmt (
fn_body f))
Int.max_unsigned);
monadInv EQ0.
simpl.
eexists;
split.
+
left.
econstructor.
econstructor.
inv H;
econstructor;
simpl;
eauto.
eapply alloc_variables_preserved;
eauto.
eapply bind_parameters_preserved;
eauto.
simpl.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
+
econstructor;
eauto.
*
unfold transf_function.
unfold obf_body.
rewrite EQ.
destruct (
zlt (
sizeof_stmt (
fn_body f))
Int.max_unsigned);
try omega.
simpl.
auto.
*
inv H.
intros.
rewrite PTree.gso;
auto.
rewrite PTree.gso;
auto.
*
apply new_ident_not_in_body.
*
eapply no_switch_label_goto_function;
eauto.
unfold transf_function.
unfold obf_body.
instantiate (2 :=
phi).
rewrite EQ.
destruct (
zlt (
sizeof_stmt (
fn_body f))
Int.max_unsigned);
try omega.
simpl.
eauto.
*
rewrite PTree.gss;
auto.
*
left.
split.
{
destruct k;
try (
inv CCONT;
simpl;
econstructor). }
{
exists 0.
replace x with (
app_lstmt LSnil (
app_lstmt x LSnil)).
-
eapply match_stmt_cont_flatten;
eauto.
+
destruct k;
try (
inv CCONT;
simpl;
econstructor).
+
intros.
subst k;
inv CCONT.
+
intros;
simpl.
rewrite select_switch_app_right;
simpl;
auto.
eapply select_switch_flatten;
eauto;
try omega.
generalize (
Int.unsigned_range_2 (
Int.zero)).
rewrite Int.unsigned_zero;
auto.
+
omega.
+
omega.
+
omega.
-
simpl.
apply app_lstmt_lsnil. }
-
monadInv TRFD.
eexists;
split.
+
left;
econstructor.
econstructor.
eapply external_call_symbols_preserved;
eauto.
exact symbols_preserved.
exact (
Genv.public_symbol_transf_partial _ _ transf_programs).
exact varinfo_preserved.
econstructor.
rewrite E0_right.
auto.
+
econstructor;
eauto.
-
destruct tk;
try (
inv TCONT;
fail).
+
inv MCONT.
*
simpl in H;
inv H.
*
simpl in H0;
inv H0.
+
inv MCONT.
*
simpl in H;
inv H.
*
destruct H4 as [
next_instr [
ls' [
tk''
H4]]].
destruct H4 as [
H4 [
A B]].
eexists.
split.
{
simpl in H0.
inv H0.
left.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
eapply star_step.
econstructor.
right;
eauto.
eapply star_step.
econstructor.
left;
eauto.
eapply star_step.
econstructor.
econstructor.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto.
eauto. }
{
simpl in H;
inv H.
simpl in H0;
inv H0.
econstructor;
eauto.
-
intros.
rewrite PTree.gso.
+
unfold set_opttemp.
destruct optid0;
eauto.
destruct (
ident_eq i id).
*
subst i;
repeat rewrite PTree.gss;
eauto.
*
repeat rewrite PTree.gso;
eauto.
+
eauto.
-
econstructor.
-
generalize (
NCONT (
new_ident_for_function f1));
intros.
inv H.
eauto.
exact H4.
-
econstructor.
-
inv NSLGK;
eauto.
-
rewrite PTree.gss;
eauto.
-
inv H5.
+
econstructor 1;
simpl in H0;
eauto.
+
econstructor 2;
simpl in H0;
eauto. }
Qed.
Lemma initial_states_simulation:
forall S,
Clight.initial_state prog S ->
exists R,
Clight.initial_state tprog R /\
match_states S R.
Proof.
Lemma final_states_simulation:
forall S R r,
match_states S R ->
Clight.final_state S r ->
Clight.final_state R r.
Proof.
intros; inv H0; inv H.
destruct tk; try inv TCONT.
- econstructor.
- inv MCONT. simpl in H0; inv H0. simpl in H; inv H.
Qed.
Final theorem of semantics preservation
Theorem transf_program_correct:
forward_simulation (
Clight.semantics1 prog) (
Clight.semantics1 tprog).
Proof.
End PRESERVATION.
Section PRESERVATION_IDENT.
Parametrisation with the identity function over 0, 2^32 - 1
Definition phi_ident :=
Int.repr.
Variable prog:
Clight.program.
Variable tprog:
Clight.program.
Hypothesis TRANSF:
transf_program phi_ident prog =
OK tprog.
Let ge :=
Genv.globalenv prog.
Let tge :=
Genv.globalenv tprog.
Theorem phi_ident_injective:
forall x y,
0 <=
x <=
Int.max_unsigned ->
0 <=
y <=
Int.max_unsigned ->
phi_ident x =
phi_ident y ->
x =
y.
Proof.
Theorem transf_program_correct_ident:
forward_simulation (
Clight.semantics1 prog) (
Clight.semantics1 tprog).
Proof.
End PRESERVATION_IDENT.
Section PRESERVATION_INV.
Parametrisation with the \ x -> 2^32 - 1 - x function
Definition phi_inv x :=
Int.repr (
Int.max_unsigned -
x).
Variable prog:
Clight.program.
Variable tprog:
Clight.program.
Hypothesis TRANSF:
transf_program phi_inv prog =
OK tprog.
Let ge :=
Genv.globalenv prog.
Let tge :=
Genv.globalenv tprog.
Theorem phi_inv_injective:
forall x y,
0 <=
x <=
Int.max_unsigned ->
0 <=
y <=
Int.max_unsigned ->
phi_inv x =
phi_inv y ->
x =
y.
Proof.
Theorem transf_program_correct_inv:
forward_simulation (
Clight.semantics1 prog) (
Clight.semantics1 tprog).
Proof.
End PRESERVATION_INV.