main.cpp

Go to the documentation of this file.
00001 #include "expr/Lexer.h"
00002 #include "expr/Parser.h"
00003 
00004 #include "klee/Constraints.h"
00005 #include "klee/Expr.h"
00006 #include "klee/Solver.h"
00007 #include "klee/util/ExprPPrinter.h"
00008 #include "klee/util/ExprVisitor.h"
00009 
00010 #include "llvm/ADT/StringExtras.h"
00011 #include "llvm/Support/CommandLine.h"
00012 #include "llvm/Support/ManagedStatic.h"
00013 #include "llvm/Support/MemoryBuffer.h"
00014 #include "llvm/Support/Streams.h"
00015 #include "llvm/System/Signals.h"
00016 
00017 #include <iomanip>
00018 #include <sstream>
00019 
00020 using namespace llvm;
00021 using namespace klee;
00022 using namespace klee::expr;
00023 
00024 namespace {
00025   llvm::cl::opt<std::string>
00026   InputFile(llvm::cl::desc("<input query log>"), llvm::cl::Positional,
00027             llvm::cl::init("-"));
00028 
00029   enum ToolActions {
00030     PrintTokens,
00031     PrintAST,
00032     Evaluate
00033   };
00034 
00035   static llvm::cl::opt<ToolActions> 
00036   ToolAction(llvm::cl::desc("Tool actions:"),
00037              llvm::cl::init(Evaluate),
00038              llvm::cl::values(
00039              clEnumValN(PrintTokens, "print-tokens",
00040                         "Print tokens from the input file."),
00041              clEnumValN(PrintAST, "print-ast",
00042                         "Print parsed AST nodes from the input file."),
00043              clEnumValN(Evaluate, "evaluate",
00044                         "Print parsed AST nodes from the input file."),
00045              clEnumValEnd));
00046 }
00047 
00048 static std::string escapedString(const char *start, unsigned length) {
00049   std::stringstream s;
00050   for (unsigned i=0; i<length; ++i) {
00051     char c = start[i];
00052     if (isprint(c)) {
00053       s << c;
00054     } else if (c == '\n') {
00055       s << "\\n";
00056     } else {
00057       s << "\\x" 
00058         << hexdigit(((unsigned char) c >> 4) & 0xF) 
00059         << hexdigit((unsigned char) c & 0xF);
00060     }
00061   }
00062   return s.str();
00063 }
00064 
00065 static void PrintInputTokens(const MemoryBuffer *MB) {
00066   Lexer L(MB);
00067   Token T;
00068   do {
00069     L.Lex(T);
00070     llvm::cout << "(Token \"" << T.getKindName() << "\" "
00071                << "\"" << escapedString(T.start, T.length) << "\" "
00072                << T.length << " "
00073                << T.line << " " << T.column << ")\n";
00074   } while (T.kind != Token::EndOfFile);
00075 }
00076 
00077 static bool PrintInputAST(const char *Filename,
00078                           const MemoryBuffer *MB) {
00079   Parser *P = Parser::Create(Filename, MB);
00080   P->SetMaxErrors(20);
00081   while (Decl *D = P->ParseTopLevelDecl()) {
00082     if (!P->GetNumErrors())
00083       D->dump();
00084     delete D;
00085   }
00086 
00087   bool success = true;
00088   if (unsigned N = P->GetNumErrors()) {
00089     llvm::cerr << Filename << ": parse failure: "
00090                << N << " errors.\n";
00091     success = false;
00092   }
00093   delete P;
00094 
00095   return success;
00096 }
00097 
00098 static bool EvaluateInputAST(const char *Filename,
00099                           const MemoryBuffer *MB) {
00100   std::vector<Decl*> Decls;
00101   Parser *P = Parser::Create(Filename, MB);
00102   P->SetMaxErrors(20);
00103   while (Decl *D = P->ParseTopLevelDecl()) {
00104     Decls.push_back(D);
00105   }
00106 
00107   bool success = true;
00108   if (unsigned N = P->GetNumErrors()) {
00109     llvm::cerr << Filename << ": parse failure: "
00110                << N << " errors.\n";
00111     success = false;
00112   }  
00113   delete P;
00114 
00115   if (!success) {
00116     for (std::vector<Decl*>::iterator it = Decls.begin(),
00117            ie = Decls.end(); it != ie; ++it)
00118       delete *it;
00119     return success;
00120   }
00121 
00122   // FIXME: Support choice of solver.
00123   Solver *S, *STP = new STPSolver(true);
00124   S = createCexCachingSolver(STP);
00125   S = createCachingSolver(S);
00126   S = createIndependentSolver(S);
00127 
00128   unsigned Index = 0;
00129   for (std::vector<Decl*>::iterator it = Decls.begin(),
00130          ie = Decls.end(); it != ie; ++it) {
00131     Decl *D = *it;
00132     if (QueryCommand *QC = dyn_cast<QueryCommand>(D)) {
00133       llvm::cout << "Query " << Index << ":\t";
00134 
00135       assert("FIXME: Support counterexample query commands!");
00136       if (QC->Values.empty() && QC->Objects.empty()) {
00137         bool result;
00138         if (S->mustBeTrue(Query(ConstraintManager(QC->Constraints), QC->Query),
00139                           result)) {
00140           llvm::cout << (result ? "VALID" : "INVALID");
00141         } else {
00142           llvm::cout << "FAIL";
00143         }
00144       } else if (!QC->Values.empty()) {
00145         assert(QC->Objects.empty() && 
00146                "FIXME: Support counterexamples for values and objects!");
00147         assert(QC->Values.size() == 1 &&
00148                "FIXME: Support counterexamples for multiple values!");
00149         assert(QC->Query->isFalse() &&
00150                "FIXME: Support counterexamples with non-trivial query!");
00151         ref<ConstantExpr> result;
00152         if (S->getValue(Query(ConstraintManager(QC->Constraints), 
00153                               QC->Values[0]),
00154                         result)) {
00155           llvm::cout << "INVALID\n";
00156           llvm::cout << "\tExpr 0:\t" << result;
00157         } else {
00158           llvm::cout << "FAIL";
00159         }
00160       } else {
00161         std::vector< std::vector<unsigned char> > result;
00162         
00163         if (S->getInitialValues(Query(ConstraintManager(QC->Constraints), 
00164                                       QC->Query),
00165                                 QC->Objects, result)) {
00166           llvm::cout << "INVALID\n";
00167 
00168           for (unsigned i = 0, e = result.size(); i != e; ++i) {
00169             llvm::cout << "\tArray " << i << ":\t"
00170                        << "arr" << QC->Objects[i]->id
00171                        << "[";
00172             for (unsigned j = 0; j != QC->Objects[i]->size; ++j) {
00173               llvm::cout << (unsigned) result[i][j];
00174               if (j + 1 != QC->Objects[i]->size)
00175                 llvm::cout << ", ";
00176             }
00177             llvm::cout << "]";
00178             if (i + 1 != e)
00179               llvm::cout << "\n";
00180           }
00181         } else {
00182           llvm::cout << "FAIL";
00183         }
00184       }
00185 
00186       llvm::cout << "\n";
00187       ++Index;
00188     }
00189 
00190     delete D;
00191   }
00192 
00193   delete S;
00194 
00195   return success;
00196 }
00197 
00198 int main(int argc, char **argv) {
00199   bool success = true;
00200 
00201   llvm::sys::PrintStackTraceOnErrorSignal();
00202   llvm::cl::ParseCommandLineOptions(argc, argv);
00203 
00204   std::string ErrorStr;
00205   MemoryBuffer *MB = MemoryBuffer::getFileOrSTDIN(InputFile.c_str(), &ErrorStr);
00206   if (!MB) {
00207     llvm::cerr << argv[0] << ": error: " << ErrorStr << "\n";
00208     return 1;
00209   }
00210 
00211   switch (ToolAction) {
00212   case PrintTokens:
00213     PrintInputTokens(MB);
00214     break;
00215   case PrintAST:
00216     success = PrintInputAST(InputFile=="-" ? "<stdin>" : InputFile.c_str(), MB);
00217     break;
00218   case Evaluate:
00219     success = EvaluateInputAST(InputFile=="-" ? "<stdin>" : InputFile.c_str(),
00220                                MB);
00221     break;
00222   default:
00223     llvm::cerr << argv[0] << ": error: Unknown program action!\n";
00224   }
00225 
00226   delete MB;
00227 
00228   llvm::llvm_shutdown();
00229   return success ? 0 : 1;
00230 }

Generated on Fri Jun 5 03:31:32 2009 for klee by  doxygen 1.5.8