Corollary mem_obs_eq_domain_ren:
    forall f m m',
      mem_obs_eq f m m' ->
      domain_memren f m.

(* Specifications: *)
Lemma mem_obs_eq_setMaxPerm : forall m, valid_mem m -> mem_obs_eq (id_ren m) m (setMaxPerm m).
Lemma mem_obs_eq_id : forall m, valid_mem m -> mem_obs_eq (id_ren m) m m.
Lemma mapped_dec : forall (f : positive -> option positive) m j (Hdomain_invalid : forall b, ~ (b < m)%positive -> f b = None) (Hdomain_valid : forall b, (b < m)%positive -> exists b', f b = Some b'), (exists i, f i = Some j) \/ ~ exists i, f i = Some j.
Lemma pigeon_positive: forall (n m: positive) (f: positive -> option positive), (forall i, (i < n)%positive -> exists j, (j < m)%positive /\ f i = Some j) -> (forall i i' j j', f i = Some j -> f i' = Some j' -> i<>i' -> j<>j') -> (n <= m)%positive.
Lemma weak_mem_obs_eq_nextblock: forall f m m' (Hobs_eq: weak_mem_obs_eq f m m'), (Mem.nextblock m <= Mem.nextblock m')%positive.
Lemma mf_align : forall (m : mem) (f : memren) (b1 b2 : block) (delta : Z) (chunk : memory_chunk) (ofs : Z) (p : permission), f b1 = Some b2 -> Mem.range_perm m b1 ofs (ofs + size_chunk chunk) Max p -> (align_chunk chunk | 0%Z)%Z.
Lemma proj_bytes_obs: forall (f : memren) (vl vl' : seq memval), Coqlib.list_forall2 (memval_obs_eq f) vl vl' -> forall bl : seq byte, proj_bytes vl = Some bl -> proj_bytes vl' = Some bl.
Lemma proj_bytes_obs_none: forall (f : memren) (vl vl' : seq memval), Coqlib.list_forall2 (memval_obs_eq f) vl vl' -> proj_bytes vl = None -> proj_bytes vl' = None.
Lemma val_obs_equal: forall f v1 v1' v2 v2' (Hinjective: forall b1 b1' b2, f b1 = Some b2 -> f b1' = Some b2 -> b1 = b1') (Hval1: val_obs f v1 v1') (Hval2: val_obs f v2 v2'), Val.eq v1 v2 <-> Val.eq v1' v2'.
Lemma check_value_obs: forall f n vl vl' v v' q (Hf: forall b1 b1' b2, f b1 = Some b2 -> f b1' = Some b2 -> b1 = b1'), Coqlib.list_forall2 (memval_obs_eq f) vl vl' -> val_obs f v v' -> check_value n v q vl = check_value n v' q vl'.
Lemma proj_value_obs: forall f q vl1 vl2, (forall b1 b1' b2 : block, f b1 = Some b2 -> f b1' = Some b2 -> b1 = b1') -> Coqlib.list_forall2 (memval_obs_eq f) vl1 vl2 -> val_obs f (proj_value q vl1) (proj_value q vl2).
Lemma load_result_obs: forall f chunk v1 v2, val_obs f v1 v2 -> val_obs f (Val.load_result chunk v1) (Val.load_result chunk v2).
Lemma decode_val_obs: forall f vl1 vl2 chunk, (forall b1 b1' b2 : block, f b1 = Some b2 -> f b1' = Some b2 -> b1 = b1') -> Coqlib.list_forall2 (memval_obs_eq f) vl1 vl2 -> val_obs f (decode_val chunk vl1) (decode_val chunk vl2).
Lemma valid_access_obs_eq: forall f m1 m2 b1 b2 chunk ofs p, strong_mem_obs_eq f m1 m2 -> f b1 = Some b2 -> Mem.valid_access m1 chunk b1 ofs p -> Mem.valid_access m2 chunk b2 ofs p.
Lemma valid_access_obs_eq': forall f m1 m2 b1 b2 chunk ofs p, strong_mem_obs_eq f m1 m2 -> f b1 = Some b2 -> Mem.valid_access m2 chunk b2 ofs p -> Mem.valid_access m1 chunk b1 ofs p.
Lemma load_val_obs: forall (mc mf : mem) (f:memren) (b1 b2 : block) chunk (ofs : Z) v1 (Hload: Mem.load chunk mc b1 ofs = Some v1) (Hf: f b1 = Some b2) (Hinjective: forall b0 b1' b3 : block, f b0 = Some b3 -> f b1' = Some b3 -> b0 = b1') (Hobs_eq: strong_mem_obs_eq f mc mf), exists v2, Mem.load chunk mf b2 ofs = Some v2 /\ val_obs f v1 v2.
Lemma load_None_obs: forall (mc mf : mem) (f:memren) (b1 b2 : block) chunk (ofs : Z) (Hload: Mem.load chunk mc b1 ofs = None) (Hf: f b1 = Some b2) (Hinjective: forall b0 b1' b3 : block, f b0 = Some b3 -> f b1' = Some b3 -> b0 = b1') (Hobs_eq: strong_mem_obs_eq f mc mf), Mem.load chunk mf b2 ofs = None.
Lemma loadv_val_obs: forall (mc mf : mem) (f:memren) (vptr1 vptr2 : val) chunk v1 (Hload: Mem.loadv chunk mc vptr1 = Some v1) (Hf: val_obs f vptr1 vptr2) (Hinjective: forall b0 b1' b3 : block, f b0 = Some b3 -> f b1' = Some b3 -> b0 = b1') (Hobs_eq: strong_mem_obs_eq f mc mf), exists v2, Mem.loadv chunk mf vptr2 = Some v2 /\ val_obs f v1 v2.
Lemma loadv_None_obs: forall (mc mf : mem) (f:memren) (vptr1 vptr2 : val) chunk (Hload: Mem.loadv chunk mc vptr1 = None) (Hf: val_obs f vptr1 vptr2) (Hinjective: forall b0 b1' b3 : block, f b0 = Some b3 -> f b1' = Some b3 -> b0 = b1') (Hobs_eq: strong_mem_obs_eq f mc mf), Mem.loadv chunk mf vptr2 = None.
Lemma loadbytes_val_obs: forall (mc mf : mem) (f:memren) (b1 b2 : block) (ofs sz : Z) mv (Hsz: sz >= 0) (Hload: Mem.loadbytes mc b1 ofs sz = Some mv) (Hf: f b1 = Some b2) (Hinjective: forall b0 b1' b3 : block, f b0 = Some b3 -> f b1' = Some b3 -> b0 = b1') (Hobs_eq: strong_mem_obs_eq f mc mf), exists mv', Mem.loadbytes mf b2 ofs sz = Some mv' /\ list_forall2 (fun a b => memval_obs_eq f a b) mv mv'.
Lemma encode_val_obs_eq: forall (f : memren) (v1 v2 : val) (chunk : memory_chunk), val_obs f v1 v2 -> list_forall2 (memval_obs_eq f) (encode_val chunk v1) (encode_val chunk v2).
Lemma setN_obs_eq : forall (access : Z -> Prop) (f : memren) (vl1 vl2 : seq memval), list_forall2 (memval_obs_eq f) vl1 vl2 -> forall (p : Z) (c1 c2 : ZMap.t memval), (forall q : Z, access q -> memval_obs_eq f (ZMap.get q c1) (ZMap.get q c2)) -> forall q : Z, access q -> memval_obs_eq f (ZMap.get q (Mem.setN vl1 p c1)) (ZMap.get q (Mem.setN vl2 p c2)).
Lemma store_val_obs: forall (mc mc' mf : mem) (f:memren) (b1 b2 : block) chunk (ofs: Z) v1 v2 (Hstore: Mem.store chunk mc b1 ofs v1 = Some mc') (Hf: f b1 = Some b2) (Hval_obs_eq: val_obs f v1 v2) (Hobs_eq: mem_obs_eq f mc mf), exists mf', Mem.store chunk mf b2 ofs v2 = Some mf' /\ mem_obs_eq f mc' mf'.
Lemma storev_val_obs: forall (mc mc' mf : mem) (f:memren) (vptr1 vptr2: val) chunk v1 v2 (Hstore: Mem.storev chunk mc vptr1 v1 = Some mc') (Hf: val_obs f vptr1 vptr2) (Hval_obs_eq: val_obs f v1 v2) (Hobs_eq: mem_obs_eq f mc mf), exists mf', Mem.storev chunk mf vptr2 v2 = Some mf' /\ mem_obs_eq f mc' mf'.
Lemma storebytes_val_obs: forall (mc mc' mf : mem) (f:memren) (b1 b2 : block) (ofs: Z) mv1 mv2 (Hstore: Mem.storebytes mc b1 ofs mv1 = Some mc') (Hf: f b1 = Some b2) (Hval_obs_eq: list_forall2 (fun a b => memval_obs_eq f a b) mv1 mv2) (Hobs_eq: mem_obs_eq f mc mf), exists mf', Mem.storebytes mf b2 ofs mv2 = Some mf' /\ mem_obs_eq f mc' mf'.
Lemma mem_obs_eq_storeF: forall f mc mf mf' chunk b ofs v pmap pmap2 (Hlt: permMapLt pmap (getMaxPerm mf)) (Hlt': permMapLt pmap (getMaxPerm mf')) (Hlt2: permMapLt pmap2 (getMaxPerm mf)) (Hstore: Mem.store chunk (restrPermMap Hlt2) b ofs v = Some mf') (Hdisjoint: permMapCoherence pmap pmap2 \/ permMapsDisjoint pmap pmap2) (Hobs_eq: mem_obs_eq f mc (restrPermMap Hlt)), mem_obs_eq f mc (restrPermMap Hlt').
Lemma weak_mem_obs_eq_store: forall mc mf mc' mf' rmap rmapF bl1 bl2 f (Hlt: permMapLt rmap (getMaxPerm mc)) (HltF: permMapLt rmapF (getMaxPerm mf)) (Hlt2: permMapLt rmap (getMaxPerm mc')) (Hlt2F: permMapLt rmapF (getMaxPerm mf')) (Hf: f bl1 = Some bl2) (Hinjective: forall b1 b1' b2 : block, f b1 = Some b2 -> f b1' = Some b2 -> b1 = b1') (Hobs_eq: weak_mem_obs_eq f (restrPermMap Hlt) (restrPermMap HltF)) (Hvb: forall b, Mem.valid_block mc b <-> Mem.valid_block mc' b) (HvbF: forall b, Mem.valid_block mf b <-> Mem.valid_block mf' b), weak_mem_obs_eq f (restrPermMap Hlt2) (restrPermMap Hlt2F).
Lemma alloc_perm_eq: forall f m m' lo hi m2 m2' b b' (Hobs_eq: mem_obs_eq f m m') (Halloc: Mem.alloc m lo hi = (m2, b)) (Halloc': Mem.alloc m' lo hi = (m2', b')) b1 b2 ofs (Hf: (if proj_sumbool (valid_block_dec m b1) then f b1 else if proj_sumbool (valid_block_dec m2 b1) then Some b' else None) = Some b2), permission_at m2 b1 ofs Cur = permission_at m2' b2 ofs Cur.
Lemma setPermBlock_var_weak_obs_eq: forall (f : block -> option block) (bl1 bl2 : block) (ofsl : Z) (pmap pmapF : access_map) (mc mf : mem) p (Hlt : permMapLt pmap (getMaxPerm mc)) (HltF : permMapLt pmapF (getMaxPerm mf)) (Hfl: f bl1 = Some bl2) (Hweak_obs_eq: weak_mem_obs_eq f (restrPermMap Hlt) (restrPermMap HltF)) (Hlt' : permMapLt (setPermBlock_var p bl1 ofsl pmap lksize.LKSIZE_nat) (getMaxPerm mc)) (HltF' : permMapLt (setPermBlock_var p bl2 ofsl pmapF lksize.LKSIZE_nat) (getMaxPerm mf)), weak_mem_obs_eq f (restrPermMap Hlt') (restrPermMap HltF').
Lemma setPermBlock_weak_obs_eq: forall (f : block -> option block) (bl1 bl2 : block) (ofsl : Z) (pmap pmapF : access_map) (mc mf : mem) (p : option permission) (Hlt : permMapLt pmap (getMaxPerm mc)) (HltF : permMapLt pmapF (getMaxPerm mf)) (Hfl: f bl1 = Some bl2) (Hweak_obs_eq: weak_mem_obs_eq f (restrPermMap Hlt) (restrPermMap HltF)) (Hlt' : permMapLt (setPermBlock p bl1 ofsl pmap lksize.LKSIZE_nat) (getMaxPerm mc)) (HltF' : permMapLt (setPermBlock p bl2 ofsl pmapF lksize.LKSIZE_nat) (getMaxPerm mf)), weak_mem_obs_eq f (restrPermMap Hlt') (restrPermMap HltF').
Lemma mem_free_obs_perm: forall f m m' m2 m2' lo hi b1 b2 (Hmem_obs_eq: mem_obs_eq f m m') (Hf: f b1 = Some b2) (Hfree: Mem.free m b1 lo hi = Some m2) (Hfree': Mem.free m' b2 lo hi = Some m2') b0 b3 ofs (Hf0: f b0 = Some b3), permissions.permission_at m2 b0 ofs Cur = permissions.permission_at m2' b3 ofs Cur.
Lemma mem_free_obs: forall f m m' lo hi b1 b2 m2 (Hmem_obs_eq: mem_obs_eq f m m') (Hf: f b1 = Some b2) (Hfree: Mem.free m b1 lo hi = Some m2), exists m2', Mem.free m' b2 lo hi = Some m2' /\ mem_obs_eq f m2 m2'.
Lemma alloc_obs_eq: forall f m m' lo hi m2 m2' b b' (Hobs_eq: mem_obs_eq f m m') (Halloc: Mem.alloc m lo hi = (m2, b)) (Halloc': Mem.alloc m' lo hi = (m2', b')), exists f', f' b = Some b' /\ mem_obs_eq f' m2 m2' /\ ren_incr f f' /\ ren_separated f f' m m' /\ (exists p : positive, Mem.nextblock m2 = (Mem.nextblock m + p)%positive /\ Mem.nextblock m2' = (Mem.nextblock m' + p)%positive) /\ (forall b0 : block, Mem.valid_block m2' b0 -> ~ Mem.valid_block m' b0 -> f' (Z.to_pos match - Z.pos_sub (Mem.nextblock m') (Mem.nextblock m) with | 0 => Z.pos b0 | Z.pos y' => Z.pos (b0 + y') | Z.neg y' => Z.pos_sub b0 y' end) = Some b0 /\ f (Z.to_pos match - Z.pos_sub (Mem.nextblock m') (Mem.nextblock m) with | 0 => Z.pos b0 | Z.pos y' => Z.pos (b0 + y') | Z.neg y' => Z.pos_sub b0 y' end) = None) /\ (Mem.nextblock m = Mem.nextblock m' -> (forall b1 b3 : block, f b1 = Some b3 -> b1 = b3) -> forall b1 b0 : block, f' b1 = Some b0 -> b1 = b0).
Lemma valid_pointer_ren: forall f m m' b1 b2 ofs (Hmem_obs_eq: mem_obs_eq f m m') (Hf: f b1 = Some b2), Mem.valid_pointer m b1 ofs = Mem.valid_pointer m' b2 ofs.
Lemma val_obs_cmpu: forall f v1 v2 v1' v2' m m' (comp : comparison) (Hval_obs': val_obs f v2 v2') (Hval_obs: val_obs f v1 v1') (Hmem_obs_eq: mem_obs_eq f m m'), val_obs f (Val.cmpu (Mem.valid_pointer m) comp v1 v2) (Val.cmpu (Mem.valid_pointer m') comp v1' v2').
Lemma val_obs_cmplu: forall f v1 v2 v1' v2' m m' (comp : comparison) (Hval_obs': val_obs f v2 v2') (Hval_obs: val_obs f v1 v1') (Hmem_obs_eq: mem_obs_eq f m m'), val_obs f (Val.maketotal (Val.cmplu (Mem.valid_pointer m) comp v1 v2)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m') comp v1' v2')).
Lemma mem_obs_eq_of_weak_strong: forall m m' f pmap1 pmap1' pmap2 pmap2' (Hlt1: permMapLt pmap1 (getMaxPerm m)) (Hlt2: permMapLt pmap2 (getMaxPerm m')) (Hlt1': permMapLt pmap1' (getMaxPerm m)) (Hlt2': permMapLt pmap2' (getMaxPerm m')) (Hstrong_obs: strong_mem_obs_eq f (restrPermMap Hlt1) (restrPermMap Hlt2)) (Hweak: weak_mem_obs_eq f (restrPermMap Hlt1') (restrPermMap Hlt2')), mem_obs_eq f (restrPermMap Hlt1) (restrPermMap Hlt2).