(** Preservation of stores *)

(* Specifications: *)
Theorem store_mapped_inject:
forall f chunk m1 b1 ofs v1 n1 m2 b2 delta v2,
inject f m1 m2 ->
store chunk m1 b1 ofs v1 = Some n1 ->
f b1 = Some (b2, delta) ->
Val.inject f v1 v2 ->
exists n2,
store chunk m2 b2 (ofs + delta) v2 = Some n2
/\ inject f n1 n2.
Theorem store_unmapped_inject:
forall f chunk m1 b1 ofs v1 n1 m2,
inject f m1 m2 ->
store chunk m1 b1 ofs v1 = Some n1 ->
f b1 = None ->
inject f n1 m2.
Theorem store_outside_inject:
forall f m1 m2 chunk b ofs v m2',
inject f m1 m2 ->
(forall b' delta ofs',
f b' = Some(b, delta) ->
perm m1 b' ofs' Cur Readable ->
ofs <= ofs' + delta < ofs + size_chunk chunk -> False) ->
store chunk m2 b ofs v = Some m2' ->
inject f m1 m2'.
Theorem storev_mapped_inject:
forall f chunk m1 a1 v1 n1 m2 a2 v2,
inject f m1 m2 ->
storev chunk m1 a1 v1 = Some n1 ->
Val.inject f a1 a2 ->
Val.inject f v1 v2 ->
exists n2,
storev chunk m2 a2 v2 = Some n2 /\ inject f n1 n2.
Theorem storebytes_mapped_inject:
forall f m1 b1 ofs bytes1 n1 m2 b2 delta bytes2,
inject f m1 m2 ->
storebytes m1 b1 ofs bytes1 = Some n1 ->
f b1 = Some (b2, delta) ->
list_forall2 (memval_inject f) bytes1 bytes2 ->
exists n2,
storebytes m2 b2 (ofs + delta) bytes2 = Some n2
/\ inject f n1 n2.
Theorem storebytes_unmapped_inject:
forall f m1 b1 ofs bytes1 n1 m2,
inject f m1 m2 ->
storebytes m1 b1 ofs bytes1 = Some n1 ->
f b1 = None ->
inject f n1 m2.
Theorem storebytes_outside_inject:
forall f m1 m2 b ofs bytes2 m2',
inject f m1 m2 ->
(forall b' delta ofs',
f b' = Some(b, delta) ->
perm m1 b' ofs' Cur Readable ->
ofs <= ofs' + delta < ofs + Z.of_nat (length bytes2) -> False) ->
storebytes m2 b ofs bytes2 = Some m2' ->
inject f m1 m2'.
Theorem storebytes_empty_inject:
forall f m1 b1 ofs1 m1' m2 b2 ofs2 m2',
inject f m1 m2 ->
storebytes m1 b1 ofs1 nil = Some m1' ->
storebytes m2 b2 ofs2 nil = Some m2' ->
inject f m1' m2'.
Theorem store_mapped_inject:
forall f chunk m1 b1 ofs v1 n1 m2 b2 delta v2,
inject f m1 m2 ->
store chunk m1 b1 ofs v1 = Some n1 ->
f b1 = Some (b2, delta) ->
Val.inject f v1 v2 ->
exists n2,
store chunk m2 b2 (ofs + delta) v2 = Some n2
/\ inject f n1 n2.
Theorem store_unmapped_inject:
forall f chunk m1 b1 ofs v1 n1 m2,
inject f m1 m2 ->
store chunk m1 b1 ofs v1 = Some n1 ->
f b1 = None ->
inject f n1 m2.
Theorem store_outside_inject:
forall f m1 m2 chunk b ofs v m2',
inject f m1 m2 ->
(forall b' delta ofs',
f b' = Some(b, delta) ->
perm m1 b' ofs' Cur Readable ->
ofs <= ofs' + delta < ofs + size_chunk chunk -> False) ->
store chunk m2 b ofs v = Some m2' ->
inject f m1 m2'.
Theorem storev_mapped_inject:
forall f chunk m1 a1 v1 n1 m2 a2 v2,
inject f m1 m2 ->
storev chunk m1 a1 v1 = Some n1 ->
Val.inject f a1 a2 ->
Val.inject f v1 v2 ->
exists n2,
storev chunk m2 a2 v2 = Some n2 /\ inject f n1 n2.
Theorem storebytes_mapped_inject:
forall f m1 b1 ofs bytes1 n1 m2 b2 delta bytes2,
inject f m1 m2 ->
storebytes m1 b1 ofs bytes1 = Some n1 ->
f b1 = Some (b2, delta) ->
list_forall2 (memval_inject f) bytes1 bytes2 ->
exists n2,
storebytes m2 b2 (ofs + delta) bytes2 = Some n2
/\ inject f n1 n2.
Theorem storebytes_unmapped_inject:
forall f m1 b1 ofs bytes1 n1 m2,
inject f m1 m2 ->
storebytes m1 b1 ofs bytes1 = Some n1 ->
f b1 = None ->
inject f n1 m2.
Theorem storebytes_outside_inject:
forall f m1 m2 b ofs bytes2 m2',
inject f m1 m2 ->
(forall b' delta ofs',
f b' = Some(b, delta) ->
perm m1 b' ofs' Cur Readable ->
ofs <= ofs' + delta < ofs + Z.of_nat (length bytes2) -> False) ->
storebytes m2 b ofs bytes2 = Some m2' ->
inject f m1 m2'.
Theorem storebytes_empty_inject:
forall f m1 b1 ofs1 m1' m2 b2 ofs2 m2',
inject f m1 m2 ->
storebytes m1 b1 ofs1 nil = Some m1' ->
storebytes m2 b2 ofs2 nil = Some m2' ->
inject f m1' m2'.