what4-domains-0.1: Abstract domains for What4 term simplification
Copyright(c) Galois Inc 2019-2020
LicenseBSD3
Maintainerhuffman@galois.com
Safe HaskellNone
LanguageHaskell2010

What4.Domains.BV.Arith

Description

Provides an interval-based implementation of bitvector abstract domains.

Synopsis

Documentation

data Domain (w :: Nat) Source #

A value of type BVDomain w represents a set of bitvectors of width w. Each BVDomain can represent a single contiguous interval of bitvectors that may wrap around from -1 to 0.

Constructors

BVDAny !Integer

The set of all bitvectors of width w. Argument caches 2^w-1.

BVDInterval !Integer !Integer !Integer

Intervals are represented by a starting value and a size. BVDInterval mask l d represents the set of values of the form x mod 2^w for x such that l <= x <= l + d. It should satisfy the invariants 0 <= l < 2^w and 0 <= d < 2^w. The first argument caches the value 2^w-1.

Instances

Instances details
Show (Domain w) Source # 
Instance details

Defined in What4.Domains.BV.Arith

Methods

showsPrec :: Int -> Domain w -> ShowS #

show :: Domain w -> String #

showList :: [Domain w] -> ShowS #

Eq (Domain w) Source # 
Instance details

Defined in What4.Domains.BV.Arith

Methods

(==) :: Domain w -> Domain w -> Bool #

(/=) :: Domain w -> Domain w -> Bool #

Ord (Domain w) Source # 
Instance details

Defined in What4.Domains.BV.Arith

Methods

compare :: Domain w -> Domain w -> Ordering #

(<) :: Domain w -> Domain w -> Bool #

(<=) :: Domain w -> Domain w -> Bool #

(>) :: Domain w -> Domain w -> Bool #

(>=) :: Domain w -> Domain w -> Bool #

max :: Domain w -> Domain w -> Domain w #

min :: Domain w -> Domain w -> Domain w #

proper :: forall (w :: Nat). NatRepr w -> Domain w -> Bool Source #

Check if the domain satisfies its invariants

bvdMask :: forall (w :: Nat). Domain w -> Integer Source #

Return the bitvector mask value from this domain

member :: forall (w :: Nat). Domain w -> Integer -> Bool Source #

Test if the given integer value is a member of the abstract domain

pmember :: forall (n :: Nat). NatRepr n -> Domain n -> Integer -> Bool Source #

Check that a domain is proper, and that the given value is a member

interval :: forall (w :: Nat). Integer -> Integer -> Integer -> Domain w Source #

Unsafe constructor for internal use only. Caller must ensure that mask = maxUnsigned w, and that aw is non-negative.

size :: forall (w :: Nat). Domain w -> Integer Source #

Compute how many concrete elements are in the abstract domain

Projection functions

asSingleton :: forall (w :: Nat). Domain w -> Maybe Integer Source #

Return value if this is a singleton.

ubounds :: forall (w :: Nat). Domain w -> (Integer, Integer) Source #

Return unsigned bounds for domain.

sbounds :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w -> (Integer, Integer) Source #

Return signed bounds for domain.

eq :: forall (w :: Nat). Domain w -> Domain w -> Maybe Bool Source #

slt :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w -> Domain w -> Maybe Bool Source #

Check if all elements in one domain are less than all elements in other.

ult :: forall (w :: Natural). 1 <= w => Domain w -> Domain w -> Maybe Bool Source #

Check if all elements in one domain are less than all elements in other.

isUltSumCommonEquiv :: forall (w :: Nat). Domain w -> Domain w -> Domain w -> Bool Source #

Check if (bvult (bvadd a c) (bvadd b c)) is equivalent to (bvult a b).

This is true if and only if for all natural values i_a, i_b, i_c in a, b, c, either both i_a + i_c and i_b + i_c are less than 2^w, or both are not. We prove this by contradiction. If i_a = i_b, then the property is trivial. Assume that i_a < i_b. Then i_a + i_c < i_b + i_c. If exactly one of the additions is less than 2^w, it must be the case that i_a + i_c < 2^w and 0 <= i_b + i_c - 2^w < 2^w. Since i_b < 2^w, it follows that i_b + i_c < 2^w + i_c, that i_b + i_c - 2^w < i_c, and that i_b + i_c - 2^w < i_a + i_c. Thus, for these values of i_a, i_b, i_c, (bvult a b) is true, but (bvult (bvadd a c) (bvadd b c)) is false, which is a contradiction.

