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 *)
Definition env_initial_value (e: env) (m: mem) :=
forall id b ty chunk,
e!id = Some(b, ty) -> access_mode ty = By_value chunk -> Mem.load chunk m b 0 = Some Vundef.
Remark var_names_app:
forall vars1 vars2, var_names (vars1 ++ vars2) = var_names vars1 ++ var_names vars2.
Remark filter_app:
forall (A: Type) (f: A -> bool) l1 l2,
List.filter f (l1 ++ l2) = List.filter f l1 ++ List.filter f l2.
Remark filter_charact:
forall (A: Type) (f: A -> bool) x l,
In x (List.filter f l) <-> In x l /\ f x = true.
Remark filter_norepet:
forall (A: Type) (f: A -> bool) l,
list_norepet l -> list_norepet (List.filter f l).
Remark filter_map:
forall (A B: Type) (f: A -> B) (pa: A -> bool) (pb: B -> bool),
(forall a, pb (f a) = pa a) ->
forall l, List.map f (List.filter pa l) = List.filter pb (List.map f l).

Lemma vars_and_temps_properties:
forall cenv params vars temps,
list_norepet (var_names params ++ var_names vars) ->
list_disjoint (var_names params) (var_names temps) ->
list_norepet (var_names params)
/\ list_norepet (var_names (remove_lifted cenv (params ++ vars)))
/\ list_disjoint (var_names params) (var_names (add_lifted cenv vars temps)).