aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/Expr
diff options
context:
space:
mode:
authorPeter Collingbourne <pcc@google.com>2014-03-09 01:15:38 -0800
committerPeter Collingbourne <pcc@google.com>2014-03-09 01:22:43 -0800
commit2ea7722ac9b43857358dc12493d7bd9de16e313b (patch)
tree8f11080c24b78167e6ebcb24dd662e019b450614 /lib/Expr
parent2f9c04b09ac8dd81c85f46d3fd89903aafed7370 (diff)
downloadklee-2ea7722ac9b43857358dc12493d7bd9de16e313b.tar.gz
Use clang-format to reformat SMT-LIB printer in LLVM style.
Diffstat (limited to 'lib/Expr')
-rw-r--r--lib/Expr/ExprSMTLIBLetPrinter.cpp442
-rw-r--r--lib/Expr/ExprSMTLIBPrinter.cpp1699
2 files changed, 1049 insertions, 1092 deletions
diff --git a/lib/Expr/ExprSMTLIBLetPrinter.cpp b/lib/Expr/ExprSMTLIBLetPrinter.cpp
index 7225704e..6a88ab5d 100644
--- a/lib/Expr/ExprSMTLIBLetPrinter.cpp
+++ b/lib/Expr/ExprSMTLIBLetPrinter.cpp
@@ -1,4 +1,5 @@
-//===-- ExprSMTLIBLetPrinter.cpp ------------------------------------------*- C++ -*-===//
+//===-- ExprSMTLIBLetPrinter.cpp ------------------------------------------*-
+//C++ -*-===//
//
// The KLEE Symbolic Virtual Machine
//
@@ -13,237 +14,220 @@
using namespace std;
-namespace ExprSMTLIBOptions
-{
- llvm::cl::opt<bool> useLetExpressions("smtlib-use-let-expressions",
- llvm::cl::desc("Enables generated SMT-LIBv2 files to use (let) expressions (default=on)"),
- llvm::cl::init(true)
- );
+namespace ExprSMTLIBOptions {
+llvm::cl::opt<bool>
+useLetExpressions("smtlib-use-let-expressions",
+ llvm::cl::desc("Enables generated SMT-LIBv2 files to use "
+ "(let) expressions (default=on)"),
+ llvm::cl::init(true));
}
-namespace klee
-{
- const char ExprSMTLIBLetPrinter::BINDING_PREFIX[] = "?B";
-
-
- ExprSMTLIBLetPrinter::ExprSMTLIBLetPrinter() :
- bindings(), firstEO(), twoOrMoreEO(),
- disablePrintedAbbreviations(false)
- {
- }
-
- void ExprSMTLIBLetPrinter::generateOutput()
- {
- if(p==NULL || query == NULL || o ==NULL)
- {
- std::cerr << "Can't print SMTLIBv2. Output or query bad!" << std::endl;
- return;
- }
-
- generateBindings();
-
- if(isHumanReadable()) printNotice();
- printOptions();
- printSetLogic();
- printArrayDeclarations();
- printLetExpression();
- printAction();
- printExit();
- }
-
- void ExprSMTLIBLetPrinter::scan(const ref<Expr>& e)
- {
- if(isa<ConstantExpr>(e))
- return; //we don't need to scan simple constants
-
- if(firstEO.insert(e).second)
- {
- //We've not seen this expression before
-
- if(const ReadExpr* re = dyn_cast<ReadExpr>(e))
- {
-
- //Attempt to insert array and if array wasn't present before do more things
- if(usedArrays.insert(re->updates.root).second)
- {
-
- //check if the array is constant
- if( re->updates.root->isConstantArray())
- haveConstantArray=true;
-
- //scan the update list
- scanUpdates(re->updates.head);
-
- }
-
- }
-
- //recurse into the children
- Expr* ep = e.get();
- for(unsigned int i=0; i < ep->getNumKids(); i++)
- scan(ep->getKid(i));
- }
- else
- {
- /* We must of seen the expression before. Add it to
- * the set of twoOrMoreOccurances. We don't need to
- * check if the insertion fails.
- */
- twoOrMoreEO.insert(e);
- }
- }
-
- void ExprSMTLIBLetPrinter::generateBindings()
- {
- //Assign a number to each binding that will be used
- unsigned int counter=0;
- for(set<ref<Expr> >::const_iterator i=twoOrMoreEO.begin();
- i!= twoOrMoreEO.end(); ++i)
- {
- bindings.insert(std::make_pair(*i,counter));
- ++counter;
- }
- }
-
- void ExprSMTLIBLetPrinter::printExpression(const ref<Expr>& e, ExprSMTLIBPrinter::SMTLIB_SORT expectedSort)
- {
- map<const ref<Expr>,unsigned int>::const_iterator i= bindings.find(e);
-
- if(disablePrintedAbbreviations || i == bindings.end())
- {
- /*There is no abbreviation for this expression so print it normally.
- * Do this by using the parent method.
- */
- ExprSMTLIBPrinter::printExpression(e,expectedSort);
- }
- else
- {
- //Use binding name e.g. "?B1"
-
- /* Handle the corner case where the expectedSort
- * doesn't match the sort of the abbreviation. Not really very efficient (calls bindings.find() twice),
- * we'll cast and call ourself again but with the correct expectedSort.
- */
- if(getSort(e) != expectedSort)
- {
- printCastToSort(e,expectedSort);
- return;
- }
-
- // No casting is needed in this depth of recursion, just print the abbreviation
- *p << BINDING_PREFIX << i->second;
- }
- }
-
- void ExprSMTLIBLetPrinter::reset()
- {
- //Let parent clean up first
- ExprSMTLIBPrinter::reset();
-
- firstEO.clear();
- twoOrMoreEO.clear();
- bindings.clear();
- }
-
- void ExprSMTLIBLetPrinter::printLetExpression()
- {
- *p << "(assert"; p->pushIndent(); printSeperator();
-
- if(bindings.size() !=0 )
- {
- //Only print let expression if we have bindings to use.
- *p << "(let"; p->pushIndent(); printSeperator();
- *p << "( "; p->pushIndent();
-
- //Print each binding
- for(map<const ref<Expr>, unsigned int>::const_iterator i= bindings.begin();
- i!=bindings.end(); ++i)
- {
- printSeperator();
- *p << "(" << BINDING_PREFIX << i->second << " ";
- p->pushIndent();
-
- //Disable abbreviations so none are used here.
- disablePrintedAbbreviations=true;
-
- //We can abbreviate SORT_BOOL or SORT_BITVECTOR in let expressions
- printExpression(i->first,getSort(i->first));
-
- p->popIndent();
- printSeperator();
- *p << ")";
- }
-
-
- p->popIndent(); printSeperator();
- *p << ")";
- printSeperator();
-
- //Re-enable printing abbreviations.
- disablePrintedAbbreviations=false;
-
- }
-
- //print out Expressions with abbreviations.
- unsigned int numberOfItems= query->constraints.size() +1; //+1 for query
- unsigned int itemsLeft=numberOfItems;
- vector<ref<Expr> >::const_iterator constraint=query->constraints.begin();
-
- /* Produce nested (and () () statements. If the constraint set
- * is empty then we will only print the "queryAssert".
- */
- for(; itemsLeft !=0; --itemsLeft)
- {
- if(itemsLeft >=2)
- {
- *p << "(and"; p->pushIndent(); printSeperator();
- printExpression(*constraint,SORT_BOOL); //We must and together bool expressions
- printSeperator();
- ++constraint;
- continue;
- }
- else
- {
- // must have 1 item left (i.e. the "queryAssert")
- if(isHumanReadable()) { *p << "; query"; p->breakLineI();}
- printExpression(queryAssert,SORT_BOOL); //The query must be a bool expression
-
- }
- }
-
- /* Produce closing brackets for nested "and statements".
- * Number of "nested ands" = numberOfItems -1
- */
- itemsLeft= numberOfItems -1;
- for(; itemsLeft!=0; --itemsLeft)
- {
- p->popIndent(); printSeperator();
- *p << ")";
- }
-
-
-
- if(bindings.size() !=0)
- {
- //end let expression
- p->popIndent(); printSeperator();
- *p << ")"; printSeperator();
- }
-
- //end assert
- p->popIndent(); printSeperator();
- *p << ")";
- p->breakLineI();
- }
-
- ExprSMTLIBPrinter* createSMTLIBPrinter()
- {
- if(ExprSMTLIBOptions::useLetExpressions)
- return new ExprSMTLIBLetPrinter();
- else
- return new ExprSMTLIBPrinter();
- }
+namespace klee {
+const char ExprSMTLIBLetPrinter::BINDING_PREFIX[] = "?B";
+ExprSMTLIBLetPrinter::ExprSMTLIBLetPrinter()
+ : bindings(), firstEO(), twoOrMoreEO(), disablePrintedAbbreviations(false) {
+}
+
+void ExprSMTLIBLetPrinter::generateOutput() {
+ if (p == NULL || query == NULL || o == NULL) {
+ std::cerr << "Can't print SMTLIBv2. Output or query bad!" << std::endl;
+ return;
+ }
+
+ generateBindings();
+
+ if (isHumanReadable())
+ printNotice();
+ printOptions();
+ printSetLogic();
+ printArrayDeclarations();
+ printLetExpression();
+ printAction();
+ printExit();
+}
+
+void ExprSMTLIBLetPrinter::scan(const ref<Expr> &e) {
+ if (isa<ConstantExpr>(e))
+ return; // we don't need to scan simple constants
+
+ if (firstEO.insert(e).second) {
+ // We've not seen this expression before
+
+ if (const ReadExpr *re = dyn_cast<ReadExpr>(e)) {
+
+ // Attempt to insert array and if array wasn't present before do more
+ // things
+ if (usedArrays.insert(re->updates.root).second) {
+
+ // check if the array is constant
+ if (re->updates.root->isConstantArray())
+ haveConstantArray = true;
+
+ // scan the update list
+ scanUpdates(re->updates.head);
+ }
+ }
+
+ // recurse into the children
+ Expr *ep = e.get();
+ for (unsigned int i = 0; i < ep->getNumKids(); i++)
+ scan(ep->getKid(i));
+ } else {
+ /* We must of seen the expression before. Add it to
+ * the set of twoOrMoreOccurances. We don't need to
+ * check if the insertion fails.
+ */
+ twoOrMoreEO.insert(e);
+ }
+}
+
+void ExprSMTLIBLetPrinter::generateBindings() {
+ // Assign a number to each binding that will be used
+ unsigned int counter = 0;
+ for (set<ref<Expr> >::const_iterator i = twoOrMoreEO.begin();
+ i != twoOrMoreEO.end(); ++i) {
+ bindings.insert(std::make_pair(*i, counter));
+ ++counter;
+ }
+}
+void ExprSMTLIBLetPrinter::printExpression(
+ const ref<Expr> &e, ExprSMTLIBPrinter::SMTLIB_SORT expectedSort) {
+ map<const ref<Expr>, unsigned int>::const_iterator i = bindings.find(e);
+
+ if (disablePrintedAbbreviations || i == bindings.end()) {
+ /*There is no abbreviation for this expression so print it normally.
+ * Do this by using the parent method.
+ */
+ ExprSMTLIBPrinter::printExpression(e, expectedSort);
+ } else {
+ // Use binding name e.g. "?B1"
+
+ /* Handle the corner case where the expectedSort
+ * doesn't match the sort of the abbreviation. Not really very efficient
+ * (calls bindings.find() twice),
+ * we'll cast and call ourself again but with the correct expectedSort.
+ */
+ if (getSort(e) != expectedSort) {
+ printCastToSort(e, expectedSort);
+ return;
+ }
+
+ // No casting is needed in this depth of recursion, just print the
+ // abbreviation
+ *p << BINDING_PREFIX << i->second;
+ }
}
+void ExprSMTLIBLetPrinter::reset() {
+ // Let parent clean up first
+ ExprSMTLIBPrinter::reset();
+
+ firstEO.clear();
+ twoOrMoreEO.clear();
+ bindings.clear();
+}
+
+void ExprSMTLIBLetPrinter::printLetExpression() {
+ *p << "(assert";
+ p->pushIndent();
+ printSeperator();
+
+ if (bindings.size() != 0) {
+ // Only print let expression if we have bindings to use.
+ *p << "(let";
+ p->pushIndent();
+ printSeperator();
+ *p << "( ";
+ p->pushIndent();
+
+ // Print each binding
+ for (map<const ref<Expr>, unsigned int>::const_iterator i =
+ bindings.begin();
+ i != bindings.end(); ++i) {
+ printSeperator();
+ *p << "(" << BINDING_PREFIX << i->second << " ";
+ p->pushIndent();
+
+ // Disable abbreviations so none are used here.
+ disablePrintedAbbreviations = true;
+
+ // We can abbreviate SORT_BOOL or SORT_BITVECTOR in let expressions
+ printExpression(i->first, getSort(i->first));
+
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+ }
+
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+ printSeperator();
+
+ // Re-enable printing abbreviations.
+ disablePrintedAbbreviations = false;
+ }
+
+ // print out Expressions with abbreviations.
+ unsigned int numberOfItems = query->constraints.size() + 1; //+1 for query
+ unsigned int itemsLeft = numberOfItems;
+ vector<ref<Expr> >::const_iterator constraint = query->constraints.begin();
+
+ /* Produce nested (and () () statements. If the constraint set
+ * is empty then we will only print the "queryAssert".
+ */
+ for (; itemsLeft != 0; --itemsLeft) {
+ if (itemsLeft >= 2) {
+ *p << "(and";
+ p->pushIndent();
+ printSeperator();
+ printExpression(*constraint,
+ SORT_BOOL); // We must and together bool expressions
+ printSeperator();
+ ++constraint;
+ continue;
+ } else {
+ // must have 1 item left (i.e. the "queryAssert")
+ if (isHumanReadable()) {
+ *p << "; query";
+ p->breakLineI();
+ }
+ printExpression(queryAssert,
+ SORT_BOOL); // The query must be a bool expression
+ }
+ }
+
+ /* Produce closing brackets for nested "and statements".
+ * Number of "nested ands" = numberOfItems -1
+ */
+ itemsLeft = numberOfItems - 1;
+ for (; itemsLeft != 0; --itemsLeft) {
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+ }
+
+ if (bindings.size() != 0) {
+ // end let expression
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+ printSeperator();
+ }
+
+ // end assert
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+ p->breakLineI();
+}
+
+ExprSMTLIBPrinter *createSMTLIBPrinter() {
+ if (ExprSMTLIBOptions::useLetExpressions)
+ return new ExprSMTLIBLetPrinter();
+ else
+ return new ExprSMTLIBPrinter();
+}
+}
diff --git a/lib/Expr/ExprSMTLIBPrinter.cpp b/lib/Expr/ExprSMTLIBPrinter.cpp
index 9e97a4e0..812c1e9a 100644
--- a/lib/Expr/ExprSMTLIBPrinter.cpp
+++ b/lib/Expr/ExprSMTLIBPrinter.cpp
@@ -1,4 +1,5 @@
-//===-- ExprSMTLIBPrinter.cpp ------------------------------------------*- C++ -*-===//
+//===-- ExprSMTLIBPrinter.cpp ------------------------------------------*- C++
+//-*-===//
//
// The KLEE Symbolic Virtual Machine
//
@@ -14,893 +15,865 @@
using namespace std;
-namespace ExprSMTLIBOptions
-{
- //Command line options
- llvm::cl::opt<klee::ExprSMTLIBPrinter::ConstantDisplayMode> argConstantDisplayMode
- ("smtlib-display-constants", llvm::cl::desc("Sets how bitvector constants are written in generated SMT-LIBv2 files (default=dec)"),
- llvm::cl::values( clEnumValN(klee::ExprSMTLIBPrinter::BINARY, "bin","Use binary form (e.g. #b00101101)"),
- clEnumValN(klee::ExprSMTLIBPrinter::HEX, "hex","Use Hexadecimal form (e.g. #x2D)"),
- clEnumValN(klee::ExprSMTLIBPrinter::DECIMAL, "dec","Use decimal form (e.g. (_ bv45 8) )"),
- clEnumValEnd
- ),
- llvm::cl::init(klee::ExprSMTLIBPrinter::DECIMAL)
+namespace ExprSMTLIBOptions {
+// Command line options
+llvm::cl::opt<klee::ExprSMTLIBPrinter::ConstantDisplayMode>
+argConstantDisplayMode(
+ "smtlib-display-constants",
+ llvm::cl::desc("Sets how bitvector constants are written in generated "
+ "SMT-LIBv2 files (default=dec)"),
+ llvm::cl::values(clEnumValN(klee::ExprSMTLIBPrinter::BINARY, "bin",
+ "Use binary form (e.g. #b00101101)"),
+ clEnumValN(klee::ExprSMTLIBPrinter::HEX, "hex",
+ "Use Hexadecimal form (e.g. #x2D)"),
+ clEnumValN(klee::ExprSMTLIBPrinter::DECIMAL, "dec",
+ "Use decimal form (e.g. (_ bv45 8) )"),
+ clEnumValEnd),
+ llvm::cl::init(klee::ExprSMTLIBPrinter::DECIMAL));
+
+llvm::cl::opt<bool> humanReadableSMTLIB(
+ "smtlib-human-readable",
+ llvm::cl::desc(
+ "Enables generated SMT-LIBv2 files to be human readable (default=off)"),
+ llvm::cl::init(false));
+}
+
+namespace klee {
+
+ExprSMTLIBPrinter::ExprSMTLIBPrinter()
+ : usedArrays(), o(NULL), query(NULL), p(NULL), haveConstantArray(false),
+ logicToUse(QF_AUFBV),
+ humanReadable(ExprSMTLIBOptions::humanReadableSMTLIB),
+ smtlibBoolOptions(), arraysToCallGetValueOn(NULL) {
+ setConstantDisplayMode(ExprSMTLIBOptions::argConstantDisplayMode);
+}
+
+ExprSMTLIBPrinter::~ExprSMTLIBPrinter() {
+ if (p != NULL)
+ delete p;
+}
+
+void ExprSMTLIBPrinter::setOutput(std::ostream &output) {
+ o = &output;
+ if (p != NULL)
+ delete p;
+
+ p = new PrintContext(output);
+}
+
+void ExprSMTLIBPrinter::setQuery(const Query &q) {
+ query = &q;
+ reset(); // clear the data structures
+ scanAll();
+ negateQueryExpression();
+}
+
+void ExprSMTLIBPrinter::reset() {
+ usedArrays.clear();
+ haveConstantArray = false;
+
+ /* Clear the PRODUCE_MODELS option if it was automatically set.
+ * We need to do this because the next query might not need the
+ * (get-value) SMT-LIBv2 command.
+ */
+ if (arraysToCallGetValueOn != NULL)
+ setSMTLIBboolOption(PRODUCE_MODELS, OPTION_DEFAULT);
+
+ arraysToCallGetValueOn = NULL;
+}
+
+bool ExprSMTLIBPrinter::isHumanReadable() { return humanReadable; }
+
+bool ExprSMTLIBPrinter::setConstantDisplayMode(ConstantDisplayMode cdm) {
+ if (cdm > DECIMAL)
+ return false;
+
+ this->cdm = cdm;
+ return true;
+}
+
+void ExprSMTLIBPrinter::printConstant(const ref<ConstantExpr> &e) {
+ /* Handle simple boolean constants */
+
+ if (e->isTrue()) {
+ *p << "true";
+ return;
+ }
+
+ if (e->isFalse()) {
+ *p << "false";
+ return;
+ }
+
+ /* Handle bitvector constants */
+
+ std::string value;
+
+ /* SMTLIBv2 deduces the bit-width (should be 8-bits in our case)
+ * from the length of the string (e.g. zero is #b00000000). LLVM
+ * doesn't know about this so we need to pad the printed output
+ * with the appropriate number of zeros (zeroPad)
+ */
+ unsigned int zeroPad = 0;
+
+ switch (cdm) {
+ case BINARY:
+ e->toString(value, 2);
+ *p << "#b";
+
+ zeroPad = e->getWidth() - value.length();
+
+ for (unsigned int count = 0; count < zeroPad; count++)
+ *p << "0";
+
+ *p << value;
+ break;
+
+ case HEX:
+ e->toString(value, 16);
+ *p << "#x";
+
+ zeroPad = (e->getWidth() / 4) - value.length();
+ for (unsigned int count = 0; count < zeroPad; count++)
+ *p << "0";
+
+ *p << value;
+ break;
+
+ case DECIMAL:
+ e->toString(value, 10);
+ *p << "(_ bv" << value << " " << e->getWidth() << ")";
+ break;
+
+ default:
+ std::cerr << "ExprSMTLIBPrinter::printConstant() : Unexpected Constant "
+ "display mode" << std::endl;
+ }
+}
+
+void ExprSMTLIBPrinter::printExpression(
+ const ref<Expr> &e, ExprSMTLIBPrinter::SMTLIB_SORT expectedSort) {
+ // check if casting might be necessary
+ if (getSort(e) != expectedSort) {
+ printCastToSort(e, expectedSort);
+ return;
+ }
+
+ switch (e->getKind()) {
+ case Expr::Constant:
+ printConstant(cast<ConstantExpr>(e));
+ return; // base case
+
+ case Expr::NotOptimized:
+ // skip to child
+ printExpression(e->getKid(0), expectedSort);
+ return;
+
+ case Expr::Read:
+ printReadExpr(cast<ReadExpr>(e));
+ return;
+
+ case Expr::Extract:
+ printExtractExpr(cast<ExtractExpr>(e));
+ return;
+
+ case Expr::SExt:
+ case Expr::ZExt:
+ printCastExpr(cast<CastExpr>(e));
+ return;
+
+ case Expr::Ne:
+ printNotEqualExpr(cast<NeExpr>(e));
+ return;
+
+ case Expr::Select:
+ // the if-then-else expression.
+ printSelectExpr(cast<SelectExpr>(e), expectedSort);
+ return;
+
+ case Expr::Eq:
+ /* The "=" operator is special in that it can take any sort but we must
+ * enforce that both arguments are the same type. We do this a lazy way
+ * by enforcing the second argument is of the same type as the first.
+ */
+ printSortArgsExpr(e, getSort(e->getKid(0)));
+
+ return;
+
+ case Expr::And:
+ case Expr::Or:
+ case Expr::Xor:
+ case Expr::Not:
+ /* These operators have a bitvector version and a bool version.
+ * For these operators only (e.g. wouldn't apply to bvult) if the expected
+ * sort the
+ * expression is T then that implies the arguments are also of type T.
+ */
+ printLogicalOrBitVectorExpr(e, expectedSort);
+
+ return;
+
+ default:
+ /* The remaining operators (Add,Sub...,Ult,Ule,..)
+ * Expect SORT_BITVECTOR arguments
+ */
+ printSortArgsExpr(e, SORT_BITVECTOR);
+ return;
+ }
+}
+
+void ExprSMTLIBPrinter::printReadExpr(const ref<ReadExpr> &e) {
+ *p << "(" << getSMTLIBKeyword(e) << " ";
+ p->pushIndent();
+
+ printSeperator();
+
+ // print array with updates recursively
+ printUpdatesAndArray(e->updates.head, e->updates.root);
+
+ // print index
+ printSeperator();
+ printExpression(e->index, SORT_BITVECTOR);
+
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+}
+
+void ExprSMTLIBPrinter::printExtractExpr(const ref<ExtractExpr> &e) {
+ unsigned int lowIndex = e->offset;
+ unsigned int highIndex = lowIndex + e->width - 1;
+
+ *p << "((_ " << getSMTLIBKeyword(e) << " " << highIndex << " " << lowIndex
+ << ") ";
+
+ p->pushIndent(); // add indent for recursive call
+ printSeperator();
+
+ // recurse
+ printExpression(e->getKid(0), SORT_BITVECTOR);
+
+ p->popIndent(); // pop indent added for the recursive call
+ printSeperator();
+ *p << ")";
+}
+
+void ExprSMTLIBPrinter::printCastExpr(const ref<CastExpr> &e) {
+ /* sign_extend and zero_extend behave slightly unusually in SMTLIBv2
+ * instead of specifying of what bit-width we would like to extend to
+ * we specify how many bits to add to the child expression
+ *
+ * e.g
+ * ((_ sign_extend 64) (_ bv5 32))
+ *
+ * gives a (_ BitVec 96) instead of (_ BitVec 64)
+ *
+ * So we must work out how many bits we need to add.
+ *
+ * (e->width) is the desired number of bits
+ * (e->src->getWidth()) is the number of bits in the child
+ */
+ unsigned int numExtraBits = (e->width) - (e->src->getWidth());
+
+ *p << "((_ " << getSMTLIBKeyword(e) << " " << numExtraBits << ") ";
+
+ p->pushIndent(); // add indent for recursive call
+ printSeperator();
+
+ // recurse
+ printExpression(e->src, SORT_BITVECTOR);
+
+ p->popIndent(); // pop indent added for recursive call
+ printSeperator();
+
+ *p << ")";
+}
+
+void ExprSMTLIBPrinter::printNotEqualExpr(const ref<NeExpr> &e) {
+ *p << "(not (";
+ p->pushIndent();
+ *p << "="
+ << " ";
+ p->pushIndent();
+ printSeperator();
+
+ /* The "=" operators allows both sorts. We assume
+ * that the second argument sort should be forced to be the same sort as the
+ * first argument
+ */
+ SMTLIB_SORT s = getSort(e->getKid(0));
+
+ printExpression(e->getKid(0), s);
+ printSeperator();
+ printExpression(e->getKid(1), s);
+ p->popIndent();
+ printSeperator();
+
+ *p << ")";
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+}
+
+const char *ExprSMTLIBPrinter::getSMTLIBKeyword(const ref<Expr> &e) {
+
+ switch (e->getKind()) {
+ case Expr::Read:
+ return "select";
+ case Expr::Select:
+ return "ite";
+ case Expr::Concat:
+ return "concat";
+ case Expr::Extract:
+ return "extract";
+ case Expr::ZExt:
+ return "zero_extend";
+ case Expr::SExt:
+ return "sign_extend";
+
+ case Expr::Add:
+ return "bvadd";
+ case Expr::Sub:
+ return "bvsub";
+ case Expr::Mul:
+ return "bvmul";
+ case Expr::UDiv:
+ return "bvudiv";
+ case Expr::SDiv:
+ return "bvsdiv";
+ case Expr::URem:
+ return "bvurem";
+ case Expr::SRem:
+ return "bvsrem";
+
+ /* And, Xor, Not and Or are not handled here because there different versions
+ * for different sorts. See printLogicalOrBitVectorExpr()
+ */
+
+ case Expr::Shl:
+ return "bvshl";
+ case Expr::LShr:
+ return "bvlshr";
+ case Expr::AShr:
+ return "bvashr";
+
+ case Expr::Eq:
+ return "=";
+
+ // Not Equal does not exist directly in SMTLIBv2
+
+ case Expr::Ult:
+ return "bvult";
+ case Expr::Ule:
+ return "bvule";
+ case Expr::Ugt:
+ return "bvugt";
+ case Expr::Uge:
+ return "bvuge";
+
+ case Expr::Slt:
+ return "bvslt";
+ case Expr::Sle:
+ return "bvsle";
+ case Expr::Sgt:
+ return "bvsgt";
+ case Expr::Sge:
+ return "bvsge";
+
+ default:
+ return "<error>";
+ }
+}
+
+void ExprSMTLIBPrinter::printUpdatesAndArray(const UpdateNode *un,
+ const Array *root) {
+ if (un != NULL) {
+ *p << "(store ";
+ p->pushIndent();
+ printSeperator();
+
+ // recurse to get the array or update that this store operations applies to
+ printUpdatesAndArray(un->next, root);
+
+ printSeperator();
+
+ // print index
+ printExpression(un->index, SORT_BITVECTOR);
+ printSeperator();
+
+ // print value that is assigned to this index of the array
+ printExpression(un->value, SORT_BITVECTOR);
+
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+ } else {
+ // The base case of the recursion
+ *p << root->name;
+ }
+}
+
+void ExprSMTLIBPrinter::scanAll() {
+ // perform scan of all expressions
+ for (ConstraintManager::const_iterator i = query->constraints.begin();
+ i != query->constraints.end(); i++)
+ scan(*i);
+
+ // Scan the query too
+ scan(query->expr);
+}
+
+void ExprSMTLIBPrinter::generateOutput() {
+ if (p == NULL || query == NULL || o == NULL) {
+ std::cerr << "ExprSMTLIBPrinter::generateOutput() Can't print SMTLIBv2. "
+ "Output or query bad!" << std::endl;
+ return;
+ }
+
+ if (humanReadable)
+ printNotice();
+ printOptions();
+ printSetLogic();
+ printArrayDeclarations();
+ printConstraints();
+ printQuery();
+ printAction();
+ printExit();
+}
+
+void ExprSMTLIBPrinter::printSetLogic() {
+ *o << "(set-logic ";
+ switch (logicToUse) {
+ case QF_ABV:
+ *o << "QF_ABV";
+ break;
+ case QF_AUFBV:
+ *o << "QF_AUFBV";
+ break;
+ }
+ *o << " )" << std::endl;
+}
+
+void ExprSMTLIBPrinter::printArrayDeclarations() {
+ // Assume scan() has been called
+ if (humanReadable)
+ *o << "; Array declarations" << endl;
+
+ // declare arrays
+ for (set<const Array *>::iterator it = usedArrays.begin();
+ it != usedArrays.end(); it++) {
+ *o << "(declare-fun " << (*it)->name << " () "
+ "(Array (_ BitVec "
+ << (*it)->getDomain() << ") "
+ "(_ BitVec " << (*it)->getRange() << ") ) )"
+ << endl;
+ }
+
+ // Set array values for constant values
+ if (haveConstantArray) {
+ if (humanReadable)
+ *o << "; Constant Array Definitions" << endl;
+
+ const Array *array;
+
+ // loop over found arrays
+ for (set<const Array *>::iterator it = usedArrays.begin();
+ it != usedArrays.end(); it++) {
+ array = *it;
+ int byteIndex = 0;
+ if (array->isConstantArray()) {
+ /*loop over elements in the array and generate an assert statement
+ for each one
+ */
+ for (vector<ref<ConstantExpr> >::const_iterator
+ ce = array->constantValues.begin();
+ ce != array->constantValues.end(); ce++, byteIndex++) {
+ *p << "(assert (";
+ p->pushIndent();
+ *p << "= ";
+ p->pushIndent();
+ printSeperator();
+
+ *p << "(select " << array->name << " (_ bv" << byteIndex << " "
+ << array->getDomain() << ") )";
+ printSeperator();
+ printConstant((*ce));
+
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+
+ p->breakLineI();
+ }
+ }
+ }
+ }
+}
+
+void ExprSMTLIBPrinter::printConstraints() {
+ if (humanReadable)
+ *o << "; Constraints" << endl;
+
+ // Generate assert statements for each constraint
+ for (ConstraintManager::const_iterator i = query->constraints.begin();
+ i != query->constraints.end(); i++) {
+ *p << "(assert ";
+ p->pushIndent();
+ printSeperator();
+
+ // recurse into Expression
+ printExpression(*i, SORT_BOOL);
+
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+ p->breakLineI();
+ }
+}
+
+void ExprSMTLIBPrinter::printAction() {
+ // Ask solver to check for satisfiability
+ *o << "(check-sat)" << endl;
+
+ /* If we has arrays to find the values of then we'll
+ * ask the solver for the value of each bitvector in each array
+ */
+ if (arraysToCallGetValueOn != NULL && !arraysToCallGetValueOn->empty()) {
+
+ const Array *theArray = 0;
+
+ // loop over the array names
+ for (vector<const Array *>::const_iterator it =
+ arraysToCallGetValueOn->begin();
+ it != arraysToCallGetValueOn->end(); it++) {
+ theArray = *it;
+ // Loop over the array indices
+ for (unsigned int index = 0; index < theArray->size; ++index) {
+ *o << "(get-value ( (select " << (**it).name << " (_ bv" << index << " "
+ << theArray->getDomain() << ") ) ) )" << endl;
+ }
+ }
+ }
+}
+void ExprSMTLIBPrinter::scan(const ref<Expr> &e) {
+ if (e.isNull()) {
+ std::cerr << "ExprSMTLIBPrinter::scan() : Found NULL expression!"
+ << std::endl;
+ return;
+ }
- );
+ if (isa<ConstantExpr>(e))
+ return; // we don't need to scan simple constants
- llvm::cl::opt<bool> humanReadableSMTLIB("smtlib-human-readable",
- llvm::cl::desc("Enables generated SMT-LIBv2 files to be human readable (default=off)"),
- llvm::cl::init(false)
+ if (const ReadExpr *re = dyn_cast<ReadExpr>(e)) {
+ // Attempt to insert array and if array wasn't present before do more things
+ if (usedArrays.insert(re->updates.root).second) {
- );
+ // check if the array is constant
+ if (re->updates.root->isConstantArray())
+ haveConstantArray = true;
+ // scan the update list
+ scanUpdates(re->updates.head);
+ }
+ }
+
+ // recurse into the children
+ Expr *ep = e.get();
+ for (unsigned int i = 0; i < ep->getNumKids(); i++)
+ scan(ep->getKid(i));
}
+void ExprSMTLIBPrinter::scanUpdates(const UpdateNode *un) {
+ while (un != NULL) {
+ scan(un->index);
+ scan(un->value);
+ un = un->next;
+ }
+}
-namespace klee
-{
+void ExprSMTLIBPrinter::printExit() { *o << "(exit)" << endl; }
- ExprSMTLIBPrinter::ExprSMTLIBPrinter() :
- usedArrays(), o(NULL), query(NULL), p(NULL), haveConstantArray(false), logicToUse(QF_AUFBV),
- humanReadable(ExprSMTLIBOptions::humanReadableSMTLIB), smtlibBoolOptions(), arraysToCallGetValueOn(NULL)
- {
- setConstantDisplayMode(ExprSMTLIBOptions::argConstantDisplayMode);
- }
+bool ExprSMTLIBPrinter::setLogic(SMTLIBv2Logic l) {
+ if (l > QF_AUFBV)
+ return false;
- ExprSMTLIBPrinter::~ExprSMTLIBPrinter()
- {
- if(p!=NULL)
- delete p;
- }
+ logicToUse = l;
+ return true;
+}
- void ExprSMTLIBPrinter::setOutput(std::ostream& output)
- {
- o = &output;
- if(p!=NULL)
- delete p;
+void ExprSMTLIBPrinter::printSeperator() {
+ if (humanReadable)
+ p->breakLineI();
+ else
+ p->write(" ");
+}
- p = new PrintContext(output);
- }
+void ExprSMTLIBPrinter::printNotice() {
+ *o << "; This file conforms to SMTLIBv2 and was generated by KLEE" << endl;
+}
+
+void ExprSMTLIBPrinter::setHumanReadable(bool hr) { humanReadable = hr; }
- void ExprSMTLIBPrinter::setQuery(const Query& q)
- {
- query = &q;
- reset(); // clear the data structures
- scanAll();
- negateQueryExpression();
- }
+void ExprSMTLIBPrinter::printOptions() {
+ // Print out SMTLIBv2 boolean options
+ for (std::map<SMTLIBboolOptions, bool>::const_iterator i =
+ smtlibBoolOptions.begin();
+ i != smtlibBoolOptions.end(); i++) {
+ *o << "(set-option :" << getSMTLIBOptionString(i->first) << " "
+ << ((i->second) ? "true" : "false") << ")" << endl;
+ }
+}
- void ExprSMTLIBPrinter::reset()
- {
- usedArrays.clear();
- haveConstantArray=false;
+void ExprSMTLIBPrinter::printQuery() {
+ if (humanReadable) {
+ *p << "; Query from solver turned into an assert";
+ p->breakLineI();
+ }
- /* Clear the PRODUCE_MODELS option if it was automatically set.
- * We need to do this because the next query might not need the
- * (get-value) SMT-LIBv2 command.
- */
- if(arraysToCallGetValueOn !=NULL)
- setSMTLIBboolOption(PRODUCE_MODELS,OPTION_DEFAULT);
+ p->pushIndent();
+ *p << "(assert";
+ p->pushIndent();
+ printSeperator();
- arraysToCallGetValueOn=NULL;
+ printExpression(queryAssert, SORT_BOOL);
+
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+ p->popIndent();
+ p->breakLineI();
+}
+
+ExprSMTLIBPrinter::SMTLIB_SORT ExprSMTLIBPrinter::getSort(const ref<Expr> &e) {
+ /* We could handle every operator in a large switch statement,
+ * but this seems more elegant.
+ */
+
+ if (e->getKind() == Expr::Extract) {
+ /* This is a special corner case. In most cases if a node in the expression
+ * tree
+ * is of width 1 it should be considered as SORT_BOOL. However it is
+ * possible to
+ * perform an extract operation on a SORT_BITVECTOR and produce a
+ * SORT_BITVECTOR of length 1.
+ * The ((_ extract i j) () ) operation in SMTLIBv2 always produces
+ * SORT_BITVECTOR
+ */
+ return SORT_BITVECTOR;
+ } else
+ return (e->getWidth() == Expr::Bool) ? (SORT_BOOL) : (SORT_BITVECTOR);
+}
+
+void ExprSMTLIBPrinter::printCastToSort(const ref<Expr> &e,
+ ExprSMTLIBPrinter::SMTLIB_SORT sort) {
+ switch (sort) {
+ case SORT_BITVECTOR:
+ if (humanReadable) {
+ p->breakLineI();
+ *p << ";Performing implicit bool to bitvector cast";
+ p->breakLine();
+ }
+ // We assume the e is a bool that we need to cast to a bitvector sort.
+ *p << "(ite";
+ p->pushIndent();
+ printSeperator();
+ printExpression(e, SORT_BOOL);
+ printSeperator();
+ *p << "(_ bv1 1)";
+ printSeperator(); // printing the "true" bitvector
+ *p << "(_ bv0 1)";
+ p->popIndent();
+ printSeperator(); // printing the "false" bitvector
+ *p << ")";
+ break;
+ case SORT_BOOL: {
+ /* We make the assumption (might be wrong) that any bitvector whos unsigned
+ *decimal value is
+ * is zero is interpreted as "false", otherwise it is true.
+ *
+ * This may not be the interpretation we actually want!
+ */
+ Expr::Width bitWidth = e->getWidth();
+ if (humanReadable) {
+ p->breakLineI();
+ *p << ";Performing implicit bitvector to bool cast";
+ p->breakLine();
+ }
+ *p << "(bvugt";
+ p->pushIndent();
+ printSeperator();
+ // We assume is e is a bitvector
+ printExpression(e, SORT_BITVECTOR);
+ printSeperator();
+ *p << "(_ bv0 " << bitWidth << ")";
+ p->popIndent();
+ printSeperator(); // Zero bitvector of required width
+ *p << ")";
+
+ if (bitWidth != Expr::Bool)
+ std::cerr << "ExprSMTLIBPrinter : Warning. Casting a bitvector (length "
+ << bitWidth << ") to bool!" << std::endl;
+
+ } break;
+ default:
+ assert(0 && "Unsupported cast!");
+ }
+}
+void ExprSMTLIBPrinter::printSelectExpr(const ref<SelectExpr> &e,
+ ExprSMTLIBPrinter::SMTLIB_SORT s) {
+ // This is the if-then-else expression
- }
-
- bool ExprSMTLIBPrinter::isHumanReadable()
- {
- return humanReadable;
- }
+ *p << "(" << getSMTLIBKeyword(e) << " ";
+ p->pushIndent(); // add indent for recursive call
- bool ExprSMTLIBPrinter::setConstantDisplayMode(ConstantDisplayMode cdm)
- {
- if(cdm > DECIMAL)
- return false;
+ // The condition
+ printSeperator();
+ printExpression(e->getKid(0), SORT_BOOL);
- this->cdm = cdm;
- return true;
- }
+ /* This operator is special in that the remaining children
+ * can be of any sort.
+ */
- void ExprSMTLIBPrinter::printConstant(const ref<ConstantExpr>& e)
- {
- /* Handle simple boolean constants */
-
- if(e->isTrue())
- {
- *p << "true";
- return;
- }
-
- if(e->isFalse())
- {
- *p << "false";
- return;
- }
-
- /* Handle bitvector constants */
-
- std::string value;
-
- /* SMTLIBv2 deduces the bit-width (should be 8-bits in our case)
- * from the length of the string (e.g. zero is #b00000000). LLVM
- * doesn't know about this so we need to pad the printed output
- * with the appropriate number of zeros (zeroPad)
- */
- unsigned int zeroPad=0;
-
- switch(cdm)
- {
- case BINARY:
- e->toString(value,2);
- *p << "#b";
-
- zeroPad = e->getWidth() - value.length();
-
- for(unsigned int count=0; count < zeroPad; count++)
- *p << "0";
-
- *p << value ;
- break;
-
- case HEX:
- e->toString(value,16);
- *p << "#x";
-
- zeroPad = (e->getWidth() / 4) - value.length();
- for(unsigned int count=0; count < zeroPad; count++)
- *p << "0";
-
- *p << value ;
- break;
-
- case DECIMAL:
- e->toString(value,10);
- *p << "(_ bv" << value<< " " << e->getWidth() << ")";
- break;
-
- default:
- std::cerr << "ExprSMTLIBPrinter::printConstant() : Unexpected Constant display mode" << std::endl;
- }
- }
-
- void ExprSMTLIBPrinter::printExpression(const ref<Expr>& e, ExprSMTLIBPrinter::SMTLIB_SORT expectedSort)
- {
- //check if casting might be necessary
- if(getSort(e) != expectedSort)
- {
- printCastToSort(e,expectedSort);
- return;
- }
-
-
- switch(e->getKind())
- {
- case Expr::Constant:
- printConstant(cast<ConstantExpr>(e));
- return; //base case
-
- case Expr::NotOptimized:
- //skip to child
- printExpression(e->getKid(0),expectedSort);
- return;
-
- case Expr::Read:
- printReadExpr(cast<ReadExpr>(e));
- return;
-
- case Expr::Extract:
- printExtractExpr(cast<ExtractExpr>(e));
- return;
-
- case Expr::SExt:
- case Expr::ZExt:
- printCastExpr(cast<CastExpr>(e));
- return;
-
- case Expr::Ne:
- printNotEqualExpr(cast<NeExpr>(e));
- return;
-
- case Expr::Select:
- //the if-then-else expression.
- printSelectExpr(cast<SelectExpr>(e),expectedSort);
- return;
-
- case Expr::Eq:
- /* The "=" operator is special in that it can take any sort but we must
- * enforce that both arguments are the same type. We do this a lazy way
- * by enforcing the second argument is of the same type as the first.
- */
- printSortArgsExpr(e,getSort(e->getKid(0)));
-
- return;
-
- case Expr::And:
- case Expr::Or:
- case Expr::Xor:
- case Expr::Not:
- /* These operators have a bitvector version and a bool version.
- * For these operators only (e.g. wouldn't apply to bvult) if the expected sort the
- * expression is T then that implies the arguments are also of type T.
- */
- printLogicalOrBitVectorExpr(e,expectedSort);
-
- return;
-
-
- default:
- /* The remaining operators (Add,Sub...,Ult,Ule,..)
- * Expect SORT_BITVECTOR arguments
- */
- printSortArgsExpr(e,SORT_BITVECTOR);
- return;
- }
- }
-
- void ExprSMTLIBPrinter::printReadExpr(const ref<ReadExpr>& e)
- {
- *p << "(" << getSMTLIBKeyword(e) << " ";
- p->pushIndent();
-
- printSeperator();
-
- //print array with updates recursively
- printUpdatesAndArray(e->updates.head,e->updates.root);
-
- //print index
- printSeperator();
- printExpression(e->index,SORT_BITVECTOR);
-
- p->popIndent();
- printSeperator();
- *p << ")";
- }
-
- void ExprSMTLIBPrinter::printExtractExpr(const ref<ExtractExpr>& e)
- {
- unsigned int lowIndex= e->offset;
- unsigned int highIndex= lowIndex + e->width -1;
-
- *p << "((_ " << getSMTLIBKeyword(e) << " " << highIndex << " " << lowIndex << ") ";
-
- p->pushIndent(); //add indent for recursive call
- printSeperator();
-
- //recurse
- printExpression(e->getKid(0),SORT_BITVECTOR);
-
- p->popIndent(); //pop indent added for the recursive call
- printSeperator();
- *p << ")";
- }
-
- void ExprSMTLIBPrinter::printCastExpr(const ref<CastExpr>& e)
- {
- /* sign_extend and zero_extend behave slightly unusually in SMTLIBv2
- * instead of specifying of what bit-width we would like to extend to
- * we specify how many bits to add to the child expression
- *
- * e.g
- * ((_ sign_extend 64) (_ bv5 32))
- *
- * gives a (_ BitVec 96) instead of (_ BitVec 64)
- *
- * So we must work out how many bits we need to add.
- *
- * (e->width) is the desired number of bits
- * (e->src->getWidth()) is the number of bits in the child
- */
- unsigned int numExtraBits= (e->width) - (e->src->getWidth());
-
- *p << "((_ " << getSMTLIBKeyword(e) << " " <<
- numExtraBits << ") ";
-
- p->pushIndent(); //add indent for recursive call
- printSeperator();
-
- //recurse
- printExpression(e->src,SORT_BITVECTOR);
-
- p->popIndent(); //pop indent added for recursive call
- printSeperator();
-
- *p << ")";
- }
-
- void ExprSMTLIBPrinter::printNotEqualExpr(const ref<NeExpr>& e)
- {
- *p << "(not (";
- p->pushIndent();
- *p << "=" << " ";
- p->pushIndent();
- printSeperator();
-
- /* The "=" operators allows both sorts. We assume
- * that the second argument sort should be forced to be the same sort as the
- * first argument
- */
- SMTLIB_SORT s = getSort(e->getKid(0));
-
- printExpression(e->getKid(0),s);
- printSeperator();
- printExpression(e->getKid(1),s);
- p->popIndent();
- printSeperator();
-
- *p << ")";
- p->popIndent();
- printSeperator();
- *p << ")";
- }
-
-
- const char* ExprSMTLIBPrinter::getSMTLIBKeyword(const ref<Expr>& e)
- {
-
- switch(e->getKind())
- {
- case Expr::Read: return "select";
- case Expr::Select: return "ite";
- case Expr::Concat: return "concat";
- case Expr::Extract: return "extract";
- case Expr::ZExt: return "zero_extend";
- case Expr::SExt: return "sign_extend";
-
- case Expr::Add: return "bvadd";
- case Expr::Sub: return "bvsub";
- case Expr::Mul: return "bvmul";
- case Expr::UDiv: return "bvudiv";
- case Expr::SDiv: return "bvsdiv";
- case Expr::URem: return "bvurem";
- case Expr::SRem: return "bvsrem";
-
-
- /* And, Xor, Not and Or are not handled here because there different versions
- * for different sorts. See printLogicalOrBitVectorExpr()
- */
-
-
- case Expr::Shl: return "bvshl";
- case Expr::LShr: return "bvlshr";
- case Expr::AShr: return "bvashr";
-
- case Expr::Eq: return "=";
-
- //Not Equal does not exist directly in SMTLIBv2
-
- case Expr::Ult: return "bvult";
- case Expr::Ule: return "bvule";
- case Expr::Ugt: return "bvugt";
- case Expr::Uge: return "bvuge";
-
- case Expr::Slt: return "bvslt";
- case Expr::Sle: return "bvsle";
- case Expr::Sgt: return "bvsgt";
- case Expr::Sge: return "bvsge";
-
- default:
- return "<error>";
-
- }
- }
-
- void ExprSMTLIBPrinter::printUpdatesAndArray(const UpdateNode* un, const Array* root)
- {
- if(un!=NULL)
- {
- *p << "(store ";
- p->pushIndent();
- printSeperator();
-
- //recurse to get the array or update that this store operations applies to
- printUpdatesAndArray(un->next,root);
-
- printSeperator();
-
- //print index
- printExpression(un->index,SORT_BITVECTOR);
- printSeperator();
-
- //print value that is assigned to this index of the array
- printExpression(un->value,SORT_BITVECTOR);
-
- p->popIndent();
- printSeperator();
- *p << ")";
- }
- else
- {
- //The base case of the recursion
- *p << root->name;
- }
-
- }
-
- void ExprSMTLIBPrinter::scanAll()
- {
- //perform scan of all expressions
- for(ConstraintManager::const_iterator i= query->constraints.begin(); i != query->constraints.end(); i++)
- scan(*i);
-
- //Scan the query too
- scan(query->expr);
- }
-
- void ExprSMTLIBPrinter::generateOutput()
- {
- if(p==NULL || query == NULL || o ==NULL)
- {
- std::cerr << "ExprSMTLIBPrinter::generateOutput() Can't print SMTLIBv2. Output or query bad!" << std::endl;
- return;
- }
-
- if(humanReadable) printNotice();
- printOptions();
- printSetLogic();
- printArrayDeclarations();
- printConstraints();
- printQuery();
- printAction();
- printExit();
- }
-
- void ExprSMTLIBPrinter::printSetLogic()
- {
- *o << "(set-logic ";
- switch(logicToUse)
- {
- case QF_ABV: *o << "QF_ABV"; break;
- case QF_AUFBV: *o << "QF_AUFBV" ; break;
- }
- *o << " )" << std::endl;
- }
-
-
- void ExprSMTLIBPrinter::printArrayDeclarations()
- {
- //Assume scan() has been called
- if(humanReadable)
- *o << "; Array declarations" << endl;
-
- //declare arrays
- for(set<const Array*>::iterator it = usedArrays.begin(); it != usedArrays.end(); it++)
- {
- *o << "(declare-fun " << (*it)->name << " () "
- "(Array (_ BitVec " << (*it)->getDomain() << ") "
- "(_ BitVec " << (*it)->getRange() << ") ) )" << endl;
- }
-
- //Set array values for constant values
- if(haveConstantArray)
- {
- if(humanReadable)
- *o << "; Constant Array Definitions" << endl;
-
- const Array* array;
-
- //loop over found arrays
- for(set<const Array*>::iterator it = usedArrays.begin(); it != usedArrays.end(); it++)
- {
- array= *it;
- int byteIndex=0;
- if(array->isConstantArray())
- {
- /*loop over elements in the array and generate an assert statement
- for each one
- */
- for(vector< ref<ConstantExpr> >::const_iterator ce= array->constantValues.begin();
- ce != array->constantValues.end(); ce++, byteIndex++)
- {
- *p << "(assert (";
- p->pushIndent();
- *p << "= ";
- p->pushIndent();
- printSeperator();
-
- *p << "(select " << array->name << " (_ bv" << byteIndex << " " << array->getDomain() << ") )";
- printSeperator();
- printConstant((*ce));
-
- p->popIndent();
- printSeperator();
- *p << ")";
- p->popIndent();
- printSeperator();
- *p << ")";
-
- p->breakLineI();
-
- }
- }
- }
- }
- }
-
- void ExprSMTLIBPrinter::printConstraints()
- {
- if(humanReadable)
- *o << "; Constraints" << endl;
-
- //Generate assert statements for each constraint
- for(ConstraintManager::const_iterator i= query->constraints.begin(); i != query->constraints.end(); i++)
- {
- *p << "(assert ";
- p->pushIndent();
- printSeperator();
-
- //recurse into Expression
- printExpression(*i,SORT_BOOL);
-
- p->popIndent();
- printSeperator();
- *p << ")"; p->breakLineI();
- }
-
- }
-
- void ExprSMTLIBPrinter::printAction()
- {
- //Ask solver to check for satisfiability
- *o << "(check-sat)" << endl;
-
- /* If we has arrays to find the values of then we'll
- * ask the solver for the value of each bitvector in each array
- */
- if(arraysToCallGetValueOn!=NULL && !arraysToCallGetValueOn->empty())
- {
-
- const Array* theArray=0;
-
- //loop over the array names
- for(vector<const Array*>::const_iterator it = arraysToCallGetValueOn->begin(); it != arraysToCallGetValueOn->end(); it++)
- {
- theArray=*it;
- //Loop over the array indices
- for(unsigned int index=0; index < theArray->size; ++index)
- {
- *o << "(get-value ( (select " << (**it).name <<
- " (_ bv" << index << " " << theArray->getDomain() << ") ) ) )" << endl;
- }
-
- }
-
-
- }
- }
-
- void ExprSMTLIBPrinter::scan(const ref<Expr>& e)
- {
- if(e.isNull())
- {
- std::cerr << "ExprSMTLIBPrinter::scan() : Found NULL expression!" << std::endl;
- return;
- }
-
- if(isa<ConstantExpr>(e))
- return; //we don't need to scan simple constants
-
- if(const ReadExpr* re = dyn_cast<ReadExpr>(e))
- {
-
- //Attempt to insert array and if array wasn't present before do more things
- if(usedArrays.insert(re->updates.root).second)
- {
-
- //check if the array is constant
- if( re->updates.root->isConstantArray())
- haveConstantArray=true;
-
- //scan the update list
- scanUpdates(re->updates.head);
-
- }
-
- }
-
- //recurse into the children
- Expr* ep = e.get();
- for(unsigned int i=0; i < ep->getNumKids(); i++)
- scan(ep->getKid(i));
- }
-
-
- void ExprSMTLIBPrinter::scanUpdates(const UpdateNode* un)
- {
- while(un != NULL)
- {
- scan(un->index);
- scan(un->value);
- un= un->next;
- }
- }
-
-
- void ExprSMTLIBPrinter::printExit()
- {
- *o << "(exit)" << endl;
- }
-
- bool ExprSMTLIBPrinter::setLogic(SMTLIBv2Logic l)
- {
- if(l > QF_AUFBV)
- return false;
-
- logicToUse=l;
- return true;
- }
-
- void ExprSMTLIBPrinter::printSeperator()
- {
- if(humanReadable)
- p->breakLineI();
- else
- p->write(" ");
- }
-
- void ExprSMTLIBPrinter::printNotice()
- {
- *o << "; This file conforms to SMTLIBv2 and was generated by KLEE" << endl;
- }
-
- void ExprSMTLIBPrinter::setHumanReadable(bool hr)
- {
- humanReadable=hr;
- }
-
- void ExprSMTLIBPrinter::printOptions()
- {
- //Print out SMTLIBv2 boolean options
- for(std::map<SMTLIBboolOptions,bool>::const_iterator i= smtlibBoolOptions.begin(); i!= smtlibBoolOptions.end(); i++)
- {
- *o << "(set-option :" << getSMTLIBOptionString(i->first) <<
- " " << ((i->second)?"true":"false") << ")" << endl;
- }
- }
-
- void ExprSMTLIBPrinter::printQuery()
- {
- if(humanReadable)
- {
- *p << "; Query from solver turned into an assert";
- p->breakLineI();
- }
-
- p->pushIndent();
- *p << "(assert";
- p->pushIndent();
- printSeperator();
-
- printExpression(queryAssert,SORT_BOOL);
-
- p->popIndent();
- printSeperator();
- *p << ")";
- p->popIndent();
- p->breakLineI();
- }
-
- ExprSMTLIBPrinter::SMTLIB_SORT ExprSMTLIBPrinter::getSort(const ref<Expr>& e)
- {
- /* We could handle every operator in a large switch statement,
- * but this seems more elegant.
- */
-
- if(e->getKind() == Expr::Extract)
- {
- /* This is a special corner case. In most cases if a node in the expression tree
- * is of width 1 it should be considered as SORT_BOOL. However it is possible to
- * perform an extract operation on a SORT_BITVECTOR and produce a SORT_BITVECTOR of length 1.
- * The ((_ extract i j) () ) operation in SMTLIBv2 always produces SORT_BITVECTOR
- */
- return SORT_BITVECTOR;
- }
- else
- return (e->getWidth() == Expr::Bool)?(SORT_BOOL):(SORT_BITVECTOR);
- }
-
- void ExprSMTLIBPrinter::printCastToSort(const ref<Expr>& e, ExprSMTLIBPrinter::SMTLIB_SORT sort)
- {
- switch(sort)
- {
- case SORT_BITVECTOR:
- if(humanReadable)
- {
- p->breakLineI(); *p << ";Performing implicit bool to bitvector cast"; p->breakLine();
- }
- //We assume the e is a bool that we need to cast to a bitvector sort.
- *p << "(ite"; p->pushIndent(); printSeperator();
- printExpression(e,SORT_BOOL); printSeperator();
- *p << "(_ bv1 1)" ; printSeperator(); //printing the "true" bitvector
- *p << "(_ bv0 1)" ; p->popIndent(); printSeperator(); //printing the "false" bitvector
- *p << ")";
- break;
- case SORT_BOOL:
- {
- /* We make the assumption (might be wrong) that any bitvector whos unsigned decimal value is
- * is zero is interpreted as "false", otherwise it is true.
- *
- * This may not be the interpretation we actually want!
- */
- Expr::Width bitWidth=e->getWidth();
- if(humanReadable)
- {
- p->breakLineI(); *p << ";Performing implicit bitvector to bool cast"; p->breakLine();
- }
- *p << "(bvugt"; p->pushIndent(); printSeperator();
- // We assume is e is a bitvector
- printExpression(e,SORT_BITVECTOR); printSeperator();
- *p << "(_ bv0 " << bitWidth << ")"; p->popIndent(); printSeperator(); //Zero bitvector of required width
- *p << ")";
-
- if(bitWidth!=Expr::Bool)
- std::cerr << "ExprSMTLIBPrinter : Warning. Casting a bitvector (length " << bitWidth << ") to bool!" << std::endl;
-
- }
- break;
- default:
- assert(0 && "Unsupported cast!");
- }
- }
-
- void ExprSMTLIBPrinter::printSelectExpr(const ref<SelectExpr>& e, ExprSMTLIBPrinter::SMTLIB_SORT s)
- {
- //This is the if-then-else expression
-
- *p << "(" << getSMTLIBKeyword(e) << " ";
- p->pushIndent(); //add indent for recursive call
-
- //The condition
- printSeperator();
- printExpression(e->getKid(0),SORT_BOOL);
-
- /* This operator is special in that the remaining children
- * can be of any sort.
- */
-
- //if true
- printSeperator();
- printExpression(e->getKid(1),s);
-
- //if false
- printSeperator();
- printExpression(e->getKid(2),s);
-
-
- p->popIndent(); //pop indent added for recursive call
- printSeperator();
- *p << ")";
- }
-
- void ExprSMTLIBPrinter::printSortArgsExpr(const ref<Expr>& e, ExprSMTLIBPrinter::SMTLIB_SORT s)
- {
- *p << "(" << getSMTLIBKeyword(e) << " ";
- p->pushIndent(); //add indent for recursive call
-
- //loop over children and recurse into each expecting they are of sort "s"
- for(unsigned int i=0; i < e->getNumKids(); i++)
- {
- printSeperator();
- printExpression(e->getKid(i),s);
- }
-
- p->popIndent(); //pop indent added for recursive call
- printSeperator();
- *p << ")";
- }
-
- void ExprSMTLIBPrinter::printLogicalOrBitVectorExpr(const ref<Expr>& e, ExprSMTLIBPrinter::SMTLIB_SORT s)
- {
- /* For these operators it is the case that the expected sort is the same as the sorts
- * of the arguments.
- */
-
- *p << "(";
- switch(e->getKind())
- {
- case Expr::And:
- *p << ((s==SORT_BITVECTOR)?"bvand":"and");
- break;
- case Expr::Not:
- *p << ((s==SORT_BITVECTOR)?"bvnot":"not");
- break;
- case Expr::Or:
- *p << ((s==SORT_BITVECTOR)?"bvor":"or");
- break;
-
- case Expr::Xor:
- *p << ((s==SORT_BITVECTOR)?"bvxor":"xor");
- break;
- default:
- *p << "ERROR"; // this shouldn't happen
- }
- *p << " ";
-
- p->pushIndent(); //add indent for recursive call
-
- //loop over children and recurse into each expecting they are of sort "s"
- for(unsigned int i=0; i < e->getNumKids(); i++)
- {
- printSeperator();
- printExpression(e->getKid(i),s);
- }
-
- p->popIndent(); //pop indent added for recursive call
- printSeperator();
- *p << ")";
- }
-
- void ExprSMTLIBPrinter::negateQueryExpression()
- {
- //Negating the query
- queryAssert = Expr::createIsZero(query->expr);
- }
-
- bool ExprSMTLIBPrinter::setSMTLIBboolOption(SMTLIBboolOptions option, SMTLIBboolValues value)
- {
- std::pair< std::map<SMTLIBboolOptions,bool>::iterator, bool> thePair;
- bool theValue= (value==OPTION_TRUE)?true:false;
-
- switch(option)
- {
- case PRINT_SUCCESS:
- case PRODUCE_MODELS:
- case INTERACTIVE_MODE:
- thePair=smtlibBoolOptions.insert(std::pair<SMTLIBboolOptions,bool>(option,theValue));
-
- if(value== OPTION_DEFAULT)
- {
- //we should unset (by removing from map) this option so the solver uses its default
- smtlibBoolOptions.erase(thePair.first);
- return true;
- }
-
- if(!thePair.second)
- {
- //option was already present so modify instead.
- thePair.first->second=value;
- }
- return true;
- default:
- return false;
-
- }
- }
-
- void ExprSMTLIBPrinter::setArrayValuesToGet(const std::vector<const Array*>& a)
- {
- arraysToCallGetValueOn = &a;
-
- //This option must be set in order to use the SMTLIBv2 command (get-value () )
- if(!a.empty())
- setSMTLIBboolOption(PRODUCE_MODELS,OPTION_TRUE);
-
- /* There is a risk that users will ask about array values that aren't
- * even in the query. We should add them to the usedArrays list and hope
- * that the solver knows what to do when we ask for the values of arrays
- * that don't feature in our query!
- */
- for(vector<const Array*>::const_iterator i = a.begin(); i!= a.end() ; ++i)
- {
- usedArrays.insert(*i);
- }
-
- }
-
-const char* ExprSMTLIBPrinter::getSMTLIBOptionString(ExprSMTLIBPrinter::SMTLIBboolOptions option)
-{
- switch(option)
- {
- case PRINT_SUCCESS: return "print-success";
- case PRODUCE_MODELS: return "produce-models";
- case INTERACTIVE_MODE: return "interactive-mode";
- default:
- return "unknown-option";
- }
+ // if true
+ printSeperator();
+ printExpression(e->getKid(1), s);
+
+ // if false
+ printSeperator();
+ printExpression(e->getKid(2), s);
+
+ p->popIndent(); // pop indent added for recursive call
+ printSeperator();
+ *p << ")";
+}
+
+void ExprSMTLIBPrinter::printSortArgsExpr(const ref<Expr> &e,
+ ExprSMTLIBPrinter::SMTLIB_SORT s) {
+ *p << "(" << getSMTLIBKeyword(e) << " ";
+ p->pushIndent(); // add indent for recursive call
+
+ // loop over children and recurse into each expecting they are of sort "s"
+ for (unsigned int i = 0; i < e->getNumKids(); i++) {
+ printSeperator();
+ printExpression(e->getKid(i), s);
+ }
+
+ p->popIndent(); // pop indent added for recursive call
+ printSeperator();
+ *p << ")";
}
+void ExprSMTLIBPrinter::printLogicalOrBitVectorExpr(
+ const ref<Expr> &e, ExprSMTLIBPrinter::SMTLIB_SORT s) {
+ /* For these operators it is the case that the expected sort is the same as
+ * the sorts
+ * of the arguments.
+ */
+
+ *p << "(";
+ switch (e->getKind()) {
+ case Expr::And:
+ *p << ((s == SORT_BITVECTOR) ? "bvand" : "and");
+ break;
+ case Expr::Not:
+ *p << ((s == SORT_BITVECTOR) ? "bvnot" : "not");
+ break;
+ case Expr::Or:
+ *p << ((s == SORT_BITVECTOR) ? "bvor" : "or");
+ break;
+
+ case Expr::Xor:
+ *p << ((s == SORT_BITVECTOR) ? "bvxor" : "xor");
+ break;
+ default:
+ *p << "ERROR"; // this shouldn't happen
+ }
+ *p << " ";
+
+ p->pushIndent(); // add indent for recursive call
+
+ // loop over children and recurse into each expecting they are of sort "s"
+ for (unsigned int i = 0; i < e->getNumKids(); i++) {
+ printSeperator();
+ printExpression(e->getKid(i), s);
+ }
+
+ p->popIndent(); // pop indent added for recursive call
+ printSeperator();
+ *p << ")";
}
+void ExprSMTLIBPrinter::negateQueryExpression() {
+ // Negating the query
+ queryAssert = Expr::createIsZero(query->expr);
+}
+
+bool ExprSMTLIBPrinter::setSMTLIBboolOption(SMTLIBboolOptions option,
+ SMTLIBboolValues value) {
+ std::pair<std::map<SMTLIBboolOptions, bool>::iterator, bool> thePair;
+ bool theValue = (value == OPTION_TRUE) ? true : false;
+
+ switch (option) {
+ case PRINT_SUCCESS:
+ case PRODUCE_MODELS:
+ case INTERACTIVE_MODE:
+ thePair = smtlibBoolOptions.insert(
+ std::pair<SMTLIBboolOptions, bool>(option, theValue));
+
+ if (value == OPTION_DEFAULT) {
+ // we should unset (by removing from map) this option so the solver uses
+ // its default
+ smtlibBoolOptions.erase(thePair.first);
+ return true;
+ }
+
+ if (!thePair.second) {
+ // option was already present so modify instead.
+ thePair.first->second = value;
+ }
+ return true;
+ default:
+ return false;
+ }
+}
+void
+ExprSMTLIBPrinter::setArrayValuesToGet(const std::vector<const Array *> &a) {
+ arraysToCallGetValueOn = &a;
+
+ // This option must be set in order to use the SMTLIBv2 command (get-value ()
+ // )
+ if (!a.empty())
+ setSMTLIBboolOption(PRODUCE_MODELS, OPTION_TRUE);
+
+ /* There is a risk that users will ask about array values that aren't
+ * even in the query. We should add them to the usedArrays list and hope
+ * that the solver knows what to do when we ask for the values of arrays
+ * that don't feature in our query!
+ */
+ for (vector<const Array *>::const_iterator i = a.begin(); i != a.end(); ++i) {
+ usedArrays.insert(*i);
+ }
+}
+const char *ExprSMTLIBPrinter::getSMTLIBOptionString(
+ ExprSMTLIBPrinter::SMTLIBboolOptions option) {
+ switch (option) {
+ case PRINT_SUCCESS:
+ return "print-success";
+ case PRODUCE_MODELS:
+ return "produce-models";
+ case INTERACTIVE_MODE:
+ return "interactive-mode";
+ default:
+ return "unknown-option";
+ }
+}
+}