Definition mkinitial_SM (mu: SM_Injection) frgnS frgnT :=
  match mu with
  Build_SM_Injection locBSrc locBTgt pSrc pTgt local extBSrc extBTgt fSrc fTgt extern =>
  Build_SM_Injection (fun b => false) (fun b => false) (fun b => false) (fun b => false) (fun b => None)
                     (DomSrc mu) (DomTgt mu) frgnS frgnT (as_inj mu)
  end.

(* Specifications: *)
Lemma mkinitial_SM_as_inj: forall mu S T, as_inj (mkinitial_SM mu S T) = as_inj mu.
Lemma mkinitial_SM_local: forall mu S T, local_of (mkinitial_SM mu S T) = fun b => None.
Lemma mkinitial_SM_extern: forall mu S T, extern_of (mkinitial_SM mu S T) = as_inj mu.
Lemma mkinitial_SM_foreign: forall mu S T b1, foreign_of (mkinitial_SM mu S T) b1 = if S b1 then as_inj mu b1 else None.
Lemma mkinitial_SM_DomSrc: forall mu S T, DomSrc (mkinitial_SM mu S T) = DomSrc mu.
Lemma mkinitial_SM_DOM: forall mu S T, DOM (mkinitial_SM mu S T) = DOM mu.
Lemma mkinitial_SM_DomTgt: forall mu S T, DomTgt (mkinitial_SM mu S T) = DomTgt mu.
Lemma mkinitial_SM_RBG: forall mu S T, RNG (mkinitial_SM mu S T) = RNG mu.
Lemma mkinitial_SM_equals_initial_SM: forall mu S T, mkinitial_SM mu S T = initial_SM (DomSrc mu) (DomTgt mu) S T (as_inj mu).
Lemma vals_def_inject_getBlock j b2: forall vals1 vals2 (INJ: Val.inject_list j vals1 vals2) (DEF : vals_def vals1 = true) (GB: getBlocks vals2 b2 = true), exists b1 d, j b1 = Some(b2,d) /\ getBlocks vals1 b1 = true.
Lemma visTgt_DomTgt mu b: visTgt mu b = true -> SM_wd mu -> DomTgt mu b = true.
Lemma replace_locals_wd_AtExternal: forall mu vals1 vals2 m1 m2 (WD : SM_wd mu) (MINJ : Mem.inject (as_inj mu) m1 m2) (AINJ : Forall2 (val_inject (as_inj mu)) vals1 vals2), SM_wd (replace_locals mu (fun b => locBlocksSrc mu b && REACH m1 (exportedSrc mu vals1) b) (fun b => locBlocksTgt mu b && REACH m2 (exportedTgt mu vals2) b)).
Lemma inject_shared_replace_locals m1 m2 mu vals1 vals2: forall (RC : REACH_closed m1 (vis mu)) (WD : SM_wd mu) (MINJ : Mem.inject (as_inj mu) m1 m2) pubSrc' pubTgt' (HPS: pubSrc' = (fun b => locBlocksSrc mu b && REACH m1 (exportedSrc mu vals1) b)) (HPT: pubTgt' = (fun b => locBlocksTgt mu b && REACH m2 (exportedTgt mu vals2) b)) nu (Hnu : nu = replace_locals mu pubSrc' pubTgt') (WDnu: SM_wd nu), Mem.inject (shared_of nu) m1 m2.
Lemma forall_vals_inject_restrictD' j vals1 vals2 X (Inj : Forall2 (val_inject (restrict j X)) vals1 vals2) : Forall2 (val_inject j) vals1 vals2 /\ (forall b : block, getBlocks vals1 b = true -> X b = true).
Lemma forall_vals_inject_intern_incr mu mu' vals1 vals2 (Inj : Forall2 (val_inject (as_inj mu)) vals1 vals2) (Incr : intern_incr mu mu') (WD : SM_wd mu') : Forall2 (val_inject (as_inj mu')) vals1 vals2.
Lemma forall_vals_inject_extern_incr mu mu' vals1 vals2 (Inj : Forall2 (val_inject (as_inj mu)) vals1 vals2) (Incr : extern_incr mu mu') (WD : SM_wd mu') : Forall2 (val_inject (as_inj mu')) vals1 vals2.
Lemma local_of_vis mu: forall b1 b2 d (LOC: local_of mu b1 = Some (b2,d)) (WD: SM_wd mu), vis mu b1 = true.
Lemma incr_local_restrictvis mu: SM_wd mu -> inject_incr (local_of mu) (restrict (as_inj mu)(vis mu)).
Lemma local_visTgt mu (WD: SM_wd mu) b1 b2 d: local_of mu b1 = Some(b2,d) -> visTgt mu b2 = true.
Lemma mkinitial_SM_as_inj: forall mu S T, as_inj (mkinitial_SM mu S T) = as_inj mu.
Lemma mkinitial_SM_local: forall mu S T, local_of (mkinitial_SM mu S T) = fun b => None.
Lemma mkinitial_SM_extern: forall mu S T, extern_of (mkinitial_SM mu S T) = as_inj mu.
Lemma mkinitial_SM_foreign: forall mu S T b1, foreign_of (mkinitial_SM mu S T) b1 = if S b1 then as_inj mu b1 else None.
Lemma mkinitial_SM_DomSrc: forall mu S T, DomSrc (mkinitial_SM mu S T) = DomSrc mu.
Lemma mkinitial_SM_DOM: forall mu S T, DOM (mkinitial_SM mu S T) = DOM mu.
Lemma mkinitial_SM_DomTgt: forall mu S T, DomTgt (mkinitial_SM mu S T) = DomTgt mu.
Lemma mkinitial_SM_RBG: forall mu S T, RNG (mkinitial_SM mu S T) = RNG mu.
Lemma mkinitial_SM_equals_initial_SM: forall mu S T, mkinitial_SM mu S T = initial_SM (DomSrc mu) (DomTgt mu) S T (as_inj mu).
Lemma mkinitial_SM_ok: forall {F1 V1 F2 V2:Type} (g1: Genv.t F1 V1) (g2: Genv.t F2 V2) (G:genvs_domain_eq g1 g2) mu (WD: SM_wd mu) (PG: meminj_preserves_globals g1 (as_inj mu)) vals1 vals2 (VALS: Forall2 (val_inject (as_inj mu)) vals1 vals2) m1 m2 (SMV: sm_valid mu m1 m2) (INJ: Mem.inject (as_inj mu) m1 m2) (RchTgt: forall b, REACH m2 (fun b' => isGlobalBlock g2 b' || getBlocks vals2 b') b = true -> DomTgt mu b = true) nu (NU: nu = mkinitial_SM mu (REACH m1 (fun b => isGlobalBlock g1 b || getBlocks vals1 b)) (REACH m2 (fun b => isGlobalBlock g2 b || getBlocks vals2 b))), SM_wd nu /\ sm_valid nu m1 m2 /\ meminj_preserves_globals g1 (extern_of nu) /\ (forall b, isGlobalBlock g1 b = true -> frgnBlocksSrc nu b = true) /\ REACH_closed m1 (vis nu) /\ REACH_closed m1 (mapped (as_inj nu)).