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.

Lemma structured_match_callstack_ext: forall mu m1 m2 cs bound
tbound
(MCS : structured_match_callstack mu m1 m2 cs bound tbound)
m1' (FwdSrc : mem_forward m1 m1')
nu vals1 vals2
(Hnu: nu = replace_locals mu
(fun b0 : Values.block =>
locBlocksSrc mu b0 &&
REACH m1 (exportedSrc mu vals1) b0)
(fun b0 : Values.block =>
locBlocksTgt mu b0 &&
REACH m2 (exportedTgt mu vals2) b0))
(SMvalMu : sm_valid mu m1 m2)
(PG : meminj_preserves_globals (Genv.globalenv prog) (as_inj mu))
nu' (INC : extern_incr nu nu')
(SEP : sm_inject_separated nu nu' m1 m2)
(UNMAPPED : Mem.unchanged_on
(fun (b : Values.block) (_ : Z) =>
locBlocksSrc nu b = true /\ pubBlocksSrc nu b = false) m1
m1')
m2' (FwdTgt : mem_forward m2 m2') (OUTOFREACH : Mem.unchanged_on (local_out_of_reach nu m1) m2 m2')
ret1 ret2 (WDnu' : SM_wd nu') (WDmu : SM_wd mu) (WDnu : SM_wd nu)
(BND: Ple bound (Mem.nextblock m1))
(TBND:Ple tbound (Mem.nextblock m2)),
structured_match_callstack
(replace_externs nu'
(fun b : Values.block =>
DomSrc nu' b &&
(negb (locBlocksSrc nu' b) && REACH m1' (exportedSrc nu' (ret1 :: nil)) b))
(fun b : Values.block =>
DomTgt nu' b &&
(negb (locBlocksTgt nu' b) && REACH m2' (exportedTgt nu' (ret2 :: nil)) b)))
m1' m2' cs bound tbound.