(** 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.

(* Specifications: *)
Lemma globalenv_inject_preserves_globals:
forall (F V: Type) (ge: Genv.t F V) j m,
m |= globalenv_inject ge j ->
meminj_preserves_globals ge j.
Lemma globalenv_inject_incr:
forall j m0 (F V: Type) (ge: Genv.t F V) m j' P,
inject_incr j j' ->
inject_separated j j' m0 m ->
m |= globalenv_inject ge j ** P ->
m |= globalenv_inject ge j' ** P.
Lemma external_call_parallel_rule:
forall (F V: Type) ef (ge: Genv.t F V) vargs1 m1 t vres1 m1' m2 j P vargs2,
external_call ef ge vargs1 m1 t vres1 m1' ->
injection_full j m1 ->
m2 |= minjection j m1 ** globalenv_inject ge j ** P ->
Val.inject_list j vargs1 vargs2 ->
exists j' vres2 m2' t',
external_call ef ge vargs2 m2 t' vres2 m2'
/\ Val.inject j' vres1 vres2
/\ m2' |= minjection j' m1' ** globalenv_inject ge j' ** P
/\ inject_incr j j'
/\ inject_separated j j' m1 m2
/\ inject_trace j' t t' /\
injection_full j m1 .
Lemma external_call_parallel_rule_strong:
forall (F V: Type) ef (ge: Genv.t F V) vargs1 m1 t vres1 m1' m2 j P vargs2,
external_call ef ge vargs1 m1 t vres1 m1' ->
injection_full j m1 ->
m2 |= minjection j m1 ** globalenv_inject ge j ** P ->
Val.inject_list j vargs1 vargs2 ->
exists j' vres2 m2' t',
external_call ef ge vargs2 m2 t' vres2 m2'
/\ Val.inject j' vres1 vres2
/\ m2' |= minjection j' m1' ** globalenv_inject ge j' ** P
/\ inject_incr j j'
/\ inject_separated j j' m1 m2
/\ inject_trace j' t t' /\
injection_full j' m1' .
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).