(** * Memory extensions *)
(**  A store [m2] extends a store [m1] if [m2] can be obtained from [m1] by increasing the sizes of the memory blocks of [m1] (decreasing the low bounds, increasing the high bounds), and replacing some of the [Vundef] values stored in [m1] by more defined values stored in [m2] at the same locations. *)
Record extends' (m1 m2: mem) : Prop :=
mk_extends {
mext_next: nextblock m1 = nextblock m2;
mext_inj:  mem_inj inject_id m1 m2;
mext_perm_inv: forall b ofs k p,
perm m2 b ofs k p ->
perm m1 b ofs k p \/ ~perm m1 b ofs Max Nonempty
}.
Definition extends := extends'.

(* Specifications: *)
Theorem extends_refl:
forall m, extends m m.
Theorem load_extends:
forall chunk m1 m2 b ofs v1,
extends m1 m2 ->
load chunk m1 b ofs = Some v1 ->
exists v2, load chunk m2 b ofs = Some v2 /\ Val.lessdef v1 v2.
Theorem loadv_extends:
forall chunk m1 m2 addr1 addr2 v1,
extends m1 m2 ->
loadv chunk m1 addr1 = Some v1 ->
Val.lessdef addr1 addr2 ->
exists v2, loadv chunk m2 addr2 = Some v2 /\ Val.lessdef v1 v2.
Theorem loadbytes_extends:
forall m1 m2 b ofs len bytes1,
extends m1 m2 ->
loadbytes m1 b ofs len = Some bytes1 ->
exists bytes2, loadbytes m2 b ofs len = Some bytes2
/\ list_forall2 memval_lessdef bytes1 bytes2.
Theorem store_within_extends:
forall chunk m1 m2 b ofs v1 m1' v2,
extends m1 m2 ->
store chunk m1 b ofs v1 = Some m1' ->
Val.lessdef v1 v2 ->
exists m2',
store chunk m2 b ofs v2 = Some m2'
/\ extends m1' m2'.
Theorem store_outside_extends:
forall chunk m1 m2 b ofs v m2',
extends m1 m2 ->
store chunk m2 b ofs v = Some m2' ->
(forall ofs', perm m1 b ofs' Cur Readable -> ofs <= ofs' < ofs + size_chunk chunk -> False) ->
extends m1 m2'.
Theorem storev_extends:
forall chunk m1 m2 addr1 v1 m1' addr2 v2,
extends m1 m2 ->
storev chunk m1 addr1 v1 = Some m1' ->
Val.lessdef addr1 addr2 ->
Val.lessdef v1 v2 ->
exists m2',
storev chunk m2 addr2 v2 = Some m2'
/\ extends m1' m2'.
Theorem storebytes_within_extends:
forall m1 m2 b ofs bytes1 m1' bytes2,
extends m1 m2 ->
storebytes m1 b ofs bytes1 = Some m1' ->
list_forall2 memval_lessdef bytes1 bytes2 ->
exists m2',
storebytes m2 b ofs bytes2 = Some m2'
/\ extends m1' m2'.
Theorem storebytes_outside_extends:
forall m1 m2 b ofs bytes2 m2',
extends m1 m2 ->
storebytes m2 b ofs bytes2 = Some m2' ->
(forall ofs', perm m1 b ofs' Cur Readable -> ofs <= ofs' < ofs + Z.of_nat (length bytes2) -> False) ->
extends m1 m2'.
Theorem alloc_extends:
forall m1 m2 lo1 hi1 b m1' lo2 hi2,
extends m1 m2 ->
alloc m1 lo1 hi1 = (m1', b) ->
lo2 <= lo1 -> hi1 <= hi2 ->
exists m2',
alloc m2 lo2 hi2 = (m2', b)
/\ extends m1' m2'.
Theorem free_left_extends:
forall m1 m2 b lo hi m1',
extends m1 m2 ->
free m1 b lo hi = Some m1' ->
extends m1' m2.
Theorem free_right_extends:
forall m1 m2 b lo hi m2',
extends m1 m2 ->
free m2 b lo hi = Some m2' ->
(forall ofs k p, perm m1 b ofs k p -> lo <= ofs < hi -> False) ->
extends m1 m2'.
Theorem free_parallel_extends:
forall m1 m2 b lo hi m1',
extends m1 m2 ->
free m1 b lo hi = Some m1' ->
exists m2',
free m2 b lo hi = Some m2'
/\ extends m1' m2'.
Theorem valid_block_extends:
forall m1 m2 b,
extends m1 m2 ->
(valid_block m1 b <-> valid_block m2 b).
Theorem perm_extends:
forall m1 m2 b ofs k p,
extends m1 m2 -> perm m1 b ofs k p -> perm m2 b ofs k p.
Theorem perm_extends_inv:
forall m1 m2 b ofs k p,
extends m1 m2 -> perm m2 b ofs k p -> perm m1 b ofs k p \/ ~perm m1 b ofs Max Nonempty.
Theorem valid_access_extends:
forall m1 m2 chunk b ofs p,
extends m1 m2 -> valid_access m1 chunk b ofs p -> valid_access m2 chunk b ofs p.
Theorem valid_pointer_extends:
forall m1 m2 b ofs,
extends m1 m2 -> valid_pointer m1 b ofs = true -> valid_pointer m2 b ofs = true.
Theorem weak_valid_pointer_extends:
forall m1 m2 b ofs,
extends m1 m2 ->
weak_valid_pointer m1 b ofs = true -> weak_valid_pointer m2 b ofs = true.
Theorem extends_refl:
forall m, extends m m.
Theorem load_extends:
forall chunk m1 m2 b ofs v1,
extends m1 m2 ->
load chunk m1 b ofs = Some v1 ->
exists v2, load chunk m2 b ofs = Some v2 /\ Val.lessdef v1 v2.
Theorem loadv_extends:
forall chunk m1 m2 addr1 addr2 v1,
extends m1 m2 ->
loadv chunk m1 addr1 = Some v1 ->
Val.lessdef addr1 addr2 ->
exists v2, loadv chunk m2 addr2 = Some v2 /\ Val.lessdef v1 v2.
Theorem loadbytes_extends:
forall m1 m2 b ofs len bytes1,
extends m1 m2 ->
loadbytes m1 b ofs len = Some bytes1 ->
exists bytes2, loadbytes m2 b ofs len = Some bytes2
/\ list_forall2 memval_lessdef bytes1 bytes2.
Theorem store_within_extends:
forall chunk m1 m2 b ofs v1 m1' v2,
extends m1 m2 ->
store chunk m1 b ofs v1 = Some m1' ->
Val.lessdef v1 v2 ->
exists m2',
store chunk m2 b ofs v2 = Some m2'
/\ extends m1' m2'.
Theorem store_outside_extends:
forall chunk m1 m2 b ofs v m2',
extends m1 m2 ->
store chunk m2 b ofs v = Some m2' ->
(forall ofs', perm m1 b ofs' Cur Readable -> ofs <= ofs' < ofs + size_chunk chunk -> False) ->
extends m1 m2'.
Theorem storev_extends:
forall chunk m1 m2 addr1 v1 m1' addr2 v2,
extends m1 m2 ->
storev chunk m1 addr1 v1 = Some m1' ->
Val.lessdef addr1 addr2 ->
Val.lessdef v1 v2 ->
exists m2',
storev chunk m2 addr2 v2 = Some m2'
/\ extends m1' m2'.
Theorem storebytes_within_extends:
forall m1 m2 b ofs bytes1 m1' bytes2,
extends m1 m2 ->
storebytes m1 b ofs bytes1 = Some m1' ->
list_forall2 memval_lessdef bytes1 bytes2 ->
exists m2',
storebytes m2 b ofs bytes2 = Some m2'
/\ extends m1' m2'.
Theorem storebytes_outside_extends:
forall m1 m2 b ofs bytes2 m2',
extends m1 m2 ->
storebytes m2 b ofs bytes2 = Some m2' ->
(forall ofs', perm m1 b ofs' Cur Readable -> ofs <= ofs' < ofs + Z.of_nat (length bytes2) -> False) ->
extends m1 m2'.
Theorem alloc_extends:
forall m1 m2 lo1 hi1 b m1' lo2 hi2,
extends m1 m2 ->
alloc m1 lo1 hi1 = (m1', b) ->
lo2 <= lo1 -> hi1 <= hi2 ->
exists m2',
alloc m2 lo2 hi2 = (m2', b)
/\ extends m1' m2'.
Theorem free_left_extends:
forall m1 m2 b lo hi m1',
extends m1 m2 ->
free m1 b lo hi = Some m1' ->
extends m1' m2.
Theorem free_right_extends:
forall m1 m2 b lo hi m2',
extends m1 m2 ->
free m2 b lo hi = Some m2' ->
(forall ofs k p, perm m1 b ofs k p -> lo <= ofs < hi -> False) ->
extends m1 m2'.
Theorem free_parallel_extends:
forall m1 m2 b lo hi m1',
extends m1 m2 ->
free m1 b lo hi = Some m1' ->
exists m2',
free m2 b lo hi = Some m2'
/\ extends m1' m2'.
Theorem valid_block_extends:
forall m1 m2 b,
extends m1 m2 ->
(valid_block m1 b <-> valid_block m2 b).
Theorem perm_extends:
forall m1 m2 b ofs k p,
extends m1 m2 -> perm m1 b ofs k p -> perm m2 b ofs k p.
Theorem perm_extends_inv:
forall m1 m2 b ofs k p,
extends m1 m2 -> perm m2 b ofs k p -> perm m1 b ofs k p \/ ~perm m1 b ofs Max Nonempty.
Theorem valid_access_extends:
forall m1 m2 chunk b ofs p,
extends m1 m2 -> valid_access m1 chunk b ofs p -> valid_access m2 chunk b ofs p.
Theorem valid_pointer_extends:
forall m1 m2 b ofs,
extends m1 m2 -> valid_pointer m1 b ofs = true -> valid_pointer m2 b ofs = true.
Theorem weak_valid_pointer_extends:
forall m1 m2 b ofs,
extends m1 m2 ->
weak_valid_pointer m1 b ofs = true -> weak_valid_pointer m2 b ofs = true.