13#include "llvm/Support/CommandLine.h"
14#include "llvm/Support/ErrorHandling.h"
20llvm::cl::opt<klee::ExprSMTLIBPrinter::ConstantDisplayMode>
22 "smtlib-display-constants",
23 llvm::cl::desc(
"Sets how bitvector constants are written in generated "
24 "SMT-LIBv2 files (default=dec)"),
26 "Use binary form (e.g. #b00101101)"),
28 "Use Hexadecimal form (e.g. #x2D)"),
30 "Use decimal form (e.g. (_ bv45 8) )")),
36 llvm::cl::desc(
"Enables generated SMT-LIBv2 files to "
37 "be human readable (default=false)"),
41 "smtlib-abbreviation-mode",
43 "Choose abbreviation mode to use in SMT-LIBv2 files (default=let)"),
47 "Abbreviate with let"),
49 "Abbreviate with :named annotations")),
57 : usedArrays(), o(NULL), query(NULL), p(NULL), haveConstantArray(false),
60 smtlibBoolOptions(), arraysToCallGetValueOn(NULL) {
131 unsigned int zeroPad = 0;
135 e->toString(value, 2);
138 zeroPad = e->getWidth() - value.length();
140 for (
unsigned int count = 0; count < zeroPad; count++)
147 e->toString(value, 16);
150 zeroPad = (e->getWidth() / 4) - value.length();
151 for (
unsigned int count = 0; count < zeroPad; count++)
158 e->toString(value, 10);
159 *
p <<
"(_ bv" << value <<
" " << e->getWidth() <<
")";
163 llvm_unreachable(
"Unexpected constant display mode");
170 if (
getSort(e) != expectedSort) {
180 BindingMap::iterator i =
bindings.find(e);
182 *
p <<
"?B" << i->second;
189 BindingMap::iterator i =
bindings.find(e);
194 *
p <<
" :named ?B" << i->second <<
")";
195 i->second = -i->second;
197 *
p <<
"?B" << -i->second;
292 unsigned int lowIndex = e->offset;
293 unsigned int highIndex = lowIndex + e->width - 1;
324 unsigned int numExtraBits = (e->width) - (e->src->getWidth());
368 assert(bitWidth > 0 &&
"Invalid bit width");
419 return "zero_extend";
421 return "sign_extend";
472 llvm_unreachable(
"Conversion from Expr to SMTLIB keyword failed");
518 if (
p == NULL ||
query == NULL ||
o == NULL) {
519 llvm::errs() <<
"ExprSMTLIBPrinter::generateOutput() Can't print SMTLIBv2. "
520 "Output or query bad!\n";
554struct ArrayPtrsByName {
555 bool operator()(
const Array *a1,
const Array *a2)
const {
565 *
o <<
"; Array declarations\n";
569 std::sort(sortedArrays.begin(), sortedArrays.end(), ArrayPtrsByName());
570 for (std::vector<const Array *>::iterator it = sortedArrays.begin();
571 it != sortedArrays.end(); it++) {
572 *
o <<
"(declare-fun " << (*it)->name <<
" () "
574 << (*it)->getDomain() <<
") "
575 "(_ BitVec " << (*it)->getRange() <<
") ) )"
582 *
o <<
"; Constant Array Definitions\n";
587 for (std::vector<const Array *>::iterator it = sortedArrays.begin();
588 it != sortedArrays.end(); it++) {
604 *
p <<
"(select " << array->
name <<
" (_ bv" << byteIndex <<
" "
624 assert(
humanReadable &&
"method must be called in humanReadable mode");
625 *
o <<
"; Constraints\n";
632 *
o <<
"; QueryExpr\n";
641 *
o <<
"; Constraints and QueryExpr\n";
646 assert(!
humanReadable &&
"method should not be called in humanReadable mode");
669 *
o <<
"(check-sat)\n";
676 const Array *theArray = 0;
679 for (std::vector<const Array *>::const_iterator it =
684 for (
unsigned int index = 0; index < theArray->
size; ++index) {
685 *
o <<
"(get-value ( (select " << (**it).name <<
" (_ bv" << index <<
" "
693 assert(e &&
"found NULL expression");
695 if (isa<ConstantExpr>(e))
701 if (
const ReadExpr *re = dyn_cast<ReadExpr>(e)) {
703 if (
usedArrays.insert(re->updates.root).second) {
707 if (re->updates.root->isConstantArray())
717 for (
unsigned int i = 0; i < ep->
getNumKids(); i++)
731 typedef std::map<const ref<Expr>, std::set<ref<Expr> > > ExprDepMap;
739 ExprDepMap usesSubExprMap;
747 ExprDepMap subExprOfMap;
750 std::vector<ref<Expr> > nonDepBindings;
753 for (BindingMap::const_iterator it =
bindings.begin();
755 std::stack<ref<Expr> > childQueue;
756 childQueue.push(it->first);
758 while (childQueue.size()) {
759 Expr *ep = childQueue.top().get();
761 for (
unsigned i = 0; i < ep->
getNumKids(); ++i) {
763 if (isa<ConstantExpr>(e))
767 usesSubExprMap[it->first].insert(e);
768 subExprOfMap[e].insert(it->first);
775 if (!usesSubExprMap.count(it->first))
776 nonDepBindings.push_back(it->first);
778 assert(nonDepBindings.size() &&
"there must be expr bindings with no deps");
782 unsigned counter = 1;
784 while (nonDepBindings.size()) {
786 std::vector<ref<Expr> > tmp(nonDepBindings);
787 nonDepBindings.clear();
788 for (std::vector<
ref<Expr> >::const_iterator nonDepExprIt = tmp.begin();
789 nonDepExprIt != tmp.end(); ++nonDepExprIt) {
791 levelExprs.insert(std::make_pair(*nonDepExprIt, counter++));
793 ExprDepMap::iterator depsIt = subExprOfMap.find(*nonDepExprIt);
794 if (depsIt != subExprOfMap.end()) {
795 for (std::set<
ref<Expr> >::iterator exprIt = depsIt->second.begin();
796 exprIt != depsIt->second.end(); ) {
798 ExprDepMap::iterator subExprIt = usesSubExprMap.find(*exprIt);
799 assert(subExprIt != usesSubExprMap.end());
800 assert(subExprIt->second.count(*nonDepExprIt));
801 subExprIt->second.erase(*nonDepExprIt);
804 if (!subExprIt->second.size()) {
805 nonDepBindings.push_back(*exprIt);
806 depsIt->second.erase(exprIt++);
844 *
o <<
"; This file conforms to SMTLIBv2 and was generated by KLEE\n";
851 for (std::map<SMTLIBboolOptions, bool>::const_iterator i =
855 << ((i->second) ?
"true" :
"false") <<
")\n";
880 for (BindingMap::const_iterator j = levelBindings.begin();
881 j != levelBindings.end(); ++j) {
883 *
p <<
"(?B" << j->second;
909 bindings.insert(levelBindings.begin(), levelBindings.end());
969 *
p <<
";Performing implicit bool to bitvector cast";
995 *
p <<
";Performing implicit bitvector to bool cast";
1004 *
p <<
"(_ bv0 " << bitWidth <<
")";
1011 <<
"ExprSMTLIBPrinter : Warning. Casting a bitvector (length "
1012 << bitWidth <<
") to bool!\n";
1016 llvm_unreachable(
"Unsupported cast");
1054 for (
unsigned int i = 0; i < e->
getNumKids(); i++) {
1087 llvm_unreachable(
"Conversion from Expr to SMTLIB keyword failed");
1094 for (
unsigned int i = 0; i < e->
getNumKids(); i++) {
1106 std::pair<std::map<SMTLIBboolOptions, bool>::iterator,
bool> thePair;
1107 bool theValue = (value ==
OPTION_TRUE) ?
true :
false;
1114 std::pair<SMTLIBboolOptions, bool>(option, theValue));
1123 if (!thePair.second) {
1125 thePair.first->second = value;
1147 for (std::vector<const Array *>::const_iterator i = a.begin(); i != a.end();
1157 return "print-success";
1159 return "produce-models";
1161 return "interactive-mode";
1163 return "unknown-option";
PrintContext & popIndent()
PrintContext & breakLineI()
void breakLine(unsigned indent=0)
PrintContext & pushIndent()
void write(const std::string &s)
bool isConstantArray() const
const std::vector< ref< ConstantExpr > > constantValues
Expr::Width getDomain() const
static ref< ConstantExpr > create(uint64_t v, Width w)
constraint_iterator end() const
constraint_iterator begin() const
@ PRODUCE_MODELS
produce-models SMTLIBv2 option
@ PRINT_SUCCESS
print-success SMTLIBv2 option
@ INTERACTIVE_MODE
interactive-mode SMTLIBv2 option
const char * getSMTLIBOptionString(ExprSMTLIBPrinter::SMTLIBboolOptions option)
std::map< SMTLIBboolOptions, bool > smtlibBoolOptions
@ ABBR_LET
Abbreviate with let.
@ ABBR_NAMED
Abbreviate with :named annotations.
@ ABBR_NONE
Do not abbreviate.
void printExit()
Print the SMTLIBv2 command to exit.
llvm::raw_ostream * o
Output stream to write to.
void printReadExpr(const ref< ReadExpr > &e)
void setQuery(const Query &q)
void setOutput(llvm::raw_ostream &output)
const char * getSMTLIBKeyword(const ref< Expr > &e)
void scan(const ref< Expr > &e)
SMTLIB_SORT getSort(const ref< Expr > &e)
Determine the SMTLIBv2 sort of the expression.
void scanBindingExprDeps()
AbbreviationMode abbrMode
void printAShrExpr(const ref< AShrExpr > &e)
bool setLogic(SMTLIBv2Logic l)
bool setConstantDisplayMode(ConstantDisplayMode cdm)
void printFullExpression(const ref< Expr > &e, SMTLIB_SORT expectedSort)
Print expression without top-level abbreviations.
void printConstant(const ref< ConstantExpr > &e)
void setAbbreviationMode(AbbreviationMode am)
void printCastExpr(const ref< CastExpr > &e)
void printQueryInSingleAssert()
volatile bool humanReadable
@ QF_ABV
Logic using Theory of Arrays and Theory of Bitvectors.
const std::vector< const Array * > * arraysToCallGetValueOn
std::map< const ref< Expr >, int > BindingMap
void printCastToSort(const ref< Expr > &e, ExprSMTLIBPrinter::SMTLIB_SORT sort)
Print an expression but cast it to a particular SMTLIBv2 sort first.
bool haveConstantArray
Indicates if there were any constant arrays founds during a scan()
const Query * query
The query to print.
SMTLIB_SORT
Different supported SMTLIBv2 sorts (a.k.a type) in QF_AUFBV.
PrintContext * p
Helper printer class.
std::set< const Array * > usedArrays
Contains the arrays found during scans.
void setArrayValuesToGet(const std::vector< const Array * > &a)
void printExpression(const ref< Expr > &e, SMTLIB_SORT expectedSort)
void setHumanReadable(bool hr)
void printSelectExpr(const ref< SelectExpr > &e, ExprSMTLIBPrinter::SMTLIB_SORT s)
void scanUpdates(const UpdateNode *un)
Helper function for scan() that scans the expressions of an update node.
void printMachineReadableQuery()
@ OPTION_TRUE
Set option to true.
void printUpdatesAndArray(const UpdateNode *un, const Array *root)
Recursively prints updatesNodes.
void printHumanReadableQuery()
void printSortArgsExpr(const ref< Expr > &e, ExprSMTLIBPrinter::SMTLIB_SORT s)
@ HEX
Display bit vector constants in Hexidecimal e.g.#x2D.
@ BINARY
Display bit vector constants in binary e.g. #b00101101.
@ DECIMAL
Display bit vector constants in Decimal e.g. (_ bv45 8)
std::set< ref< Expr > > seenExprs
Set of expressions seen during scan.
void printAssert(const ref< Expr > &e)
Print an assert statement for the given expr.
void printArrayDeclarations()
ExprSMTLIBPrinter()
Create a new printer that will print a query in the SMTLIBv2 language.
std::vector< BindingMap > orderedBindings
void printExtractExpr(const ref< ExtractExpr > &e)
bool setSMTLIBboolOption(SMTLIBboolOptions option, SMTLIBboolValues value)
void printLogicalOrBitVectorExpr(const ref< Expr > &e, ExprSMTLIBPrinter::SMTLIB_SORT s)
Class representing symbolic expressions.
virtual Kind getKind() const =0
static ref< Expr > createIsZero(ref< Expr > e)
virtual Width getWidth() const =0
virtual unsigned getNumKids() const =0
@ Sge
Not used in canonical form.
@ Ne
Not used in canonical form.
@ Ugt
Not used in canonical form.
@ Sgt
Not used in canonical form.
@ Uge
Not used in canonical form.
unsigned Width
The type of an expression is simply its width, in bits.
virtual ref< Expr > getKid(unsigned i) const =0
Class representing a one byte read from an array.
Class representing a byte update of an array.
const ref< UpdateNode > next
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) )")), llvm::cl::init(klee::ExprSMTLIBPrinter::DECIMAL), llvm::cl::cat(klee::ExprCat))
llvm::cl::opt< bool > humanReadableSMTLIB("smtlib-human-readable", llvm::cl::desc("Enables generated SMT-LIBv2 files to " "be human readable (default=false)"), llvm::cl::init(false), llvm::cl::cat(klee::ExprCat))
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")), llvm::cl::init(klee::ExprSMTLIBPrinter::ABBR_LET), llvm::cl::cat(klee::ExprCat))
llvm::cl::OptionCategory ExprCat
const ConstraintSet & constraints