Section TRANSLATION.
Variable prog: Csharpminor.program.
Variable tprog: Cminor.program.
Hypothesis TRANSL: transl_program prog = OK tprog.
Let ge : Csharpminor.genv := Genv.globalenv prog.
Let tge: genv := Genv.globalenv tprog.
Let core_data := CSharpMin_core.
Record match_env (f: meminj) (cenv: compilenv)
(e: Csharpminor.env) (sp: Values.block)
(lo hi: Values.block) : Prop :=
mk_match_env {
(** C#minor local variables match sub-blocks of the Cminor stack data block. *)
me_vars:
forall id, match_var f sp (e!id) (cenv!id);
(** [lo, hi] is a proper interval. *)
me_low_high:
Ple lo hi;
(** Every block appearing in the C#minor environment [e] must be in the range [lo, hi]. *)
me_bounded:
forall id b sz, PTree.get id e = Some(b, sz) -> Ple lo b /\ Plt b hi;
(** All blocks mapped to sub-blocks of the Cminor stack data must be images of variables from the C#minor environment [e] *)
me_inv:
forall b delta,
f b = Some(sp, delta) ->
exists id, exists sz, PTree.get id e = Some(b, sz)
(*LENB: MOVED TO structured_match_callstack below me_incr: forall b tb delta, f b = Some(tb, delta) -> Plt b lo -> Plt tb sp*)
}.
Ltac geninv x :=
let H := fresh in (generalize x; intro H; inv H).
Remark inject_incr_separated_same:
forall f1 f2 m1 m1',
inject_incr f1 f2 -> inject_separated f1 f2 m1 m1' ->
forall b, Mem.valid_block m1 b -> f2 b = f1 b.
Remark inject_incr_separated_same':
forall f1 f2 m1 m1',
inject_incr f1 f2 -> inject_separated f1 f2 m1 m1' ->
forall b b' delta,
f2 b = Some(b', delta) -> Mem.valid_block m1' b' -> f1 b = Some(b', delta).
Inductive structured_match_callstack mu (m: mem) (tm: mem):
callstack -> Values.block -> Values.block -> Prop :=
| st_mcs_nil:
forall hi bound tbound,
match_globalenvs prog (restrict (as_inj mu) (vis mu)) hi ->
Ple hi bound -> Ple hi tbound ->
structured_match_callstack mu m tm nil bound tbound
| st_mcs_cons:
forall cenv tf e le te sp lo hi cs bound tbound
(BOUND: Ple hi bound)
(TBOUND: Plt sp tbound)
(MTMP: match_temps (restrict (as_inj mu) (vis mu)) le te)
(MENV: match_env (restrict (as_inj mu) (vis mu)) cenv e sp lo hi)
(BOUND: match_bounds e m)
(PERM: padding_freeable (restrict (as_inj mu) (vis mu)) e tm sp tf.(fn_stackspace))
(SPlocal: locBlocksTgt mu sp = true) (*NEW*)
(*LENB: Here is the condition me_incr from match_env above, but we assert it on the entire as_inj mu*)
(ME_INCR: forall b tb delta,
(as_inj mu) b = Some(tb, delta) -> Plt b lo -> Plt tb sp)
(MCS: structured_match_callstack mu m tm cs lo sp),
structured_match_callstack mu m tm (Frame cenv tf e le te sp lo hi :: cs) bound tbound.
(*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). *)
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_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'.