18
18
#include " klee/Solver/IncompleteSolver.h"
19
19
#include " klee/Support/Debug.h"
20
20
#include " klee/Support/ErrorHandling.h"
21
+ #include " klee/Support/OptionCategories.h"
21
22
22
23
#include " klee/Support/CompilerWarning.h"
23
24
DISABLE_WARNING_PUSH
@@ -33,6 +34,20 @@ DISABLE_WARNING_POP
33
34
#include < vector>
34
35
35
36
using 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
36
51
37
52
// Hacker's Delight, pgs 58-63
38
53
static uint64_t minOR (uint64_t a, uint64_t b, uint64_t c, uint64_t d) {
@@ -403,10 +418,12 @@ class CexPossibleEvaluator : public ExprEvaluator {
403
418
ref<Expr> getInitialValue (const Array &array, unsigned index) {
404
419
// If the index is out of range, we cannot assign it a value, since that
405
420
// 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 ));
407
423
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 " );
410
427
std::abort ();
411
428
}
412
429
@@ -433,11 +450,11 @@ class CexExactEvaluator : public ExprEvaluator {
433
450
ref<Expr> getInitialValue (const Array &array, unsigned index) {
434
451
// If the index is out of range, we cannot assign it a value, since that
435
452
// 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 ));
437
455
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 ()));
441
458
}
442
459
443
460
if (index >= constantArraySize->getZExtValue ()) {
@@ -485,10 +502,11 @@ class CexData {
485
502
CexObjectData &getObjectData (const Array *A) {
486
503
CexObjectData *&Entry = objects[A];
487
504
488
- ref<ConstantExpr> constantArraySize = dyn_cast<ConstantExpr>(A->size );
505
+ ref<ConstantExpr> constantArraySize =
506
+ dyn_cast<ConstantExpr>(evaluatePossible (A->size ));
489
507
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 " );
492
510
std::abort ();
493
511
}
494
512
@@ -529,7 +547,7 @@ class CexData {
529
547
// to see if this is an initial read or not.
530
548
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(re->index )) {
531
549
if (ref<ConstantExpr> constantArraySize =
532
- dyn_cast<ConstantExpr>(array->size )) {
550
+ dyn_cast<ConstantExpr>(evaluatePossible ( array->size ) )) {
533
551
uint64_t index = CE->getZExtValue ();
534
552
535
553
if (index < constantArraySize->getZExtValue ()) {
@@ -1171,6 +1189,7 @@ bool FastCexSolver::computeInitialValues(
1171
1189
const Query &query, const std::vector<const Array *> &objects,
1172
1190
std::vector<SparseStorage<unsigned char >> &values, bool &hasSolution) {
1173
1191
CexData cd;
1192
+ query.dump ();
1174
1193
1175
1194
bool isValid;
1176
1195
bool success = propagateValues (query, cd, true , isValid);
@@ -1187,7 +1206,7 @@ bool FastCexSolver::computeInitialValues(
1187
1206
for (unsigned i = 0 ; i != objects.size (); ++i) {
1188
1207
const Array *array = objects[i];
1189
1208
assert (array);
1190
- SparseStorage<unsigned char > data;
1209
+ SparseStorage<unsigned char > data ( 0 ) ;
1191
1210
ref<ConstantExpr> arrayConstantSize =
1192
1211
dyn_cast<ConstantExpr>(cd.evaluatePossible (array->size ));
1193
1212
assert (arrayConstantSize &&
@@ -1212,7 +1231,45 @@ bool FastCexSolver::computeInitialValues(
1212
1231
return true ;
1213
1232
}
1214
1233
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
+
1215
1266
std::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
+ }
1218
1275
}
0 commit comments