Definition genvs_domain_eq {F1 F2 V1 V2: Type} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2) :=
  (forall b, fst (genv2blocks ge1) b <-> fst (genv2blocks ge2) b) /\
  (forall b, snd (genv2blocks ge1) b <-> snd (genv2blocks ge2) b).

(* Specifications: *)
Lemma genvs_domain_eq_preserves: forall {F1 F2 V1 V2: Type} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2) j, genvs_domain_eq ge1 ge2 -> (meminj_preserves_globals_ind (genv2blocks ge1) j <-> meminj_preserves_globals_ind (genv2blocks ge2) j).
Lemma genvs_domain_eq_sym: forall {F1 F2 V1 V2: Type} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2), genvs_domain_eq ge1 ge2 -> genvs_domain_eq ge2 ge1.
Lemma genvs_domain_eq_refl: forall F V (ge: Genv.t F V), genvs_domain_eq ge ge.
Lemma genvs_domain_eq_trans: forall {F1 F2 F3 V1 V2 V3: Type} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2) (ge3: Genv.t F3 V3), genvs_domain_eq ge1 ge2 -> genvs_domain_eq ge2 ge3 -> genvs_domain_eq ge1 ge3.
Lemma genvs_domain_eq_match_genvs: forall {F1 V1 F2 V2:Type} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2), genvs_domain_eq ge1 ge2 -> genv2blocks ge1 = genv2blocks ge2.
Lemma meminj_preserves_globals_ind_compose: forall {F1 V1 F2 V2} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2) j1 j2 (G: genvs_domain_eq ge1 ge2) (PG1: meminj_preserves_globals_ind (genv2blocks ge1) j1) (PG2: meminj_preserves_globals_ind (genv2blocks ge2) j2), meminj_preserves_globals_ind (genv2blocks ge1) (compose_meminj j1 j2).
Lemma meminj_preserves_incr_sep: forall {F V:Type} ge j (PG: @meminj_preserves_globals F V ge j) m tm (MINJ : Mem.inject j m tm) j' (INCR : inject_incr j j') (SEP: inject_separated j j' m tm), meminj_preserves_globals ge j'.
Lemma meminj_preserves_incr_sep_vb: forall {F V:Type} ge j (PG: @meminj_preserves_globals F V ge j) m tm (VB: forall b1 b2 ofs, j b1 = Some(b2,ofs) -> (Mem.valid_block m b1 /\ Mem.valid_block tm b2)) j' (INCR : inject_incr j j') (SEP: inject_separated j j' m tm), meminj_preserves_globals ge j'.
Lemma forward_unchanged_on: forall m m' (FWD: mem_forward m m') b ofs (P: ~ Mem.perm m b ofs Max Nonempty), Mem.unchanged_on (fun b' ofs' => b' = b /\ ofs' = ofs) m m'.
Lemma unchanged_on_union: forall m m' P Q (HP: Mem.unchanged_on P m m') (HQ: Mem.unchanged_on Q m m') (PQ: block -> Z -> Prop) (HPQ: forall b ofs, PQ b ofs -> P b ofs \/ Q b ofs), Mem.unchanged_on PQ m m'.
Lemma unchanged_on_validblock: forall m m' (U V: Values.block -> Z -> Prop) (UV: forall b ofs, Mem.valid_block m b -> (U b ofs -> V b ofs)), Mem.unchanged_on V m m' -> Mem.unchanged_on U m m'.
Lemma unchanged_on_validblock_invariant: forall m m' U V (UV: forall b ofs, Mem.valid_block m b -> (U b ofs <-> V b ofs)), Mem.unchanged_on V m m' <-> Mem.unchanged_on U m m'.
Lemma unchanged_on_perm_intersection: forall m m' U (Fwd: mem_forward m m'), Mem.unchanged_on U m m' <-> Mem.unchanged_on (fun b z => U b z /\ Mem.perm m b z Max Nonempty) m m'.
Lemma unchanged_on_trans: forall m1 m2 m3 U (U1: Mem.unchanged_on U m1 m2) (U2: Mem.unchanged_on U m2 m3) (Fwd12: mem_forward m1 m2), Mem.unchanged_on U m1 m3.
Lemma genvs_domain_eq_preserves: forall {F1 F2 V1 V2: Type} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2) j, genvs_domain_eq ge1 ge2 -> (meminj_preserves_globals_ind (genv2blocks ge1) j <-> meminj_preserves_globals_ind (genv2blocks ge2) j).
Lemma genvs_domain_eq_sym: forall {F1 F2 V1 V2: Type} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2), genvs_domain_eq ge1 ge2 -> genvs_domain_eq ge2 ge1.
Lemma genvs_domain_eq_refl: forall F V (ge: Genv.t F V), genvs_domain_eq ge ge.
Lemma genvs_domain_eq_trans: forall {F1 F2 F3 V1 V2 V3: Type} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2) (ge3: Genv.t F3 V3), genvs_domain_eq ge1 ge2 -> genvs_domain_eq ge2 ge3 -> genvs_domain_eq ge1 ge3.
Lemma genvs_domain_eq_match_genvs: forall {F1 V1 F2 V2:Type} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2), genvs_domain_eq ge1 ge2 -> genv2blocks ge1 = genv2blocks ge2.
Lemma meminj_preserves_globals_ind_compose: forall {F1 V1 F2 V2} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2) j1 j2 (G: genvs_domain_eq ge1 ge2) (PG1: meminj_preserves_globals_ind (genv2blocks ge1) j1) (PG2: meminj_preserves_globals_ind (genv2blocks ge2) j2), meminj_preserves_globals_ind (genv2blocks ge1) (compose_meminj j1 j2).
Lemma meminj_preserves_incr_sep: forall {F V:Type} ge j (PG: @meminj_preserves_globals F V ge j) m tm (MINJ : Mem.inject j m tm) j' (INCR : inject_incr j j') (SEP: inject_separated j j' m tm), meminj_preserves_globals ge j'.
Lemma meminj_preserves_incr_sep_vb: forall {F V:Type} ge j (PG: @meminj_preserves_globals F V ge j) m tm (VB: forall b1 b2 ofs, j b1 = Some(b2,ofs) -> (Mem.valid_block m b1 /\ Mem.valid_block tm b2)) j' (INCR : inject_incr j j') (SEP: inject_separated j j' m tm), meminj_preserves_globals ge j'.