Add Morphism mconj
with signature massert_imp ==> massert_imp ==> massert_imp
as mconj_morph_1.
Add Morphism mconj
with signature massert_eqv ==> massert_eqv ==> massert_eqv
as mconj_morph_2.
(** The image of a memory injection *)
Program Definition minjection (j: meminj) (m0: mem) : massert := {|
m_pred := fun m => Mem.inject j m0 m;
m_footprint := fun b ofs => exists b0 delta, j b0 = Some(b, delta) /\ Mem.perm m0 b0 (ofs - delta) Max Nonempty
|}.
Next Obligation.
set (img := fun b' ofs => exists b delta, j b = Some(b', delta) /\ Mem.perm m0 b (ofs - delta) Max Nonempty) in *.
assert (IMG: forall b1 b2 delta ofs k p,
j b1 = Some (b2, delta) -> Mem.perm m0 b1 ofs k p -> img b2 (ofs + delta)).
{ intros. red. exists b1, delta; split; auto.
replace (ofs + delta - delta) with ofs by omega.
eauto with mem. }
destruct H. constructor.
- destruct mi_inj. constructor; intros.
+ eapply Mem.perm_unchanged_on; eauto.
+ eauto.
+ rewrite (Mem.unchanged_on_contents _ _ _ H0); eauto.
- assumption.
- intros. eapply Mem.valid_block_unchanged_on; eauto.
- assumption.
- assumption.
- intros. destruct (Mem.perm_dec m0 b1 ofs Max Nonempty); auto.
eapply mi_perm_inv; eauto.
eapply Mem.perm_unchanged_on_2; eauto.
Qed.
Next Obligation.
eapply Mem.valid_block_inject_2; eauto.
Qed.

Lemma alloc_parallel_rule:
forall m1 sz1 m1' b1 m2 sz2 m2' b2 P j lo hi delta,
m2 |= minjection j m1 ** 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' ** P
/\ inject_incr j j'
/\ j' b1 = Some(b2, delta)
/\ (forall b, b <> b1 -> j' b = j b).