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'
  }.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'
  }.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.
Lemma preserve_free {P} (HP: memstep_preserve P): forall m b lo hi m', Mem.free m b lo hi = Some m' -> P m m'.
Theorem preserve_conj {P Q} (HP:memstep_preserve P) (HQ: memstep_preserve Q): memstep_preserve (fun m m' => P m m' /\ Q m m').
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.
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'.
Lemma freelist_perm_inv: forall l m m' (L : Mem.free_list m l = Some m') b (B: Mem.valid_block m b) ofs k p (P: Mem.perm m b ofs k p), Mem.perm m b ofs Max Freeable \/ Mem.perm m' b ofs k p.
Lemma memsem_preserves {C} (s: @MemSem C) P (HP:memstep_preserve P): forall c m c' m', corestep s c m c' m'-> P m m'.
Lemma corestep_fwd {C} (s:@MemSem C) c m c' m' (CS:corestep s c m c' m' ): mem_forward m m'.
Lemma corestep_rdonly {C} (s:@MemSem C) c m c' m' (CS:corestep s c m c' m') b (VB:Mem.valid_block m b): readonly m b m'.
Lemma mem_step_nextblock: memstep_preserve (fun m m' => Mem.nextblock m <= Mem.nextblock m')%positive.
Lemma mem_step_nextblock': forall m m', mem_step m m' -> (Mem.nextblock m <= Mem.nextblock m')%positive.
Lemma mem_step_obeys_cur_write: forall m b ofs m', Mem.valid_block m b -> ~ Mem.perm m b ofs Cur Writable -> mem_step m m' -> ZMap.get ofs (PMap.get b (Mem.mem_contents m)) = ZMap.get ofs (PMap.get b (Mem.mem_contents m')).
Lemma ple_load m ch a v (LD: Mem.loadv ch m a = Some v) m1 (PLE: perm_lesseq m m1): Mem.loadv ch m1 a = Some v.
Lemma ple_store: forall ch m v1 v2 m' m1 (PLE: perm_lesseq m m1), Mem.storev ch m v1 v2 = Some m' -> exists m1', perm_lesseq m' m1' /\ Mem.storev ch m1 v1 v2 = Some m1'.
Lemma ple_free: forall m m' b lo hi (FL: Mem.free m b lo hi = Some m') m1 (PLE:perm_lesseq m m1), exists m1', Mem.free m1 b lo hi = Some m1' /\ perm_lesseq m' m1'.
Lemma ple_freelist: forall l m m' (FL: Mem.free_list m l = Some m') m1 (PLE:perm_lesseq m m1), exists m1', Mem.free_list m1 l = Some m1' /\ perm_lesseq m' m1'.
Lemma ple_storebytes: forall m b ofs bytes m' m1 (PLE: perm_lesseq m m1), Mem.storebytes m b ofs bytes = Some m' -> exists m1', perm_lesseq m' m1' /\ Mem.storebytes m1 b ofs bytes = Some m1'.
Lemma ple_loadbytes m b ofs n bytes (LD: Mem.loadbytes m b ofs n = Some bytes) m1 (PLE: perm_lesseq m m1) (N: 0 <= n): Mem.loadbytes m1 b ofs n = Some bytes.
Lemma alloc_inc_perm: forall m lo hi m' b (M: Mem.alloc m lo hi = (m',b)) m1 (PLE: perm_lesseq m m1), exists m1' : mem, Mem.alloc m1 lo hi =(m1',b) /\ perm_lesseq m' m1'.
Lemma perm_lesseq_refl: forall m, perm_lesseq m m.
Lemma preserve_refl {P} (HP: memstep_preserve P): forall m, P m m.
Lemma preserve_free {P} (HP: memstep_preserve P): forall m b lo hi m', Mem.free m b lo hi = Some m' -> P m m'.
Theorem preserve_conj {P Q} (HP:memstep_preserve P) (HQ: memstep_preserve Q): memstep_preserve (fun m m' => P m m' /\ Q m m').
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.
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'.
Lemma freelist_perm_inv: forall l m m' (L : Mem.free_list m l = Some m') b (B: Mem.valid_block m b) ofs k p (P: Mem.perm m b ofs k p), Mem.perm m b ofs Max Freeable \/ Mem.perm m' b ofs k p.
Lemma memsem_preserves {C} (s: @MemSem C) P (HP:memstep_preserve P): forall c m c' m', corestep s c m c' m'-> P m m'.
Lemma corestep_fwd {C} (s:@MemSem C) c m c' m' (CS:corestep s c m c' m' ): mem_forward m m'.
Lemma corestep_rdonly {C} (s:@MemSem C) c m c' m' (CS:corestep s c m c' m') b (VB:Mem.valid_block m b): readonly m b m'.
Lemma mem_step_nextblock: memstep_preserve (fun m m' => Mem.nextblock m <= Mem.nextblock m')%positive.
Lemma mem_step_nextblock': forall m m', mem_step m m' -> (Mem.nextblock m <= Mem.nextblock m')%positive.
Lemma mem_step_obeys_cur_write: forall m b ofs m', Mem.valid_block m b -> ~ Mem.perm m b ofs Cur Writable -> mem_step m m' -> ZMap.get ofs (PMap.get b (Mem.mem_contents m)) = ZMap.get ofs (PMap.get b (Mem.mem_contents m')).
Lemma ple_load m ch a v (LD: Mem.loadv ch m a = Some v) m1 (PLE: perm_lesseq m m1): Mem.loadv ch m1 a = Some v.
Lemma ple_store: forall ch m v1 v2 m' m1 (PLE: perm_lesseq m m1), Mem.storev ch m v1 v2 = Some m' -> exists m1', perm_lesseq m' m1' /\ Mem.storev ch m1 v1 v2 = Some m1'.
Lemma ple_free: forall m m' b lo hi (FL: Mem.free m b lo hi = Some m') m1 (PLE:perm_lesseq m m1), exists m1', Mem.free m1 b lo hi = Some m1' /\ perm_lesseq m' m1'.
Lemma ple_freelist: forall l m m' (FL: Mem.free_list m l = Some m') m1 (PLE:perm_lesseq m m1), exists m1', Mem.free_list m1 l = Some m1' /\ perm_lesseq m' m1'.
Lemma ple_storebytes: forall m b ofs bytes m' m1 (PLE: perm_lesseq m m1), Mem.storebytes m b ofs bytes = Some m' -> exists m1', perm_lesseq m' m1' /\ Mem.storebytes m1 b ofs bytes = Some m1'.
Lemma ple_loadbytes m b ofs n bytes (LD: Mem.loadbytes m b ofs n = Some bytes) m1 (PLE: perm_lesseq m m1) (N: 0 <= n): Mem.loadbytes m1 b ofs n = Some bytes.
Lemma alloc_inc_perm: forall m lo hi m' b (M: Mem.alloc m lo hi = (m',b)) m1 (PLE: perm_lesseq m m1), exists m1' : mem, Mem.alloc m1 lo hi =(m1',b) /\ perm_lesseq m' m1'.
Lemma perm_lesseq_refl: forall m, perm_lesseq m m.