Section TRANSLATION.
Variable prog: Csharpminor.program.
Variable tprog: program.
Hypothesis TRANSL: match_prog prog tprog.
Let ge : Csharpminor.genv := Genv.globalenv prog.
Let tge: genv := Genv.globalenv tprog.
Proof (Genv.find_symbol_transf_partial TRANSL).
Proof (Genv.senv_transf_partial TRANSL).
Proof (Genv.find_funct_ptr_transf_partial TRANSL).
Proof (Genv.find_funct_transf_partial TRANSL).
(** * Derived properties of memory operations *)
(** * Correspondence between C#minor's and Cminor's environments and memory states *)
(** In C#minor, every variable is stored in a separate memory block. In the corresponding Cminor code, these variables become sub-blocks of the stack data block.  We capture these changes in memory via a memory injection [f]: [f b = Some(b', ofs)] means that C#minor block [b] corresponds to a sub-block of Cminor block [b] at offset [ofs].  A memory injection [f] defines a relation [Val.inject f] between values and a relation [Mem.inject f] between memory states.  These relations will be used intensively in our proof of simulation between C#minor and Cminor executions. *)
(** ** Matching between Cshaprminor's temporaries and Cminor's variables *)
Definition match_temps (f: meminj) (le: Csharpminor.temp_env) (te: env) : Prop :=
forall id v, le!id = Some v -> exists v', te!(id) = Some v' /\ Val.inject f v v'.
(** ** Matching between C#minor's variable environment and Cminor's stack pointer *)
Inductive match_var (f: meminj) (sp: block): option (block * Z) -> option Z -> Prop :=
| match_var_local: forall b sz ofs,
Val.inject f (Vptr b Ptrofs.zero) (Vptr sp (Ptrofs.repr ofs)) ->
match_var f sp (Some(b, sz)) (Some ofs)
| match_var_global:
match_var f sp None None.
(** Matching between a C#minor environment [e] and a Cminor stack pointer [sp]. The [lo] and [hi] parameters delimit the range of addresses for the blocks referenced from [te]. *)
Record match_env (f: meminj) (cenv: compilenv)
(e: Csharpminor.env) (sp: block)
(lo hi: 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);
(** All C#minor blocks below [lo] (i.e. allocated before the blocks referenced from [e]) must map to blocks that are below [sp] (i.e. allocated before the stack data for the current Cminor function). *)
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).
(** [match_env] and external calls *)
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).
(** [match_env] and allocations *)
(** The sizes of blocks appearing in [e] are respected. *)
Definition match_bounds (e: Csharpminor.env) (m: mem) : Prop :=
forall id b sz ofs p,
PTree.get id e = Some(b, sz) -> Mem.perm m b ofs Max p -> 0 <= ofs < sz.
(** ** Permissions on the Cminor stack block *)
(** The parts of the Cminor stack data block that are not images of C#minor local variable blocks remain freeable at all times. *)
Inductive is_reachable_from_env (f: meminj) (e: Csharpminor.env) (sp: block) (ofs: Z) : Prop :=
| is_reachable_intro: forall id b sz delta,
e!id = Some(b, sz) ->
f b = Some(sp, delta) ->
delta <= ofs < delta + sz ->
is_reachable_from_env f e sp ofs.
Definition padding_freeable (f: meminj) (e: Csharpminor.env) (tm: mem) (sp: block) (sz: Z) : Prop :=
forall ofs,
0 <= ofs < sz -> Mem.perm tm sp ofs Cur Freeable \/ is_reachable_from_env f e sp ofs.

Lemma padding_freeable_invariant:
forall f1 e tm1 sp sz cenv lo hi f2 tm2,
padding_freeable f1 e tm1 sp sz ->
match_env f1 cenv e sp lo hi ->
(forall ofs, Mem.perm tm1 sp ofs Cur Freeable -> Mem.perm tm2 sp ofs Cur Freeable) ->
(forall b, Plt b hi -> f2 b = f1 b) ->
padding_freeable f2 e tm2 sp sz.