(** The following lemmas establish the absence of machine integer overflow during address computations. *)

(* Specifications: *)
Lemma address_inject:
forall f m1 m2 b1 ofs1 b2 delta p,
inject f m1 m2 ->
perm m1 b1 (Ptrofs.unsigned ofs1) Cur p ->
f b1 = Some (b2, delta) ->
Ptrofs.unsigned (Ptrofs.add ofs1 (Ptrofs.repr delta)) = Ptrofs.unsigned ofs1 + delta.
Lemma address_inject':
forall f m1 m2 chunk b1 ofs1 b2 delta,
inject f m1 m2 ->
valid_access m1 chunk b1 (Ptrofs.unsigned ofs1) Nonempty ->
f b1 = Some (b2, delta) ->
Ptrofs.unsigned (Ptrofs.add ofs1 (Ptrofs.repr delta)) = Ptrofs.unsigned ofs1 + delta.
Theorem weak_valid_pointer_inject_no_overflow:
forall f m1 m2 b ofs b' delta,
inject f m1 m2 ->
weak_valid_pointer m1 b (Ptrofs.unsigned ofs) = true ->
f b = Some(b', delta) ->
0 <= Ptrofs.unsigned ofs + Ptrofs.unsigned (Ptrofs.repr delta) <= Ptrofs.max_unsigned.
Theorem valid_pointer_inject_no_overflow:
forall f m1 m2 b ofs b' delta,
inject f m1 m2 ->
valid_pointer m1 b (Ptrofs.unsigned ofs) = true ->
f b = Some(b', delta) ->
0 <= Ptrofs.unsigned ofs + Ptrofs.unsigned (Ptrofs.repr delta) <= Ptrofs.max_unsigned.
Theorem valid_pointer_inject_val:
forall f m1 m2 b ofs b' ofs',
inject f m1 m2 ->
valid_pointer m1 b (Ptrofs.unsigned ofs) = true ->
Val.inject f (Vptr b ofs) (Vptr b' ofs') ->
valid_pointer m2 b' (Ptrofs.unsigned ofs') = true.
Theorem weak_valid_pointer_inject_val:
forall f m1 m2 b ofs b' ofs',
inject f m1 m2 ->
weak_valid_pointer m1 b (Ptrofs.unsigned ofs) = true ->
Val.inject f (Vptr b ofs) (Vptr b' ofs') ->
weak_valid_pointer m2 b' (Ptrofs.unsigned ofs') = true.
Theorem inject_no_overlap:
forall f m1 m2 b1 b2 b1' b2' delta1 delta2 ofs1 ofs2,
inject f m1 m2 ->
b1 <> b2 ->
f b1 = Some (b1', delta1) ->
f b2 = Some (b2', delta2) ->
perm m1 b1 ofs1 Max Nonempty ->
perm m1 b2 ofs2 Max Nonempty ->
b1' <> b2' \/ ofs1 + delta1 <> ofs2 + delta2.
Theorem different_pointers_inject:
forall f m m' b1 ofs1 b2 ofs2 b1' delta1 b2' delta2,
inject f m m' ->
b1 <> b2 ->
valid_pointer m b1 (Ptrofs.unsigned ofs1) = true ->
valid_pointer m b2 (Ptrofs.unsigned ofs2) = true ->
f b1 = Some (b1', delta1) ->
f b2 = Some (b2', delta2) ->
b1' <> b2' \/
Ptrofs.unsigned (Ptrofs.add ofs1 (Ptrofs.repr delta1)) <>
Ptrofs.unsigned (Ptrofs.add ofs2 (Ptrofs.repr delta2)).
Theorem disjoint_or_equal_inject:
forall f m m' b1 b1' delta1 b2 b2' delta2 ofs1 ofs2 sz,
inject f m m' ->
f b1 = Some(b1', delta1) ->
f b2 = Some(b2', delta2) ->
range_perm m b1 ofs1 (ofs1 + sz) Max Nonempty ->
range_perm m b2 ofs2 (ofs2 + sz) Max Nonempty ->
sz > 0 ->
b1 <> b2 \/ ofs1 = ofs2 \/ ofs1 + sz <= ofs2 \/ ofs2 + sz <= ofs1 ->
b1' <> b2' \/ ofs1 + delta1 = ofs2 + delta2
\/ ofs1 + delta1 + sz <= ofs2 + delta2
\/ ofs2 + delta2 + sz <= ofs1 + delta1.
Theorem aligned_area_inject:
forall f m m' b ofs al sz b' delta,
inject f m m' ->
al = 1 \/ al = 2 \/ al = 4 \/ al = 8 -> sz > 0 ->
(al | sz) ->
range_perm m b ofs (ofs + sz) Cur Nonempty ->
(al | ofs) ->
f b = Some(b', delta) ->
(al | ofs + delta).