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

Lemma match_env_external_call:
forall f1 cenv e sp lo hi f2 m1 m1' (WD2: SM_wd f2),
match_env (restrict (as_inj f1) (vis f1)) cenv e sp lo hi ->
extern_incr f1 f2 ->
inject_separated (restrict (as_inj f1) (vis f1)) (as_inj f2) m1 m1' ->
Ple hi (Mem.nextblock m1) -> Plt sp (Mem.nextblock m1') ->
match_env (as_inj f2) cenv e sp lo hi.