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 FPV(self, ast): 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))
def prepare_float(val, signext=False, size=SIZE) -> z3.FPRef: if z3.is_fp(val): return val size_class = z3.Float64() if size == 32: size_class = z3.Float32() elif size == 128: size_class = z3.Float128() if type(val) in (int, float): result = z3.FPVal(val) else: bv_val = prepare(val, signext, size) result = z3.fpBVToFP(bv_val, size_class) return result
def prepare_float(val, signext=False, size=SIZE) -> z3.FPRef: size_class = fp_size_to_sort(size) if z3.is_fp(val): result = val elif type(val) in (int, float): result = z3.FPVal(float(val), size_class) else: bv_val = z3.simplify(prepare(val, signext, size)) if bv_val.decl().name() == "fp.to_ieee_bv": result = bv_val.arg(0) else: result = z3.fpToFP(bv_val, size_class) if result.sort() != size_class: result = z3.fpFPToFP(result, size_class) return result
def cast(self, value, is_type, to_type): if is_type is Types.STRING and isinstance(to_type, z3.z3.DatatypeSortRef): # the value is a string and it should be cast to a datatyperef # (i.e. an enum-type), just return the value because we can deal with it return value value_is_int = isinstance(value, int) value_is_float = isinstance(value, float) if is_type is to_type: # already correct type, just return the value return value """ INT <---> INTEGER """ elif is_type is Types.INT and to_type is Types.INTEGER: if value_is_int or value_is_float: return value # this happens if it is an int numeral (e.g. 2) else: return z3.BV2Int(value) elif is_type is Types.INTEGER and to_type is Types.INT: if value_is_int or value_is_float: return value else: return z3.Int2BV(value, 32) """ INT <---> FLOAT """ elif is_type is Types.FLOAT and to_type is Types.INT: if value_is_float: return value # this happens if it is a float numeral (e.g. 3.14) else: return z3.fpToSBV(z3.RNE(), value, z3.BitVecSort(32)) elif is_type is Types.INT and to_type is Types.FLOAT: if value_is_int: return value else: return z3.fpSignedToFP(z3.RNE(), value, z3.Float32()) """ INTEGER <---> FLOAT """ elif is_type is Types.FLOAT and to_type is Types.INTEGER: if value_is_float: return value # this happens if it is a float numeral (e.g. 3.14) else: return self.cast(self.cast(value, Types.FLOAT, Types.INT), Types.INT, Types.INTEGER) elif is_type is Types.INTEGER and to_type is Types.FLOAT: if value_is_int: return value else: return self.cast(self.cast(value, Types.INTEGER, Types.INT), Types.INT, Types.FLOAT) """ from REAL """ elif is_type is Types.REAL and to_type is Types.INTEGER: if value_is_float: return value else: return z3.ToInt(value) elif is_type is Types.REAL and to_type is Types.INT: return self.cast(self.cast(value, Types.REAL, Types.INTEGER), Types.INTEGER, Types.INT) elif is_type is Types.REAL and to_type is Types.FLOAT: """ Rounding modes: probably should make these parameterizable! roundNearestTiesToEven ... RNE() = default roundNearestTiesToAway ... RNA() roundTowardPositive ...... RTP() roundTowardNegative ...... RTN() roundTowardZero .......... RTZ() """ if value_is_int or value_is_float: # int numeral return value else: return z3.fpRealToFP(z3.RNE(), value, z3.Float32()) """ to REAL """ elif is_type is Types.INT and to_type is Types.REAL: if value_is_int or value_is_float: # int numeral return value else: return z3.ToReal(self.cast(value, Types.INT, Types.INTEGER)) elif is_type is Types.INTEGER and to_type is Types.REAL: if value_is_int or value_is_float: # int numeral return value else: return z3.ToReal(value) elif is_type is Types.FLOAT and to_type is Types.REAL: if value_is_int or value_is_float: return value # this happens if it is a float numeral (e.g. 3.14) else: return z3.fpToReal(value) """ FROM BOOL conversions """ elif is_type is Types.BOOL and to_type is Types.INT: return z3.If(value, z3.BitVecVal(1, 32), z3.BitVecVal(0, 32)) elif is_type is Types.BOOL and to_type is Types.INTEGER: return z3.If(value, 1, 0) elif is_type is Types.BOOL and to_type is Types.REAL: return z3.If(value, 1.0, 0.0) elif is_type is Types.BOOL and to_type is Types.FLOAT: return z3.If(value, z3.FPVal(1.0, z3.Float32()), z3.FPVal(0.0, z3.Float32())) """ TO BOOL conversions """ elif is_type is Types.INT and to_type is Types.BOOL: return value == 1 elif is_type is Types.INTEGER and to_type is Types.BOOL: return value == 1 elif is_type is Types.REAL and to_type is Types.BOOL: return value == 1 elif is_type is Types.FLOAT and to_type is Types.BOOL: return value == 1 raise TypeError(f"Don't know how to cast from {is_type} to {to_type}!")
from .esilclasses import * import z3 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 _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)
# Constants # --------- @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 as_z3(self) -> z3.ExprRef: return z3.FPVal(self.number)