aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/Solver
diff options
context:
space:
mode:
authorCristian Cadar <cristic@cs.stanford.edu>2013-01-02 15:49:34 +0000
committerCristian Cadar <cristic@cs.stanford.edu>2013-01-02 15:49:34 +0000
commit79237753a1e9cbe653e5763ffd61f3cb5b8759c1 (patch)
tree574e2bf199f64ea7ecf8c5a38963bfe2e6192d4c /lib/Solver
parentd369654e361782b3f4a52303114db11959a346f7 (diff)
downloadklee-79237753a1e9cbe653e5763ffd61f3cb5b8759c1.tar.gz
Patch by Tomasz Kuchta adding more detailed information on query failures.
git-svn-id: https://llvm.org/svn/llvm-project/klee/trunk@171391 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Solver')
-rw-r--r--lib/Solver/CachingSolver.cpp6
-rw-r--r--lib/Solver/CexCachingSolver.cpp6
-rw-r--r--lib/Solver/IncompleteSolver.cpp4
-rw-r--r--lib/Solver/IndependentSolver.cpp6
-rw-r--r--lib/Solver/Solver.cpp143
5 files changed, 101 insertions, 64 deletions
diff --git a/lib/Solver/CachingSolver.cpp b/lib/Solver/CachingSolver.cpp
index f7b88855..b6a93c7b 100644
--- a/lib/Solver/CachingSolver.cpp
+++ b/lib/Solver/CachingSolver.cpp
@@ -82,7 +82,7 @@ public:
return solver->impl->computeInitialValues(query, objects, values,
hasSolution);
}
- bool hasTimeoutOccurred();
+ SolverRunStatus getOperationStatusCode();
};
/** @returns the canonical version of the given query. The reference
@@ -235,8 +235,8 @@ bool CachingSolver::computeTruth(const Query& query,
return true;
}
-bool CachingSolver::hasTimeoutOccurred() {
- return solver->impl->hasTimeoutOccurred();
+SolverImpl::SolverRunStatus CachingSolver::getOperationStatusCode() {
+ return solver->impl->getOperationStatusCode();
}
///
diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp
index c84ae409..3d7a754c 100644
--- a/lib/Solver/CexCachingSolver.cpp
+++ b/lib/Solver/CexCachingSolver.cpp
@@ -82,7 +82,7 @@ public:
const std::vector<const Array*> &objects,
std::vector< std::vector<unsigned char> > &values,
bool &hasSolution);
- bool hasTimeoutOccurred();
+ SolverRunStatus getOperationStatusCode();
};
///
@@ -340,8 +340,8 @@ CexCachingSolver::computeInitialValues(const Query& query,
return true;
}
-bool CexCachingSolver::hasTimeoutOccurred() {
- return solver->impl->hasTimeoutOccurred();
+SolverImpl::SolverRunStatus CexCachingSolver::getOperationStatusCode() {
+ return solver->impl->getOperationStatusCode();
}
///
diff --git a/lib/Solver/IncompleteSolver.cpp b/lib/Solver/IncompleteSolver.cpp
index 45e2ea9b..7bc8058d 100644
--- a/lib/Solver/IncompleteSolver.cpp
+++ b/lib/Solver/IncompleteSolver.cpp
@@ -135,6 +135,6 @@ StagedSolverImpl::computeInitialValues(const Query& query,
hasSolution);
}
-bool StagedSolverImpl::hasTimeoutOccurred() {
- return secondary->impl->hasTimeoutOccurred();
+SolverImpl::SolverRunStatus StagedSolverImpl::getOperationStatusCode() {
+ return secondary->impl->getOperationStatusCode();
}
diff --git a/lib/Solver/IndependentSolver.cpp b/lib/Solver/IndependentSolver.cpp
index 0eb86720..b3ef1e57 100644
--- a/lib/Solver/IndependentSolver.cpp
+++ b/lib/Solver/IndependentSolver.cpp
@@ -284,7 +284,7 @@ public:
return solver->impl->computeInitialValues(query, objects, values,
hasSolution);
}
- bool hasTimeoutOccurred();
+ SolverRunStatus getOperationStatusCode();
};
bool IndependentSolver::computeValidity(const Query& query,
@@ -314,8 +314,8 @@ bool IndependentSolver::computeValue(const Query& query, ref<Expr> &result) {
return solver->impl->computeValue(Query(tmp, query.expr), result);
}
-bool IndependentSolver::hasTimeoutOccurred() {
- return solver->impl->hasTimeoutOccurred();
+SolverImpl::SolverRunStatus IndependentSolver::getOperationStatusCode() {
+ return solver->impl->getOperationStatusCode();
}
Solver *klee::createIndependentSolver(Solver *s) {
diff --git a/lib/Solver/Solver.cpp b/lib/Solver/Solver.cpp
index 366a7b05..abb70770 100644
--- a/lib/Solver/Solver.cpp
+++ b/lib/Solver/Solver.cpp
@@ -39,6 +39,48 @@ using namespace klee;
/***/
+SolverImpl::~SolverImpl() {
+}
+
+bool SolverImpl::computeValidity(const Query& query, Solver::Validity &result) {
+ bool isTrue, isFalse;
+ if (!computeTruth(query, isTrue))
+ return false;
+ if (isTrue) {
+ result = Solver::True;
+ } else {
+ if (!computeTruth(query.negateExpr(), isFalse))
+ return false;
+ result = isFalse ? Solver::False : Solver::Unknown;
+ }
+ return true;
+}
+
+const char* SolverImpl::getOperationStatusString(SolverRunStatus statusCode)
+{
+ switch (statusCode)
+ {
+ case SOLVER_RUN_STATUS_SUCCESS_SOLVABLE:
+ return "OPERATION SUCCESSFUL, QUERY IS SOLVABLE";
+ case SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE:
+ return "OPERATION SUCCESSFUL, QUERY IS UNSOLVABLE";
+ case SOLVER_RUN_STATUS_FAILURE:
+ return "OPERATION FAILED";
+ case SOLVER_RUN_STATUS_TIMEOUT:
+ return "SOLVER TIMEOUT";
+ case SOLVER_RUN_STATUS_FORK_FAILED:
+ return "FORK FAILED";
+ case SOLVER_RUN_STATUS_INTERRUPTED:
+ return "SOLVER PROCESS INTERRUPTED";
+ case SOLVER_RUN_STATUS_UNEXPECTED_EXIT_CODE:
+ return "UNEXPECTED SOLVER PROCESS EXIT CODE";
+ case SOLVER_RUN_STATUS_WAITPID_FAILED:
+ return "WAITPID FAILED FOR SOLVER PROCESS";
+ default:
+ return "UNRECOGNIZED OPERATION STATUS";
+ }
+}
+
const char *Solver::validity_to_str(Validity v) {
switch (v) {
default: return "Unknown";
@@ -51,9 +93,6 @@ Solver::~Solver() {
delete impl;
}
-SolverImpl::~SolverImpl() {
-}
-
bool Solver::evaluate(const Query& query, Validity &result) {
assert(query.expr->getWidth() == Expr::Bool && "Invalid expression type!");
@@ -66,20 +105,6 @@ bool Solver::evaluate(const Query& query, Validity &result) {
return impl->computeValidity(query, result);
}
-bool SolverImpl::computeValidity(const Query& query, Solver::Validity &result) {
- bool isTrue, isFalse;
- if (!computeTruth(query, isTrue))
- return false;
- if (isTrue) {
- result = Solver::True;
- } else {
- if (!computeTruth(query.negateExpr(), isFalse))
- return false;
- result = isFalse ? Solver::False : Solver::Unknown;
- }
- return true;
-}
-
bool Solver::mustBeTrue(const Query& query, bool &result) {
assert(query.expr->getWidth() == Expr::Bool && "Invalid expression type!");
@@ -273,7 +298,7 @@ public:
const std::vector<const Array*> &objects,
std::vector< std::vector<unsigned char> > &values,
bool &hasSolution);
- bool hasTimeoutOccurred();
+ SolverRunStatus getOperationStatusCode();
};
bool ValidatingSolver::computeTruth(const Query& query,
@@ -371,8 +396,8 @@ ValidatingSolver::computeInitialValues(const Query& query,
return true;
}
-bool ValidatingSolver::hasTimeoutOccurred() {
- return solver->impl->hasTimeoutOccurred();
+SolverImpl::SolverRunStatus ValidatingSolver::getOperationStatusCode() {
+ return solver->impl->getOperationStatusCode();
}
Solver *klee::createValidatingSolver(Solver *s, Solver *oracle) {
@@ -408,8 +433,8 @@ public:
++stats::queryCounterexamples;
return false;
}
- bool hasTimeoutOccurred() {
- return false;
+ SolverRunStatus getOperationStatusCode() {
+ return SOLVER_RUN_STATUS_FAILURE;
}
};
@@ -428,7 +453,7 @@ private:
STPBuilder *builder;
double timeout;
bool useForkedSTP;
- bool timeoutOccurred;
+ SolverRunStatus runStatusCode;
public:
STPSolverImpl(STPSolver *_solver, bool _useForkedSTP, bool _optimizeDivides = true);
@@ -443,7 +468,7 @@ public:
const std::vector<const Array*> &objects,
std::vector< std::vector<unsigned char> > &values,
bool &hasSolution);
- bool hasTimeoutOccurred();
+ SolverRunStatus getOperationStatusCode();
};
static unsigned char *shared_memory_ptr;
@@ -461,7 +486,7 @@ STPSolverImpl::STPSolverImpl(STPSolver *_solver, bool _useForkedSTP, bool _optim
builder(new STPBuilder(vc, _optimizeDivides)),
timeout(0.0),
useForkedSTP(_useForkedSTP),
- timeoutOccurred(false)
+ runStatusCode(SOLVER_RUN_STATUS_FAILURE)
{
assert(vc && "unable to create validity checker");
assert(builder && "unable to create STPBuilder");
@@ -558,10 +583,10 @@ bool STPSolverImpl::computeValue(const Query& query,
return true;
}
-static void runAndGetCex(::VC vc, STPBuilder *builder, ::VCExpr q,
- const std::vector<const Array*> &objects,
- std::vector< std::vector<unsigned char> > &values,
- bool &hasSolution) {
+static SolverImpl::SolverRunStatus runAndGetCex(::VC vc, STPBuilder *builder, ::VCExpr q,
+ const std::vector<const Array*> &objects,
+ std::vector< std::vector<unsigned char> > &values,
+ bool &hasSolution) {
// XXX I want to be able to timeout here, safely
hasSolution = !vc_query(vc, q);
@@ -583,20 +608,27 @@ static void runAndGetCex(::VC vc, STPBuilder *builder, ::VCExpr q,
values.push_back(data);
}
}
+
+ if (true == hasSolution) {
+ return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE;
+ }
+ else {
+ return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE;
+ }
}
static void stpTimeoutHandler(int x) {
_exit(52);
}
-static SolverRunStatus runAndGetCexForked(::VC vc,
- STPBuilder *builder,
- ::VCExpr q,
- const std::vector<const Array*> &objects,
- std::vector< std::vector<unsigned char> >
- &values,
- bool &hasSolution,
- double timeout) {
+static SolverImpl::SolverRunStatus runAndGetCexForked(::VC vc,
+ STPBuilder *builder,
+ ::VCExpr q,
+ const std::vector<const Array*> &objects,
+ std::vector< std::vector<unsigned char> >
+ &values,
+ bool &hasSolution,
+ double timeout) {
unsigned char *pos = shared_memory_ptr;
unsigned sum = 0;
for (std::vector<const Array*>::const_iterator
@@ -609,7 +641,7 @@ static SolverRunStatus runAndGetCexForked(::VC vc,
int pid = fork();
if (pid==-1) {
fprintf(stderr, "error: fork failed (for STP)");
- return SOLVER_RUN_STATUS_FORK_FAILED;
+ return SolverImpl::SOLVER_RUN_STATUS_FORK_FAILED;
}
if (pid == 0) {
@@ -641,7 +673,7 @@ static SolverRunStatus runAndGetCexForked(::VC vc,
if (res < 0) {
fprintf(stderr, "error: waitpid() for STP failed");
- return SOLVER_RUN_STATUS_WAITPID_FAILED;
+ return SolverImpl::SOLVER_RUN_STATUS_WAITPID_FAILED;
}
// From timed_run.py: It appears that linux at least will on
@@ -649,7 +681,7 @@ static SolverRunStatus runAndGetCexForked(::VC vc,
// signal, so test signal first.
if (WIFSIGNALED(status) || !WIFEXITED(status)) {
fprintf(stderr, "error: STP did not return successfully");
- return SOLVER_RUN_STATUS_INTERRUPTED;
+ return SolverImpl::SOLVER_RUN_STATUS_INTERRUPTED;
}
int exitcode = WEXITSTATUS(status);
@@ -660,10 +692,10 @@ static SolverRunStatus runAndGetCexForked(::VC vc,
} else if (exitcode==52) {
fprintf(stderr, "error: STP timed out");
// mark that a timeout occurred
- return SOLVER_RUN_STATUS_TIMEOUT;
+ return SolverImpl::SOLVER_RUN_STATUS_TIMEOUT;
} else {
fprintf(stderr, "error: STP did not return a recognized code");
- return SOLVER_RUN_STATUS_UNEXPECTED_EXIT_CODE;
+ return SolverImpl::SOLVER_RUN_STATUS_UNEXPECTED_EXIT_CODE;
}
if (hasSolution) {
@@ -677,11 +709,16 @@ static SolverRunStatus runAndGetCexForked(::VC vc,
pos += array->size;
}
}
-
- return SOLVER_RUN_STATUS_SUCCESS;
+
+ if (true == hasSolution) {
+ return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE;
+ }
+ else {
+ return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE;
+ }
}
}
-
+#include <iostream>
bool
STPSolverImpl::computeInitialValues(const Query &query,
const std::vector<const Array*>
@@ -689,7 +726,7 @@ STPSolverImpl::computeInitialValues(const Query &query,
std::vector< std::vector<unsigned char> >
&values,
bool &hasSolution) {
- timeoutOccurred = false;
+ runStatusCode = SOLVER_RUN_STATUS_FAILURE;
TimerStatIncrementer t(stats::queryTime);
@@ -713,12 +750,12 @@ STPSolverImpl::computeInitialValues(const Query &query,
bool success;
if (useForkedSTP) {
- SolverRunStatus runStatus = runAndGetCexForked(vc, builder, stp_e, objects, values,
- hasSolution, timeout);
- success = (SOLVER_RUN_STATUS_SUCCESS == runStatus);
- timeoutOccurred = (SOLVER_RUN_STATUS_TIMEOUT == runStatus);
+ runStatusCode = runAndGetCexForked(vc, builder, stp_e, objects, values,
+ hasSolution, timeout);
+ success = ((SOLVER_RUN_STATUS_SUCCESS_SOLVABLE == runStatusCode) ||
+ (SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE == runStatusCode));
} else {
- runAndGetCex(vc, builder, stp_e, objects, values, hasSolution);
+ runStatusCode = runAndGetCex(vc, builder, stp_e, objects, values, hasSolution);
success = true;
}
@@ -734,6 +771,6 @@ STPSolverImpl::computeInitialValues(const Query &query,
return success;
}
-bool STPSolverImpl::hasTimeoutOccurred() {
- return timeoutOccurred;
+SolverImpl::SolverRunStatus STPSolverImpl::getOperationStatusCode() {
+ return runStatusCode;
}