We check this property by case analysis on whether c is a single non-wrapping interval, or it wraps around and is a union of two non-wrapping intervals. For a non-wrapping (sub)interval c' of c, there are four possible cases: 1. a and b contain a single value. 2. (bvadd a c') and (bvadd b c') do not wrap around for any values in a, b, c'. 3. (bvadd a c') and (bvadd b c') wrap around for all values in a, b, c'.

This is used to simplify bvult.

domainsOverlap :: forall (w :: Nat). Domain w -> Domain w -> Bool Source #

Return true if domains contain a common element.

arithDomainData :: forall (w :: Nat). Domain w -> Maybe (Integer, Integer) Source #

Return the (lo,sz), the low bound and size of the given arithmetic interval. A value x is in the set defined by this domain iff (x - lo) mod w <= sz holds. Returns Nothing if the domain contains all values.

bitbounds :: forall (w :: Nat). Domain w -> (Integer, Integer) Source #

Return bitwise bounds for domain (i.e. logical AND of all possible values, paired with logical OR of all possible values).

unknowns :: forall (w :: Nat). Domain w -> Integer Source #

unknowns lo hi returns a bitmask representing the set of bit positions whose values are not constant throughout the range lo..hi.

fillright :: Integer -> Integer Source #

fillright x rounds up x to the nearest 2^n-1.

Lattice operations

top :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w Source #

Top element of the lattice: represents all bitvectors of width w.

any :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w Source #

Deprecated: Use top instead

Represents all values.

bottom :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w Source #

Bottom element of the lattice: represents the empty set of bitvectors. This is an improper domain whose membership predicate is unsatisfiable.

isBottom :: forall (w :: Nat). Domain w -> Bool Source #

Returns True if this domain has no members (i.e., is bottom), detected as an improper interval with negative size.

join :: forall (w :: Natural). 1 <= w => Domain w -> Domain w -> Domain w Source #

Lattice join (least upper bound) of two domains. If both inputs are proper (or bottom), so is the result.

For two non-bottom intervals, the result is the shortest single interval containing both. The trick is to compare each interval's "average value" 2*lo + sz (twice the midpoint, doubled to avoid fractions). If the averages are more than half the modulus apart, the inputs sit on opposite sides of zero, so we lift the smaller- midpoint interval by 2^w before taking the enclosing range. This yields the shorter of the two enclosing arcs — the one that wraps around zero when appropriate — rather than always going clockwise. interval then collapses sizes >= 2^w to BVDAny.

    Visualize the modular number line [0, mask] as a horizontal strip.

    midpoints close — naive convex hull is already optimal:
           0                                     mask
    a:     [-----]
    b:               [-----]
    naive: [---------------]   (= our result)

    midpoints far apart — naive hull is wasteful, wrapping is shorter:
           0                                     mask
    a:     [-----]
    b:                                   [-----]
    naive: [-----------------------------------]   (covers nearly everything)
    ours:  -----]                        [------   (wraps around; tight)

union :: forall (w :: Natural). 1 <= w => Domain w -> Domain w -> Domain w Source #

Deprecated: Use join instead

Return union of two domains.

meet :: forall (w :: Natural). 1 <= w => Domain w -> Domain w -> Domain w Source #

Lattice meet: an over-approximation of the intersection of two domains. For any concrete value x, if x is a member of both a and b, then x is a member of meet a b. If both inputs are proper (or bottom), so is the result.

leq :: forall (w :: Nat). Domain w -> Domain w -> Bool Source #

Lattice ordering: leq a b returns True if every concrete value represented by a is also represented by b.

Operations

singleton :: forall (w :: Natural). (HasCallStack, 1 <= w) => NatRepr w -> Integer -> Domain w Source #

Create a bitvector domain representing the integer.

range :: forall (w :: Nat). NatRepr w -> Integer -> Integer -> Domain w Source #

range w l u returns domain containing all bitvectors formed from the w low order bits of some i in [l,u]. Note that per testBit, the least significant bit has index 0.

fromAscEltList :: forall (w :: Natural). 1 <= w => NatRepr w -> [Integer] -> Domain w Source #

Create an abstract domain from an ascending list of elements. The elements are assumed to be distinct.

concat :: forall (u :: Nat) (v :: Nat). NatRepr u -> Domain u -> NatRepr v -> Domain v -> Domain (u + v) Source #

concat a y returns domain where each element in a has been concatenated with an element in y. The most-significant bits are a, and the least significant bits are y.

select :: forall (n :: Natural) (i :: Natural) (w :: Natural). (1 <= n, (i + n) <= w) => NatRepr i -> NatRepr n -> Domain w -> Domain n Source #

select i n a selects n bits starting from index i from a.

zext :: forall (w :: Natural) (u :: Natural). (1 <= w, (w + 1) <= u) => Domain w -> NatRepr u -> Domain u Source #

sext :: forall (w :: Natural) (u :: Natural). (1 <= w, (w + 1) <= u) => NatRepr w -> Domain w -> NatRepr u -> Domain u Source #

Shifts

shl :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w -> Domain w -> Domain w Source #

lshr :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w -> Domain w -> Domain w Source #

ashr :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w -> Domain w -> Domain w Source #

Arithmetic

add :: forall (w :: Natural). 1 <= w => Domain w -> Domain w -> Domain w Source #

negate :: forall (w :: Natural). 1 <= w => Domain w -> Domain w Source #

scale :: forall (w :: Natural). 1 <= w => Integer -> Domain w -> Domain w Source #

mul :: forall (w :: Natural). 1 <= w => Domain w -> Domain w -> Domain w Source #

udiv :: forall (w :: Natural). 1 <= w => Domain w -> Domain w -> Domain w Source #

urem :: forall (w :: Natural). 1 <= w => Domain w -> Domain w -> Domain w Source #

sdiv :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w -> Domain w -> Domain w Source #

srem :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w -> Domain w -> Domain w Source #

Arithmetic (SMT-LIB div-by-zero semantics)

udivSmtlib :: forall (w :: Natural). 1 <= w => Domain w -> Domain w -> Domain w Source #

Like udiv, but using the SMT-LIB FixedSizeBitVectors theory's div-by-zero semantics:

[[(bvudiv s t)]] := if bv2nat([[t]]) = 0
                    then λx:[0, m). 1
                    else nat2bv[m](bv2nat([[s]]) div bv2nat([[t]]))

i.e. the all-ones bitvector when the divisor is zero. See Note [SMT-LIB division] in What4.Interface for the design rationale.

uremSmtlib :: forall (w :: Natural). 1 <= w => Domain w -> Domain w -> Domain w Source #

Like urem, but using the SMT-LIB FixedSizeBitVectors theory's div-by-zero semantics:

[[(bvurem s t)]] := if bv2nat([[t]]) = 0
                    then [[s]]
                    else nat2bv[m](bv2nat([[s]]) mod bv2nat([[t]]))

i.e. the dividend itself when the divisor is zero. See Note [SMT-LIB division] in What4.Interface for the design rationale.

sdivSmtlib :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w -> Domain w -> Domain w Source #

Like sdiv, but using the SMT-LIB QF_BV logic's div-by-zero convention: (bvsdiv s 0) is all-ones when the dividend is non-negative, 1 when it is negative. The signed variants are not in the core FixedSizeBitVectors theory; this convention matches Z3, CVC5, Bitwuzla, and Yices. See Note [SMT-LIB division] in What4.Interface for the design rationale.

sremSmtlib :: forall (w :: Natural). 1 <= w => NatRepr w -> Domain w -> Domain w -> Domain w Source #

Like srem, but using the SMT-LIB QF_BV logic's div-by-zero convention: (bvsrem s 0) is the dividend itself. The signed variants are not in the core FixedSizeBitVectors theory; this convention matches Z3, CVC5, Bitwuzla, and Yices. See Note [SMT-LIB division] in What4.Interface for the design rationale.

Bitwise

not :: forall (w :: Nat). Domain w -> Domain w Source #

Complement bits in range.

Correctness properties

genDomain :: forall (w :: Nat). NatRepr w -> Gen (Domain w) Source #

Random generator for domain values

genElement :: forall (w :: Nat). Domain w -> Gen Integer Source #

Generate a random element from a domain

genPair :: forall (w :: Nat). NatRepr w -> Gen (Domain w, Integer) Source #

Generate a random domain and an element contained in that domain.

correct_any :: forall (n :: Natural). 1 <= n => NatRepr n -> Integer -> Property Source #

correct_ubounds :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> Property Source #

correct_sbounds :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> Property Source #

correct_singleton :: forall (n :: Natural). 1 <= n => NatRepr n -> Integer -> Integer -> Property Source #

correct_overlap :: forall (n :: Nat). Domain n -> Domain n -> Integer -> Property Source #

correct_overlap_inv :: forall (n :: Nat). Domain n -> Domain n -> Property Source #

If domainsOverlap returns True, then a shared witness exists among the low-bound candidates of either domain.

correct_asSingleton :: forall (n :: Natural). 1 <= n => NatRepr n -> Domain n -> Property Source #

correct_union :: forall (n :: Natural). 1 <= n => NatRepr n -> Domain n -> Domain n -> Integer -> Property Source #

correct_join :: forall (n :: Natural). 1 <= n => NatRepr n -> Domain n -> Domain n -> Integer -> Property Source #

correct_meet :: forall (n :: Natural). 1 <= n => Domain n -> Domain n -> Integer -> Property Source #

correct_leq :: forall (n :: Nat). Domain n -> Domain n -> Integer -> Property Source #

Lattice laws

join_commutative :: forall (n :: Natural). 1 <= n => Domain n -> Domain n -> Integer -> Property Source #

join_idempotent :: forall (n :: Natural). 1 <= n => Domain n -> Integer -> Property Source #

meet_commutative :: forall (n :: Natural). 1 <= n => Domain n -> Domain n -> Integer -> Property Source #

meet_idempotent :: forall (n :: Natural). 1 <= n => Domain n -> Integer -> Property Source #

join_top :: forall (n :: Natural). 1 <= n => NatRepr n -> Domain n -> Integer -> Property Source #

join_bottom :: forall (n :: Natural). 1 <= n => NatRepr n -> Domain n -> Integer -> Property Source #

meet_top :: forall (n :: Natural). 1 <= n => NatRepr n -> Domain n -> Integer -> Property Source #

meet_bottom :: forall (n :: Natural). 1 <= n => NatRepr n -> Domain n -> Integer -> Property Source #

leq_reflexive :: forall (n :: Nat). Domain n -> Property Source #

leq_transitive :: forall (n :: Nat). Domain n -> Domain n -> Domain n -> Property Source #

join_upper_bound :: forall (n :: Natural). 1 <= n => Domain n -> Domain n -> Property Source #

join_proper :: forall (n :: Natural). 1 <= n => NatRepr n -> Domain n -> Domain n -> Property Source #

meet_proper :: forall (n :: Natural). 1 <= n => NatRepr n -> Domain n -> Domain n -> Property Source #

correct_zero_ext :: forall (w :: Natural) (u :: Natural). (1 <= w, (w + 1) <= u) => NatRepr w -> Domain w -> NatRepr u -> Integer -> Property Source #

correct_sign_ext :: forall (w :: Natural) (u :: Natural). (1 <= w, (w + 1) <= u) => NatRepr w -> Domain w -> NatRepr u -> Integer -> Property Source #

correct_concat :: forall (m :: Nat) (n :: Nat). NatRepr m -> (Domain m, Integer) -> NatRepr n -> (Domain n, Integer) -> Property Source #

correct_shrink :: forall (i :: Nat) (n :: Nat). NatRepr i -> NatRepr n -> (Domain (i + n), Integer) -> Property Source #

correct_trunc :: forall (n :: Nat) (w :: Nat). n <= w => NatRepr n -> (Domain w, Integer) -> Property Source #

correct_select :: forall (n :: Natural) (i :: Natural) (w :: Natural). (1 <= n, (i + n) <= w) => NatRepr i -> NatRepr n -> (Domain w, Integer) -> Property Source #

correct_add :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_neg :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> Property Source #

correct_mul :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_scale :: forall (n :: Natural). 1 <= n => NatRepr n -> Integer -> (Domain n, Integer) -> Property Source #

correct_scale_eq :: forall (n :: Natural). 1 <= n => NatRepr n -> Integer -> Domain n -> Property Source #

correct_udiv :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_urem :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_sdiv :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_srem :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_udivSmtlib :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_uremSmtlib :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_sdivSmtlib :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_sremSmtlib :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_not :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> Property Source #

correct_shl :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_lshr :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_ashr :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_eq :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_ult :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_slt :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_isUltSumCommonEquiv :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> (Domain n, Integer) -> (Domain n, Integer) -> Property Source #

correct_unknowns :: forall (n :: Natural). 1 <= n => Domain n -> Integer -> Integer -> Property Source #

correct_bitbounds :: forall (n :: Natural). 1 <= n => NatRepr n -> (Domain n, Integer) -> Property Source #