Inductive match_freelists (j:meminj): list (block * Z * Z) -> list (block * Z * Z) -> Prop :=
  match_freelists_nil: match_freelists j nil nil
| match_freelists_cons: forall b1 lo1 hi1 t1 b2 lo2 hi2 t2 delta,
        j b1 = Some (b2,delta) ->
        lo2 = lo1+delta -> hi2 = hi1+delta ->
        match_freelists j t1 t2 ->
        match_freelists j ((b1,lo1,hi1)::t1) ((b2,lo2,hi2)::t2).Inductive match_freelists (j:meminj): list (block * Z * Z) -> list (block * Z * Z) -> Prop :=
  match_freelists_nil: match_freelists j nil nil
| match_freelists_cons: forall b1 lo1 hi1 t1 b2 lo2 hi2 t2 delta,
        j b1 = Some (b2,delta) ->
        lo2 = lo1+delta -> hi2 = hi1+delta ->
        match_freelists j t1 t2 ->
        match_freelists j ((b1,lo1,hi1)::t1) ((b2,lo2,hi2)::t2).Inductive match_freelists (j:meminj): list (block * Z * Z) -> list (block * Z * Z) -> Prop :=
  match_freelists_nil: match_freelists j nil nil
| match_freelists_cons: forall b1 lo1 hi1 t1 b2 lo2 hi2 t2 delta,
        j b1 = Some (b2,delta) ->
        lo2 = lo1+delta -> hi2 = hi1+delta ->
        match_freelists j t1 t2 ->
        match_freelists j ((b1,lo1,hi1)::t1) ((b2,lo2,hi2)::t2).

(* Specifications: *)
Lemma freelist_freelist_inject : forall f l1 l2 (F: match_freelists f l1 l2) m1 m1' m2 m2' (INJ: Mem.inject f m1 m2) (FREE1: Mem.free_list m1 l1 = Some m1') (FREE2: Mem.free_list m2 l2 = Some m2'), Mem.inject f m1' m2'.
Lemma FreeEffect_PropagateLeft: forall m sp lo hi m' (FREE : Mem.free m sp lo hi = Some m') mu m2 (SMV : sm_valid mu m m2) (WD: SM_wd mu) spb' (AI: as_inj mu sp = Some (spb', 0)) (VIS : vis mu sp = true) b2 ofs (EFF : FreeEffect m2 lo hi spb' b2 ofs = true) (LB: locBlocksTgt mu b2 = false), exists b1 delta, foreign_of mu b1 = Some (b2, delta) /\ FreeEffect m lo hi sp b1 (ofs - delta) = true /\ Mem.perm m b1 (ofs - delta) Max Nonempty.
Lemma match_genv_meminj_preserves_globals_extern_implies_foreign: 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)), meminj_preserves_globals ge (foreign_of mu).
Lemma match_genv_meminj_preserves_extern_iff_all: forall {F V} (ge: Genv.t F V) mu (WDmu : SM_wd mu) (GF: forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu b = true), meminj_preserves_globals ge (as_inj mu) <-> meminj_preserves_globals ge (extern_of mu).
Lemma meminj_preserves_globals_initSM_all: forall {F1 V1} (ge: Genv.t F1 V1) j (PG : meminj_preserves_globals ge j) DomS DomT X Y, meminj_preserves_globals ge (as_inj (initial_SM DomS DomT X Y j)).
Lemma meminj_preserves_globals_initSM_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), meminj_preserves_globals ge (foreign_of (initial_SM DomS DomT (REACH m R) Y j)).
Lemma core_initial_wd_as_inj : 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 (as_inj mu) /\ (forall b, isGlobalBlock ge1 b = true -> frgnBlocksSrc mu b = true).
Lemma intern_incr_meminj_preserves_globals_frgn: forall {F V} (ge: Genv.t F V) mu (PG: meminj_preserves_globals ge (foreign_of mu)) mu' (Inc: intern_incr mu mu'), meminj_preserves_globals ge (foreign_of mu').
Lemma intern_incr_meminj_preserves_globals_as_inj: forall {F V} (ge: Genv.t F V) mu (WDmu: SM_wd mu) (PG: meminj_preserves_globals ge (as_inj mu) /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu b = true)) mu' (WDmu': SM_wd mu') (Inc: intern_incr mu mu'), meminj_preserves_globals ge (as_inj mu') /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu' b = true).
Lemma replace_externs_meminj_preserves_globals_as_inj: forall {F V} (ge: Genv.t F V) nu (WDnu: SM_wd nu) (PG: meminj_preserves_globals ge (as_inj nu) /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc nu b = true)) mu fSrc fTgt (Hyp: mu = replace_externs nu fSrc fTgt) (WDmu: SM_wd mu) (FRG: forall b, frgnBlocksSrc nu b = true -> fSrc b = true), meminj_preserves_globals ge (as_inj mu) /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu b = true).
Lemma after_external_meminj_preserves_globals_as_inj: forall {F V} (ge: Genv.t F V) mu (WDmu : SM_wd mu) (PG: meminj_preserves_globals ge (as_inj 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' (WDmu': SM_wd mu') (Mu'Hyp: mu' = replace_externs nu' frgnSrc' frgnTgt'), meminj_preserves_globals ge (as_inj mu') /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu' b = true).
Lemma match_genv_meminj_preserves_globals_foreign_and_extern: forall {F V} (ge: Genv.t F V) mu (WDmu : SM_wd mu) (PG: meminj_preserves_globals ge (as_inj mu) /\ (forall b, isGlobalBlock ge b = true -> frgnBlocksSrc mu b = true)), meminj_preserves_globals ge (foreign_of mu) /\ meminj_preserves_globals ge (extern_of mu).