(** Tracking leakage of pointers through arithmetic operations.  In the CompCert semantics, arithmetic operations (e.g. "xor") applied to pointer values are undefined or produce the [Vundef] result. So, in strict mode, we can abstract the result values of such operations as [Ifptr Pbot], namely: [Vundef], or any number, but not a pointer.  In real code, such arithmetic over pointers occurs, so we need to be more prudent.  The policy we take, inspired by that of GCC, is that "undefined" arithmetic operations involving pointer arguments can produce a pointer, but not any pointer: rather, a pointer to the same block, but possibly with a different offset.  Hence, if the operation has a pointer to abstract region [p] as argument, the result value can be a pointer to abstract region [poffset p].  In other words, the result value is abstracted as [Ifptr (poffset p)].  We encapsulate this reasoning in the following [ntop1] and [ntop2] functions ("numerical top"). *)
Definition provenance (x: aval) : aptr :=
if va_strict tt then Pbot else
match x with
| Ptr p | Ifptr p | Uns p _ | Sgn p _ => poffset p
| _ => Pbot
end.
Definition ntop : aval := Ifptr Pbot.
Definition ntop1 (x: aval) : aval := Ifptr (provenance x).
Definition ntop2 (x y: aval) : aval := Ifptr (plub (provenance x) (provenance y)).
(** Smart constructors for [Uns] and [Sgn]. *)
Definition uns (p: aptr) (n: Z) : aval :=
if zle n 1 then Uns p 1
else if zle n 7 then Uns p 7
else if zle n 8 then Uns p 8
else if zle n 15 then Uns p 15
else if zle n 16 then Uns p 16
else Ifptr p.
Definition sgn (p: aptr) (n: Z) : aval :=
if zle n 8 then Sgn p 8 else if zle n 16 then Sgn p 16 else Ifptr p.

Lemma vmatch_uns:
forall p i n, is_uns n i -> vmatch (Vint i) (uns p n).