(* 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.