ExprRangeEvaluator.h

Go to the documentation of this file.
00001 //===-- ExprRangeEvaluator.h ------------------------------------*- C++ -*-===//
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 #ifndef KLEE_EXPRRANGEEVALUATOR_H
00011 #define KLEE_EXPRRANGEEVALUATOR_H
00012 
00013 #include "klee/Expr.h"
00014 #include "klee/util/Bits.h"
00015 
00016 namespace klee {
00017 
00018 /*
00019 class ValueType {
00020 public:
00021   ValueType(); // empty range
00022   ValueType(uint64_t value);
00023   ValueType(uint64_t min, uint64_t max);
00024   
00025   bool mustEqual(const uint64_t b);
00026   bool mustEqual(const ValueType &b);
00027   bool mayEqual(const uint64_t b);  
00028   bool mayEqual(const ValueType &b);
00029 
00030   bool isFullRange(unsigned width);
00031 
00032   ValueType set_union(ValueType &);
00033   ValueType set_intersection(ValueType &);
00034   ValueType set_difference(ValueType &);
00035 
00036   ValueType binaryAnd(ValueType &);
00037   ValueType binaryOr(ValueType &);
00038   ValueType binaryXor(ValueType &);
00039   ValueType concat(ValueType &, unsigned width);
00040   ValueType add(ValueType &, unsigned width);
00041   ValueType sub(ValueType &, unsigned width);
00042   ValueType mul(ValueType &, unsigned width);
00043   ValueType udiv(ValueType &, unsigned width);
00044   ValueType sdiv(ValueType &, unsigned width);
00045   ValueType urem(ValueType &, unsigned width);
00046   ValueType srem(ValueType &, unsigned width);
00047 
00048   uint64_t min();
00049   uint64_t max();
00050   int64_t minSigned(unsigned width);
00051   int64_t maxSigned(unsigned width);
00052 }
00053 */
00054 
00055 template<class T>
00056 class ExprRangeEvaluator {
00057 protected:
00058   virtual T getInitialReadRange(const Array &os, T index) = 0;
00059 
00060   T evalRead(const UpdateList &ul, T index);
00061 
00062 public:
00063   ExprRangeEvaluator() {}
00064   virtual ~ExprRangeEvaluator() {}
00065 
00066   T evaluate(const ref<Expr> &e);
00067 };
00068 
00069 template<class T>
00070 T ExprRangeEvaluator<T>::evalRead(const UpdateList &ul,
00071                                   T index) {
00072   T res;
00073 
00074   for (const UpdateNode *un=ul.head; un; un=un->next) {
00075     T ui = evaluate(un->index);
00076 
00077     if (ui.mustEqual(index)) {
00078       return res.set_union(evaluate(un->value));
00079     } else if (ui.mayEqual(index)) {
00080       res = res.set_union(evaluate(un->value));
00081       if (res.isFullRange(8)) {
00082         return res;
00083       } 
00084     }
00085   }
00086 
00087   return res.set_union(getInitialReadRange(*ul.root, index));
00088 }
00089 
00090 template<class T>
00091 T ExprRangeEvaluator<T>::evaluate(const ref<Expr> &e) {
00092   switch (e->getKind()) {
00093   case Expr::Constant:
00094     return T(cast<ConstantExpr>(e)->getConstantValue());
00095 
00096   case Expr::NotOptimized: 
00097     break;
00098 
00099   case Expr::Read: {
00100     const ReadExpr *re = cast<ReadExpr>(e);
00101     T index = evaluate(re->index);
00102 
00103     assert(re->getWidth()==Expr::Int8 && "unexpected multibyte read");
00104 
00105     return evalRead(re->updates, index);
00106   }
00107 
00108   case Expr::Select: {
00109     const SelectExpr *se = cast<SelectExpr>(e);
00110     T cond = evaluate(se->cond);
00111       
00112     if (cond.mustEqual(1)) {
00113       return evaluate(se->trueExpr);
00114     } else if (cond.mustEqual(0)) {
00115       return evaluate(se->falseExpr);
00116     } else {
00117       return evaluate(se->trueExpr).set_union(evaluate(se->falseExpr));
00118     }
00119   }
00120 
00121     // XXX these should be unrolled to ensure nice inline
00122   case Expr::Concat: {
00123     const Expr *ep = e.get();
00124     T res(0);
00125     for (unsigned i=0; i<ep->getNumKids(); i++)
00126       res = res.concat(evaluate(ep->getKid(i)),8);
00127     return res;
00128   }
00129 
00130     // Arithmetic
00131 
00132   case Expr::Add: {
00133     const BinaryExpr *be = cast<BinaryExpr>(e);
00134     unsigned width = be->left->getWidth();
00135     return evaluate(be->left).add(evaluate(be->right), width);
00136   }
00137   case Expr::Sub: {
00138     const BinaryExpr *be = cast<BinaryExpr>(e);
00139     unsigned width = be->left->getWidth();
00140     return evaluate(be->left).sub(evaluate(be->right), width);
00141   }
00142   case Expr::Mul: {
00143     const BinaryExpr *be = cast<BinaryExpr>(e);
00144     unsigned width = be->left->getWidth();
00145     return evaluate(be->left).mul(evaluate(be->right), width);
00146   }
00147   case Expr::UDiv: {
00148     const BinaryExpr *be = cast<BinaryExpr>(e);
00149     unsigned width = be->left->getWidth();
00150     return evaluate(be->left).udiv(evaluate(be->right), width);
00151   }
00152   case Expr::SDiv: {
00153     const BinaryExpr *be = cast<BinaryExpr>(e);
00154     unsigned width = be->left->getWidth();
00155     return evaluate(be->left).sdiv(evaluate(be->right), width);
00156   }
00157   case Expr::URem: {
00158     const BinaryExpr *be = cast<BinaryExpr>(e);
00159     unsigned width = be->left->getWidth();
00160     return evaluate(be->left).urem(evaluate(be->right), width);
00161   }
00162   case Expr::SRem: {
00163     const BinaryExpr *be = cast<BinaryExpr>(e);
00164     unsigned width = be->left->getWidth();
00165     return evaluate(be->left).srem(evaluate(be->right), width);
00166   }
00167 
00168     // Binary
00169 
00170   case Expr::And: {
00171     const BinaryExpr *be = cast<BinaryExpr>(e);
00172     return evaluate(be->left).binaryAnd(evaluate(be->right));
00173   }
00174   case Expr::Or: {
00175     const BinaryExpr *be = cast<BinaryExpr>(e);
00176     return evaluate(be->left).binaryOr(evaluate(be->right));
00177   }
00178   case Expr::Xor: {
00179     const BinaryExpr *be = cast<BinaryExpr>(e);
00180     return evaluate(be->left).binaryXor(evaluate(be->right));
00181   }
00182   case Expr::Shl: {
00183     //    BinaryExpr *be = cast<BinaryExpr>(e);
00184     //    unsigned width = be->left->getWidth();
00185     //    return evaluate(be->left).shl(evaluate(be->right), width);
00186     break;
00187   }
00188   case Expr::LShr: {
00189     //    BinaryExpr *be = cast<BinaryExpr>(e);
00190     //    unsigned width = be->left->getWidth();
00191     //    return evaluate(be->left).lshr(evaluate(be->right), width);
00192     break;
00193   }
00194   case Expr::AShr: {
00195     //    BinaryExpr *be = cast<BinaryExpr>(e);
00196     //    unsigned width = be->left->getWidth();
00197     //    return evaluate(be->left).ashr(evaluate(be->right), width);
00198     break;
00199   }
00200 
00201     // Comparison
00202 
00203   case Expr::Eq: {
00204     const BinaryExpr *be = cast<BinaryExpr>(e);
00205     T left = evaluate(be->left);
00206     T right = evaluate(be->right);
00207       
00208     if (left.mustEqual(right)) {
00209       return T(1);
00210     } else if (!left.mayEqual(right)) {
00211       return T(0);
00212     }
00213     break;
00214   }
00215 
00216   case Expr::Ult: {
00217     const BinaryExpr *be = cast<BinaryExpr>(e);
00218     T left = evaluate(be->left);
00219     T right = evaluate(be->right);
00220       
00221     if (left.max() < right.min()) {
00222       return T(1);
00223     } else if (left.min() >= right.max()) {
00224       return T(0);
00225     }
00226     break;
00227   }
00228   case Expr::Ule: {
00229     const BinaryExpr *be = cast<BinaryExpr>(e);
00230     T left = evaluate(be->left);
00231     T right = evaluate(be->right);
00232       
00233     if (left.max() <= right.min()) {
00234       return T(1);
00235     } else if (left.min() > right.max()) {
00236       return T(0);
00237     }
00238     break;
00239   }
00240   case Expr::Slt: {
00241     const BinaryExpr *be = cast<BinaryExpr>(e);
00242     T left = evaluate(be->left);
00243     T right = evaluate(be->right);
00244     unsigned bits = be->left->getWidth();
00245 
00246     if (left.maxSigned(bits) < right.minSigned(bits)) {
00247       return T(1);
00248     } else if (left.minSigned(bits) >= right.maxSigned(bits)) {
00249       return T(0);
00250     }
00251     break;
00252   }
00253   case Expr::Sle: {
00254     const BinaryExpr *be = cast<BinaryExpr>(e);
00255     T left = evaluate(be->left);
00256     T right = evaluate(be->right);
00257     unsigned bits = be->left->getWidth();
00258       
00259     if (left.maxSigned(bits) <= right.minSigned(bits)) {
00260       return T(1);
00261     } else if (left.minSigned(bits) > right.maxSigned(bits)) {
00262       return T(0);
00263     }
00264     break;
00265   }
00266 
00267   case Expr::Ne:
00268   case Expr::Ugt:
00269   case Expr::Uge:
00270   case Expr::Sgt:
00271   case Expr::Sge:
00272     assert(0 && "invalid expressions (uncanonicalized)");
00273 
00274   default:
00275     break;
00276   }
00277 
00278   return T(0, bits64::maxValueOfNBits(e->getWidth()));
00279 }
00280 
00281 }
00282 
00283 #endif

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