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 REACH_is_closed: forall R m1,
REACH_closed m1 (fun b : block => REACH m1 R b).
(*Generic proof that the inital structured injection satisfies the match_genv, match_wd and match_valid conditions of the LSR*)
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)).
(*Proof the match_genv is preserved by callsteps*)
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).
(*Proof the match_genv is preserved by callsteps*)
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).