//===-- Solver.cpp --------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "klee/Solver/Solver.h" #include "klee/Expr/Constraints.h" #include "klee/Solver/SolverImpl.h" #include using namespace klee; const char *Solver::validity_to_str(Validity v) { switch (v) { default: return "Unknown"; case True: return "True"; case False: return "False"; } } Solver::Solver(std::unique_ptr impl) : impl(std::move(impl)) {} Solver::~Solver() = default; std::string Solver::getConstraintLog(const Query& query) { return impl->getConstraintLog(query); } void Solver::setCoreSolverTimeout(time::Span timeout) { impl->setCoreSolverTimeout(timeout); } bool Solver::evaluate(const Query& query, Validity &result) { assert(query.expr->getWidth() == Expr::Bool && "Invalid expression type!"); // Maintain invariants implementations expect. if (ConstantExpr *CE = dyn_cast(query.expr)) { result = CE->isTrue() ? True : False; return true; } return impl->computeValidity(query, result); } bool Solver::mustBeTrue(const Query& query, bool &result) { assert(query.expr->getWidth() == Expr::Bool && "Invalid expression type!"); // Maintain invariants implementations expect. if (ConstantExpr *CE = dyn_cast(query.expr)) { result = CE->isTrue() ? true : false; return true; } return impl->computeTruth(query, result); } bool Solver::mustBeFalse(const Query& query, bool &result) { return mustBeTrue(query.negateExpr(), result); } bool Solver::mayBeTrue(const Query& query, bool &result) { bool res; if (!mustBeFalse(query, res)) return false; result = !res; return true; } bool Solver::mayBeFalse(const Query& query, bool &result) { bool res; if (!mustBeTrue(query, res)) return false; result = !res; return true; } bool Solver::getValue(const Query& query, ref &result) { // Maintain invariants implementation expect. if (ConstantExpr *CE = dyn_cast(query.expr)) { result = CE; return true; } // FIXME: Push ConstantExpr requirement down. ref tmp; if (!impl->computeValue(query, tmp)) return false; result = cast(tmp); return true; } bool Solver::getInitialValues(const Query& query, const std::vector &objects, std::vector< std::vector > &values) { bool hasSolution; bool success = impl->computeInitialValues(query, objects, values, hasSolution); // FIXME: Propagate this out. if (!hasSolution) return false; return success; } std::pair< ref, ref > Solver::getRange(const Query& query) { ref e = query.expr; Expr::Width width = e->getWidth(); uint64_t min, max; if (width==1) { Solver::Validity result; if (!evaluate(query, result)) assert(0 && "computeValidity failed"); switch (result) { case Solver::True: min = max = 1; break; case Solver::False: min = max = 0; break; default: min = 0, max = 1; break; } } else if (ConstantExpr *CE = dyn_cast(e)) { min = max = CE->getZExtValue(); } else { // binary search for # of useful bits uint64_t lo=0, hi=width, mid, bits=0; while (lodump(); llvm::errs() << "]\n"; llvm::errs() << "Query [\n"; expr->dump(); llvm::errs() << "]\n"; }