Section PRESERVATION.
Variable prog: Csyntax.program.
Variable tprog: Clight.program.
Hypothesis TRANSL: match_prog prog tprog.
Let ge := Csem.globalenv prog.
Let tge := Clight.globalenv tprog.
(** Invariance properties. *)
Proof (Genv.find_symbol_match (proj1 TRANSL)).
Proof (Genv.senv_match (proj1 TRANSL)).
(** Properties of smart constructors. *)
(** Translation of simple expressions. *)
Proof (proj1 tr_simple_nil).
Proof (proj2 tr_simple_nil).
(** Translation of [deref_loc] and [assign_loc] operations. *)
Remark deref_loc_translated:
forall ty m b ofs t v,
Csem.deref_loc ge ty m b ofs t v ->
match chunk_for_volatile_type ty with
| None => t = E0 /\ Clight.deref_loc ty m b ofs v
| Some chunk => volatile_load tge chunk m b ofs t v
end.
Remark assign_loc_translated:
forall ty m b ofs v t m',
Csem.assign_loc ge ty m b ofs v t m' ->
match chunk_for_volatile_type ty with
| None => t = E0 /\ Clight.assign_loc tge ty m b ofs v m'
| Some chunk => volatile_store tge chunk m b ofs v t m'
end.
(** Evaluation of simple expressions and of their translation *)
(** Commutation between the translation of expressions and left contexts. *)
Scheme leftcontext_ind2 := Minimality for leftcontext Sort Prop
with leftcontextlist_ind2 := Minimality for leftcontextlist Sort Prop.
Combined Scheme leftcontext_leftcontextlist_ind from leftcontext_ind2, leftcontextlist_ind2.
(** Semantics of smart constructors *)
Remark sem_cast_deterministic:
forall v ty ty' m1 v1 m2 v2,
sem_cast v ty ty' m1 = Some v1 ->
sem_cast v ty ty' m2 = Some v2 ->
v1 = v2.
Fixpoint Kseqlist (sl: list statement) (k: cont) :=
match sl with
| nil => k
| s :: l => Kseq s (Kseqlist l k)
end.
Remark Kseqlist_app:
forall sl1 sl2 k,
Kseqlist (sl1 ++ sl2) k = Kseqlist sl1 (Kseqlist sl2 k).
(** Matching between continuations *)
Inductive match_cont : Csem.cont -> cont -> Prop :=
| match_Kstop:
match_cont Csem.Kstop Kstop
| match_Kseq: forall s k ts tk,
tr_stmt s ts ->
match_cont k tk ->
match_cont (Csem.Kseq s k) (Kseq ts tk)
| match_Kwhile2: forall r s k s' ts tk,
tr_if r Sskip Sbreak s' ->
tr_stmt s ts ->
match_cont k tk ->
match_cont (Csem.Kwhile2 r s k)
(Kloop1 (Ssequence s' ts) Sskip tk)
| match_Kdowhile1: forall r s k s' ts tk,
tr_if r Sskip Sbreak s' ->
tr_stmt s ts ->
match_cont k tk ->
match_cont (Csem.Kdowhile1 r s k)
(Kloop1 ts s' tk)
| match_Kfor3: forall r s3 s k ts3 s' ts tk,
tr_if r Sskip Sbreak s' ->
tr_stmt s3 ts3 ->
tr_stmt s ts ->
match_cont k tk ->
match_cont (Csem.Kfor3 r s3 s k)
(Kloop1 (Ssequence s' ts) ts3 tk)
| match_Kfor4: forall r s3 s k ts3 s' ts tk,
tr_if r Sskip Sbreak s' ->
tr_stmt s3 ts3 ->
tr_stmt s ts ->
match_cont k tk ->
match_cont (Csem.Kfor4 r s3 s k)
(Kloop2 (Ssequence s' ts) ts3 tk)
| match_Kswitch2: forall k tk,
match_cont k tk ->
match_cont (Csem.Kswitch2 k) (Kswitch tk)
| match_Kcall: forall f e C ty k optid tf le sl tk a dest tmps,
tr_function f tf ->
leftcontext RV RV C ->
(forall v m, tr_top tge e (set_opttemp optid v le) m dest (C (Csyntax.Eval v ty)) sl a tmps) ->
match_cont_exp dest a k tk ->
match_cont (Csem.Kcall f e C ty k)
(Kcall optid tf e le (Kseqlist sl tk))
(* | match_Kcall_some: forall f e C ty k dst tf le sl tk a dest tmps, transl_function f = Errors.OK tf -> leftcontext RV RV C -> (forall v m, tr_top tge e (PTree.set dst v le) m dest (C (C.Eval v ty)) sl a tmps) -> match_cont_exp dest a k tk -> match_cont (Csem.Kcall f e C ty k) (Kcall (Some dst) tf e le (Kseqlist sl tk)) *)
with match_cont_exp : destination -> expr -> Csem.cont -> cont -> Prop :=
| match_Kdo: forall k a tk,
match_cont k tk ->
match_cont_exp For_effects a (Csem.Kdo k) tk
| match_Kifthenelse_empty: forall a k tk,
match_cont k tk ->
match_cont_exp For_val a (Csem.Kifthenelse Csyntax.Sskip Csyntax.Sskip k) (Kseq Sskip tk)
| match_Kifthenelse_1: forall a s1 s2 k ts1 ts2 tk,
tr_stmt s1 ts1 -> tr_stmt s2 ts2 ->
match_cont k tk ->
match_cont_exp For_val a (Csem.Kifthenelse s1 s2 k) (Kseq (Sifthenelse a ts1 ts2) tk)
| match_Kwhile1: forall r s k s' a ts tk,
tr_if r Sskip Sbreak s' ->
tr_stmt s ts ->
match_cont k tk ->
match_cont_exp For_val a
(Csem.Kwhile1 r s k)
(Kseq (makeif a Sskip Sbreak)
(Kseq ts (Kloop1 (Ssequence s' ts) Sskip tk)))
| match_Kdowhile2: forall r s k s' a ts tk,
tr_if r Sskip Sbreak s' ->
tr_stmt s ts ->
match_cont k tk ->
match_cont_exp For_val a
(Csem.Kdowhile2 r s k)
(Kseq (makeif a Sskip Sbreak) (Kloop2 ts s' tk))
| match_Kfor2: forall r s3 s k s' a ts3 ts tk,
tr_if r Sskip Sbreak s' ->
tr_stmt s3 ts3 ->
tr_stmt s ts ->
match_cont k tk ->
match_cont_exp For_val a
(Csem.Kfor2 r s3 s k)
(Kseq (makeif a Sskip Sbreak)
(Kseq ts (Kloop1 (Ssequence s' ts) ts3 tk)))
| match_Kswitch1: forall ls k a tls tk,
tr_lblstmts ls tls ->
match_cont k tk ->
match_cont_exp For_val a (Csem.Kswitch1 ls k) (Kseq (Sswitch a tls) tk)
| match_Kreturn: forall k a tk,
match_cont k tk ->
match_cont_exp For_val a (Csem.Kreturn k) (Kseq (Sreturn (Some a)) tk).

Lemma match_cont_call:
forall k tk,
match_cont k tk ->
match_cont (Csem.call_cont k) (call_cont tk).