Section PRESERVATION.
Variable prog: program.
Variable tprog: program.
Hypothesis TRANSF: match_prog prog tprog.
Let ge := globalenv prog.
Let tge := globalenv tprog.
Proof (Genv.find_symbol_match (proj1 TRANSF)).
Proof (Genv.senv_match (proj1 TRANSF)).
Proof (Genv.find_funct_transf_partial (proj1 TRANSF)).
Proof (Genv.find_funct_ptr_transf_partial (proj1 TRANSF)).
(** Matching between environments before and after *)
Inductive match_var (f: meminj) (cenv: compilenv) (e: env) (m: mem) (te: env) (tle: temp_env) (id: ident) : Prop :=
| match_var_lifted: forall b ty chunk v tv
(ENV: e!id = Some(b, ty))
(TENV: te!id = None)
(LIFTED: VSet.mem id cenv = true)
(MAPPED: f b = None)
(MODE: access_mode ty = By_value chunk)
(LOAD: Mem.load chunk m b 0 = Some v)
(TLENV: tle!(id) = Some tv)
(VINJ: Val.inject f v tv),
match_var f cenv e m te tle id
| match_var_not_lifted: forall b ty b'
(ENV: e!id = Some(b, ty))
(TENV: te!id = Some(b', ty))
(LIFTED: VSet.mem id cenv = false)
(MAPPED: f b = Some(b', 0)),
match_var f cenv e m te tle id
| match_var_not_local: forall
(ENV: e!id = None)
(TENV: te!id = None)
(LIFTED: VSet.mem id cenv = false),
match_var f cenv e m te tle id.
Record match_envs (f: meminj) (cenv: compilenv)
(e: env) (le: temp_env) (m: mem) (lo hi: block)
(te: env) (tle: temp_env) (tlo thi: block) : Prop :=
mk_match_envs {
me_vars:
forall id, match_var f cenv e m te tle id;
me_temps:
forall id v,
le!id = Some v ->
(exists tv, tle!id = Some tv /\ Val.inject f v tv)
/\ (VSet.mem id cenv = true -> v = Vundef);
me_inj:
forall id1 b1 ty1 id2 b2 ty2, e!id1 = Some(b1, ty1) -> e!id2 = Some(b2, ty2) -> id1 <> id2 -> b1 <> b2;
me_range:
forall id b ty, e!id = Some(b, ty) -> Ple lo b /\ Plt b hi;
me_trange:
forall id b ty, te!id = Some(b, ty) -> Ple tlo b /\ Plt b thi;
me_mapped:
forall id b' ty,
te!id = Some(b', ty) -> exists b, f b = Some(b', 0) /\ e!id = Some(b, ty);
me_flat:
forall id b' ty b delta,
te!id = Some(b', ty) -> f b = Some(b', delta) -> e!id = Some(b, ty) /\ delta = 0;
me_incr:
Ple lo hi;
me_tincr:
Ple tlo thi
}.
(** Invariance by change of memory and injection *)
(** Invariance by external call *)
(** Properties of values resulting from a cast *)
Inductive val_casted_list: list val -> typelist -> Prop :=
| vcl_nil:
val_casted_list nil Tnil
| vcl_cons: forall v1 vl ty1 tyl,
val_casted v1 ty1 -> val_casted_list vl tyl ->
val_casted_list (v1 :: vl) (Tcons  ty1 tyl).
(** Correctness of [make_cast] *)
(** Debug annotations. *)
Remark bind_parameter_temps_inv:
forall id params args le le',
bind_parameter_temps params args le = Some le' ->
~In id (var_names params) ->
le'!id = le!id.
(** Preservation by assignment to lifted variable. *)
(** Preservation by assignment to a temporary *)
(** Extensionality with respect to temporaries *)
(** Invariance by assignment to an irrelevant temporary *)
(** Properties of [cenv_for]. *)
Definition cenv_for_gen (atk: VSet.t) (vars: list (ident * type)) : compilenv :=
List.fold_right (add_local_variable atk) VSet.empty vars.
Remark add_local_variable_charact:
forall id ty atk cenv id1,
VSet.In id1 (add_local_variable atk (id, ty) cenv) <->
VSet.In id1 cenv \/ exists chunk, access_mode ty = By_value chunk /\ id = id1 /\ VSet.mem id atk = false.
(** Compatibility between a compilation environment and an address-taken set. *)
Definition compat_cenv (atk: VSet.t) (cenv: compilenv) : Prop :=
forall id, VSet.In id atk -> VSet.In id cenv -> False.
Hint Resolve compat_cenv_union_l compat_cenv_union_r compat_cenv_empty: compat.
(** Allocation and initialization of parameters *)

Lemma match_alloc_variables:
forall cenv e m vars e' m',
alloc_variables ge e m vars e' m' ->
forall j tm te,
list_norepet (var_names vars) ->
Mem.inject j m tm ->
exists j', exists te', exists tm',
alloc_variables tge te tm (remove_lifted cenv vars) te' tm'
/\ Mem.inject j' m' tm'
/\ inject_incr j j'
/\ (forall b, Mem.valid_block m b -> j' b = j b)
/\ (forall b b' delta, j' b = Some(b', delta) -> Mem.valid_block tm b' -> j' b = j b)
/\ (forall b b' delta, j' b = Some(b', delta) -> ~Mem.valid_block tm b' ->
exists id, exists ty, e'!id = Some(b, ty) /\ te'!id = Some(b', ty) /\ delta = 0)
/\ (forall id ty, In (id, ty) vars ->
exists b,
e'!id = Some(b, ty)
/\ if VSet.mem id cenv
then te'!id = te!id /\ j' b = None
else exists tb, te'!id = Some(tb, ty) /\ j' b = Some(tb, 0))
/\ (forall id, ~In id (var_names vars) -> e'!id = e!id /\ te'!id = te!id).