Definition alloc_right_sm (mu: SM_Injection) sp: SM_Injection :=
Build_SM_Injection (locBlocksSrc mu)
(fun b => eq_block b sp || locBlocksTgt mu b)
(pubBlocksSrc mu) (pubBlocksTgt mu)
(local_of mu)
(extBlocksSrc mu) (extBlocksTgt mu)
(frgnBlocksSrc mu) (frgnBlocksTgt mu) (extern_of mu).

(* Specifications: *)
Lemma alloc_right_sm_wd: forall mu sp (WD: SM_wd mu)
(NEW1: DomTgt mu sp = false),
SM_wd (alloc_right_sm mu sp).
Lemma alloc_right_sm_locBlocksTgt: forall mu sp,
locBlocksTgt (alloc_right_sm mu sp) = fun b => eq_block b sp || locBlocksTgt mu b.
Lemma alloc_right_sm_DomTgt: forall mu sp,
DomTgt (alloc_right_sm mu sp) = fun b => eq_block b sp || DomTgt mu b.
Lemma alloc_right_sm_as_inj: forall mu sp,
as_inj (alloc_right_sm mu sp) = as_inj mu.
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.
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.
(*New Lemma, based on (proof of) Mem.alloc_parallel_inject*)
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'.