(** ** Memory invariants *)

(** A stack location is private if it is not the image of a valid
   location and we have full rights on it. *)

Definition loc_private (F: meminj) (m m': mem) (sp: block) (ofs: Z) : Prop :=
  Mem.perm m' sp ofs Cur Freeable /\
  (forall b delta, F b = Some(sp, delta) -> ~Mem.perm m b (ofs - delta) Max Nonempty).(** Likewise, for a range of locations. *)

Definition range_private (F: meminj) (m m': mem) (sp: block) (lo hi: Z) : Prop :=
  forall ofs, lo <= ofs < hi -> loc_private F m m' sp ofs.

(* Specifications: *)
Lemma range_private_invariant: forall F m m' sp lo hi F1 m1 m1', range_private F m m' sp lo hi -> (forall b delta ofs, F1 b = Some(sp, delta) -> Mem.perm m1 b ofs Max Nonempty -> lo <= ofs + delta < hi -> F b = Some(sp, delta) /\ Mem.perm m b ofs Max Nonempty) -> (forall ofs, Mem.perm m' sp ofs Cur Freeable -> Mem.perm m1' sp ofs Cur Freeable) -> range_private F1 m1 m1' sp lo hi.
Lemma range_private_perms: forall F m m' sp lo hi, range_private F m m' sp lo hi -> Mem.range_perm m' sp lo hi Cur Freeable.
Lemma range_private_alloc_left: forall F m m' sp' base hi sz m1 sp F1, range_private F m m' sp' base hi -> Mem.alloc m 0 sz = (m1, sp) -> F1 sp = Some(sp', base) -> (forall b, b <> sp -> F1 b = F b) -> range_private F1 m1 m' sp' (base + Z.max sz 0) hi.
Lemma range_private_free_left: forall F m m' sp base sz hi b m1, range_private F m m' sp (base + Z.max sz 0) hi -> Mem.free m b 0 sz = Some m1 -> F b = Some(sp, base) -> Mem.inject F m m' -> range_private F m1 m' sp base hi.
Lemma range_private_extcall: forall F F' m1 m2 m1' m2' sp base hi, range_private F m1 m1' sp base hi -> (forall b ofs p, Mem.valid_block m1 b -> Mem.perm m2 b ofs Max p -> Mem.perm m1 b ofs Max p) -> Mem.unchanged_on (loc_out_of_reach F m1) m1' m2' -> Mem.inject F m1 m1' -> inject_incr F F' -> inject_separated F F' m1 m1' -> Mem.valid_block m1' sp -> range_private F' m2 m2' sp base hi.