(** Preservation of a global environment by a memory injection *)
Inductive globalenv_preserved {F V: Type} (ge: Genv.t F V) (j: meminj) (bound: block) : Prop :=
| globalenv_preserved_intro
(DOMAIN: forall b, Plt b bound -> j b = Some(b, 0))
(IMAGE: forall b1 b2 delta, j b1 = Some(b2, delta) -> Plt b2 bound -> b1 = b2)
(SYMBOLS: forall id b, Genv.find_symbol ge id = Some b -> Plt b bound)
(FUNCTIONS: forall b fd, Genv.find_funct_ptr ge b = Some fd -> Plt b bound)
(VARINFOS: forall b gv, Genv.find_var_info ge b = Some gv -> Plt b bound).
Program Definition globalenv_inject {F V: Type} (ge: Genv.t F V) (j: meminj) : massert := {|
m_pred := fun m => exists bound, Ple bound (Mem.nextblock m) /\ globalenv_preserved ge j bound;
m_footprint := fun b ofs => False
|}.
Next Obligation.
rename H into bound. exists bound; split; auto. eapply Ple_trans; eauto. eapply Mem.unchanged_on_nextblock; eauto.
Qed.
Next Obligation.
tauto.
Qed.

Lemma alloc_parallel_rule_2:
forall (F V: Type) (ge: Genv.t F V) m1 sz1 m1' b1 m2 sz2 m2' b2 P j lo hi delta,
m2 |= minjection j m1 ** globalenv_inject ge j ** P ->
Mem.alloc m1 0 sz1 = (m1', b1) ->
Mem.alloc m2 0 sz2 = (m2', b2) ->
(8 | delta) ->
lo = delta ->
hi = delta + Z.max 0 sz1 ->
0 <= sz2 <= Ptrofs.max_unsigned ->
0 <= delta -> hi <= sz2 ->
exists j',
m2' |= range b2 0 lo ** range b2 hi sz2 ** minjection j' m1' ** globalenv_inject ge j' ** P
/\ inject_incr j j'
/\ j' b1 = Some(b2, delta).