00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "klee/Solver.h"
00011
00012 #include "klee/Constraints.h"
00013 #include "klee/Expr.h"
00014 #include "klee/IncompleteSolver.h"
00015 #include "klee/util/ExprEvaluator.h"
00016 #include "klee/util/ExprRangeEvaluator.h"
00017 #include "klee/util/ExprVisitor.h"
00018
00019 #include "klee/Internal/Support/IntEvaluation.h"
00020
00021 #include <iostream>
00022 #include <sstream>
00023 #include <cassert>
00024 #include <map>
00025 #include <vector>
00026
00027 using namespace klee;
00028
00029
00030
00031
00032 #ifdef LOG
00033 std::ostream *theLog;
00034 #endif
00035
00036
00037 static uint64_t minOR(uint64_t a, uint64_t b,
00038 uint64_t c, uint64_t d) {
00039 uint64_t temp, m = ((uint64_t) 1)<<63;
00040 while (m) {
00041 if (~a & c & m) {
00042 temp = (a | m) & -m;
00043 if (temp <= b) { a = temp; break; }
00044 } else if (a & ~c & m) {
00045 temp = (c | m) & -m;
00046 if (temp <= d) { c = temp; break; }
00047 }
00048 m >>= 1;
00049 }
00050
00051 return a | c;
00052 }
00053 static uint64_t maxOR(uint64_t a, uint64_t b,
00054 uint64_t c, uint64_t d) {
00055 uint64_t temp, m = ((uint64_t) 1)<<63;
00056
00057 while (m) {
00058 if (b & d & m) {
00059 temp = (b - m) | (m - 1);
00060 if (temp >= a) { b = temp; break; }
00061 temp = (d - m) | (m -1);
00062 if (temp >= c) { d = temp; break; }
00063 }
00064 m >>= 1;
00065 }
00066
00067 return b | d;
00068 }
00069 static uint64_t minAND(uint64_t a, uint64_t b,
00070 uint64_t c, uint64_t d) {
00071 uint64_t temp, m = ((uint64_t) 1)<<63;
00072 while (m) {
00073 if (~a & ~c & m) {
00074 temp = (a | m) & -m;
00075 if (temp <= b) { a = temp; break; }
00076 temp = (c | m) & -m;
00077 if (temp <= d) { c = temp; break; }
00078 }
00079 m >>= 1;
00080 }
00081
00082 return a & c;
00083 }
00084 static uint64_t maxAND(uint64_t a, uint64_t b,
00085 uint64_t c, uint64_t d) {
00086 uint64_t temp, m = ((uint64_t) 1)<<63;
00087 while (m) {
00088 if (b & ~d & m) {
00089 temp = (b & ~m) | (m - 1);
00090 if (temp >= a) { b = temp; break; }
00091 } else if (~b & d & m) {
00092 temp = (d & ~m) | (m - 1);
00093 if (temp >= c) { d = temp; break; }
00094 }
00095 m >>= 1;
00096 }
00097
00098 return b & d;
00099 }
00100
00102
00103 class ValueRange {
00104 private:
00105 uint64_t m_min, m_max;
00106
00107 public:
00108 ValueRange() : m_min(1),m_max(0) {}
00109 ValueRange(uint64_t value) : m_min(value), m_max(value) {}
00110 ValueRange(uint64_t _min, uint64_t _max) : m_min(_min), m_max(_max) {}
00111 ValueRange(const ValueRange &b) : m_min(b.m_min), m_max(b.m_max) {}
00112
00113 void print(std::ostream &os) const {
00114 if (isFixed()) {
00115 os << m_min;
00116 } else {
00117 os << "[" << m_min << "," << m_max << "]";
00118 }
00119 }
00120
00121 bool isEmpty() const {
00122 return m_min>m_max;
00123 }
00124 bool contains(uint64_t value) const {
00125 return this->intersects(ValueRange(value));
00126 }
00127 bool intersects(const ValueRange &b) const {
00128 return !this->set_intersection(b).isEmpty();
00129 }
00130
00131 bool isFullRange(unsigned bits) {
00132 return m_min==0 && m_max==bits64::maxValueOfNBits(bits);
00133 }
00134
00135 ValueRange set_intersection(const ValueRange &b) const {
00136 return ValueRange(std::max(m_min,b.m_min), std::min(m_max,b.m_max));
00137 }
00138 ValueRange set_union(const ValueRange &b) const {
00139 return ValueRange(std::min(m_min,b.m_min), std::max(m_max,b.m_max));
00140 }
00141 ValueRange set_difference(const ValueRange &b) const {
00142 if (b.isEmpty() || b.m_min > m_max || b.m_max < m_min) {
00143 return *this;
00144 } else if (b.m_min <= m_min && b.m_max >= m_max) {
00145 return ValueRange(1,0);
00146 } else if (b.m_min <= m_min) {
00147
00148 return ValueRange(b.m_max+1, m_max);
00149 } else if (b.m_max >= m_max) {
00150
00151 return ValueRange(m_min, b.m_min-1);
00152 } else {
00153
00154 return ValueRange(m_min, b.m_min-1);
00155 }
00156 }
00157 ValueRange binaryAnd(const ValueRange &b) const {
00158
00159 assert(!isEmpty() && !b.isEmpty() && "XXX");
00160 if (isFixed() && b.isFixed()) {
00161 return ValueRange(m_min & b.m_min);
00162 } else {
00163 return ValueRange(minAND(m_min, m_max, b.m_min, b.m_max),
00164 maxAND(m_min, m_max, b.m_min, b.m_max));
00165 }
00166 }
00167 ValueRange binaryAnd(uint64_t b) const { return binaryAnd(ValueRange(b)); }
00168 ValueRange binaryOr(ValueRange b) const {
00169
00170 assert(!isEmpty() && !b.isEmpty() && "XXX");
00171 if (isFixed() && b.isFixed()) {
00172 return ValueRange(m_min | b.m_min);
00173 } else {
00174 return ValueRange(minOR(m_min, m_max, b.m_min, b.m_max),
00175 maxOR(m_min, m_max, b.m_min, b.m_max));
00176 }
00177 }
00178 ValueRange binaryOr(uint64_t b) const { return binaryOr(ValueRange(b)); }
00179 ValueRange binaryXor(ValueRange b) const {
00180 if (isFixed() && b.isFixed()) {
00181 return ValueRange(m_min ^ b.m_min);
00182 } else {
00183 uint64_t t = m_max | b.m_max;
00184 while (!bits64::isPowerOfTwo(t))
00185 t = bits64::withoutRightmostBit(t);
00186 return ValueRange(0, (t<<1)-1);
00187 }
00188 }
00189
00190 ValueRange binaryShiftLeft(unsigned bits) const {
00191 return ValueRange(m_min<<bits, m_max<<bits);
00192 }
00193 ValueRange binaryShiftRight(unsigned bits) const {
00194 return ValueRange(m_min>>bits, m_max>>bits);
00195 }
00196
00197 ValueRange concat(const ValueRange &b, unsigned bits) const {
00198 return binaryShiftLeft(bits).binaryOr(b);
00199 }
00200 ValueRange extract(uint64_t lowBit, uint64_t maxBit) const {
00201 return binaryShiftRight(lowBit).binaryAnd(bits64::maxValueOfNBits(maxBit-lowBit));
00202 }
00203
00204 ValueRange add(const ValueRange &b, unsigned width) const {
00205 return ValueRange(0, bits64::maxValueOfNBits(width));
00206 }
00207 ValueRange sub(const ValueRange &b, unsigned width) const {
00208 return ValueRange(0, bits64::maxValueOfNBits(width));
00209 }
00210 ValueRange mul(const ValueRange &b, unsigned width) const {
00211 return ValueRange(0, bits64::maxValueOfNBits(width));
00212 }
00213 ValueRange udiv(const ValueRange &b, unsigned width) const {
00214 return ValueRange(0, bits64::maxValueOfNBits(width));
00215 }
00216 ValueRange sdiv(const ValueRange &b, unsigned width) const {
00217 return ValueRange(0, bits64::maxValueOfNBits(width));
00218 }
00219 ValueRange urem(const ValueRange &b, unsigned width) const {
00220 return ValueRange(0, bits64::maxValueOfNBits(width));
00221 }
00222 ValueRange srem(const ValueRange &b, unsigned width) const {
00223 return ValueRange(0, bits64::maxValueOfNBits(width));
00224 }
00225
00226
00227
00228 bool isFixed() const { return m_min==m_max; }
00229
00230 bool operator==(const ValueRange &b) const { return m_min==b.m_min && m_max==b.m_max; }
00231 bool operator!=(const ValueRange &b) const { return !(*this==b); }
00232
00233 bool mustEqual(const uint64_t b) const { return m_min==m_max && m_min==b; }
00234 bool mayEqual(const uint64_t b) const { return m_min<=b && m_max>=b; }
00235
00236 bool mustEqual(const ValueRange &b) const { return isFixed() && b.isFixed() && m_min==b.m_min; }
00237 bool mayEqual(const ValueRange &b) const { return this->intersects(b); }
00238
00239 uint64_t min() const {
00240 assert(!isEmpty() && "cannot get minimum of empty range");
00241 return m_min;
00242 }
00243
00244 uint64_t max() const {
00245 assert(!isEmpty() && "cannot get maximum of empty range");
00246 return m_max;
00247 }
00248
00249 int64_t minSigned(unsigned bits) const {
00250 assert((m_min>>bits)==0 && (m_max>>bits)==0 &&
00251 "range is outside given number of bits");
00252
00253
00254
00255
00256
00257 uint64_t smallest = ((uint64_t) 1 << (bits-1));
00258 if (m_max >= smallest) {
00259 return ints::sext(smallest, 64, bits);
00260 } else {
00261 return m_min;
00262 }
00263 }
00264
00265 int64_t maxSigned(unsigned bits) const {
00266 assert((m_min>>bits)==0 && (m_max>>bits)==0 &&
00267 "range is outside given number of bits");
00268
00269 uint64_t smallest = ((uint64_t) 1 << (bits-1));
00270
00271
00272
00273
00274
00275 if (m_min < smallest && m_max >= smallest) {
00276 return smallest - 1;
00277 } else {
00278 return ints::sext(m_max, 64, bits);
00279 }
00280 }
00281 };
00282
00283 inline std::ostream &operator<<(std::ostream &os, const ValueRange &vr) {
00284 vr.print(os);
00285 return os;
00286 }
00287
00288
00289
00290 class ObjectFinder : public ExprVisitor {
00291 protected:
00292 Action visitRead(const ReadExpr &re) {
00293 addUpdates(re.updates);
00294 return Action::doChildren();
00295 }
00296
00297
00298
00299 void addUpdates(const UpdateList &ul) {
00300 for (const UpdateNode *un=ul.head; un; un=un->next) {
00301 visit(un->index);
00302 visit(un->value);
00303 }
00304
00305 addObject(*ul.root);
00306 }
00307
00308 public:
00309 void addObject(const Array& array) {
00310 unsigned id = array.id;
00311 std::map<unsigned,unsigned>::iterator it = results.find(id);
00312
00313
00314 if (it == results.end()) {
00315 results[id] = (unsigned) array.size;
00316 } else {
00317 it->second = std::max(it->second, (unsigned) array.size);
00318 }
00319 }
00320
00321 public:
00322 std::map<unsigned, unsigned> results;
00323 };
00324
00325
00326 typedef ValueRange CexValueData;
00327
00328 class CexObjectData {
00329 public:
00330 unsigned size;
00331 CexValueData *values;
00332
00333 public:
00334 CexObjectData(unsigned _size) : size(_size), values(new CexValueData[size]) {
00335 for (unsigned i=0; i<size; i++)
00336 values[i] = ValueRange(0, 255);
00337 }
00338 };
00339
00340 class CexRangeEvaluator : public ExprRangeEvaluator<ValueRange> {
00341 public:
00342 std::map<unsigned, CexObjectData> &objectValues;
00343 CexRangeEvaluator(std::map<unsigned, CexObjectData> &_objectValues)
00344 : objectValues(_objectValues) {}
00345
00346 ValueRange getInitialReadRange(const Array &os, ValueRange index) {
00347 return ValueRange(0, 255);
00348 }
00349 };
00350
00351 class CexConstifier : public ExprEvaluator {
00352 protected:
00353 ref<Expr> getInitialValue(const Array& array, unsigned index) {
00354 std::map<unsigned, CexObjectData>::iterator it =
00355 objectValues.find(array.id);
00356 assert(it != objectValues.end() && "missing object?");
00357 CexObjectData &cod = it->second;
00358
00359 if (index >= cod.size) {
00360 return ReadExpr::create(UpdateList(&array, true, 0),
00361 ConstantExpr::alloc(index, Expr::Int32));
00362 } else {
00363 CexValueData &cvd = cod.values[index];
00364 assert(cvd.min() == cvd.max() && "value is not fixed");
00365 return ConstantExpr::alloc(cvd.min(), Expr::Int8);
00366 }
00367 }
00368
00369 public:
00370 std::map<unsigned, CexObjectData> &objectValues;
00371 CexConstifier(std::map<unsigned, CexObjectData> &_objectValues)
00372 : objectValues(_objectValues) {}
00373 };
00374
00375 class CexData {
00376 public:
00377 std::map<unsigned, CexObjectData> objectValues;
00378
00379 public:
00380 CexData(ObjectFinder &finder) {
00381 for (std::map<unsigned,unsigned>::iterator it = finder.results.begin(),
00382 ie = finder.results.end(); it != ie; ++it) {
00383 objectValues.insert(std::pair<unsigned, CexObjectData>(it->first,
00384 CexObjectData(it->second)));
00385 }
00386 }
00387 ~CexData() {
00388 for (std::map<unsigned, CexObjectData>::iterator it = objectValues.begin(),
00389 ie = objectValues.end(); it != ie; ++it)
00390 delete[] it->second.values;
00391 }
00392
00393 void forceExprToValue(ref<Expr> e, uint64_t value) {
00394 forceExprToRange(e, CexValueData(value,value));
00395 }
00396
00397 void forceExprToRange(ref<Expr> e, CexValueData range) {
00398 #ifdef LOG
00399
00400 #endif
00401 switch (e->getKind()) {
00402 case Expr::Constant: {
00403
00404
00405 break;
00406 }
00407
00408
00409
00410 case Expr::NotOptimized: break;
00411
00412 case Expr::Read: {
00413 ReadExpr *re = cast<ReadExpr>(e);
00414 const Array *array = re->updates.root;
00415 CexObjectData &cod = objectValues.find(array->id)->second;
00416
00417
00418
00419 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(re->index)) {
00420 if (CE->getConstantValue() < array->size) {
00421 CexValueData &cvd = cod.values[CE->getConstantValue()];
00422 CexValueData tmp = cvd.set_intersection(range);
00423
00424 if (tmp.isEmpty()) {
00425 if (range.isFixed())
00426 cvd = range;
00427 } else {
00428 cvd = tmp;
00429 }
00430 }
00431 } else {
00432
00433 }
00434
00435 break;
00436 }
00437
00438 case Expr::Select: {
00439 SelectExpr *se = cast<SelectExpr>(e);
00440 ValueRange cond = evalRangeForExpr(se->cond);
00441 if (cond.isFixed()) {
00442 if (cond.min()) {
00443 forceExprToRange(se->trueExpr, range);
00444 } else {
00445 forceExprToRange(se->falseExpr, range);
00446 }
00447 } else {
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 forceExprToRange(se->trueExpr, range);
00471 forceExprToRange(se->falseExpr, range);
00472 }
00473 break;
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 case Expr::Concat: {
00486 ConcatExpr *ce = cast<ConcatExpr>(e);
00487 if (ce->is2ByteConcat()) {
00488 forceExprToRange(ce->getKid(0), range.extract( 8, 16));
00489 forceExprToRange(ce->getKid(1), range.extract( 0, 8));
00490 }
00491 else if (ce->is4ByteConcat()) {
00492 forceExprToRange(ce->getKid(0), range.extract(24, 32));
00493 forceExprToRange(ce->getKid(1), range.extract(16, 24));
00494 forceExprToRange(ce->getKid(2), range.extract( 8, 16));
00495 forceExprToRange(ce->getKid(3), range.extract( 0, 8));
00496 }
00497 else if (ce->is8ByteConcat()) {
00498 forceExprToRange(ce->getKid(0), range.extract(56, 64));
00499 forceExprToRange(ce->getKid(1), range.extract(48, 56));
00500 forceExprToRange(ce->getKid(2), range.extract(40, 48));
00501 forceExprToRange(ce->getKid(3), range.extract(32, 40));
00502 forceExprToRange(ce->getKid(4), range.extract(24, 32));
00503 forceExprToRange(ce->getKid(5), range.extract(16, 24));
00504 forceExprToRange(ce->getKid(6), range.extract( 8, 16));
00505 forceExprToRange(ce->getKid(7), range.extract( 0, 8));
00506 }
00507
00508 break;
00509 }
00510
00511 case Expr::Extract: {
00512
00513 break;
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 case Expr::ZExt: {
00525 CastExpr *ce = cast<CastExpr>(e);
00526 unsigned inBits = ce->src->getWidth();
00527 ValueRange input = range.set_intersection(ValueRange(0, bits64::maxValueOfNBits(inBits)));
00528 forceExprToRange(ce->src, input);
00529 break;
00530 }
00531
00532
00533 case Expr::SExt: {
00534 CastExpr *ce = cast<CastExpr>(e);
00535 unsigned inBits = ce->src->getWidth();
00536 unsigned outBits = ce->width;
00537 ValueRange output = range.set_difference(ValueRange(1<<(inBits-1),
00538 (bits64::maxValueOfNBits(outBits)-
00539 bits64::maxValueOfNBits(inBits-1)-1)));
00540 ValueRange input = output.binaryAnd(bits64::maxValueOfNBits(inBits));
00541 forceExprToRange(ce->src, input);
00542 break;
00543 }
00544
00545
00546
00547 case Expr::And: {
00548 BinaryExpr *be = cast<BinaryExpr>(e);
00549 if (be->getWidth()==Expr::Bool) {
00550 if (range.isFixed()) {
00551 ValueRange left = evalRangeForExpr(be->left);
00552 ValueRange right = evalRangeForExpr(be->right);
00553
00554 if (!range.min()) {
00555 if (left.mustEqual(0) || right.mustEqual(0)) {
00556
00557 } else {
00558
00559
00560 forceExprToValue(be->left, 0);
00561 left = evalRangeForExpr(be->left);
00562
00563
00564 if (!left.mustEqual(1))
00565 forceExprToValue(be->right, 0);
00566 }
00567 } else {
00568 if (!left.mustEqual(1)) forceExprToValue(be->left, 1);
00569 if (!right.mustEqual(1)) forceExprToValue(be->right, 1);
00570 }
00571 }
00572 } else {
00573
00574 }
00575 break;
00576 }
00577
00578 case Expr::Or: {
00579 BinaryExpr *be = cast<BinaryExpr>(e);
00580 if (be->getWidth()==Expr::Bool) {
00581 if (range.isFixed()) {
00582 ValueRange left = evalRangeForExpr(be->left);
00583 ValueRange right = evalRangeForExpr(be->right);
00584
00585 if (range.min()) {
00586 if (left.mustEqual(1) || right.mustEqual(1)) {
00587
00588 } else {
00589
00590
00591
00592 forceExprToValue(be->left, 1);
00593 left = evalRangeForExpr(be->left);
00594
00595
00596 if (!left.mustEqual(1))
00597 forceExprToValue(be->right, 1);
00598 }
00599 } else {
00600 if (!left.mustEqual(0)) forceExprToValue(be->left, 0);
00601 if (!right.mustEqual(0)) forceExprToValue(be->right, 0);
00602 }
00603 }
00604 } else {
00605
00606 }
00607 break;
00608 }
00609
00610 case Expr::Xor: break;
00611
00612
00613
00614 case Expr::Eq: {
00615 BinaryExpr *be = cast<BinaryExpr>(e);
00616 if (range.isFixed()) {
00617 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(be->left)) {
00618 uint64_t value = CE->getConstantValue();
00619 if (range.min()) {
00620 forceExprToValue(be->right, value);
00621 } else {
00622 if (value==0) {
00623 forceExprToRange(be->right,
00624 CexValueData(1,
00625 ints::sext(1,
00626 be->right->getWidth(),
00627 1)));
00628 } else {
00629
00630 forceExprToRange(be->right, CexValueData(0, value-1));
00631 }
00632 }
00633 } else {
00634
00635 }
00636 }
00637 break;
00638 }
00639
00640 case Expr::Ult: {
00641 BinaryExpr *be = cast<BinaryExpr>(e);
00642
00643
00644
00645 if (range.isFixed()) {
00646 ValueRange left = evalRangeForExpr(be->left);
00647 ValueRange right = evalRangeForExpr(be->right);
00648
00649 uint64_t maxValue = bits64::maxValueOfNBits(be->right->getWidth());
00650
00651
00652
00653 if (left.isFixed()) {
00654 if (range.min()) {
00655 forceExprToRange(be->right, CexValueData(left.min()+1, maxValue));
00656 } else {
00657 forceExprToRange(be->right, CexValueData(0, left.min()));
00658 }
00659 } else if (right.isFixed()) {
00660 if (range.min()) {
00661 forceExprToRange(be->left, CexValueData(0, right.min()-1));
00662 } else {
00663 forceExprToRange(be->left, CexValueData(right.min(), maxValue));
00664 }
00665 } else {
00666
00667 }
00668 }
00669 break;
00670 }
00671 case Expr::Ule: {
00672 BinaryExpr *be = cast<BinaryExpr>(e);
00673
00674
00675
00676 if (range.isFixed()) {
00677 ValueRange left = evalRangeForExpr(be->left);
00678 ValueRange right = evalRangeForExpr(be->right);
00679
00680
00681
00682 uint64_t maxValue = bits64::maxValueOfNBits(be->right->getWidth());
00683 if (left.isFixed()) {
00684 if (range.min()) {
00685 forceExprToRange(be->right, CexValueData(left.min(), maxValue));
00686 } else {
00687 forceExprToRange(be->right, CexValueData(0, left.min()-1));
00688 }
00689 } else if (right.isFixed()) {
00690 if (range.min()) {
00691 forceExprToRange(be->left, CexValueData(0, right.min()));
00692 } else {
00693 forceExprToRange(be->left, CexValueData(right.min()+1, maxValue));
00694 }
00695 } else {
00696
00697 }
00698 }
00699 break;
00700 }
00701
00702 case Expr::Ne:
00703 case Expr::Ugt:
00704 case Expr::Uge:
00705 case Expr::Sgt:
00706 case Expr::Sge:
00707 assert(0 && "invalid expressions (uncanonicalized");
00708
00709 default:
00710 break;
00711 }
00712 }
00713
00714 void fixValues() {
00715 for (std::map<unsigned, CexObjectData>::iterator it = objectValues.begin(),
00716 ie = objectValues.end(); it != ie; ++it) {
00717 CexObjectData &cod = it->second;
00718 for (unsigned i=0; i<cod.size; i++) {
00719 CexValueData &cvd = cod.values[i];
00720 cvd = CexValueData(cvd.min() + (cvd.max()-cvd.min())/2);
00721 }
00722 }
00723 }
00724
00725 ValueRange evalRangeForExpr(ref<Expr> &e) {
00726 CexRangeEvaluator ce(objectValues);
00727 return ce.evaluate(e);
00728 }
00729
00730 bool exprMustBeValue(ref<Expr> e, uint64_t value) {
00731 CexConstifier cc(objectValues);
00732 ref<Expr> v = cc.visit(e);
00733 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(v))
00734 return CE->getConstantValue() == value;
00735 return false;
00736 }
00737 };
00738
00739
00740
00741
00742 class FastCexSolver : public IncompleteSolver {
00743 public:
00744 FastCexSolver();
00745 ~FastCexSolver();
00746
00747 IncompleteSolver::PartialValidity computeTruth(const Query&);
00748 bool computeValue(const Query&, ref<Expr> &result);
00749 bool computeInitialValues(const Query&,
00750 const std::vector<const Array*> &objects,
00751 std::vector< std::vector<unsigned char> > &values,
00752 bool &hasSolution);
00753 };
00754
00755 FastCexSolver::FastCexSolver() { }
00756
00757 FastCexSolver::~FastCexSolver() { }
00758
00759 IncompleteSolver::PartialValidity
00760 FastCexSolver::computeTruth(const Query& query) {
00761 #ifdef LOG
00762 std::ostringstream log;
00763 theLog = &log;
00764
00765 log << "-- QUERY --\n";
00766 unsigned i=0;
00767 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00768 ie = query.constraints.end(); it != ie; ++it)
00769 log << " C" << i++ << ": " << *it << ", \n";
00770 log << " Q : " << query.expr << "\n";
00771 #endif
00772
00773 ObjectFinder of;
00774 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00775 ie = query.constraints.end(); it != ie; ++it)
00776 of.visit(*it);
00777 of.visit(query.expr);
00778 CexData cd(of);
00779
00780 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00781 ie = query.constraints.end(); it != ie; ++it)
00782 cd.forceExprToValue(*it, 1);
00783 cd.forceExprToValue(query.expr, 0);
00784
00785 #ifdef LOG
00786 log << " -- ranges --\n";
00787 for (std::map<unsigned, CexObjectData>::iterator it = objectValues.begin(),
00788 ie = objectValues.end(); it != ie; ++it) {
00789 CexObjectData &cod = it->second;
00790 log << " arr" << it->first << "[" << cod.size << "] = [";
00791 unsigned continueFrom=cod.size-1;
00792 for (; continueFrom>0; continueFrom--)
00793 if (cod.values[continueFrom-1]!=cod.values[continueFrom])
00794 break;
00795 for (unsigned i=0; i<cod.size; i++) {
00796 log << cod.values[i];
00797 if (i<cod.size-1) {
00798 log << ", ";
00799 if (i==continueFrom) {
00800 log << "...";
00801 break;
00802 }
00803 }
00804 }
00805 log << "]\n";
00806 }
00807 #endif
00808
00809
00810 cd.fixValues();
00811
00812 #ifdef LOG
00813 log << " -- fixed values --\n";
00814 for (std::map<unsigned, CexObjectData>::iterator it = objectValues.begin(),
00815 ie = objectValues.end(); it != ie; ++it) {
00816 CexObjectData &cod = it->second;
00817 log << " arr" << it->first << "[" << cod.size << "] = [";
00818 unsigned continueFrom=cod.size-1;
00819 for (; continueFrom>0; continueFrom--)
00820 if (cod.values[continueFrom-1]!=cod.values[continueFrom])
00821 break;
00822 for (unsigned i=0; i<cod.size; i++) {
00823 log << cod.values[i];
00824 if (i<cod.size-1) {
00825 log << ", ";
00826 if (i==continueFrom) {
00827 log << "...";
00828 break;
00829 }
00830 }
00831 }
00832 log << "]\n";
00833 }
00834 #endif
00835
00836
00837
00838 bool isGood = true;
00839
00840 if (!cd.exprMustBeValue(query.expr, 0)) isGood = false;
00841
00842 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00843 ie = query.constraints.end(); it != ie; ++it)
00844 if (!cd.exprMustBeValue(*it, 1))
00845 isGood = false;
00846
00847 #ifdef LOG
00848 log << " -- evaluating result --\n";
00849
00850 i=0;
00851 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00852 ie = query.constraints.end(); it != ie; ++it) {
00853 bool res = cd.exprMustBeValue(*it, 1);
00854 log << " C" << i++ << ": " << (res?"true":"false") << "\n";
00855 }
00856 log << " Q : "
00857 << (cd.exprMustBeValue(query.expr, 0)?"true":"false") << "\n";
00858
00859 log << "\n\n";
00860 #endif
00861
00862 return isGood ? IncompleteSolver::MayBeFalse : IncompleteSolver::None;
00863 }
00864
00865 bool FastCexSolver::computeValue(const Query& query, ref<Expr> &result) {
00866 ObjectFinder of;
00867 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00868 ie = query.constraints.end(); it != ie; ++it)
00869 of.visit(*it);
00870 of.visit(query.expr);
00871 CexData cd(of);
00872
00873 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00874 ie = query.constraints.end(); it != ie; ++it)
00875 cd.forceExprToValue(*it, 1);
00876
00877
00878 cd.fixValues();
00879
00880
00881 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00882 ie = query.constraints.end(); it != ie; ++it)
00883 if (!cd.exprMustBeValue(*it, 1))
00884 return false;
00885
00886 CexConstifier cc(cd.objectValues);
00887 ref<Expr> value = cc.visit(query.expr);
00888
00889 if (isa<ConstantExpr>(value)) {
00890 result = value;
00891 return true;
00892 } else {
00893 return false;
00894 }
00895 }
00896
00897 bool
00898 FastCexSolver::computeInitialValues(const Query& query,
00899 const std::vector<const Array*>
00900 &objects,
00901 std::vector< std::vector<unsigned char> >
00902 &values,
00903 bool &hasSolution) {
00904 ObjectFinder of;
00905 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00906 ie = query.constraints.end(); it != ie; ++it)
00907 of.visit(*it);
00908 of.visit(query.expr);
00909 for (unsigned i = 0; i != objects.size(); ++i)
00910 of.addObject(*objects[i]);
00911 CexData cd(of);
00912
00913 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00914 ie = query.constraints.end(); it != ie; ++it)
00915 cd.forceExprToValue(*it, 1);
00916 cd.forceExprToValue(query.expr, 0);
00917
00918
00919 cd.fixValues();
00920
00921
00922 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00923 ie = query.constraints.end(); it != ie; ++it)
00924 if (!cd.exprMustBeValue(*it, 1))
00925 return false;
00926 if (!cd.exprMustBeValue(query.expr, 0))
00927 return false;
00928
00929 hasSolution = true;
00930 CexConstifier cc(cd.objectValues);
00931 for (unsigned i = 0; i != objects.size(); ++i) {
00932 const Array *array = objects[i];
00933 std::vector<unsigned char> data;
00934 data.reserve(array->size);
00935
00936 for (unsigned i=0; i < array->size; i++) {
00937 ref<Expr> value =
00938 cc.visit(ReadExpr::create(UpdateList(array, true, 0),
00939 ConstantExpr::create(i,
00940 kMachinePointerType)));
00941
00942 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(value)) {
00943 data.push_back(CE->getConstantValue());
00944 } else {
00945
00946 return false;
00947 }
00948 }
00949
00950 values.push_back(data);
00951 }
00952
00953 return true;
00954 }
00955
00956
00957 Solver *klee::createFastCexSolver(Solver *s) {
00958 return new Solver(new StagedSolverImpl(new FastCexSolver(), s));
00959 }