def visit_float_is_infinite(self, e): arg = e.arg(0) self._check_fp_sort(arg) arg_sort = arg.sort() pos_inf = None neg_inf = None if self._is_float32_sort(arg_sort): pos_inf = z3.fpPlusInfinity(z3.Float32()) neg_inf = z3.fpMinusInfinity(z3.Float32()) elif self._is_float64_sort(arg_sort): pos_inf = z3.fpPlusInfinity(z3.Float64()) neg_inf = z3.fpMinusInfinity(z3.Float64()) else: raise CoralPrinterException('Unhandled fp.isInfinite op case') temp = z3.Or(z3.fpEQ(arg, pos_inf), z3.fpEQ(arg, neg_inf)) self.visit(temp)
def _float_binary_operator(self, term, op): logger.debug('_fbo: %s\n%s', term, self.attrs[term]) x = self.eval(term.x) y = self.eval(term.y) z = op(x, y) conds = [] if 'nnan' in self.attrs[term]: df = z3.And(z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)), z3.Not(z3.fpIsNaN(z))) conds.append(z3.Implies(self.attrs[term]['nnan'], df)) elif 'nnan' in term.flags: conds += [ z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)), z3.Not(z3.fpIsNaN(z)) ] if 'ninf' in self.attrs[term]: df = z3.And(z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)), z3.Not(z3.fpIsInf(z))) conds.append(z3.Implies(self.attrs[term]['ninf'], df)) elif 'ninf' in term.flags: conds += [ z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)), z3.Not(z3.fpIsInf(z)) ] if 'nsz' in self.attrs[term] or 'nsz' in term.flags: # NOTE: this will return a different qvar for each (in)direct reference # to this term. Is this desirable? b = self.fresh_bool() self.add_qvar(b) z = op(x, y) c = z3.fpIsZero(z) if 'nsz' in self.attrs[term]: c = z3.And(self.attrs[term]['nsz'], c) s = _ty_sort(self.type(term)) z = z3.If(c, z3.If(b, 0, z3.fpMinusZero(s)), z) if isinstance(term, FDivInst): c = [z3.Not(z3.fpIsZero(x)), z3.fpIsZero(y)] if 'nsz' in self.attrs[term]: c.append(self.attrs[term]['nsz']) z = z3.If( z3.And(c), z3.If(b, z3.fpPlusInfinity(s), z3.fpMinusInfinity(s)), z) return self._conditional_value(conds, z, term.name)
def visit_float_is_normal(self, e): arg = e.arg(0) self._check_fp_sort(arg) arg_sort = e.arg(0).sort() smallest_positive_normal = self._get_smallest_positive_normal_for( arg_sort) largest_negative_normal = self._get_largest_negative_normal_for( arg_sort) temp = z3.Or( z3.And(z3.fpGEQ(arg, smallest_positive_normal), z3.fpLT(arg, z3.fpPlusInfinity(arg_sort))), z3.And(z3.fpLEQ(arg, largest_negative_normal), z3.fpGT(arg, z3.fpMinusInfinity(arg_sort)))) self.visit(temp)
def _float_binary_operator(self, term, op): logger.debug('_fbo: %s\n%s', term, self.attrs[term]) x = self.eval(term.x) y = self.eval(term.y) z = op(x,y) conds = [] if 'nnan' in self.attrs[term]: df = z3.And(z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)), z3.Not(z3.fpIsNaN(z))) conds.append(z3.Implies(self.attrs[term]['nnan'], df)) elif 'nnan' in term.flags: conds += [z3.Not(z3.fpIsNaN(x)), z3.Not(z3.fpIsNaN(y)), z3.Not(z3.fpIsNaN(z))] if 'ninf' in self.attrs[term]: df = z3.And(z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)), z3.Not(z3.fpIsInf(z))) conds.append(z3.Implies(self.attrs[term]['ninf'], df)) elif 'ninf' in term.flags: conds += [z3.Not(z3.fpIsInf(x)), z3.Not(z3.fpIsInf(y)), z3.Not(z3.fpIsInf(z))] if 'nsz' in self.attrs[term] or 'nsz' in term.flags: # NOTE: this will return a different qvar for each (in)direct reference # to this term. Is this desirable? b = self.fresh_bool() self.add_qvar(b) z = op(x,y) c = z3.fpIsZero(z) if 'nsz' in self.attrs[term]: c = z3.And(self.attrs[term]['nsz'], c) s = _ty_sort(self.type(term)) z = z3.If(c, z3.If(b, 0, z3.fpMinusZero(s)), z) if isinstance(term, FDivInst): c = [z3.Not(z3.fpIsZero(x)), z3.fpIsZero(y)] if 'nsz' in self.attrs[term]: c.append(self.attrs[term]['nsz']) z = z3.If(z3.And(c), z3.If(b, z3.fpPlusInfinity(s), z3.fpMinusInfinity(s)), z) return self._conditional_value(conds, z, term.name)
def FPV(self, ast): #pylint:disable=unused-argument val = str(ast.args[0]) sort = self._convert(ast.args[1]) 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(ast.args[0])) return z3.FPVal(better_val, sort, ctx=self._context)
def FPV(self, ast, result=None): #pylint:disable=unused-argument val = str(ast.args[0]) sort = self._convert(ast.args[1]) 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(ast.args[0])) return z3.FPVal(better_val, sort, ctx=self._context)
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))
@eval.register(Literal, BaseSMTTranslator) def _literal(term, smt): ty = smt.type(term) if isinstance(ty, FloatType): return z3.FPVal(term.val, _ty_sort(ty)) return z3.BitVecVal(term.val, ty.width) eval.register(FLiteralVal, BaseSMTTranslator, lambda term, smt: z3.FPVal(term.val, _ty_sort(smt.type(term)))) eval.register(FLiteralNaN, BaseSMTTranslator, lambda term, smt: z3.fpNaN(_ty_sort(smt.type(term)))) eval.register(FLiteralPlusInf, BaseSMTTranslator, lambda term, smt: z3.fpPlusInfinity(_ty_sort(smt.type(term)))) eval.register(FLiteralMinusInf, BaseSMTTranslator, lambda term, smt: z3.fpMinusInfinity(_ty_sort(smt.type(term)))) eval.register(FLiteralMinusZero, BaseSMTTranslator, lambda term, smt: z3.fpMinusZero(_ty_sort(smt.type(term)))) @eval.register(UndefValue, BaseSMTTranslator) def _undef(term, smt): ty = smt.type(term) x = smt.fresh_var(ty) smt.add_qvar(x) return x @eval.register(PoisonValue, BaseSMTTranslator)
def _literal(term, smt): ty = smt.type(term) if isinstance(ty, FloatType): return z3.FPVal(term.val, _ty_sort(ty)) return z3.BitVecVal(term.val, ty.width) eval.register(FLiteralVal, BaseSMTTranslator, lambda term, smt: z3.FPVal(term.val, _ty_sort(smt.type(term)))) eval.register(FLiteralNaN, BaseSMTTranslator, lambda term, smt: z3.fpNaN(_ty_sort(smt.type(term)))) eval.register(FLiteralPlusInf, BaseSMTTranslator, lambda term, smt: z3.fpPlusInfinity(_ty_sort(smt.type(term)))) eval.register(FLiteralMinusInf, BaseSMTTranslator, lambda term, smt: z3.fpMinusInfinity(_ty_sort(smt.type(term)))) eval.register(FLiteralMinusZero, BaseSMTTranslator, lambda term, smt: z3.fpMinusZero(_ty_sort(smt.type(term)))) @eval.register(UndefValue, BaseSMTTranslator) def _undef(term, smt): ty = smt.type(term) x = smt.fresh_var(ty) smt.add_qvar(x) return x