(*LENB: We omit the clauses INJ and PG, since they are required for the
  enitre mu, not just restrict mu (vis mu), and hence better enforced
  uniformly in definition MatchCore below*)
Inductive structured_match_cores: core_data -> SM_Injection -> CSharpMin_core -> mem -> CMin_core -> mem -> Prop :=
  | SMC_states:
      forall d fn s k e le m tfn ts tk sp te tm cenv xenv mu lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk  cenv xenv cs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_State fn s k e le) m
                   (CMin_State tfn ts tk (Vptr sp Int.zero) te) tm
  | SMC_state_seq:
      forall d fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv mu lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_State fn (Csharpminor.Sseq s1 s2) k e le) m
                   (CMin_State tfn ts1 tk (Vptr sp Int.zero) te) tm
  | SMC_callstate:
      forall d fd args k m tfd targs tk tm mu cs cenv
      (TR: transl_fundef fd = OK tfd)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject (restrict (as_inj mu) (vis mu)) args targs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),

      structured_match_cores d mu (CSharpMin_Callstate fd args k) m
                   (CMin_Callstate tfd targs tk) tm
  | SMC_returnstate:
      forall d v k m tv tk tm mu cs cenv
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject (restrict (as_inj mu) (vis mu)) v tv)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_Returnstate v k) m
                   (CMin_Returnstate tv tk) tm.(*LENB: We omit the clauses INJ and PG, since they are required for the
  enitre mu, not just restrict mu (vis mu), and hence better enforced
  uniformly in definition MatchCore below*)
Inductive structured_match_cores: core_data -> SM_Injection -> CSharpMin_core -> mem -> CMin_core -> mem -> Prop :=
  | SMC_states:
      forall d fn s k e le m tfn ts tk sp te tm cenv xenv mu lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk  cenv xenv cs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_State fn s k e le) m
                   (CMin_State tfn ts tk (Vptr sp Int.zero) te) tm
  | SMC_state_seq:
      forall d fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv mu lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_State fn (Csharpminor.Sseq s1 s2) k e le) m
                   (CMin_State tfn ts1 tk (Vptr sp Int.zero) te) tm
  | SMC_callstate:
      forall d fd args k m tfd targs tk tm mu cs cenv
      (TR: transl_fundef fd = OK tfd)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject (restrict (as_inj mu) (vis mu)) args targs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),

      structured_match_cores d mu (CSharpMin_Callstate fd args k) m
                   (CMin_Callstate tfd targs tk) tm
  | SMC_returnstate:
      forall d v k m tv tk tm mu cs cenv
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject (restrict (as_inj mu) (vis mu)) v tv)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_Returnstate v k) m
                   (CMin_Returnstate tv tk) tm.(*LENB: We omit the clauses INJ and PG, since they are required for the
  enitre mu, not just restrict mu (vis mu), and hence better enforced
  uniformly in definition MatchCore below*)
Inductive structured_match_cores: core_data -> SM_Injection -> CSharpMin_core -> mem -> CMin_core -> mem -> Prop :=
  | SMC_states:
      forall d fn s k e le m tfn ts tk sp te tm cenv xenv mu lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk  cenv xenv cs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_State fn s k e le) m
                   (CMin_State tfn ts tk (Vptr sp Int.zero) te) tm
  | SMC_state_seq:
      forall d fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv mu lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_State fn (Csharpminor.Sseq s1 s2) k e le) m
                   (CMin_State tfn ts1 tk (Vptr sp Int.zero) te) tm
  | SMC_callstate:
      forall d fd args k m tfd targs tk tm mu cs cenv
      (TR: transl_fundef fd = OK tfd)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject (restrict (as_inj mu) (vis mu)) args targs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),

      structured_match_cores d mu (CSharpMin_Callstate fd args k) m
                   (CMin_Callstate tfd targs tk) tm
  | SMC_returnstate:
      forall d v k m tv tk tm mu cs cenv
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject (restrict (as_inj mu) (vis mu)) v tv)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_Returnstate v k) m
                   (CMin_Returnstate tv tk) tm.(*LENB: We omit the clauses INJ and PG, since they are required for the
  enitre mu, not just restrict mu (vis mu), and hence better enforced
  uniformly in definition MatchCore below*)
Inductive structured_match_cores: core_data -> SM_Injection -> CSharpMin_core -> mem -> CMin_core -> mem -> Prop :=
  | SMC_states:
      forall d fn s k e le m tfn ts tk sp te tm cenv xenv mu lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk  cenv xenv cs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_State fn s k e le) m
                   (CMin_State tfn ts tk (Vptr sp Int.zero) te) tm
  | SMC_state_seq:
      forall d fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv mu lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_State fn (Csharpminor.Sseq s1 s2) k e le) m
                   (CMin_State tfn ts1 tk (Vptr sp Int.zero) te) tm
  | SMC_callstate:
      forall d fd args k m tfd targs tk tm mu cs cenv
      (TR: transl_fundef fd = OK tfd)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject (restrict (as_inj mu) (vis mu)) args targs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),

      structured_match_cores d mu (CSharpMin_Callstate fd args k) m
                   (CMin_Callstate tfd targs tk) tm
  | SMC_returnstate:
      forall d v k m tv tk tm mu cs cenv
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject (restrict (as_inj mu) (vis mu)) v tv)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_Returnstate v k) m
                   (CMin_Returnstate tv tk) tm.(*LENB: We omit the clauses INJ and PG, since they are required for the
  enitre mu, not just restrict mu (vis mu), and hence better enforced
  uniformly in definition MatchCore below*)
