FastCexSolver.cpp

Go to the documentation of this file.
00001 //===-- FastCexSolver.cpp -------------------------------------------------===//
00002 //
00003 //                     The KLEE Symbolic Virtual Machine
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
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 // FIXME: Use APInt.
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 //#define LOG
00032 #ifdef LOG
00033 std::ostream *theLog;
00034 #endif
00035 
00036       // Hacker's Delight, pgs 58-63
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) { // no intersection
00143       return *this;
00144     } else if (b.m_min <= m_min && b.m_max >= m_max) { // empty
00145       return ValueRange(1,0); 
00146     } else if (b.m_min <= m_min) { // one range out
00147       // cannot overflow because b.m_max < m_max
00148       return ValueRange(b.m_max+1, m_max);
00149     } else if (b.m_max >= m_max) {
00150       // cannot overflow because b.min > m_min
00151       return ValueRange(m_min, b.m_min-1);
00152     } else {
00153       // two ranges, take bottom
00154       return ValueRange(m_min, b.m_min-1);
00155     }
00156   }
00157   ValueRange binaryAnd(const ValueRange &b) const {
00158     // XXX
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     // XXX
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   // use min() to get value if true (XXX should we add a method to
00227   // make code clearer?)
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     // if max allows sign bit to be set then it can be smallest value,
00254     // otherwise since the range is not empty, min cannot have a sign
00255     // bit
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     // if max and min have sign bit then max is max, otherwise if only
00272     // max has sign bit then max is largest signed integer, otherwise
00273     // max is max
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 // used to find all memory object ids and the maximum size of any
00289 // object state that references them (for symbolic size).
00290 class ObjectFinder : public ExprVisitor {
00291 protected:
00292   Action visitRead(const ReadExpr &re) {
00293     addUpdates(re.updates);
00294     return Action::doChildren();
00295   }
00296 
00297   // XXX nice if this information was cached somewhere, used by
00298   // independence as well right?
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     // FIXME: Not 64-bit size clean.
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 // XXX waste of space, rather have ByteValueRange
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     //    *theLog << "force: " << e << " to " << range << "\n";
00400 #endif
00401     switch (e->getKind()) {
00402     case Expr::Constant: {
00403       // rather a pity if the constant isn't in the range, but how can
00404       // we use this?
00405       break;
00406     }
00407 
00408       // Special
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       // XXX we need to respect the version here and object state chain
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()) // ranges conflict, if new one is fixed use that
00426               cvd = range;
00427           } else {
00428             cvd = tmp;
00429           }
00430         }
00431       } else {
00432         // XXX        fatal("XXX not implemented");
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         // XXX imprecise... we have a choice here. One method is to
00449         // simply force both sides into the specified range (since the
00450         // condition is indetermined). This may lose in two ways, the
00451         // first is that the condition chosen may limit further
00452         // restrict the range in each of the children, however this is
00453         // less of a problem as the range will be a superset of legal
00454         // values. The other is if the condition ends up being forced
00455         // by some other constraints, then we needlessly forced one
00456         // side into the given range.
00457         //
00458         // The other method would be to force the condition to one
00459         // side and force that side into the given range. This loses
00460         // when we force the condition to an unsatisfiable value
00461         // (either because the condition cannot be that, or the
00462         // resulting range given that condition is not in the required
00463         // range).
00464         // 
00465         // Currently we just force both into the range. A hybrid would
00466         // be to evaluate the ranges for each of the children... if
00467         // one of the ranges happens to already be a subset of the
00468         // required range then it may be preferable to force the
00469         // condition to that side.
00470         forceExprToRange(se->trueExpr, range);
00471         forceExprToRange(se->falseExpr, range);
00472       }
00473       break;
00474     }
00475 
00476       // XXX imprecise... the problem here is that extracting bits
00477       // loses information about what bits are connected across the
00478       // bytes. if a value can be 1 or 256 then either the top or
00479       // lower byte is 0, but just extraction loses this information
00480       // and will allow neither,one,or both to be 1.
00481       //
00482       // we can protect against this in a limited fashion by writing
00483       // the extraction a byte at a time, then checking the evaluated
00484       // value, isolating for that range, and continuing.
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       // XXX
00513       break;
00514     }
00515 
00516       // Casting
00517 
00518       // Simply intersect the output range with the range of all
00519       // possible outputs and then truncate to the desired number of
00520       // bits. 
00521 
00522       // For ZExt this simplifies to just intersection with the
00523       // possible input range.
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       // For SExt instead of doing the intersection we just take the output range
00532       // minus the impossible values. This is nicer since it is a single interval.
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       // Binary
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               // all is well
00557             } else {
00558               // XXX heuristic, which order
00559 
00560               forceExprToValue(be->left, 0);
00561               left = evalRangeForExpr(be->left);
00562 
00563               // see if that worked
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         // XXX
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               // all is well
00588             } else {
00589               // XXX heuristic, which order?
00590               
00591               // force left to value we need
00592               forceExprToValue(be->left, 1);
00593               left = evalRangeForExpr(be->left);
00594 
00595               // see if that worked
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         // XXX
00606       }
00607       break;
00608     }
00609 
00610     case Expr::Xor: break;
00611 
00612       // Comparison
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               // XXX heuristic / lossy, could be better to pick larger range?
00630               forceExprToRange(be->right, CexValueData(0, value-1));
00631             }
00632           }
00633         } else {
00634           // XXX what now
00635         }
00636       }
00637       break;
00638     }
00639 
00640     case Expr::Ult: {
00641       BinaryExpr *be = cast<BinaryExpr>(e);
00642       
00643       // XXX heuristic / lossy, what order if conflict
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         // XXX should deal with overflow (can lead to empty range)
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           // XXX ???
00667         }
00668       }
00669       break;
00670     }
00671     case Expr::Ule: {
00672       BinaryExpr *be = cast<BinaryExpr>(e);
00673       
00674       // XXX heuristic / lossy, what order if conflict
00675 
00676       if (range.isFixed()) {
00677         ValueRange left = evalRangeForExpr(be->left);
00678         ValueRange right = evalRangeForExpr(be->right);
00679 
00680         // XXX should deal with overflow (can lead to empty range)
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           // XXX ???
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   //  log << "------ start FastCexSolver::mustBeTrue ------\n";
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   // this could be done lazily of course
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   // check the result
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   // this could be done lazily of course
00878   cd.fixValues();
00879 
00880   // check the result
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   // this could be done lazily of course
00919   cd.fixValues();
00920 
00921   // check the result
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         // FIXME: When does this happen?
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 }

Generated on Fri Jun 5 03:31:32 2009 for klee by  doxygen 1.5.8