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 free_parallel_rule:
forall j m1 b1 sz1 m1' m2 b2 sz2 lo hi delta P,
m2 |= range b2 0 lo ** range b2 hi sz2 ** minjection j m1 ** P ->
Mem.free m1 b1 0 sz1 = Some m1' ->
j b1 = Some (b2, delta) ->
lo = delta -> hi = delta + Z.max 0 sz1 ->
exists m2',
Mem.free m2 b2 0 sz2 = Some m2'
/\ m2' |= minjection j m1' ** P.