(* A minimal preservation property we sometimes require. *)
(* Definition readonly {F V} (ge: Genv.t F V) m1 b m2 := forall gv, Genv.find_var_info ge b = Some gv -> gvar_readonly gv && negb (gvar_volatile gv) = true -> forall ch ofs, Mem.load ch m2 b ofs = Mem.load ch m1 b ofs. *)
Definition readonlyLD m1 b m2 :=
forall chunk ofs
(NWR: forall ofs', ofs <= ofs' < ofs + size_chunk chunk ->
~(Mem.perm m1 b ofs' Cur Writable)),
Mem.load chunk m2 b ofs = Mem.load chunk m1 b ofs /\
(forall ofs', ofs <= ofs' < ofs + size_chunk chunk ->
(forall k p, Mem.perm m1 b ofs' k p <-> Mem.perm m2 b ofs' k p)).
Definition readonly m1 b m2 :=
forall n ofs
(NWR: forall i, 0 <= i < n ->
~(Mem.perm m1 b (ofs + i) Cur Writable)),
Mem.loadbytes m2 b ofs n = Mem.loadbytes m1 b ofs n /\
(forall i, 0 <= i < n ->
(forall k p, Mem.perm m1 b (ofs+i) k p <-> Mem.perm m2 b (ofs+i) k p)).
Definition max_readonlyLD m1 b m2 :=
forall chunk ofs
(NWR: forall ofs', ofs <= ofs' < ofs + size_chunk chunk ->
~(Mem.perm m1 b ofs' Max Writable)),
Mem.load chunk m2 b ofs = Mem.load chunk m1 b ofs /\
(forall ofs', ofs <= ofs' < ofs + size_chunk chunk ->
(forall k p, Mem.perm m1 b ofs' k p <-> Mem.perm m2 b ofs' k p)).
Definition max_readonly m1 b m2 :=
forall n ofs
(NWR: forall i, 0 <= i < n ->
~(Mem.perm m1 b (ofs + i) Max Writable)),
Mem.loadbytes m2 b ofs n = Mem.loadbytes m1 b ofs n /\
(forall i, 0 <= i < n ->
(forall k p, Mem.perm m1 b (ofs+i) k p <-> Mem.perm m2 b (ofs+i) k p)).

Lemma readonly_trans m1 m2 m3 b: readonly m1 b m2 -> readonly m2 b m3 -> readonly m1 b m3.
Definition mem_forward (m1 m2:mem) :=
forall b, Mem.valid_block m1 b ->
(Mem.valid_block m2 b
/\ (forall ofs p, Mem.perm m2 b ofs Max p -> Mem.perm m1 b ofs Max p)