(** 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.

(* Specifications: *)
Lemma vmatch_uns': forall p i n, is_uns (Z.max 0 n) i -> vmatch (Vint i) (uns p n).
Lemma vmatch_uns: forall p i n, is_uns n i -> vmatch (Vint i) (uns p n).
Lemma vmatch_uns_undef: forall p n, vmatch Vundef (uns p n).
Lemma vmatch_sgn': forall p i n, is_sgn (Z.max 1 n) i -> vmatch (Vint i) (sgn p n).
Lemma vmatch_sgn: forall p i n, is_sgn n i -> vmatch (Vint i) (sgn p n).
Lemma vmatch_sgn_undef: forall p n, vmatch Vundef (sgn p n).
Lemma vmatch_Uns_1: forall p v, vmatch v (Uns p 1) -> v = Vundef \/ v = Vint Int.zero \/ v = Vint Int.one.