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