(*--------------------------------------------------------------------*)

(*NEW:*) (PG: meminj_preserves_globals ge j), exists c2' : CMin_core, exists m2' : mem, corestep_plus CMin_core_sem tge (CMin_State tfn (Sexit (shift_exit xenv (S n))) k (Vptr sp Int.zero) te) tm c2' m2' /\ match_cores (CSharpMin_State f (Csharpminor.Sexit n) tk e lenv)  j (CSharpMin_State f (Csharpminor.Sexit n) tk e lenv) m c2' m2'.  Lemma MS_switch_descent: forall cenv xenv k ls body s, transl_lblstmt cenv (switch_env ls xenv) ls body = OK s -> exists k', transl_lblstmt_cont cenv xenv ls k k' /\ (forall f sp e m, corestep_plus CMin_core_sem tge (CMin_State f s k sp e) m (CMin_State f body k' sp e) m).  Lemma MS_switch_ascent: forall f n sp e m cenv xenv k ls k1, let tbl := switch_table ls O in let ls' := select_switch n ls in transl_lblstmt_cont cenv xenv ls k k1 -> exists k2, corestep_star CMin_core_sem tge (CMin_State f (Sexit (Switch.switch_target n (length tbl) tbl)) k1 sp e) m (CMin_State f (Sexit O) k2 sp e) m /\ transl_lblstmt_cont cenv xenv ls' k k2.  Lemma MS_switch_MSI: forall fn k e lenv m tfn ts tk sp te tm cenv xenv j lo hi cs sz ls body tk' (TRF: transl_funbody cenv sz fn = OK tfn) (TR: transl_lblstmt cenv (switch_env ls xenv) ls body = OK ts) (MINJ: Mem.inject j m tm) (MCS: match_callstack prog j m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK: match_cont k tk cenv xenv cs) (TK: transl_lblstmt_cont cenv xenv ls tk tk'), exists S, exists mm, corestep_plus CMin_core_sem tge (CMin_State tfn (Sexit O) tk' (Vptr sp Int.zero) te) tm S mm /\ match_statesInj prog j (Csharpminor.State fn (seq_of_lbl_stmt ls) k e lenv m) (Cminor_coop.ToState S mm).  Lemma MS_step_case_Switch: forall cenv sz f tfn j m tm e lenv te sp lo hi cs k tk xenv a x x0 ts cases n (EvalA: Csharpminor.eval_expr ge e lenv m a (Vint n)) (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack prog j m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont k tk cenv xenv cs) (EQ : transl_expr cenv a = OK (x, x0)) (EQ0 : transl_lblstmt cenv (switch_env cases xenv) cases (Sswitch x (switch_table cases 0) (length (switch_table cases 0))) = OK ts) (*NEW:*) (PG: meminj_preserves_globals ge j), exists c2' : CMin_core, exists m2' : mem, corestep_plus CMin_core_sem tge (CMin_State tfn ts tk (Vptr sp Int.zero) te) tm c2' m2' /\ match_cores (CSharpMin_State f (seq_of_lbl_stmt (select_switch n cases)) k e lenv)  j (CSharpMin_State f (seq_of_lbl_stmt (select_switch n cases)) k e lenv) m c2' m2'.  Lemma MS_step_case_ReturnNone: forall cenv sz f tfn j m tm e lenv te sp lo hi cs k tk xenv m' (Freelist: Mem.free_list m (blocks_of_env e) = Some m') (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack prog j m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont tk k cenv xenv cs) (*NEW:*) (PG: meminj_preserves_globals ge j), exists c2' : CMin_core, exists m2' : mem, corestep_plus CMin_core_sem tge (CMin_State tfn (Sreturn None) k (Vptr sp Int.zero) te) tm c2' m2'  /\ match_cores (CSharpMin_Returnstate Vundef (Csharpminor.call_cont tk))  j (CSharpMin_Returnstate Vundef (Csharpminor.call_cont tk)) m' c2' m2'.  Lemma MS_step_case_ReturnSome: forall cenv sz f tfn j m tm e lenv te sp lo hi cs k tk xenv a x x0 m' v (EvalA: Csharpminor.eval_expr ge e lenv m a v) (Freelist: Mem.free_list m (blocks_of_env e) = Some m') (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack prog j m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont tk k cenv xenv cs) (EQ : transl_expr cenv a = OK (x, x0)) (*NEW:*) (PG: meminj_preserves_globals ge j), exists c2' : CMin_core, exists m2' : mem, corestep_plus CMin_core_sem tge (CMin_State tfn (Sreturn (Some x)) k (Vptr sp Int.zero) te) tm c2' m2' /\ match_cores  (CSharpMin_Returnstate v (Csharpminor.call_cont tk)) j (CSharpMin_Returnstate v (Csharpminor.call_cont tk)) m' c2' m2'.  Lemma MS_step_case_Label: forall cenv sz f tfn j m tm e lenv te sp lo hi cs k tk xenv lbl x s (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack prog j m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont k tk cenv xenv cs) (EQ : transl_stmt cenv xenv s = OK x) (*NEW:*) (PG: meminj_preserves_globals ge j), exists c2' : CMin_core, exists m2' : mem, corestep_plus CMin_core_sem tge (CMin_State tfn (Slabel lbl x) tk (Vptr sp Int.zero) te) tm c2' m2' /\ match_cores (CSharpMin_State f s k e lenv)  j (CSharpMin_State f s k e lenv) m c2' m2'.  Lemma MS_step_case_Goto: forall cenv sz f tfn j m tm e lenv te sp lo hi cs k tk xenv lbl s' k' (FindLab: Csharpminor.find_label lbl (Csharpminor.fn_body f) (Csharpminor.call_cont k) = Some (s', k')) (TRF : transl_funbody cenv sz f = OK tfn) (MINJ : Mem.inject j m tm) (MCS : match_callstack prog j m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont k tk cenv xenv cs) (*NEW:*) (PG: meminj_preserves_globals ge j), exists c2' : CMin_core, exists m2' : mem, corestep_plus CMin_core_sem tge (CMin_State tfn (Sgoto lbl) tk (Vptr sp Int.zero) te) tm c2' m2' /\ match_cores  (CSharpMin_State f s' k' e lenv) j (CSharpMin_State f s' k' e lenv) m c2' m2'.  (******************************Functions required for internal call rule*****************************)
(****These extend the original lemmas by additional guarantees of the (now exposed) memory injections, in order for the overall lemma for internal calls to establish the inject_separated fact******************************)
Lemma MS_match_callstack_alloc_variables_rec:
forall tm sp tf cenv le te lo cs,
Mem.valid_block tm sp ->
fn_stackspace tf <= Int.max_unsigned ->
(forall ofs k p, Mem.perm tm sp ofs k p -> 0 <= ofs < fn_stackspace tf) ->
(forall ofs k p, 0 <= ofs < fn_stackspace tf -> Mem.perm tm sp ofs k p) ->
forall e1 m1 vars e2 m2,
alloc_variables e1 m1 vars e2 m2 ->
forall f1,
list_norepet (map fst vars) ->
cenv_compat cenv vars (fn_stackspace tf) ->
cenv_separated cenv vars ->
cenv_mem_separated cenv vars f1 sp m1 ->
(forall id sz, In (id, sz) vars -> e1!id = None) ->
match_callstack prog f1 m1 tm
(Frame (cenv_remove cenv vars) tf e1 le te sp lo (Mem.nextblock m1) :: cs)
(Mem.nextblock m1) (Mem.nextblock tm) ->
Mem.inject f1 m1 tm ->
exists f2,
match_callstack prog f2 m2 tm
(Frame cenv tf e2 le te sp lo (Mem.nextblock m2) :: cs)
(Mem.nextblock m2) (Mem.nextblock tm)
/\ Mem.inject f2 m2 tm
/\ (*LENB: THIS IS NEW*) inject_incr f1 f2
/\ (forall b, Mem.valid_block m1 b -> f2 b = f1 b)
/\ (forall b b' d', f1 b = None -> f2 b = Some (b',d') -> b' = sp)
/\ forall j',  inject_incr f2 j' -> inject_separated f2 j' m2 tm ->
inject_separated f2 j' m1 tm.