aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/Expr/ExprSMTLIBPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Expr/ExprSMTLIBPrinter.cpp')
-rw-r--r--lib/Expr/ExprSMTLIBPrinter.cpp150
1 files changed, 123 insertions, 27 deletions
diff --git a/lib/Expr/ExprSMTLIBPrinter.cpp b/lib/Expr/ExprSMTLIBPrinter.cpp
index bbb82d0d..fb7e270e 100644
--- a/lib/Expr/ExprSMTLIBPrinter.cpp
+++ b/lib/Expr/ExprSMTLIBPrinter.cpp
@@ -31,6 +31,19 @@ llvm::cl::opt<bool> humanReadableSMTLIB(
llvm::cl::desc(
"Enables generated SMT-LIBv2 files to be human readable (default=off)"),
llvm::cl::init(false));
+
+llvm::cl::opt<klee::ExprSMTLIBPrinter::AbbreviationMode> abbreviationMode(
+ "smtlib-abbreviation-mode",
+ llvm::cl::desc(
+ "Choose abbreviation mode to use in SMT-LIBv2 files (default=let)"),
+ llvm::cl::values(clEnumValN(klee::ExprSMTLIBPrinter::ABBR_NONE, "none",
+ "Do not abbreviate"),
+ clEnumValN(klee::ExprSMTLIBPrinter::ABBR_LET, "let",
+ "Abbreviate with let"),
+ clEnumValN(klee::ExprSMTLIBPrinter::ABBR_NAMED, "named",
+ "Abbreviate with :named annotations"),
+ clEnumValEnd),
+ llvm::cl::init(klee::ExprSMTLIBPrinter::ABBR_LET));
}
namespace klee {
@@ -41,6 +54,7 @@ ExprSMTLIBPrinter::ExprSMTLIBPrinter()
humanReadable(ExprSMTLIBOptions::humanReadableSMTLIB),
smtlibBoolOptions(), arraysToCallGetValueOn(NULL) {
setConstantDisplayMode(ExprSMTLIBOptions::argConstantDisplayMode);
+ setAbbreviationMode(ExprSMTLIBOptions::abbreviationMode);
}
ExprSMTLIBPrinter::~ExprSMTLIBPrinter() {
@@ -60,10 +74,11 @@ void ExprSMTLIBPrinter::setQuery(const Query &q) {
query = &q;
reset(); // clear the data structures
scanAll();
- negateQueryExpression();
}
void ExprSMTLIBPrinter::reset() {
+ bindings.clear();
+ seenExprs.clear();
usedArrays.clear();
haveConstantArray = false;
@@ -154,6 +169,41 @@ void ExprSMTLIBPrinter::printExpression(
return;
}
+ switch (abbrMode) {
+ case ABBR_NONE:
+ break;
+
+ case ABBR_LET: {
+ BindingMap::iterator i = bindings.find(e);
+ if (i != bindings.end()) {
+ *p << "?B" << i->second;
+ return;
+ }
+ break;
+ }
+
+ case ABBR_NAMED: {
+ BindingMap::iterator i = bindings.find(e);
+ if (i != bindings.end()) {
+ if (i->second > 0) {
+ *p << "(! ";
+ printFullExpression(e, expectedSort);
+ *p << " :named ?B" << i->second << ")";
+ i->second = -i->second;
+ } else {
+ *p << "?B" << -i->second;
+ }
+ return;
+ }
+ break;
+ }
+ }
+
+ printFullExpression(e, expectedSort);
+}
+
+void ExprSMTLIBPrinter::printFullExpression(
+ const ref<Expr> &e, ExprSMTLIBPrinter::SMTLIB_SORT expectedSort) {
switch (e->getKind()) {
case Expr::Constant:
printConstant(cast<ConstantExpr>(e));
@@ -431,7 +481,7 @@ void ExprSMTLIBPrinter::generateOutput() {
printSetLogic();
printArrayDeclarations();
printConstraints();
- printQuery();
+ printQueryExpr();
printAction();
printExit();
}
@@ -576,24 +626,32 @@ void ExprSMTLIBPrinter::scan(const ref<Expr> &e) {
if (isa<ConstantExpr>(e))
return; // we don't need to scan simple constants
- if (const ReadExpr *re = dyn_cast<ReadExpr>(e)) {
+ if (seenExprs.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) {
+ // 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;
+ // check if the array is constant
+ if (re->updates.root->isConstantArray())
+ haveConstantArray = true;
- // scan the update list
- scanUpdates(re->updates.head);
+ // 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));
+ // recurse into the children
+ Expr *ep = e.get();
+ for (unsigned int i = 0; i < ep->getNumKids(); i++)
+ scan(ep->getKid(i));
+ } else {
+ // Add the expression to the binding map. The semantics of std::map::insert
+ // are such that it will not be inserted twice.
+ bindings.insert(std::make_pair(e, bindings.size()+1));
+ }
}
void ExprSMTLIBPrinter::scanUpdates(const UpdateNode *un) {
@@ -637,18 +695,52 @@ void ExprSMTLIBPrinter::printOptions() {
}
}
-void ExprSMTLIBPrinter::printQuery() {
- if (humanReadable) {
- *p << "; Query from solver turned into an assert";
- p->breakLineI();
- }
-
+void ExprSMTLIBPrinter::printAssert(const ref<Expr> &e) {
p->pushIndent();
*p << "(assert";
p->pushIndent();
printSeperator();
- printExpression(queryAssert, SORT_BOOL);
+ if (abbrMode == ABBR_LET && bindings.size() != 0) {
+ // Only print let expression if we have bindings to use.
+ *p << "(let";
+ p->pushIndent();
+ printSeperator();
+ *p << "( ";
+ p->pushIndent();
+
+ // Disable abbreviations so none are used here.
+ abbrMode = ABBR_NONE;
+
+ // Print each binding
+ for (BindingMap::const_iterator i = bindings.begin(); i != bindings.end();
+ ++i) {
+ printSeperator();
+ *p << "(?B" << i->second << " ";
+ p->pushIndent();
+
+ // We can abbreviate SORT_BOOL or SORT_BITVECTOR in let expressions
+ printExpression(i->first, getSort(i->first));
+
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+ }
+
+ // Re-enable printing abbreviations.
+ abbrMode = ABBR_LET;
+
+ p->popIndent();
+ printSeperator();
+ *p << ")";
+ printSeperator();
+
+ printExpression(e, SORT_BOOL);
+
+ *p << ")";
+ } else {
+ printExpression(e, SORT_BOOL);
+ }
p->popIndent();
printSeperator();
@@ -657,6 +749,15 @@ void ExprSMTLIBPrinter::printQuery() {
p->breakLineI();
}
+void ExprSMTLIBPrinter::printQueryExpr() {
+ if (humanReadable) {
+ *p << "; Query from solver turned into an assert";
+ p->breakLineI();
+ }
+ ref<Expr> queryAssert = Expr::createIsZero(query->expr);
+ printAssert(queryAssert);
+}
+
ExprSMTLIBPrinter::SMTLIB_SORT ExprSMTLIBPrinter::getSort(const ref<Expr> &e) {
switch (e->getKind()) {
case Expr::NotOptimized:
@@ -831,11 +932,6 @@ void ExprSMTLIBPrinter::printLogicalOrBitVectorExpr(
*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;