1818#include " klee/Solver/IncompleteSolver.h"
1919#include " klee/Support/Debug.h"
2020#include " klee/Support/ErrorHandling.h"
21+ #include " klee/Support/OptionCategories.h"
2122
2223#include " klee/Support/CompilerWarning.h"
2324DISABLE_WARNING_PUSH
@@ -33,6 +34,20 @@ DISABLE_WARNING_POP
3334#include < vector>
3435
3536using namespace klee ;
37+ using namespace llvm ;
38+
39+ namespace {
40+ enum class FastCexSolverType { EQUALITY, ALL };
41+
42+ cl::opt<FastCexSolverType> FastCexFor (
43+ " fast-cex-for" ,
44+ cl::desc (
45+ " Specifiy a query predicate to filter queries for FastCexSolver using" ),
46+ cl::values(clEnumValN(FastCexSolverType::EQUALITY, " equality" ,
47+ " Query with only equality expressions" ),
48+ clEnumValN(FastCexSolverType::ALL, " all" , " All queries" )),
49+ cl::init(FastCexSolverType::EQUALITY), cl::cat(SolvingCat));
50+ } // namespace
3651
3752// Hacker's Delight, pgs 58-63
3853static uint64_t minOR (uint64_t a, uint64_t b, uint64_t c, uint64_t d) {
@@ -403,10 +418,12 @@ class CexPossibleEvaluator : public ExprEvaluator {
403418 ref<Expr> getInitialValue (const Array &array, unsigned index) {
404419 // If the index is out of range, we cannot assign it a value, since that
405420 // value cannot be part of the assignment.
406- ref<ConstantExpr> constantArraySize = dyn_cast<ConstantExpr>(array.size );
421+ ref<ConstantExpr> constantArraySize =
422+ dyn_cast<ConstantExpr>(visit (array.size ));
407423 if (!constantArraySize) {
408- klee_error (
409- " FIXME: Arrays of symbolic sizes are unsupported in FastCex\n " );
424+ visit (array.size )->dump ();
425+ klee_error (" FIXME: CexPossibleEvaluator: Arrays of symbolic sizes are "
426+ " unsupported in FastCex\n " );
410427 std::abort ();
411428 }
412429
@@ -433,11 +450,11 @@ class CexExactEvaluator : public ExprEvaluator {
433450 ref<Expr> getInitialValue (const Array &array, unsigned index) {
434451 // If the index is out of range, we cannot assign it a value, since that
435452 // value cannot be part of the assignment.
436- ref<ConstantExpr> constantArraySize = dyn_cast<ConstantExpr>(array.size );
453+ ref<ConstantExpr> constantArraySize =
454+ dyn_cast<ConstantExpr>(visit (array.size ));
437455 if (!constantArraySize) {
438- klee_error (
439- " FIXME: Arrays of symbolic sizes are unsupported in FastCex\n " );
440- std::abort ();
456+ return ReadExpr::create (UpdateList (&array, 0 ),
457+ ConstantExpr::alloc (index, array.getDomain ()));
441458 }
442459
443460 if (index >= constantArraySize->getZExtValue ()) {
@@ -485,10 +502,11 @@ class CexData {
485502 CexObjectData &getObjectData (const Array *A) {
486503 CexObjectData *&Entry = objects[A];
487504
488- ref<ConstantExpr> constantArraySize = dyn_cast<ConstantExpr>(A->size );
505+ ref<ConstantExpr> constantArraySize =
506+ dyn_cast<ConstantExpr>(evaluatePossible (A->size ));
489507 if (!constantArraySize) {
490- klee_error (
491- " FIXME: Arrays of symbolic sizes are unsupported in FastCex\n " );
508+ klee_error (" FIXME: CexData: Arrays of symbolic sizes are unsupported in "
509+ " FastCex\n " );
492510 std::abort ();
493511 }
494512
@@ -529,7 +547,7 @@ class CexData {
529547 // to see if this is an initial read or not.
530548 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(re->index )) {
531549 if (ref<ConstantExpr> constantArraySize =
532- dyn_cast<ConstantExpr>(array->size )) {
550+ dyn_cast<ConstantExpr>(evaluatePossible ( array->size ) )) {
533551 uint64_t index = CE->getZExtValue ();
534552
535553 if (index < constantArraySize->getZExtValue ()) {
@@ -1171,6 +1189,7 @@ bool FastCexSolver::computeInitialValues(
11711189 const Query &query, const std::vector<const Array *> &objects,
11721190 std::vector<SparseStorage<unsigned char >> &values, bool &hasSolution) {
11731191 CexData cd;
1192+ query.dump ();
11741193
11751194 bool isValid;
11761195 bool success = propagateValues (query, cd, true , isValid);
@@ -1187,7 +1206,7 @@ bool FastCexSolver::computeInitialValues(
11871206 for (unsigned i = 0 ; i != objects.size (); ++i) {
11881207 const Array *array = objects[i];
11891208 assert (array);
1190- SparseStorage<unsigned char > data;
1209+ SparseStorage<unsigned char > data ( 0 ) ;
11911210 ref<ConstantExpr> arrayConstantSize =
11921211 dyn_cast<ConstantExpr>(cd.evaluatePossible (array->size ));
11931212 assert (arrayConstantSize &&
@@ -1212,7 +1231,45 @@ bool FastCexSolver::computeInitialValues(
12121231 return true ;
12131232}
12141233
1234+ class OnlyEqualityWithConstantQueryPredicate {
1235+ public:
1236+ explicit OnlyEqualityWithConstantQueryPredicate () {}
1237+
1238+ bool operator ()(const Query &query) const {
1239+ for (auto constraint : query.constraints .cs ()) {
1240+ if (const EqExpr *ee = dyn_cast<EqExpr>(constraint)) {
1241+ if (!isa<ConstantExpr>(ee->left )) {
1242+ return false ;
1243+ }
1244+ } else {
1245+ return false ;
1246+ }
1247+ }
1248+ if (ref<EqExpr> ee = dyn_cast<EqExpr>(query.negateExpr ().expr )) {
1249+ if (!isa<ConstantExpr>(ee->left )) {
1250+ return false ;
1251+ }
1252+ } else {
1253+ return false ;
1254+ }
1255+ return true ;
1256+ }
1257+ };
1258+
1259+ class TrueQueryPredicate {
1260+ public:
1261+ explicit TrueQueryPredicate () {}
1262+
1263+ bool operator ()(const Query &query) const { return true ; }
1264+ };
1265+
12151266std::unique_ptr<Solver> klee::createFastCexSolver (std::unique_ptr<Solver> s) {
1216- return std::make_unique<Solver>(std::make_unique<StagedSolverImpl>(
1217- std::make_unique<FastCexSolver>(), std::move (s)));
1267+ if (FastCexFor == FastCexSolverType::EQUALITY) {
1268+ return std::make_unique<Solver>(std::make_unique<StagedSolverImpl>(
1269+ std::make_unique<FastCexSolver>(), std::move (s),
1270+ OnlyEqualityWithConstantQueryPredicate ()));
1271+ } else {
1272+ return std::make_unique<Solver>(std::make_unique<StagedSolverImpl>(
1273+ std::make_unique<FastCexSolver>(), std::move (s), TrueQueryPredicate ()));
1274+ }
12181275}
0 commit comments