(** 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 *)

Lemma match_envs_invariant:
forall f cenv e le m lo hi te tle tlo thi f' m',
match_envs f cenv e le m lo hi te tle tlo thi ->
(forall b chunk v,
f b = None -> Ple lo b /\ Plt b hi -> Mem.load chunk m b 0 = Some v -> Mem.load chunk m' b 0 = Some v) ->
inject_incr f f' ->
(forall b, Ple lo b /\ Plt b hi -> f' b = f b) ->
(forall b b' delta, f' b = Some(b', delta) -> Ple tlo b' /\ Plt b' thi -> f' b = f b) ->
match_envs f' cenv e le m' lo hi te tle tlo thi.