def _convert(self, obj): if isinstance(obj, FSort): return z3.FPSort(obj.exp, obj.mantissa, ctx=self._context) elif isinstance(obj, RM): if obj == RM_RNE: return z3.RNE(ctx=self._context) elif obj == RM_RNA: return z3.RNA(ctx=self._context) elif obj == RM_RTP: return z3.RTP(ctx=self._context) elif obj == RM_RTN: return z3.RTN(ctx=self._context) elif obj == RM_RTZ: return z3.RTZ(ctx=self._context) else: raise BackendError("unrecognized rounding mode") elif obj is True: return z3.BoolVal(True, ctx=self._context) elif obj is False: return z3.BoolVal(False, ctx=self._context) elif isinstance(obj, (numbers.Number, str)): return obj elif hasattr(obj, '__module__') and obj.__module__ in ('z3', 'z3.z3'): return obj else: l.debug("BackendZ3 encountered unexpected type %s", type(obj)) raise BackendError("unexpected type %s encountered in BackendZ3" % type(obj))
def _fptoui(term, smt): v = smt.eval(term.arg) src = smt.type(term.arg) tgt = smt.type(term) # TODO: don't generate trivial conds return smt._conditional_conv_value([0 <= v, v <= (2**tgt.width) - 1], z3.fpToUBV(z3.RTZ(), v, _ty_sort(tgt)), term.name)
def _fptosi(term, smt): v = smt.eval(term.arg) src = smt.type(term.arg) tgt = smt.type(term) m = 2**(tgt.width - 1) # TODO: don't generate trivial conds return smt._conditional_conv_value([v >= -m, v <= m - 1], z3.fpToSBV(z3.RTZ(), v, _ty_sort(tgt)), term.name)
def _convert(self, obj, result=None): if type(obj) is NativeBVV: return z3.BitVecVal(obj.value, obj.bits) elif isinstance(obj, FSort): return z3.FPSort(obj.exp, obj.mantissa) elif isinstance(obj, RM): if obj == RM_RNE: return z3.RNE() elif obj == RM_RNA: return z3.RNA() elif obj == RM_RTP: return z3.RTP() elif obj == RM_RTN: return z3.RTN() elif obj == RM_RTZ: return z3.RTZ() else: raise BackendError("unrecognized rounding mode") elif isinstance(obj, NativeFPV): val = str(obj.value) sort = self._convert(obj.sort) if val == 'inf': return z3.fpPlusInfinity(sort) elif val == '-inf': return z3.fpMinusInfinity(sort) elif val == '0.0': return z3.fpPlusZero(sort) elif val == '-0.0': return z3.fpMinusZero(sort) elif val == 'nan': return z3.fpNaN(sort) else: better_val = str(Decimal(obj.value)) return z3.FPVal(better_val, sort) elif obj is True: return z3.BoolVal(True) elif obj is False: return z3.BoolVal(False) elif type(obj) in (int, long, float, str): return obj elif hasattr(obj, '__module__') and obj.__module__ == 'z3': return obj else: l.debug("BackendZ3 encountered unexpected type %s", type(obj)) raise BackendError("unexpected type %s encountered in BackendZ3" % type(obj))
# We do float16 because it lets the solver run much faster. These results # should generalize to fp32 and fp64, and you can verify this by changing the # value of FLOAT_TY (and then waiting a while). FLOAT_TY = z3.Float16 a = z3.FP("a", FLOAT_TY()) b = z3.FP("b", FLOAT_TY()) c = z3.FP("c", FLOAT_TY()) s = z3.Solver() # C must be a power of 2, i.e. significand bits must all be 0. s.add(z3.Extract(FLOAT_TY().sbits() - 1, 0, z3.fpToIEEEBV(c)) == 0) for rm in [z3.RTZ(), z3.RNE()]: z3.set_default_rounding_mode(rm) before = a * c + b * c after = (a + b) * c # Check that before == after, allowing that 0 == -0. s.add( z3.Not( z3.Or( before == after, # z3.And(z3.fpIsZero(before), z3.fpIsZero(after))))) for x in [ (a * c), (b * c), (a + b),
SIZE = 64 FSIZE = z3.Float64() ONE = z3.BitVecVal(1, SIZE) ZERO = z3.BitVecVal(0, SIZE) NEGONE = z3.BitVecVal(-1, SIZE) FONE = z3.FPVal(1.0, FSIZE) FZERO = z3.FPVal(0.0, FSIZE) FNEGONE = z3.FPVal(-1.0, FSIZE) INT = 1 FLOAT = 2 FPM = z3.RTZ() def pop_values(stack, state, num: int = 1, signext=False) -> List[z3.BitVecRef]: size = state.esil["size"] val_type = state.esil["type"] return [ get_value(stack.pop(), state, signext, size, val_type) for i in range(num) ] def get_value(val, state, signext=False, size=SIZE, val_type=INT) \ -> z3.BitVecRef:
def _uitofp(term, smt): x = smt.eval(term._args[0]) tgt = smt.type(term) return z3.fpToFPUnsigned(z3.RTZ(), x, _ty_sort(tgt))
def _fptoui(term, smt): x = smt.eval(term._args[0]) tgt = smt.type(term) return z3.fpToUBV(z3.RTZ(), x, _ty_sort(tgt))
# only the signed ones can be FP, so this is safe return cmp(smt.eval(term.x), smt.eval(term.y)) def _must(op): return lambda t, s: s._must_analysis(t, op) eval.register(CannotBeNegativeZeroPred, BaseSMTTranslator, _must(lambda x: z3.Not(x == z3.fpMinusZero(x.sort())))) eval.register(FPIdenticalPred, BaseSMTTranslator, _handler(operator.eq)) eval.register(FPIntegerPred, BaseSMTTranslator, _handler(lambda x: x == z3.fpRoundToIntegral(z3.RTZ(), x))) def _has_attr(attr): return lambda t, s: s._has_attr(attr, t._args[0]) eval.register(HasNInfPred, BaseSMTTranslator, _has_attr('ninf')) eval.register(HasNNaNPred, BaseSMTTranslator, _has_attr('nnan')) eval.register(HasNSWPred, BaseSMTTranslator, _has_attr('nsw')) eval.register(HasNSZPred, BaseSMTTranslator, _has_attr('nsz')) eval.register(HasNUWPred, BaseSMTTranslator, _has_attr('nuw')) eval.register(IsExactPred, BaseSMTTranslator, _has_attr('exact')) @eval.register(IsConstantPred, BaseSMTTranslator)