4

The C API for z3 has functions such as Z3_mk_bvadd_no_overflow, but these do not seem to be available from the Python API. Before I start hacking to solve this I'd just like to verify that this is the case and also request that these be added to the official version.

I'm trying adding things like this to z3.py, but so far haven't managed to get the details right. Suggestions about where I'm going wrong would be appreciated. I'm working on the contrib branch.

def Bvadd_no_overflow(a, b, si, ctx=None):
    """Create a Z3 bvadd_no_overflow expression.

    """
    ctx = _get_ctx(_ctx_from_ast_arg_list([a, b], ctx))
    # argh can't hard-code the 32
    s = BitVecSort(32,ctx)
    a = s.cast(a)
    b = s.cast(b)
    # this function requires a bool as the last argument but is it a python bool, a
    # z3 bool, or what?
    return BitVecRef(Z3_mk_bvadd_no_overflow(ctx.ref(), a.as_ast(), b.as_ast(), 1), ctx) 
John Regehr
  • 123
  • 1
  • 6

2 Answers2

5

Indeed, it seems those functions not available in the higher level API yet. Something along these lines may do the job for you:

def bvadd_no_overflow(x, y, signed=False):
    assert x.ctx_ref()==y.ctx_ref()
    a, b = z3._coerce_exprs(x, y)
    return BoolRef(Z3_mk_bvadd_no_overflow(a.ctx_ref(), a.as_ast(), b.as_ast(), signed))

Here's an example of using this function, which works for me:

q = BitVec('q', 32)
r = BitVec('r', 32)
s.add(bvadd_no_overflow(q, r))
print(s)

which prints

[Extract(32, 32, ZeroExt(1, q) + ZeroExt(1, r)) == 0]

(Internally, this is represented as taking the + of two bit-vectors and then extracting the most significant bit.)

Christoph Wintersteiger
  • 8,234
  • 1
  • 16
  • 30
  • Christoph, thanks! When called this code dies with a "sort mismatch on argument at position 2" but I'm sure it's close, I'll keep trying. – John Regehr Mar 24 '14 at 18:26
  • Well, I tried a lot of little variations on this theme and keep getting the same error message, argh. – John Regehr Mar 24 '14 at 19:40
  • I've update this with a call to z3._coerce_exprs (which the API does). Both this and the previous version work for me. I've added an example of using it just in case the problem lies there. – Christoph Wintersteiger Mar 24 '14 at 21:33
  • Thanks Christoph! I'll submit a pull request once I get this integrated. – John Regehr Mar 25 '14 at 21:06
1

I encountered the same problem 8 years after the last answer was posted. So here is an update:

The Z3 Python API now has a function BVAddNoOverflow which is defined as such:

def BVAddNoOverflow(a, b, signed):
    """A predicate the determines that bit-vector addition does not overflow"""
    _check_bv_args(a, b)
    a, b = _coerce_exprs(a, b)
    return BoolRef(Z3_mk_bvadd_no_overflow(a.ctx_ref(), a.as_ast(),
                   b.as_ast(), signed), a.ctx)

Equivalent functions also exist for overflow and underflow on other arithmetic operations: BVSubNoOverflow, BVMulNoUnderflow, etc.

I post this here for posterity as this is where I landed when trying to answer a similar question.

Olivier Melançon
  • 21,584
  • 4
  • 41
  • 73