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
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 }