Record memstep_preserve (P:mem -> mem -> Prop) :=
{
preserve_trans: forall m1 m2 m3, P m1 m2 -> P m2 m3 -> P m1 m3;
preserve_mem: forall m m', mem_step m m' -> P m m'
}.

(* Specifications: *)
Lemma preserve_refl {P} (HP: memstep_preserve P): forall m, P m m.
(*opposite direction appears not to hold*)
Theorem preserve_impl {A} (P:A -> mem -> mem -> Prop) (Q:A->Prop):
(forall a, Q a -> memstep_preserve (P a)) -> memstep_preserve (fun m m' => forall a, Q a -> P a m m').
Lemma preserve_exensional {P Q} (HP:memstep_preserve P) (PQ:P=Q): memstep_preserve Q.
subst; trivial. Qed.
(*opposite direction appears not to hold*)
Theorem preserve_univ {A} (P:A -> mem -> mem -> Prop):
(forall a, memstep_preserve (P a)) -> memstep_preserve (fun m m' => forall a, P a m m').
Theorem mem_forward_preserve: memstep_preserve mem_forward.
Theorem readonly_preserve b: memstep_preserve (fun m m' => mem_forward m m' /\ (Mem.valid_block m b -> readonly m b m')).
Theorem readonly_preserve':
memstep_preserve (fun m m' => mem_forward m m' /\ (forall b, Mem.valid_block m b -> readonly m b m')).
Lemma storebytes_unch_loc_unwritable b ofs: forall l m m' (L: Mem.storebytes m b ofs l = Some m'),
Mem.unchanged_on (loc_not_writable m) m m'.
Lemma unch_on_loc_not_writable_trans m1 m2 m3
(Q : Mem.unchanged_on (loc_not_writable m1) m1 m2)
(W : Mem.unchanged_on (loc_not_writable m2) m2 m3)
(F:mem_forward m1 m2):
Mem.unchanged_on (loc_not_writable m1) m1 m3.
Theorem loc_not_writable_preserve:
memstep_preserve (fun m m' => mem_forward m m' /\ Mem.unchanged_on (loc_not_writable m) m m').
Lemma freelist_perm: forall l m m' (L : Mem.free_list m l = Some m') b (B: Mem.valid_block m b)
ofs (P': Mem.perm m' b ofs Max Nonempty) k p,
Mem.perm m b ofs k p <-> Mem.perm m' b ofs k p.
Theorem perm_preserve:
memstep_preserve (fun m m' =>  mem_forward m m' /\ forall b, Mem.valid_block m b -> forall ofs, Mem.perm m' b ofs Max Nonempty ->
forall k p, Mem.perm m b ofs k p <-> Mem.perm m' b ofs k p).
Lemma mem_step_forward m m': mem_step m m' -> mem_forward m m'.
intros. apply preserve_mem; trivial.
Lemma preserve_refl {P} (HP: memstep_preserve P): forall m, P m m.
(*opposite direction appears not to hold*)
Theorem preserve_impl {A} (P:A -> mem -> mem -> Prop) (Q:A->Prop):
(forall a, Q a -> memstep_preserve (P a)) -> memstep_preserve (fun m m' => forall a, Q a -> P a m m').
Lemma preserve_exensional {P Q} (HP:memstep_preserve P) (PQ:P=Q): memstep_preserve Q.
subst; trivial. Qed.
(*opposite direction appears not to hold*)
Theorem preserve_univ {A} (P:A -> mem -> mem -> Prop):
(forall a, memstep_preserve (P a)) -> memstep_preserve (fun m m' => forall a, P a m m').
Theorem mem_forward_preserve: memstep_preserve mem_forward.
Theorem readonly_preserve b: memstep_preserve (fun m m' => mem_forward m m' /\ (Mem.valid_block m b -> readonly m b m')).
Theorem readonly_preserve':
memstep_preserve (fun m m' => mem_forward m m' /\ (forall b, Mem.valid_block m b -> readonly m b m')).
Lemma storebytes_unch_loc_unwritable b ofs: forall l m m' (L: Mem.storebytes m b ofs l = Some m'),
Mem.unchanged_on (loc_not_writable m) m m'.
Lemma unch_on_loc_not_writable_trans m1 m2 m3
(Q : Mem.unchanged_on (loc_not_writable m1) m1 m2)
(W : Mem.unchanged_on (loc_not_writable m2) m2 m3)
(F:mem_forward m1 m2):
Mem.unchanged_on (loc_not_writable m1) m1 m3.
Theorem loc_not_writable_preserve:
memstep_preserve (fun m m' => mem_forward m m' /\ Mem.unchanged_on (loc_not_writable m) m m').
Lemma freelist_perm: forall l m m' (L : Mem.free_list m l = Some m') b (B: Mem.valid_block m b)
ofs (P': Mem.perm m' b ofs Max Nonempty) k p,
Mem.perm m b ofs k p <-> Mem.perm m' b ofs k p.
Theorem perm_preserve:
memstep_preserve (fun m m' =>  mem_forward m m' /\ forall b, Mem.valid_block m b -> forall ofs, Mem.perm m' b ofs Max Nonempty ->
forall k p, Mem.perm m b ofs k p <-> Mem.perm m' b ofs k p).
Lemma mem_step_forward m m': mem_step m m' -> mem_forward m m'.
intros. apply preserve_mem; trivial.