public void Run() { Dictionary<string, string> cfg = new Dictionary<string, string>() { { "AUTO_CONFIG", "true" } }; using (Context ctx = new Context(cfg)) { BitVecExpr x = ctx.MkBVConst("x", 32); BitVecExpr[] powers = new BitVecExpr[32]; for (uint i = 0; i < 32; i++) powers[i] = ctx.MkBVSHL(ctx.MkBV(1, 32), ctx.MkBV(i, 32)); BoolExpr step_zero = ctx.MkEq(ctx.MkBVAND(x, ctx.MkBVSub(x, ctx.MkBV(1, 32))), ctx.MkBV(0, 32)); BoolExpr fast = ctx.MkAnd(ctx.MkNot(ctx.MkEq(x, ctx.MkBV(0, 32))), step_zero); BoolExpr slow = ctx.MkFalse(); foreach (BitVecExpr p in powers) slow = ctx.MkOr(slow, ctx.MkEq(x, p)); TestDriver.CheckString(fast, "(and (not (= x #x00000000)) (= (bvand x (bvsub x #x00000001)) #x00000000))"); Solver s = ctx.MkSolver(); s.Assert(ctx.MkNot(ctx.MkEq(fast, slow))); TestDriver.CheckUNSAT(s.Check()); s = ctx.MkSolver(); s.Assert(ctx.MkNot(step_zero)); TestDriver.CheckSAT(s.Check()); } }
/// <summary> /// Arithmetic shift right /// </summary> /// <remarks> /// It is like logical shift right except that the most significant /// bits of the result always copy the most significant bit of the /// second argument. /// /// NB. The semantics of shift operations varies between environments. This /// definition does not necessarily capture directly the semantics of the /// programming language or assembly architecture you are modeling. /// /// The arguments must have a bit-vector sort. /// </remarks> public BitVecExpr MkBVASHR(BitVecExpr t1, BitVecExpr t2) { Contract.Requires(t1 != null); Contract.Requires(t2 != null); Contract.Ensures(Contract.Result<BitVecExpr>() != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvashr(nCtx, t1.NativeObject, t2.NativeObject)); }
/// <summary> /// Create a predicate that checks that the bit-wise addition does not underflow. /// </summary> /// <remarks> /// The arguments must be of bit-vector sort. /// </remarks> public BoolExpr MkBVAddNoUnderflow(BitVecExpr t1, BitVecExpr t2) { Contract.Requires(t1 != null); Contract.Requires(t2 != null); Contract.Ensures(Contract.Result<BoolExpr>() != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvadd_no_underflow(nCtx, t1.NativeObject, t2.NativeObject)); }
/// <summary> /// Create an integer from the bit-vector argument <paramref name="t"/>. /// </summary> /// <remarks> /// If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. /// So the result is non-negative and in the range <c>[0..2^N-1]</c>, where /// N are the number of bits in <paramref name="t"/>. /// If \c is_signed is true, \c t1 is treated as a signed bit-vector. /// /// NB. This function is essentially treated as uninterpreted. /// So you cannot expect Z3 to precisely reflect the semantics of this function /// when solving constraints with this function. /// /// The argument must be of bit-vector sort. /// </remarks> public IntExpr MkBV2Int(BitVecExpr t, bool signed) { Contract.Requires(t != null); Contract.Ensures(Contract.Result<IntExpr>() != null); CheckContextMatch(t); return new IntExpr(this, Native.Z3_mk_bv2int(nCtx, t.NativeObject, (signed) ? 1 : 0)); }
/// <summary> /// Bit-vector zero extension. /// </summary> /// <remarks> /// Extend the given bit-vector with zeros to the (unsigned) equivalent /// bitvector of size <c>m+i</c>, where \c m is the size of the /// given bit-vector. /// The argument <paramref name="t"/> must have a bit-vector sort. /// </remarks> public BitVecExpr MkZeroExt(uint i, BitVecExpr t) { Contract.Requires(t != null); Contract.Ensures(Contract.Result<BitVecExpr>() != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_zero_ext(nCtx, i, t.NativeObject)); }
/// <summary> /// Bit-vector extraction. /// </summary> /// <remarks> /// Extract the bits <paramref name="high"/> down to <paramref name="low"/> from a bitvector of /// size <c>m</c> to yield a new bitvector of size <c>n</c>, where /// <c>n = high - low + 1</c>. /// The argument <paramref name="t"/> must have a bit-vector sort. /// </remarks> public BitVecExpr MkExtract(uint high, uint low, BitVecExpr t) { Contract.Requires(t != null); Contract.Ensures(Contract.Result<BitVecExpr>() != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_extract(nCtx, high, low, t.NativeObject)); }
/// <summary> /// Create a predicate that checks that the bit-wise subtraction does not underflow. /// </summary> /// <remarks> /// The arguments must be of bit-vector sort. /// </remarks> public BoolExpr MkBVSubNoUnderflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) { Contract.Requires(t1 != null); Contract.Requires(t2 != null); Contract.Ensures(Contract.Result<BoolExpr>() != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvsub_no_underflow(nCtx, t1.NativeObject, t2.NativeObject, (isSigned) ? 1 : 0)); }
/// <summary> /// Take disjunction of bits in a vector, return vector of length 1. /// </summary> /// <remarks>The argument must have a bit-vector sort.</remarks> public BitVecExpr MkBVRedOR(BitVecExpr t) { Contract.Requires(t != null); Contract.Ensures(Contract.Result<BitVecExpr>() != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_bvredor(nCtx, t.NativeObject)); }
/// <summary> /// Create a predicate that checks that the bit-wise negation does not overflow. /// </summary> /// <remarks> /// The arguments must be of bit-vector sort. /// </remarks> public BoolExpr MkBVNegNoOverflow(BitVecExpr t) { Contract.Requires(t != null); Contract.Ensures(Contract.Result<BoolExpr>() != null); CheckContextMatch(t); return new BoolExpr(this, Native.Z3_mk_bvneg_no_overflow(nCtx, t.NativeObject)); }
/// <summary> /// Conversion of a 2's complement signed bit-vector term into a term of FloatingPoint sort. /// </summary> /// <remarks> /// Produces a term that represents the conversion of the bit-vector term t into a /// floating-point term of sort s. The bit-vector t is taken to be in signed /// 2's complement format (when signed==true, otherwise unsigned). If necessary, the /// result will be rounded according to rounding mode rm. /// </remarks> /// <param name="rm">RoundingMode term.</param> /// <param name="t">term of bit-vector sort.</param> /// <param name="s">FloatingPoint sort.</param> /// <param name="signed">flag indicating whether t is interpreted as signed or unsigned bit-vector.</param> public FPExpr MkFPToFP(FPRMExpr rm, BitVecExpr t, FPSort s, bool signed) { Contract.Ensures(Contract.Result<FPExpr>() != null); if (signed) return new FPExpr(this, Native.Z3_mk_fpa_to_fp_signed(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject)); else return new FPExpr(this, Native.Z3_mk_fpa_to_fp_unsigned(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject)); }
/// <summary> /// Conversion of a single IEEE 754-2008 bit-vector into a floating-point number. /// </summary> /// <remarks> /// Produces a term that represents the conversion of a bit-vector term bv to a /// floating-point term of sort s. The bit-vector size of bv (m) must be equal /// to ebits+sbits of s. The format of the bit-vector is as defined by the /// IEEE 754-2008 interchange format. /// </remarks> /// <param name="bv">bit-vector value (of size m).</param> /// <param name="s">FloatingPoint sort (ebits+sbits == m)</param> public FPExpr MkFPToFP(BitVecExpr bv, FPSort s) { Contract.Ensures(Contract.Result<FPExpr>() != null); return new FPExpr(this, Native.Z3_mk_fpa_to_fp_bv(this.nCtx, bv.NativeObject, s.NativeObject)); }
/// <summary> /// Create an expression of FloatingPoint sort from three bit-vector expressions. /// </summary> /// <remarks> /// This is the operator named `fp' in the SMT FP theory definition. /// Note that sgn is required to be a bit-vector of size 1. Significand and exponent /// are required to be greater than 1 and 2 respectively. The FloatingPoint sort /// of the resulting expression is automatically determined from the bit-vector sizes /// of the arguments. /// </remarks> /// <param name="sgn">bit-vector term (of size 1) representing the sign.</param> /// <param name="sig">bit-vector term representing the significand.</param> /// <param name="exp">bit-vector term representing the exponent.</param> public FPExpr MkFP(BitVecExpr sgn, BitVecExpr sig, BitVecExpr exp) { Contract.Ensures(Contract.Result<FPExpr>() != null); return new FPExpr(this, Native.Z3_mk_fpa_fp(this.nCtx, sgn.NativeObject, sig.NativeObject, exp.NativeObject)); }
/// <summary> /// Demonstrate how to use <code>Push</code>and <code>Pop</code>to /// control the size of models. /// </summary> /// <remarks>Note: this test is specialized to 32-bit bitvectors.</remarks> public static void CheckSmall(Context ctx, Solver solver, BitVecExpr[] to_minimize) { Sort bv32 = ctx.MkBitVecSort(32); int num_Exprs = to_minimize.Length; UInt32[] upper = new UInt32[num_Exprs]; UInt32[] lower = new UInt32[num_Exprs]; BitVecExpr[] values = new BitVecExpr[num_Exprs]; for (int i = 0; i < upper.Length; ++i) { upper[i] = UInt32.MaxValue; lower[i] = 0; } bool some_work = true; int last_index = -1; UInt32 last_upper = 0; while (some_work) { solver.Push(); bool check_is_sat = true; while (check_is_sat && some_work) { // Assert all feasible bounds. for (int i = 0; i < num_Exprs; ++i) { solver.Assert(ctx.MkBVULE(to_minimize[i], ctx.MkBV(upper[i], 32))); } check_is_sat = Status.SATISFIABLE == solver.Check(); if (!check_is_sat) { if (last_index != -1) { lower[last_index] = last_upper + 1; } break; } Console.WriteLine("{0}", solver.Model); // narrow the bounds based on the current model. for (int i = 0; i < num_Exprs; ++i) { Expr v = solver.Model.Evaluate(to_minimize[i]); UInt64 ui = ((BitVecNum)v).UInt64; if (ui < upper[i]) { upper[i] = (UInt32)ui; } Console.WriteLine("{0} {1} {2}", i, lower[i], upper[i]); } // find a new bound to add some_work = false; last_index = 0; for (int i = 0; i < num_Exprs; ++i) { if (lower[i] < upper[i]) { last_upper = (upper[i] + lower[i]) / 2; last_index = i; solver.Assert(ctx.MkBVULE(to_minimize[i], ctx.MkBV(last_upper, 32))); some_work = true; break; } } } solver.Pop(); } }
/// <summary> /// Translates an ASTVector into a BitVecExpr[] /// </summary> public BitVecExpr[] ToBitVecExprArray() { uint n = Size; BitVecExpr[] res = new BitVecExpr[n]; for (uint i = 0; i < n; i++) res[i] = (BitVecExpr)Expr.Create(this.Context, this[i].NativeObject); return res; }