Inductive structured_match_cores: core_data -> SM_Injection -> CSharpMin_core -> mem -> CMin_core -> mem -> Prop :=
  | SMC_states:
      forall d fn s k e le m tfn ts tk sp te tm cenv xenv mu lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk  cenv xenv cs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_State fn s k e le) m
                   (CMin_State tfn ts tk (Vptr sp Int.zero) te) tm
  | SMC_state_seq:
      forall d fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv mu lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_State fn (Csharpminor.Sseq s1 s2) k e le) m
                   (CMin_State tfn ts1 tk (Vptr sp Int.zero) te) tm
  | SMC_callstate:
      forall d fd args k m tfd targs tk tm mu cs cenv
      (TR: transl_fundef fd = OK tfd)
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject (restrict (as_inj mu) (vis mu)) args targs)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),

      structured_match_cores d mu (CSharpMin_Callstate fd args k) m
                   (CMin_Callstate tfd targs tk) tm
  | SMC_returnstate:
      forall d v k m tv tk tm mu cs cenv
      (*(MINJ: Mem.inject (as_inj mu) m tm)*)
      (MCS: structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject (restrict (as_inj mu) (vis mu)) v tv)
      (*(PG: meminj_preserves_globals ge (as_inj mu))*),
      structured_match_cores d mu (CSharpMin_Returnstate v k) m
                   (CMin_Returnstate tv tk) tm.(*
Definition protected m mu:=
   forall b, REACH m (extBlocksSrc mu) b = true ->
             locBlocksSrc mu b = true ->
             REACH m (frgnBlocksSrc mu) b = true.

Lemma protected_restr: forall m mu X
      (PROT : protected m mu), protected m (restrict_sm mu X).
Proof. intros.
red. rewrite restrict_sm_frgnBlocksSrc, restrict_sm_extBlocksSrc,
             restrict_sm_locBlocksSrc; intros.
  eapply PROT; eassumption.
Qed.
*)
Definition Match_cores d mu c1 m1 c2 m2:Prop :=
  structured_match_cores d mu c1 m1 c2 m2 (*(restrict_sm mu (vis mu)) doesn't work here, since
                              some of the conditions of match_env are "global"*) /\
  REACH_closed m1 (vis mu) /\
  meminj_preserves_globals ge (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(* /\ protected m1 mu*).

(* Specifications: *)
Lemma Match_sm_wd: forall d mu c1 m1 c2 m2, Match_cores d mu c1 m1 c2 m2 -> SM_wd mu.
Lemma Match_genv: forall d mu c1 m1 c2 m2 (MC:Match_cores d mu c1 m1 c2 m2), meminj_preserves_globals ge (extern_of mu) /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu b = true).
Lemma Match_visible: forall d mu c1 m1 c2 m2, Match_cores d mu c1 m1 c2 m2 -> REACH_closed m1 (vis mu).
Lemma structured_match_callstack_restrict: forall mu m1 m2 X (HX: forall b, vis mu b = true -> X b = true) (RC: REACH_closed m1 X) cs bound tbound (MCS: structured_match_callstack mu m1 m2 cs bound tbound), structured_match_callstack (restrict_sm mu X) m1 m2 cs bound tbound.
Lemma structured_match_cores_restrict: forall mu d m1 m2 c1 c2 X (HX: forall b, vis mu b = true -> X b = true) (RC: REACH_closed m1 X) (MC: structured_match_cores d mu c1 m1 c2 m2), structured_match_cores d (restrict_sm mu X) c1 m1 c2 m2.
Lemma Match_restrict: forall d mu c1 m1 c2 m2 X (MC: Match_cores d mu c1 m1 c2 m2) (HX: forall b, vis mu b = true -> X b = true) (RC: REACH_closed m1 X), Match_cores d (restrict_sm mu X) c1 m1 c2 m2.
Lemma Match_validblocks: forall d mu c1 m1 c2 m2, Match_cores d mu c1 m1 c2 m2 -> sm_valid mu m1 m2.
Lemma Match_init_core: forall (v1 v2 : val) (sig : signature) entrypoints (EP: In (v1, v2, sig) entrypoints) (entry_points_ok : forall (v1 v2 : val) (sig : signature), In (v1, v2, sig) entrypoints -> exists (b : Values.block) (f1 : Csharpminor.fundef) (f2 : fundef), v1 = Vptr b Int.zero /\ v2 = Vptr b Int.zero /\ Genv.find_funct_ptr ge b = Some f1 /\ Genv.find_funct_ptr tge b = Some f2) (vals1 : list val) (c1 : CSharpMin_core) (m1 : mem) (j : meminj) (vals2 : list val) (m2 : mem) (DomS DomT : Values.block -> bool) (CSM_Ini :initial_core csharpmin_eff_sem ge v1 vals1 = Some c1) (Inj: Mem.inject j m1 m2) (VInj: Forall2 (val_inject j) vals1 vals2) (PG: meminj_preserves_globals ge j) (R : list_norepet (map fst (prog_defs prog))) (J: forall b1 b2 d, j b1 = Some (b2, d) -> DomS b1 = true /\ DomT b2 = true) (RCH: forall b, REACH m2 (fun b' : Values.block => isGlobalBlock tge b' || getBlocks vals2 b') b = true -> DomT b = true) (InitMem : exists m0 : mem, Genv.init_mem prog = Some m0 /\ Ple (Mem.nextblock m0) (Mem.nextblock m1) /\ Ple (Mem.nextblock m0) (Mem.nextblock m2)) (GDE: genvs_domain_eq ge tge) (HDomS: forall b : Values.block, DomS b = true -> Mem.valid_block m1 b) (HDomT: forall b : Values.block, DomT b = true -> Mem.valid_block m2 b), exists c2 : CMin_core, initial_core cmin_eff_sem tge v2 vals2 = Some c2 /\ Match_cores c1 (initial_SM DomS DomT (REACH m1 (fun b : Values.block => isGlobalBlock ge b || getBlocks vals1 b)) (REACH m2 (fun b : Values.block => isGlobalBlock tge b || getBlocks vals2 b)) j) c1 m1 c2 m2.
Lemma Match_AfterExternal: forall mu st1 st2 m1 e vals1 m2 ef_sig vals2 e' ef_sig' (MemInjMu : Mem.inject (as_inj mu) m1 m2) (MatchMu : Match_cores st1 mu st1 m1 st2 m2) (AtExtSrc : at_external csharpmin_eff_sem st1 = Some (e, ef_sig, vals1)) (AtExtTgt : at_external cmin_eff_sem st2 = Some (e', ef_sig', vals2)) (ValInjMu : Forall2 (val_inject (restrict (as_inj mu) (vis mu))) vals1 vals2) (pubSrc' : Values.block -> bool) (pubSrcHyp : pubSrc' = (fun b : Values.block => locBlocksSrc mu b && REACH m1 (exportedSrc mu vals1) b)) (pubTgt' : Values.block -> bool) (pubTgtHyp : pubTgt' = (fun b : Values.block => locBlocksTgt mu b && REACH m2 (exportedTgt mu vals2) b)) nu (NuHyp : nu = replace_locals mu pubSrc' pubTgt') nu' ret1 m1' ret2 m2' (INC : extern_incr nu nu') (SEP : sm_inject_separated nu nu' m1 m2) (WDnu' : SM_wd nu') (SMvalNu' : sm_valid nu' m1' m2') (MemInjNu' : Mem.inject (as_inj nu') m1' m2') (RValInjNu' : val_inject (as_inj nu') ret1 ret2) (FwdSrc : mem_forward m1 m1') (FwdTgt : mem_forward m2 m2') (frgnSrc' : Values.block -> bool) (frgnSrcHyp : frgnSrc' = (fun b : Values.block => DomSrc nu' b && (negb (locBlocksSrc nu' b) && REACH m1' (exportedSrc nu' (ret1 :: nil)) b))) (frgnTgt' : Values.block -> bool) (frgnTgtHyp : frgnTgt' = (fun b : Values.block => DomTgt nu' b && (negb (locBlocksTgt nu' b) && REACH m2' (exportedTgt nu' (ret2 :: nil)) b))) mu' (Mu'Hyp : mu' = replace_externs nu' frgnSrc' frgnTgt') (UnchPrivSrc : Mem.unchanged_on (fun (b : Values.block) (_ : Z) => locBlocksSrc nu b = true /\ pubBlocksSrc nu b = false) m1 m1') (UnchLOOR : Mem.unchanged_on (local_out_of_reach nu m1) m2 m2'), exists (st1' : CSharpMin_core) (st2' : CMin_core), after_external csharpmin_eff_sem (Some ret1) st1 = Some st1' /\ after_external cmin_eff_sem (Some ret2) st2 = Some st2' /\ Match_cores st1' mu' st1' m1' st2' m2'.
Lemma MATCH_safely_halted: forall cd mu c1 m1 c2 m2 v1 (SMC: structured_match_cores cd mu c1 m1 c2 m2) (HALT: halted CSharpMin_core_sem c1 = Some v1), exists v2, halted CMin_core_sem c2 = Some v2 /\ val_inject (restrict (as_inj mu) (vis mu)) v1 v2.
Lemma Match_at_external: forall mu st1 m1 st2 m2 e vals1 sig (MC: structured_match_cores st1 mu st1 m1 st2 m2) (AtExt: at_external CSharpMin_core_sem st1 = Some (e, sig, vals1)), exists vals2, Forall2 (val_inject (restrict (as_inj mu) (vis mu))) vals1 vals2 /\ at_external CMin_core_sem st2 = Some (e, sig, vals2).
Lemma match_callstack_freelist: forall mu cenv tf e le te sp lo hi cs m m' tm (WD: SM_wd mu), Mem.inject (as_inj mu) m tm -> Mem.free_list m (blocks_of_env e) = Some m' -> structured_match_callstack mu m tm (Frame cenv tf e le te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm) -> exists tm', Mem.free tm sp 0 tf.(fn_stackspace) = Some tm' /\ structured_match_callstack mu m' tm' cs (Mem.nextblock m') (Mem.nextblock tm') /\ Mem.inject (as_inj mu) m' tm'.
Lemma var_addr_correct: forall cenv id mu tf e le te sp lo hi m cs tm b, structured_match_callstack mu m tm (Frame cenv tf e le te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm) -> eval_var_addr ge e id b -> exists tv, eval_expr tge (Vptr sp Int.zero) te tm (var_addr cenv id) tv /\ val_inject (restrict (as_inj mu) (vis mu)) (Vptr b Int.zero) tv.
Lemma transl_expr_correct: forall mu m tm cenv tf e lenv te sp lo hi cs (MINJ: Mem.inject (as_inj mu) m tm) (RC: REACH_closed m (vis mu)) (MATCH: structured_match_callstack mu m tm (Frame cenv tf e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)), forall a v, Csharpminor.eval_expr ge e lenv m a v -> forall ta app (TR: transl_expr cenv a = OK (ta, app)), exists tv, eval_expr tge (Vptr sp Int.zero) te tm ta tv /\ val_inject (restrict (as_inj mu) (vis mu)) v tv /\ val_match_approx app v.
Lemma transl_exprlist_correct: forall mu m tm cenv tf e lenv te sp lo hi cs (MINJ: Mem.inject (as_inj mu) m tm) (RC: REACH_closed m (vis mu)) (MATCH: structured_match_callstack mu m tm (Frame cenv tf e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)), forall a v, Csharpminor.eval_exprlist ge e lenv m a v -> forall ta (TR: transl_exprlist cenv a = OK ta), exists tv, eval_exprlist tge (Vptr sp Int.zero) te tm ta tv /\ val_list_inject (restrict (as_inj mu) (vis mu)) v tv.
Theorem MS_structured_match_callstack_function_entry: forall fn cenv tf m' tm' sp cs args targs, build_compilenv fn = (cenv, tf.(fn_stackspace)) -> tf.(fn_stackspace) <= Int.max_unsigned -> list_norepet (map fst (Csharpminor.fn_vars fn)) -> list_norepet (Csharpminor.fn_params fn) -> list_disjoint (Csharpminor.fn_params fn) (Csharpminor.fn_temps fn) -> alloc_variables Csharpminor.empty_env m (Csharpminor.fn_vars fn) e m' -> bind_parameters (Csharpminor.fn_params fn) args (create_undef_temps fn.(fn_temps)) = Some lenv -> val_list_inject (restrict (as_inj mu) (vis mu)) args targs -> Mem.alloc tm 0 tf.(fn_stackspace) = (tm', sp) -> structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm) -> REACH_closed m (vis mu) -> sm_valid mu m tm -> SM_wd mu -> Mem.inject (as_inj mu) m tm -> let te := set_locals (Csharpminor.fn_temps fn) (set_params targs (Csharpminor.fn_params fn)) in exists mu', structured_match_callstack mu' m' tm' (Frame cenv tf e lenv te sp (Mem.nextblock m) (Mem.nextblock m') :: cs) (Mem.nextblock m') (Mem.nextblock tm') /\ Mem.inject (as_inj mu') m' tm' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m' tm' /\ SM_wd mu' /\ sm_valid mu' m' tm' /\ REACH_closed m' (vis mu').
Lemma MS_step_case_InternalCall: forall (MCS : structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm)) (PRE: REACH_closed m (vis mu) /\ meminj_preserves_globals ge (as_inj mu) /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu b = true) /\ sm_valid mu m tm /\ SM_wd mu /\ Mem.inject (as_inj mu) m tm) vargs targs x m1 (Param1: list_norepet (map fst (Csharpminor.fn_vars f))) (Param2 : list_norepet (Csharpminor.fn_params f)) (Param3 : list_disjoint (Csharpminor.fn_params f) (fn_temps f)) (AlocVars : alloc_variables empty_env m (Csharpminor.fn_vars f) e m1) (BindParams: bind_parameters (Csharpminor.fn_params f) vargs (create_undef_temps (fn_temps f)) = Some lenv) (MK : match_cont k tk cenv nil cs) (ISCC : Csharpminor.is_call_cont k) (ARGSINJ : val_list_inject (restrict (as_inj mu) (vis mu)) vargs targs) (EQ : transl_function f = OK x), exists (c2' : CMin_core) m2' mu', corestep_plus CMin_core_sem tge (CMin_Callstate (AST.Internal x) targs tk) tm c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m1 m2' /\ SM_wd mu' /\ sm_valid mu' m1 m2' /\ Match_cores (CSharpMin_State f (Csharpminor.fn_body f) k e lenv) mu' (CSharpMin_State f (Csharpminor.fn_body f) k e lenv) m1 c2' m2'.
Lemma MS_step_case_SkipSeq: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kseq s k) tk cenv xenv cs), exists st2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn Sskip tk (Vptr sp Int.zero) te) tm st2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f s k e lenv) mu' (CSharpMin_State f s k e lenv) m st2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma MS_step_case_SkipBlock: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kblock k) tk cenv xenv cs), exists st2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn Sskip tk (Vptr sp Int.zero) te) tm st2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f Csharpminor.Sskip k e lenv) mu' (CSharpMin_State f Csharpminor.Sskip k e lenv) m st2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma MS_match_is_call_cont: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) v (MK: match_cont k tk cenv xenv cs) (CC: Csharpminor.is_call_cont k), exists tk', corestep_star CMin_core_sem tge (CMin_State tfn Sskip tk v te) tm (CMin_State tfn Sskip tk' v te) tm /\ is_call_cont tk' /\ match_cont k tk' cenv nil cs.
Lemma MS_step_case_SkipCall:forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) m' (CC: Csharpminor.is_call_cont k) (FL: Mem.free_list m (blocks_of_env e) = Some m') (MK : match_cont k tk cenv xenv cs), exists st2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn Sskip tk (Vptr sp Int.zero) te) tm st2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m' m2' /\ Match_cores (CSharpMin_Returnstate Vundef k) mu' (CSharpMin_Returnstate Vundef k) m' st2' m2' /\ SM_wd mu' /\ sm_valid mu' m' m2'.
Lemma MS_step_case_Assign: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) a v id x x0 (EE: Csharpminor.eval_expr ge e lenv m a v) (MK : match_cont k tk cenv xenv cs) (EQ : transl_expr cenv a = OK (x, x0)), exists st2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn (Sassign id x) tk (Vptr sp Int.zero) te) tm st2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f Csharpminor.Sskip k e (PTree.set id v lenv)) mu' (CSharpMin_State f Csharpminor.Sskip k e (PTree.set id v lenv)) m st2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma MS_step_case_Store: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) x x0 x1 x2 chunk m' a addr vaddr v (CH: Mem.storev chunk m vaddr v = Some m') (MK : match_cont k tk cenv xenv cs) (EvAddr : Csharpminor.eval_expr ge e lenv m addr vaddr) (EvA : Csharpminor.eval_expr ge e lenv m a v) (EQ : transl_expr cenv addr = OK (x, x0)) (EQ1 : transl_expr cenv a = OK (x1, x2)), exists st2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn (make_store chunk x x1) tk (Vptr sp Int.zero) te) tm st2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m' m2' /\ Match_cores (CSharpMin_State f Csharpminor.Sskip k e lenv) mu' (CSharpMin_State f Csharpminor.Sskip k e lenv) m' st2' m2' /\ SM_wd mu' /\ sm_valid mu' m' m2'.
Lemma MS_step_case_Call: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) x x0 x1 a vf fd optid vargs bl (MK : match_cont k tk cenv xenv cs) (EvalA: Csharpminor.eval_expr ge e lenv m a vf) (EvalBL: Csharpminor.eval_exprlist ge e lenv m bl vargs) (FF: Genv.find_funct ge vf = Some fd) (EQ : transl_expr cenv a = OK (x, x0)) (EQ1 : transl_exprlist cenv bl = OK x1), exists c2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn (Scall optid (Csharpminor.funsig fd) x x1) tk (Vptr sp Int.zero) te) tm c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_Callstate fd vargs (Csharpminor.Kcall optid f e lenv k)) mu' (CSharpMin_Callstate fd vargs (Csharpminor.Kcall optid f e lenv k)) m c2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma MS_step_case_Ite: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) x x0 x1 x2 b v a s1 s2 (H : Csharpminor.eval_expr ge e lenv m a v) (BoolOfVal : Val.bool_of_val v b) (MK : match_cont k tk cenv xenv cs) (EQ : transl_expr cenv a = OK (x, x0)) (EQ1 : transl_stmt cenv xenv s1 = OK x1) (EQ0 : transl_stmt cenv xenv s2 = OK x2), exists c2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn (Sifthenelse x x1 x2) tk (Vptr sp Int.zero) te) tm c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f (if b then s1 else s2) k e lenv) mu' (CSharpMin_State f (if b then s1 else s2) k e lenv) m c2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma MS_step_case_Loop: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) x s (MK : match_cont k tk cenv xenv cs) (EQ : transl_stmt cenv xenv s = OK x), exists c2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn (Sloop x) tk (Vptr sp Int.zero) te) tm c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f s (Csharpminor.Kseq (Csharpminor.Sloop s) k) e lenv) mu' (CSharpMin_State f s (Csharpminor.Kseq (Csharpminor.Sloop s) k) e lenv) m c2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma MS_step_case_Block: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) x s (MK : match_cont k tk cenv xenv cs) (EQ : transl_stmt cenv (true :: xenv) s = OK x), exists c2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn (Sblock x) tk (Vptr sp Int.zero) te) tm c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f s (Csharpminor.Kblock k) e lenv) mu' (CSharpMin_State f s (Csharpminor.Kblock k) e lenv) m c2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma MS_step_case_ExitSeq: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) n s (MK : match_cont (Csharpminor.Kseq s k) tk cenv xenv cs), exists c2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn (Sexit (shift_exit xenv n)) tk (Vptr sp Int.zero) te) tm c2' m2' /\ Match_cores (CSharpMin_State f (Csharpminor.Sexit n) k e lenv) mu' (CSharpMin_State f (Csharpminor.Sexit n) k e lenv) m c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma MS_step_case_ExitBlockZero: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kblock k) tk cenv xenv cs), exists c2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn (Sexit (shift_exit xenv 0)) tk (Vptr sp Int.zero) te) tm c2' m2' /\ Match_cores (CSharpMin_State f Csharpminor.Sskip k e lenv) mu' (CSharpMin_State f Csharpminor.Sskip k e lenv) m c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma MS_step_case_ExitBlockNonzero: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) n (MK : match_cont (Csharpminor.Kblock k) tk cenv xenv cs), exists c2' : CMin_core, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn (Sexit (shift_exit xenv (S n))) tk (Vptr sp Int.zero) te) tm c2' m2' /\ Match_cores (CSharpMin_State f (Csharpminor.Sexit n) k e lenv) mu' (CSharpMin_State f (Csharpminor.Sexit n) k e lenv) m c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma MS_switch_MSI: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) ts ls body tk' (TR: transl_lblstmt cenv (switch_env ls xenv) ls body = OK ts) (MK: match_cont k tk cenv xenv cs) (TK: transl_lblstmt_cont cenv xenv ls tk tk'), exists S, exists m2' mu', corestep_plus CMin_core_sem tge (CMin_State tfn (Sexit O) tk' (Vptr sp Int.zero) te) tm S m2' /\ Match_cores (CSharpMin_State f (seq_of_lbl_stmt ls) k e lenv) mu' (CSharpMin_State f (seq_of_lbl_stmt ls) k e lenv) m S m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma MS_step_case_Switch: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) a x x0 ts cases n (MK : match_cont k tk cenv xenv cs) (EvalA: Csharpminor.eval_expr ge e lenv m a (Vint n)) (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), exists c2' : CMin_core, exists m2' mu', 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) mu' (CSharpMin_State f (seq_of_lbl_stmt (select_switch n cases)) k e lenv) m c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma Match_corestep: forall st1 m1 st1' m1' (CS1:corestep csharpmin_eff_sem ge st1 m1 st1' m1') st2 mu m2 (MC: Match_cores st1 mu st1 m1 st2 m2), exists st2' m2' mu', intern_incr mu mu' /\ sm_inject_separated mu mu' m1 m2 /\ sm_locally_allocated mu mu' m1 m2 m1' m2' /\ Match_cores st1' mu' st1' m1' st2' m2' /\ SM_wd mu' /\ sm_valid mu' m1' m2' /\ (corestep_plus cmin_eff_sem tge st2 m2 st2' m2' \/ (MC_measure st1' < MC_measure st1)%nat /\ corestep_star cmin_eff_sem tge st2 m2 st2' m2').
Lemma EFF_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, effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State f s k sp e) m (CMin_State f body k' sp e) m).
Lemma EFF_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, effstep_star cmin_eff_sem tge EmptyEffect (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 eff_make_store_correct: forall f sp te tm addr tvaddr rhs tvrhs chunk m vaddr vrhs m' fn k, eval_expr tge sp te tm addr tvaddr -> eval_expr tge sp te tm rhs tvrhs -> Mem.storev chunk m vaddr vrhs = Some m' -> Mem.inject f m tm -> val_inject f vaddr tvaddr -> val_inject f vrhs tvrhs -> exists tm', exists tvrhs', cmin_effstep tge (StoreEffect tvaddr (encode_val chunk tvrhs')) (CMin_State fn (make_store chunk addr rhs) k sp te) tm (CMin_State fn Sskip k sp te) tm' /\ Mem.storev chunk tm tvaddr tvrhs' = Some tm' /\ Mem.inject f m' tm'.
Lemma EFF_step_case_SkipSeq: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kseq s k) tk cenv xenv cs), exists st2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State tfn Sskip tk (Vptr sp Int.zero) te) tm st2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f s k e lenv) mu' (CSharpMin_State f s k e lenv) m st2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_step_case_SkipBlock: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kblock k) tk cenv xenv cs), exists st2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State tfn Sskip tk (Vptr sp Int.zero) te) tm st2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f Csharpminor.Sskip k e lenv) mu' (CSharpMin_State f Csharpminor.Sskip k e lenv) m st2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_match_is_call_cont: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) v (MK: match_cont k tk cenv xenv cs) (CC: Csharpminor.is_call_cont k), exists tk', effstep_star cmin_eff_sem tge EmptyEffect (CMin_State tfn Sskip tk v te) tm (CMin_State tfn Sskip tk' v te) tm /\ is_call_cont tk' /\ match_cont k tk' cenv nil cs.
Lemma EFF_step_case_SkipCall:forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) m' (CC: Csharpminor.is_call_cont k) (FL: Mem.free_list m (blocks_of_env e) = Some m') (MK : match_cont k tk cenv xenv cs), exists st2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge (FreeEffect tm 0 (fn_stackspace tfn) sp) (CMin_State tfn Sskip tk (Vptr sp Int.zero) te) tm st2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m' m2' /\ Match_cores (CSharpMin_Returnstate Vundef k) mu' (CSharpMin_Returnstate Vundef k) m' st2' m2' /\ SM_wd mu' /\ sm_valid mu' m' m2'.
Lemma EFF_step_case_Assign: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) a v id x x0 (EE: Csharpminor.eval_expr ge e lenv m a v) (MK : match_cont k tk cenv xenv cs) (EQ : transl_expr cenv a = OK (x, x0)), exists st2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State tfn (Sassign id x) tk (Vptr sp Int.zero) te) tm st2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f Csharpminor.Sskip k e (PTree.set id v lenv)) mu' (CSharpMin_State f Csharpminor.Sskip k e (PTree.set id v lenv)) m st2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_step_case_Store: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) x x0 x1 x2 chunk m' a addr vaddr v (CH: Mem.storev chunk m vaddr v = Some m') (MK : match_cont k tk cenv xenv cs) (EvAddr : Csharpminor.eval_expr ge e lenv m addr vaddr) (EvA : Csharpminor.eval_expr ge e lenv m a v) (EQ : transl_expr cenv addr = OK (x, x0)) (EQ1 : transl_expr cenv a = OK (x1, x2)), (*exists tv, (eval_expr tge (Vptr sp Int.zero) te tm x1 tv /\ val_inject (restrict (as_inj mu) (vis mu)) v tv /\ val_match_approx x2 v) /\*) exists tv', (eval_expr tge (Vptr sp Int.zero) te tm x tv' /\ val_inject (restrict (as_inj mu) (vis mu)) vaddr tv' /\ val_match_approx x0 vaddr) /\ exists st2' : CMin_core, exists m2' mu', exists vv, effstep_plus cmin_eff_sem tge (StoreEffect tv' (encode_val chunk vv)) (CMin_State tfn (make_store chunk x x1) tk (Vptr sp Int.zero) te) tm st2' m2' /\ Mem.storev chunk tm tv' vv = Some m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m' m2' /\ Match_cores (CSharpMin_State f Csharpminor.Sskip k e lenv) mu' (CSharpMin_State f Csharpminor.Sskip k e lenv) m' st2' m2' /\ SM_wd mu' /\ sm_valid mu' m' m2'.
Lemma EFF_step_case_Call: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) x x0 x1 a vf fd optid vargs bl (MK : match_cont k tk cenv xenv cs) (EvalA: Csharpminor.eval_expr ge e lenv m a vf) (EvalBL: Csharpminor.eval_exprlist ge e lenv m bl vargs) (FF: Genv.find_funct ge vf = Some fd) (EQ : transl_expr cenv a = OK (x, x0)) (EQ1 : transl_exprlist cenv bl = OK x1), exists c2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State tfn (Scall optid (Csharpminor.funsig fd) x x1) tk (Vptr sp Int.zero) te) tm c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_Callstate fd vargs (Csharpminor.Kcall optid f e lenv k)) mu' (CSharpMin_Callstate fd vargs (Csharpminor.Kcall optid f e lenv k)) m c2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_step_case_Ite: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) x x0 x1 x2 b v a s1 s2 (H : Csharpminor.eval_expr ge e lenv m a v) (BoolOfVal : Val.bool_of_val v b) (MK : match_cont k tk cenv xenv cs) (EQ : transl_expr cenv a = OK (x, x0)) (EQ1 : transl_stmt cenv xenv s1 = OK x1) (EQ0 : transl_stmt cenv xenv s2 = OK x2), exists c2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State tfn (Sifthenelse x x1 x2) tk (Vptr sp Int.zero) te) tm c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f (if b then s1 else s2) k e lenv) mu' (CSharpMin_State f (if b then s1 else s2) k e lenv) m c2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_step_case_Loop: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) x s (MK : match_cont k tk cenv xenv cs) (EQ : transl_stmt cenv xenv s = OK x), exists c2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State tfn (Sloop x) tk (Vptr sp Int.zero) te) tm c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f s (Csharpminor.Kseq (Csharpminor.Sloop s) k) e lenv) mu' (CSharpMin_State f s (Csharpminor.Kseq (Csharpminor.Sloop s) k) e lenv) m c2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_step_case_Block: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) x s (MK : match_cont k tk cenv xenv cs) (EQ : transl_stmt cenv (true :: xenv) s = OK x), exists c2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State tfn (Sblock x) tk (Vptr sp Int.zero) te) tm c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ Match_cores (CSharpMin_State f s (Csharpminor.Kblock k) e lenv) mu' (CSharpMin_State f s (Csharpminor.Kblock k) e lenv) m c2' m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_step_case_ExitSeq: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) n s (MK : match_cont (Csharpminor.Kseq s k) tk cenv xenv cs), exists c2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State tfn (Sexit (shift_exit xenv n)) tk (Vptr sp Int.zero) te) tm c2' m2' /\ Match_cores (CSharpMin_State f (Csharpminor.Sexit n) k e lenv) mu' (CSharpMin_State f (Csharpminor.Sexit n) k e lenv) m c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_step_case_ExitBlockZero: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) (MK : match_cont (Csharpminor.Kblock k) tk cenv xenv cs), exists c2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State tfn (Sexit (shift_exit xenv 0)) tk (Vptr sp Int.zero) te) tm c2' m2' /\ Match_cores (CSharpMin_State f Csharpminor.Sskip k e lenv) mu' (CSharpMin_State f Csharpminor.Sskip k e lenv) m c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_step_case_ExitBlockNonzero: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) n (MK : match_cont (Csharpminor.Kblock k) tk cenv xenv cs), exists c2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State tfn (Sexit (shift_exit xenv (S n))) tk (Vptr sp Int.zero) te) tm c2' m2' /\ Match_cores (CSharpMin_State f (Csharpminor.Sexit n) k e lenv) mu' (CSharpMin_State f (Csharpminor.Sexit n) k e lenv) m c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_switch_MSI: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) ts ls body tk' (TR: transl_lblstmt cenv (switch_env ls xenv) ls body = OK ts) (MK: match_cont k tk cenv xenv cs) (TK: transl_lblstmt_cont cenv xenv ls tk tk'), exists S, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_State tfn (Sexit O) tk' (Vptr sp Int.zero) te) tm S m2' /\ Match_cores (CSharpMin_State f (seq_of_lbl_stmt ls) k e lenv) mu' (CSharpMin_State f (seq_of_lbl_stmt ls) k e lenv) m S m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_step_case_Switch: forall (MCS : structured_match_callstack mu m tm (Frame cenv tfn e lenv te sp lo hi :: cs) (Mem.nextblock m) (Mem.nextblock tm)) a x x0 ts cases n (MK : match_cont k tk cenv xenv cs) (EvalA: Csharpminor.eval_expr ge e lenv m a (Vint n)) (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), exists c2' : CMin_core, exists m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (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) mu' (CSharpMin_State f (seq_of_lbl_stmt (select_switch n cases)) k e lenv) m c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m m2' /\ SM_wd mu' /\ sm_valid mu' m m2'.
Lemma EFF_step_case_InternalCall: forall (MCS : structured_match_callstack mu m tm cs (Mem.nextblock m) (Mem.nextblock tm)) (PRE: REACH_closed m (vis mu) /\ meminj_preserves_globals ge (as_inj mu) /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu b = true) /\ sm_valid mu m tm /\ SM_wd mu /\ Mem.inject (as_inj mu) m tm) vargs targs x m1 (Param1: list_norepet (map fst (Csharpminor.fn_vars f))) (Param2 : list_norepet (Csharpminor.fn_params f)) (Param3 : list_disjoint (Csharpminor.fn_params f) (fn_temps f)) (AlocVars : alloc_variables empty_env m (Csharpminor.fn_vars f) e m1) (BindParams: bind_parameters (Csharpminor.fn_params f) vargs (create_undef_temps (fn_temps f)) = Some lenv) (MK : match_cont k tk cenv nil cs) (ISCC : Csharpminor.is_call_cont k) (ARGSINJ : val_list_inject (restrict (as_inj mu) (vis mu)) vargs targs) (EQ : transl_function f = OK x), exists (c2' : CMin_core) m2' mu', effstep_plus cmin_eff_sem tge EmptyEffect (CMin_Callstate (AST.Internal x) targs tk) tm c2' m2' /\ intern_incr mu mu' /\ sm_inject_separated mu mu' m tm /\ sm_locally_allocated mu mu' m tm m1 m2' /\ SM_wd mu' /\ sm_valid mu' m1 m2' /\ Match_cores (CSharpMin_State f (Csharpminor.fn_body f) k e lenv) mu' (CSharpMin_State f (Csharpminor.fn_body f) k e lenv) m1 c2' m2'.
Lemma Match_effcore_diagram: forall st1 m1 st1' m1' (U1 : Values.block -> Z -> bool) (EFFSTEP: effstep csharpmin_eff_sem ge U1 st1 m1 st1' m1') st2 mu m2 (UHyp: forall b ofs, U1 b ofs = true -> Mem.valid_block m1 b -> vis mu b = true) (MC: Match_cores st1 mu st1 m1 st2 m2), exists st2' m2' mu', intern_incr mu mu' /\ sm_inject_separated mu mu' m1 m2 /\ sm_locally_allocated mu mu' m1 m2 m1' m2' /\ Match_cores st1' mu' st1' m1' st2' m2' /\ (exists U2 : Values.block -> Z -> bool, (effstep_plus cmin_eff_sem tge U2 st2 m2 st2' m2' \/ (MC_measure st1' < MC_measure st1)%nat /\ effstep_star cmin_eff_sem tge U2 st2 m2 st2' m2') /\ (forall (b : Values.block) (ofs : Z), U2 b ofs = true -> Mem.valid_block m2 b /\ (locBlocksTgt mu b = false -> exists (b1 : Values.block) (delta1 : Z), foreign_of mu b1 = Some (b, delta1) /\ U1 b1 (ofs - delta1) = true /\ Mem.perm m1 b1 (ofs - delta1) Max Nonempty))).
Theorem transl_program_correct: forall (R: list_norepet (map fst (prog_defs prog))) entrypoints (entry_points_ok : forall v1 v2 sig, In (v1, v2, sig) entrypoints -> exists b f1 f2, v1 = Vptr b Int.zero /\ v2 = Vptr b Int.zero /\ Genv.find_funct_ptr ge b = Some f1 /\ Genv.find_funct_ptr tge b = Some f2) (init_mem: exists m0, Genv.init_mem prog = Some m0), SM_simulation.SM_simulation_inject csharpmin_eff_sem cmin_eff_sem ge tge entrypoints.