From 1eaf909d3ed3ef47f0304ee6c1be2b221e4c4b1c Mon Sep 17 00:00:00 2001 From: Philippe Suter <philippe.suter@gmail.com> Date: Thu, 2 Jun 2011 16:46:49 +0200 Subject: [PATCH] Support for --BV flag to use bit-vectors instead of mathematical ints. --- src/funcheck/FunCheckPlugin.scala | 6 ++++-- src/purescala/FairZ3Solver.scala | 34 ++++++++++++++++++++----------- src/purescala/Settings.scala | 2 ++ 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/funcheck/FunCheckPlugin.scala b/src/funcheck/FunCheckPlugin.scala index c11533467..c5bcb8d9c 100644 --- a/src/funcheck/FunCheckPlugin.scala +++ b/src/funcheck/FunCheckPlugin.scala @@ -33,6 +33,7 @@ class FunCheckPlugin(val global: Global, val actionAfterExtraction : Option[Prog " -P:funcheck:testbounds=l:u Lower and upper bounds for integers in recursive datatypes" + "\n" + " -P:funcheck:timeout=N Sets a timeout of N seconds" + "\n" + " -P:funcheck:XP Enable weird transformations and other bug-producing features" + "\n" + + " -P:funcheck:BV Use bit-vectors for integers" + "\n" + " -P:funcheck:prune Use additional SMT queries to rule out some unrollings" + "\n" + " -P:funcheck:cores Use UNSAT cores in the unrolling/refinement step" + "\n" + " -P:funcheck:quickcheck Use QuickCheck-like random search in parrallel with Z3" + "\n" + @@ -53,8 +54,9 @@ class FunCheckPlugin(val global: Global, val actionAfterExtraction : Option[Prog case "bapa" => purescala.Settings.useBAPA = true case "impure" => purescala.Settings.impureTestcases = true case "XP" => purescala.Settings.experimental = true - case "prune" => purescala.Settings.pruneBranches = true - case "cores" => purescala.Settings.useCores = true + case "BV" => purescala.Settings.bitvectorBitwidth = Some(32) + case "prune" => purescala.Settings.pruneBranches = true + case "cores" => purescala.Settings.useCores = true case "quickcheck" => purescala.Settings.useQuickCheck = true case "noLuckyTests" => purescala.Settings.luckyTest = false case s if s.startsWith("unrolling=") => purescala.Settings.unrollingLevel = try { s.substring("unrolling=".length, s.length).toInt } catch { case _ => 0 } diff --git a/src/purescala/FairZ3Solver.scala b/src/purescala/FairZ3Solver.scala index 28e78b837..e3a4002ae 100644 --- a/src/purescala/FairZ3Solver.scala +++ b/src/purescala/FairZ3Solver.scala @@ -15,6 +15,8 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac // assert(Settings.useFairInstantiator) private final val UNKNOWNASSAT : Boolean = !Settings.noForallAxioms + private final val USEBV : Boolean = Settings.bitvectorBitwidth.isDefined + private final val BVWIDTH : Int = Settings.bitvectorBitwidth.getOrElse(-1) val description = "Fair Z3 Solver" override val shortDescription = "Z3-f" @@ -121,7 +123,11 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac case Some(z3sort) => z3sort case None => { import Z3Context.{ADTSortReference, RecursiveType, RegularSort} - intSort = z3.mkIntSort + intSort = if(USEBV) { + z3.mkBVSort(BVWIDTH) + } else { + z3.mkIntSort + } boolSort = z3.mkBoolSort def typeToSortRef(tt: TypeTree): ADTSortReference = tt match { @@ -163,7 +169,11 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac import Z3Context.{ADTSortReference, RecursiveType, RegularSort} // NOTE THAT abstract classes that extend abstract classes are not // currently supported in the translation - intSort = z3.mkIntSort + intSort = if(USEBV) { + z3.mkBVSort(BVWIDTH) + } else { + z3.mkIntSort + } boolSort = z3.mkBoolSort setSorts = Map.empty setCardFuns = Map.empty @@ -349,7 +359,7 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac case None => { val newSetSort = z3.mkSetSort(typeToSort(base)) setSorts = setSorts + (base -> newSetSort) - val newCardFun = z3.mkFreshFuncDecl("card", Seq(newSetSort), z3.mkIntSort) + val newCardFun = z3.mkFreshFuncDecl("card", Seq(newSetSort), intSort) setCardFuns = setCardFuns + (base -> newCardFun) newSetSort } @@ -859,15 +869,15 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac case IntLiteral(v) => z3.mkInt(v, intSort) case BooleanLiteral(v) => if (v) z3.mkTrue() else z3.mkFalse() case Equals(l, r) => z3.mkEq(rec(l), rec(r)) - case Plus(l, r) => z3.mkAdd(rec(l), rec(r)) - case Minus(l, r) => z3.mkSub(rec(l), rec(r)) - case Times(l, r) => z3.mkMul(rec(l), rec(r)) - case Division(l, r) => z3.mkDiv(rec(l), rec(r)) - case UMinus(e) => z3.mkUnaryMinus(rec(e)) - case LessThan(l, r) => z3.mkLT(rec(l), rec(r)) - case LessEquals(l, r) => z3.mkLE(rec(l), rec(r)) - case GreaterThan(l, r) => z3.mkGT(rec(l), rec(r)) - case GreaterEquals(l, r) => z3.mkGE(rec(l), rec(r)) + case Plus(l, r) => if(USEBV) z3.mkBVAdd(rec(l), rec(r)) else z3.mkAdd(rec(l), rec(r)) + case Minus(l, r) => if(USEBV) z3.mkBVSub(rec(l), rec(r)) else z3.mkSub(rec(l), rec(r)) + case Times(l, r) => if(USEBV) z3.mkBVMul(rec(l), rec(r)) else z3.mkMul(rec(l), rec(r)) + case Division(l, r) => if(USEBV) z3.mkBVSdiv(rec(l), rec(r)) else z3.mkDiv(rec(l), rec(r)) + case UMinus(e) => if(USEBV) z3.mkBVNeg(rec(e)) else z3.mkUnaryMinus(rec(e)) + case LessThan(l, r) => if(USEBV) z3.mkBVSlt(rec(l), rec(r)) else z3.mkLT(rec(l), rec(r)) + case LessEquals(l, r) => if(USEBV) z3.mkBVSle(rec(l), rec(r)) else z3.mkLE(rec(l), rec(r)) + case GreaterThan(l, r) => if(USEBV) z3.mkBVSgt(rec(l), rec(r)) else z3.mkGT(rec(l), rec(r)) + case GreaterEquals(l, r) => if(USEBV) z3.mkBVSge(rec(l), rec(r)) else z3.mkGE(rec(l), rec(r)) case c@CaseClass(cd, args) => { val constructor = adtConstructors(cd) constructor(args.map(rec(_)): _*) diff --git a/src/purescala/Settings.scala b/src/purescala/Settings.scala index b369a6387..651a13c26 100644 --- a/src/purescala/Settings.scala +++ b/src/purescala/Settings.scala @@ -23,4 +23,6 @@ object Settings { var solverTimeout : Option[Int] = None var luckyTest : Boolean = true var useQuickCheck : Boolean = false + // When this is None, use real integers + var bitvectorBitwidth : Option[Int] = None } -- GitLab