Type_domain.S
module BR : Memory_sig.Fixed_size_value_domain
type t = Ctypes.typ
PtrT {ptyp;idx;fe;ofs;ppred}
abstracts the type ptyp.o* with ppred
, with o = i * sizeof(ptyp) + ofs
, where i
belongs to the concretizations of both idx
and fe
.
val index_zero : BR.Scalar.Context.t -> BR.binary
val index_minus_one : BR.Scalar.Context.t -> BR.binary
val eq : only_descr:bool -> BR.Scalar.Context.t -> t -> t -> bool
val symbol : BR.Scalar.Context.t -> string -> int * BR.binary * t
Retrieve the abstract numeric value corresponding to a global symbolic constant (along with its size in bits). May throw Global_symbol_not_found
.
val simple_symbol : BR.Scalar.Context.t -> string -> int * BR.binary * t
val add_symbol : BR.Scalar.Context.t -> string -> int -> BR.binary -> t -> unit
val is_symbol : BR.Scalar.Context.t -> string -> bool
val type_of_binary : BR.Scalar.Context.t -> BR.binary -> t option
Utility functions to manipulate predicates over abstract values of the numeric domain. These functions are not really about types but it was convenient to put them here.
val cond_of_pred_subdomain :
size:int ->
BR.Scalar.Context.t ->
Ctypes.Pred.t ->
BR.binary ->
BR.boolean
val check_invariant_subdomain :
size:int ->
BR.Scalar.Context.t ->
Ctypes.Pred.t ->
BR.binary ->
bool
Required by the domain signature, but don't expect this order to make any sense. WARNING: this function is NOT the lattice comparison function!
val pp : BR.Scalar.Context.t -> Stdlib.Format.formatter -> t -> unit
val serialize :
BR.Scalar.Context.t ->
t ->
BR.Scalar.Context.t ->
t ->
'a BR.Scalar.Context.in_acc ->
(t option, 'a) BR.Scalar.Context.result
val join : BR.Scalar.Context.t -> t -> t -> t option
val serialize_with_bottom_left :
BR.Scalar.Context.t ->
BR.Scalar.Context.t ->
t ->
'a BR.Scalar.Context.in_acc ->
(t, 'a) BR.Scalar.Context.result
val serialize_with_bottom_right :
BR.Scalar.Context.t ->
t ->
BR.Scalar.Context.t ->
'a BR.Scalar.Context.in_acc ->
(t, 'a) BR.Scalar.Context.result
type dereferenced_value = Ctypes.typ
val deref :
size:int ->
BR.Scalar.Context.t ->
t ->
(int * dereferenced_value) list
We represent the result of dereferencing a type as a sequence of word-sized types for ease of type checking upon store. This does not endanger soundness nor precision since we do not support predicates on product types yet. The return value is a list of (size in bytes, type) pairs, obtained by dereferencing the argument type which must be of size
bytes. May throw a Type_error
.
val deref_to_ctype : size:int -> BR.Scalar.Context.t -> t -> Ctypes.typ
Simpler version of above.
val dereferenced_value_of_typ :
size:int ->
BR.Scalar.Context.t ->
Ctypes.typ list ->
(int * dereferenced_value) list
Temporary.
val subtype : BR.Scalar.Context.t -> t -> t -> bool
Lattice comparison function.
val may_subtype : BR.Scalar.Context.t -> t -> t -> bool
Non-standard but needed operator. See notes. Returns true iff one of the concrete types in the concretization of the first operand is a subtype of one of the concrete types in the concretization of the first operand.
val add_offset : BR.Scalar.Context.t -> BR.Binary.t -> t -> t
add_offset ctx t ~idx ~fe ~old_ofs ~pred ~incr
returns the result of adding the abstract offset incr
to a pointer to t
, with an index described by idx
and fe
and an offset in the pointed object old_ofs
.
val in_bounds : BR.Scalar.Context.t -> t -> bool
Determines whether the offset associated with a pointer is in the bounds of the pointed type. Assumes that the argument has been produced using only applications of add_offset
starting from a zero-offset pointer, and not crafted by other means. As a consequence, this operation only makes sense on arrays, since only on array pointers can add_offset
return an out-of-bounds pointer. On pointers to non-array types, it returns true.
val is_empty : BR.Scalar.Context.t -> t -> bool
Returns true
iff the concretization of the type is empty, i.e. if the concretization of the index is the empty set.