Definition alloc_left_sm (mu: SM_Injection) b1 b2 delta: SM_Injection :=
  Build_SM_Injection (fun b => eq_block b b1 || locBlocksSrc mu b)
                     (locBlocksTgt mu) (*b2 is already in locBlocksTgt!*)
                     (pubBlocksSrc mu) (pubBlocksTgt mu)
                     (fun b => if eq_block b b1 then Some(b2, delta)
                               else local_of mu b)
                     (extBlocksSrc mu) (extBlocksTgt mu)
                     (frgnBlocksSrc mu) (frgnBlocksTgt mu) (extern_of mu).

(* Specifications: *)
Lemma alloc_left_sm_wd: forall mu b1 b2 delta (WD: SM_wd mu) (NEW1: DomSrc mu b1 = false) (NEW2: locBlocksTgt mu b2 = true), SM_wd (alloc_left_sm mu b1 b2 delta).
Lemma alloc_left_sm_as_inj_same: forall mu b1 b2 delta (WD: SM_wd mu) (NEW1: DomSrc mu b1 = false), as_inj (alloc_left_sm mu b1 b2 delta) b1 = Some(b2,delta).
Lemma alloc_left_sm_as_inj_other: forall mu b1 b2 delta b (H: b<>b1), as_inj (alloc_left_sm mu b1 b2 delta) b = as_inj mu b.
Lemma alloc_left_sm_intern_incr: forall mu b1 b2 delta (H: as_inj mu b1 = None) (WD: SM_wd mu), intern_incr mu (alloc_left_sm mu b1 b2 delta).
Lemma alloc_left_sm_inject_incr: forall mu b1 b2 delta (H: as_inj mu b1 = None), inject_incr (as_inj mu) (as_inj (alloc_left_sm mu b1 b2 delta)).
Lemma alloc_DomSrc: forall mu m1 m2 (SMV: sm_valid mu m1 m2) lo hi m1' b1 (ALLOC: Mem.alloc m1 lo hi = (m1', b1)), DomSrc mu b1 = false.
Lemma alloc_left_sm_DomSrc: forall mu b1 b2 delta, DomSrc (alloc_left_sm mu b1 b2 delta) = fun b => eq_block b b1 || DomSrc mu b.
Lemma alloc_left_sm_DomTgt: forall mu b1 b2 delta, DomTgt (alloc_left_sm mu b1 b2 delta) = DomTgt mu.
Lemma REACH_closed_alloc_left_sm: forall m lo hi sp m' (ALLOC : Mem.alloc m lo hi = (m', sp)) mu (RC: REACH_closed m (vis mu)) b' delta, REACH_closed m' (vis (alloc_left_sm mu sp b' delta)).
Theorem alloc_left_mapped_sm_inject: forall mu m1 m2 lo hi m1' b1 b2 delta (WD: SM_wd mu) (SMV: sm_valid mu m1 m2) (RC: REACH_closed m1 (vis mu)) (Locb2: locBlocksTgt mu b2 = true), Mem.inject (as_inj mu) m1 m2 -> Mem.alloc m1 lo hi = (m1', b1) -> Mem.valid_block m2 b2 -> 0 <= delta <= Int.max_unsigned -> (forall ofs k p, Mem.perm m2 b2 ofs k p -> delta = 0 \/ 0 <= ofs < Int.max_unsigned) -> (forall ofs k p, lo <= ofs < hi -> Mem.perm m2 b2 (ofs + delta) k p) -> Mem.inj_offset_aligned delta (hi-lo) -> (forall b delta' ofs k p, as_inj mu b = Some (b2, delta') -> Mem.perm m1 b ofs k p -> lo + delta <= ofs + delta' < hi + delta -> False) -> exists mu', Mem.inject (as_inj mu') m1' m2 /\ intern_incr mu mu' /\ as_inj mu' b1 = Some(b2, delta) /\ (forall b, b <> b1 -> as_inj mu' b = as_inj mu b) /\ SM_wd mu' /\ sm_valid mu' m1' m2 /\ sm_locally_allocated mu mu' m1 m2 m1' m2 /\ REACH_closed m1' (vis mu').
Lemma genv_find_add_globals_fresh: forall {F V} defs (g:Genv.t F V) i (G: ~ In i (map fst defs)), Genv.find_symbol (Genv.add_globals g defs) i = Genv.find_symbol g i.
Lemma add_globals_find_symbol: forall {F V} (defs : list (ident * globdef F V)) (R: list_norepet (map fst defs)) (g: Genv.t F V) m0 m (G: Genv.alloc_globals (Genv.add_globals g defs) m0 defs = Some m) (N: Genv.genv_next g = Mem.nextblock m0) b (VB: Mem.valid_block m b), Mem.valid_block m0 b \/ exists id, Genv.find_symbol (Genv.add_globals g defs) id = Some b.
Lemma valid_init_is_global : forall {F V} (prog:AST.program F V) (R: list_norepet (map fst (prog_defs prog))) m (G: Genv.init_mem prog = Some m) b (VB: Mem.valid_block m b), exists id, Genv.find_symbol (Genv.globalenv prog) id = Some b.
Lemma find_symbol_isGlobal: forall {V F} (ge : Genv.t F V) x b (Find: Genv.find_symbol ge x = Some b), isGlobalBlock ge b = true.
Theorem alloc_parallel_intern: forall mu m1 m2 lo1 hi1 m1' b1 lo2 hi2 (SMV: sm_valid mu m1 m2) (WD: SM_wd mu), Mem.inject (as_inj mu) m1 m2 -> Mem.alloc m1 lo1 hi1 = (m1', b1) -> lo2 <= lo1 -> hi1 <= hi2 -> exists mu', exists m2', exists b2, Mem.alloc m2 lo2 hi2 = (m2', b2) /\ Mem.inject (as_inj mu') m1' m2' /\ intern_incr mu mu' /\ as_inj mu' b1 = Some(b2, 0) /\ (forall b, b <> b1 -> as_inj mu' b = as_inj mu b) /\ sm_inject_separated mu mu' m1 m2 /\ sm_locally_allocated mu mu' m1 m2 m1' m2' /\ SM_wd mu' /\ sm_valid mu' m1' m2' /\ (REACH_closed m1 (vis mu) -> REACH_closed m1' (vis mu')).
Lemma freelist_right_inject: forall j m1 l m2 m2' (F:Mem.free_list m2 l = Some m2') (Inj : Mem.inject j m1 m2) (Hyp: forall b2 lo2 hi2 (L:In ((b2,lo2),hi2) l) b1 delta ofs k p (J:j b1 = Some (b2, delta)) (P: Mem.perm m1 b1 ofs k p) (OFS: lo2 <= ofs + delta < hi2), False), Mem.inject j m1 m2'.