(*Lenb: these conditions are modified*)
(*Lenb: these conditions are new here*)
(* Lemma sel_exprlist_correct: forall sp e m a v, Cminor.eval_exprlist ge sp e m a v -> forall e' le m', env_lessdef e e' -> Mem.extends m m' -> exists v', eval_exprlist tge sp e' m' le (sel_exprlist hf a) v' /\ Val.lessdef_list v v'. *)
(** Semantic preservation for functions and statements. *)
Inductive match_cont (*NEW:*)(j:meminj): Cminor.cont -> CminorSel.cont -> Prop :=
| match_cont_stop:
match_cont j Cminor.Kstop Kstop
| match_cont_seq: forall s k k',
match_cont j k k' ->
match_cont j (Cminor.Kseq s k) (Kseq (sel_stmt hf ge s) k')
| match_cont_block: forall k k',
match_cont j k k' ->
match_cont j (Cminor.Kblock k) (Kblock k')
(*sp' and sp_preserved_condition are new*)
| match_cont_call: forall id f sp e k sp' e' k',
match_cont j k k' ->
(*env_lessdef e e' ->*)
env_inject j e e' -> sp_preserved j sp sp' ->
match_cont j (Cminor.Kcall id f sp e k) (Kcall id (sel_function hf ge f) sp' e' k').
Inductive match_states (j:meminj) : CMin_core -> mem -> CMinSel_core -> mem -> Prop :=
| match_state: forall f s k s' k' sp e m sp' e' m',
s' = sel_stmt hf ge s ->
match_cont j k k' ->
(*      env_lessdef e e' -> Mem.extends m m' ->*)
env_inject j e e' -> Mem.inject j m m' -> sp_preserved j sp sp' ->
match_states j
(CMin_State f s k sp e) m
(CMinSel_State (sel_function hf ge f) s' k' sp' e') m'
| match_callstate: forall f args args' k k' m m',
match_cont j k k' ->
(*      Val.lessdef_list args args' -> Mem.extends m m' ->*)
val_list_inject j args args' -> Mem.inject j m m' ->
match_states j
(CMin_Callstate f args k) m
(CMinSel_Callstate (sel_fundef hf ge f) args' k') m'
| match_returnstate: forall v v' k k' m m',
match_cont j k k' ->
(*Val.lessdef v v' -> Mem.extends m m' ->*)
val_inject j v v' -> Mem.inject j m m' ->
match_states j
(CMin_Returnstate v k) m
(CMinSel_Returnstate v' k') m'
| match_builtin_1: forall ef args args' optid f sp e k m al sp' e' k' m',
match_cont j k k' ->
(*Val.lessdef_list args args' -> env_lessdef e e' -> Mem.extends m m' -> *)
val_list_inject j args args' -> env_inject j e e' -> Mem.inject j m m' ->
sp_preserved j sp sp' ->
CminorSel.eval_exprlist tge sp' e' m' nil al args' ->
match_states j
(CMin_Callstate (External ef) args (Cminor.Kcall optid f sp e k)) m
(CMinSel_State (sel_function hf ge f) (Sbuiltin optid ef al) k' sp' e') m'
| match_builtin_2: forall v v' optid f sp e k m sp' e' m' k',
match_cont j k k' ->
(*Val.lessdef v v' -> env_lessdef e e' -> Mem.extends m m' ->*)
val_inject j v v' -> env_inject j e e' -> Mem.inject j m m' -> sp_preserved j sp sp' ->
match_states j
(CMin_Returnstate v (Cminor.Kcall optid f sp e k)) m
(CMinSel_State (sel_function hf ge f) Sskip k' sp' (set_optvar optid v' e')) m'.
Definition Match_cores (d:CMin_core) mu c1 m1 c2 m2:Prop :=
match_states (restrict (as_inj mu) (vis mu)) c1 m1 c2 m2 /\
REACH_closed m1 (vis mu) /\
meminj_preserves_globals ge (as_inj mu) /\
globalfunction_ptr_inject (as_inj mu) /\
(forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu b = true) /\
sm_valid mu m1 m2 /\ SM_wd mu /\ Mem.inject (as_inj mu) m1 m2.

Lemma env_inject_sub: forall j e e' (E: env_inject j e e')
j' (I: inject_incr j j'), env_inject j' e e'.