00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "klee/Solver.h"
00011
00012
00013 #include "klee/ExecutionState.h"
00014 #include "klee/Expr.h"
00015 #include "klee/SolverImpl.h"
00016 #include "klee/Statistics.h"
00017 #include "klee/util/ExprPPrinter.h"
00018 #include "klee/Internal/Support/QueryLog.h"
00019 #include "klee/Internal/System/Time.h"
00020
00021 #include "llvm/Support/CommandLine.h"
00022
00023 #include <fstream>
00024
00025 using namespace klee;
00026 using namespace llvm;
00027 using namespace klee::util;
00028
00030
00031 class PCLoggingSolver : public SolverImpl {
00032 Solver *solver;
00033 std::ofstream os;
00034 ExprPPrinter *printer;
00035 unsigned queryCount;
00036 double startTime;
00037
00038 void startQuery(const Query& query, const char *typeName,
00039 const ref<Expr> *evalExprsBegin = 0,
00040 const ref<Expr> *evalExprsEnd = 0,
00041 const Array * const* evalArraysBegin = 0,
00042 const Array * const* evalArraysEnd = 0) {
00043 Statistic *S = theStatisticManager->getStatisticByName("Instructions");
00044 uint64_t instructions = S ? S->getValue() : 0;
00045 os << "# Query " << queryCount++ << " -- "
00046 << "Type: " << typeName << ", "
00047 << "Instructions: " << instructions << "\n";
00048 printer->printQuery(os, query.constraints, query.expr,
00049 evalExprsBegin, evalExprsEnd,
00050 evalArraysBegin, evalArraysEnd);
00051
00052 startTime = getWallTime();
00053 }
00054
00055 void finishQuery(bool success) {
00056 double delta = getWallTime() - startTime;
00057 os << "# " << (success ? "OK" : "FAIL") << " -- "
00058 << "Elapsed: " << delta << "\n";
00059 }
00060
00061 public:
00062 PCLoggingSolver(Solver *_solver, std::string path)
00063 : solver(_solver),
00064 os(path.c_str(), std::ios::trunc),
00065 printer(ExprPPrinter::create(os)),
00066 queryCount(0) {
00067 }
00068 ~PCLoggingSolver() {
00069 delete printer;
00070 delete solver;
00071 }
00072
00073 bool computeTruth(const Query& query, bool &isValid) {
00074 startQuery(query, "Truth");
00075 bool success = solver->impl->computeTruth(query, isValid);
00076 finishQuery(success);
00077 if (success)
00078 os << "# Is Valid: " << (isValid ? "true" : "false") << "\n";
00079 os << "\n";
00080 return success;
00081 }
00082
00083 bool computeValidity(const Query& query, Solver::Validity &result) {
00084 startQuery(query, "Validity");
00085 bool success = solver->impl->computeValidity(query, result);
00086 finishQuery(success);
00087 if (success)
00088 os << "# Validity: " << result << "\n";
00089 os << "\n";
00090 return success;
00091 }
00092
00093 bool computeValue(const Query& query, ref<Expr> &result) {
00094 startQuery(query.withFalse(), "Value",
00095 &query.expr, &query.expr + 1);
00096 bool success = solver->impl->computeValue(query, result);
00097 finishQuery(success);
00098 if (success)
00099 os << "# Result: " << result << "\n";
00100 os << "\n";
00101 return success;
00102 }
00103
00104 bool computeInitialValues(const Query& query,
00105 const std::vector<const Array*> &objects,
00106 std::vector< std::vector<unsigned char> > &values,
00107 bool &hasSolution) {
00108 const ref<Expr> *evalExprBegin = 0, *evalExprEnd = 0;
00109 if (!query.expr->isFalse()) {
00110 evalExprBegin = &query.expr;
00111 evalExprEnd = evalExprBegin + 1;
00112 }
00113 if (objects.empty()) {
00114 startQuery(query.withFalse(), "InitialValues",
00115 evalExprBegin, evalExprEnd);
00116 } else {
00117 startQuery(query.withFalse(), "InitialValues",
00118 evalExprBegin, evalExprEnd,
00119 &objects[0], &objects[0] + objects.size());
00120 }
00121 bool success = solver->impl->computeInitialValues(query, objects,
00122 values, hasSolution);
00123 finishQuery(success);
00124 if (success) {
00125 os << "# Solvable: " << (hasSolution ? "true" : "false") << "\n";
00126 if (hasSolution) {
00127 std::vector< std::vector<unsigned char> >::iterator
00128 values_it = values.begin();
00129 for (std::vector<const Array*>::const_iterator i = objects.begin(),
00130 e = objects.end(); i != e; ++i, ++values_it) {
00131 const Array *array = *i;
00132 std::vector<unsigned char> &data = *values_it;
00133 os << "# arr" << array->id << " = [";
00134 for (unsigned j = 0; j < array->size; j++) {
00135 os << (int) data[j];
00136 if (j+1 < array->size)
00137 os << ",";
00138 }
00139 os << "]\n";
00140 }
00141 }
00142 }
00143 os << "\n";
00144 return success;
00145 }
00146 };
00147
00149
00150 Solver *klee::createPCLoggingSolver(Solver *_solver, std::string path) {
00151 return new Solver(new PCLoggingSolver(_solver, path));
00152 }