Definition local_out_of_reach mu (m : mem) (b : block) (ofs : Z): Prop :=
  locBlocksTgt mu b = true /\
  forall b0 delta, local_of mu b0 = Some (b, delta) ->
                  (~ Mem.perm m b0 (ofs - delta) Max Nonempty \/
                   pubBlocksSrc mu b0 = false).

(* Specifications: *)
Lemma genvs_domain_eq_match_genvsB: forall {F1 V1 F2 V2:Type} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2), genvs_domain_eq ge1 ge2 -> genv2blocksBool ge1 = genv2blocksBool ge2.
Lemma genv2blocksBool_char1: forall F V (ge : Genv.t F V) b, (fst (genv2blocksBool ge)) b = true <-> fst (genv2blocks ge) b.
Lemma genv2blocksBool_char2: forall F V (ge : Genv.t F V) b, (snd (genv2blocksBool ge)) b = true <-> snd (genv2blocks ge) b.
Lemma genv2blocksBool_char1': forall F V (ge : Genv.t F V) b, (fst (genv2blocksBool ge)) b = false <-> ~ fst (genv2blocks ge) b.
Lemma genv2blocksBool_char2': forall F V (ge : Genv.t F V) b, (snd (genv2blocksBool ge)) b = false <-> ~ snd (genv2blocks ge) b.
Lemma restrict_preserves_globals: forall {F V} (ge:Genv.t F V) j X (PG : meminj_preserves_globals ge j) (Glob : forall b, isGlobalBlock ge b = true -> X b = true), meminj_preserves_globals ge (restrict j X).
Lemma genvs_domain_eq_isGlobal: forall {F1 V1 F2 V2} ge1 ge2 (DomainEQ: @genvs_domain_eq F1 V1 F2 V2 ge1 ge2), isGlobalBlock ge1 = isGlobalBlock ge2.
Lemma meminj_preserves_globals_isGlobalBlock: forall {F V} (g: Genv.t F V) j (PG: meminj_preserves_globals g j) b (GB: isGlobalBlock g b = true), j b = Some (b, 0).
Lemma meminj_preserves_globals_initSM: forall {F1 V1} (ge: Genv.t F1 V1) j (PG : meminj_preserves_globals ge j) DomS DomT X Y, meminj_preserves_globals ge (extern_of (initial_SM DomS DomT X Y j)).
Lemma meminj_preserves_globals_init_REACH_frgn: forall {F1 V1} (ge: Genv.t F1 V1) j (PG : meminj_preserves_globals ge j) DomS DomT m R Y (HR: forall b, isGlobalBlock ge b = true -> R b = true), (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc (initial_SM DomS DomT (REACH m R) Y j) b = true).
Lemma REACH_is_closed: forall R m1, REACH_closed m1 (fun b : block => REACH m1 R b).
Lemma core_initial_wd : forall {F1 V1 F2 V2} (ge1: Genv.t F1 V1) (ge2: Genv.t F2 V2) vals1 m1 j vals2 m2 DomS DomT (MInj: Mem.inject j m1 m2) (VInj: Forall2 (val_inject j) vals1 vals2) (HypJ: forall b1 b2 d, j b1 = Some (b2, d) -> DomS b1 = true /\ DomT b2 = true) (R: forall b, REACH m2 (fun b' => isGlobalBlock ge2 b' || getBlocks vals2 b') b = true -> DomT b = true) (PG: meminj_preserves_globals ge1 j) (GenvsDomEQ: genvs_domain_eq ge1 ge2) (HS: forall b, DomS b = true -> Mem.valid_block m1 b) (HT: forall b, DomT b = true -> Mem.valid_block m2 b) mu (Hmu: mu = initial_SM DomS DomT (REACH m1 (fun b => isGlobalBlock ge1 b || getBlocks vals1 b)) (REACH m2 (fun b => isGlobalBlock ge2 b || getBlocks vals2 b)) j), (forall b, REACH m1 (fun b' => isGlobalBlock ge1 b' || getBlocks vals1 b') b = true -> DomS b = true) /\ SM_wd mu /\ sm_valid mu m1 m2 /\ meminj_preserves_globals ge1 (extern_of mu) /\ (forall b, isGlobalBlock ge1 b = true -> frgnBlocksSrc mu b = true) /\ REACH_closed m1 (vis mu) /\ REACH_closed m1 (mapped (as_inj mu)).
Lemma intern_incr_meminj_preserves_globals: forall {F V} (ge: Genv.t F V) mu (PG: meminj_preserves_globals ge (extern_of mu) /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu b = true)) mu' (Inc: intern_incr mu mu'), meminj_preserves_globals ge (extern_of mu') /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu' b = true).
Lemma replace_externs_meminj_preserves_globals: forall {F V} (ge: Genv.t F V) nu (PG: meminj_preserves_globals ge (extern_of nu) /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc nu b = true)) mu fSrc fTgt (Hyp: mu = replace_externs nu fSrc fTgt) (FRG: forall b, frgnBlocksSrc nu b = true -> fSrc b = true), meminj_preserves_globals ge (extern_of mu) /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu b = true).
Lemma after_external_meminj_preserves_globals: forall {F V} (ge: Genv.t F V) mu (WDmu : SM_wd mu) (PG: meminj_preserves_globals ge (extern_of mu) /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu b = true)) nu pubSrc' pubTgt' vals1 m1 (pubSrcHyp: pubSrc' = fun b => andb (locBlocksSrc mu b) (REACH m1 (exportedSrc mu vals1) b)) (Hnu: nu = replace_locals mu pubSrc' pubTgt') nu' (WDnu' : SM_wd nu') (INC: extern_incr nu nu') m2 (SMV: sm_valid mu m1 m2) (SEP: sm_inject_separated nu nu' m1 m2) frgnSrc' ret1 m1' (frgnSrcHyp: frgnSrc' = fun b => andb (DomSrc nu' b) (andb (negb (locBlocksSrc nu' b)) (REACH m1' (exportedSrc nu' (ret1::nil)) b))) frgnTgt' ret2 m2' (frgnTgtHyp: frgnTgt' = fun b => andb (DomTgt nu' b) (andb (negb (locBlocksTgt nu' b)) (REACH m2' (exportedTgt nu' (ret2::nil)) b))) mu' (Mu'Hyp: mu' = replace_externs nu' frgnSrc' frgnTgt'), meminj_preserves_globals ge (extern_of mu') /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu' b = true).
Lemma restrict_SharedSrc mu: SM_wd mu -> restrict (as_inj mu) (sharedSrc mu) = shared_of mu.
Lemma restrict_vis_foreign_local mu: forall (WD: SM_wd mu), restrict (as_inj mu) (vis mu) = join (foreign_of mu) (local_of mu).