(*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*).

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.