Expr.h

Go to the documentation of this file.
00001 //===-- Expr.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_EXPR_H
00011 #define KLEE_EXPR_H
00012 
00013 #include "Machine.h"
00014 #include "klee/util/Bits.h"
00015 #include "klee/util/Ref.h"
00016 
00017 #include "llvm/ADT/SmallVector.h"
00018 #include "llvm/Support/Streams.h"
00019 
00020 #include <set>
00021 #include <vector>
00022 
00023 namespace llvm {
00024   class Type;
00025 }
00026 
00027 namespace klee {
00028 
00029 class Array;
00030 class ConstantExpr;
00031 class ObjectState;
00032 class MemoryObject;
00033 
00034 template<class T> class ref;
00035 
00036 
00038 
00085 class Expr {
00086 public:
00087   static unsigned count;
00088   static const unsigned MAGIC_HASH_CONSTANT = 39;
00089 
00091   typedef unsigned Width; 
00092   
00093   static const Width InvalidWidth = 0;
00094   static const Width Bool = 1;
00095   static const Width Int8 = 8;
00096   static const Width Int16 = 16;
00097   static const Width Int32 = 32;
00098   static const Width Int64 = 64;
00099   
00100 
00101   enum Kind {
00102     InvalidKind = -1,
00103 
00104     // Primitive
00105 
00106     Constant = 0,
00107 
00108     // Special
00109 
00113     NotOptimized,
00114 
00116     Read=NotOptimized+2, 
00117     Select,
00118     Concat,
00119     Extract,
00120 
00121     // Casting,
00122     ZExt,
00123     SExt,
00124 
00125     // All subsequent kinds are binary.
00126 
00127     // Arithmetic
00128     Add,
00129     Sub,
00130     Mul,
00131     UDiv,
00132     SDiv,
00133     URem,
00134     SRem,
00135 
00136     // Bit
00137     And,
00138     Or,
00139     Xor,
00140     Shl,
00141     LShr,
00142     AShr,
00143     
00144     // Compare
00145     Eq,
00146     Ne,  
00147     Ult,
00148     Ule,
00149     Ugt, 
00150     Uge, 
00151     Slt,
00152     Sle,
00153     Sgt, 
00154     Sge, 
00155 
00156     LastKind=Sge,
00157 
00158     CastKindFirst=ZExt,
00159     CastKindLast=SExt,
00160     BinaryKindFirst=Add,
00161     BinaryKindLast=Sge,
00162     CmpKindFirst=Eq,
00163     CmpKindLast=Sge
00164   };
00165 
00166   unsigned refCount;
00167 
00168 protected:  
00169   unsigned hashValue;
00170   
00171 public:
00172   Expr() : refCount(0) { Expr::count++; }
00173   virtual ~Expr() { Expr::count--; } 
00174 
00175   virtual Kind getKind() const = 0;
00176   virtual Width getWidth() const = 0;
00177   
00178   virtual unsigned getNumKids() const = 0;
00179   virtual ref<Expr> getKid(unsigned i) const = 0;
00180     
00181   virtual void print(std::ostream &os) const;
00182 
00184   virtual unsigned hash() const { return hashValue; }
00185 
00188   virtual unsigned computeHash();
00189   
00191   int compare(const Expr &b) const;
00192   virtual int compareContents(const Expr &b) const { return 0; }
00193 
00194   // Given an array of new kids return a copy of the expression
00195   // but using those children. 
00196   virtual ref<Expr> rebuild(ref<Expr> kids[/* getNumKids() */]) const = 0;
00197 
00198   //
00199 
00201   bool isZero() const;
00202   
00204   bool isTrue() const;
00205 
00207   bool isFalse() const;
00208 
00209   /* Static utility methods */
00210 
00211   static void printKind(std::ostream &os, Kind k);
00212   static void printWidth(std::ostream &os, Expr::Width w);
00213   static Width getWidthForLLVMType(const llvm::Type *type);
00214 
00216   static inline unsigned getMinBytesForWidth(Width w) {
00217       return (w + 7) / 8;
00218   }
00219 
00220   /* Kind utilities */
00221 
00222   /* Utility creation functions */
00223   static ref<Expr> createCoerceToPointerType(ref<Expr> e);
00224   static ref<Expr> createNot(ref<Expr> e);
00225   static ref<Expr> createImplies(ref<Expr> hyp, ref<Expr> conc);
00226   static ref<Expr> createIsZero(ref<Expr> e);
00227 
00230   static ref<Expr> createTempRead(const Array *array, Expr::Width w);
00231   
00232   static ref<Expr> createPointer(uint64_t v);
00233 
00234   struct CreateArg;
00235   static ref<Expr> createFromKind(Kind k, std::vector<CreateArg> args);
00236 
00237   static bool isValidKidWidth(unsigned kid, Width w) { return true; }
00238   static bool needsResultType() { return false; }
00239 
00240   static bool classof(const Expr *) { return true; }
00241 };
00242 
00243 struct Expr::CreateArg {
00244   ref<Expr> expr;
00245   Width width;
00246   
00247   CreateArg(Width w = Bool) : expr(0), width(w) {}
00248   CreateArg(ref<Expr> e) : expr(e), width(Expr::InvalidWidth) {}
00249   
00250   bool isExpr() { return !isWidth(); }
00251   bool isWidth() { return width != Expr::InvalidWidth; }
00252 };
00253 
00254 // Comparison operators
00255 
00256 inline bool operator==(const Expr &lhs, const Expr &rhs) {
00257   return lhs.compare(rhs) == 0;
00258 }
00259 
00260 inline bool operator<(const Expr &lhs, const Expr &rhs) {
00261   return lhs.compare(rhs) < 0;
00262 }
00263 
00264 inline bool operator!=(const Expr &lhs, const Expr &rhs) {
00265   return !(lhs == rhs);
00266 }
00267 
00268 inline bool operator>(const Expr &lhs, const Expr &rhs) {
00269   return rhs < lhs;
00270 }
00271 
00272 inline bool operator<=(const Expr &lhs, const Expr &rhs) {
00273   return !(lhs > rhs);
00274 }
00275 
00276 inline bool operator>=(const Expr &lhs, const Expr &rhs) {
00277   return !(lhs < rhs);
00278 }
00279 
00280 // Printing operators
00281 
00282 inline std::ostream &operator<<(std::ostream &os, const Expr &e) {
00283   e.print(os);
00284   return os;
00285 }
00286 
00287 inline std::ostream &operator<<(std::ostream &os, const Expr::Kind kind) {
00288   Expr::printKind(os, kind);
00289   return os;
00290 }
00291 
00292 // Terminal Exprs
00293 
00294 class ConstantExpr : public Expr {
00295 public:
00296   static const Kind kind = Constant;
00297   static const unsigned numKids = 0;
00298 
00299 private:
00300   uint64_t value;
00301 
00302   ConstantExpr(uint64_t v, Width w) : value(v), width(w) {}
00303 
00304 public:
00305   Width width;
00306 
00307 public:
00308   ~ConstantExpr() {};
00309   
00310   Width getWidth() const { return width; }
00311   Kind getKind() const { return Constant; }
00312 
00313   unsigned getNumKids() const { return 0; }
00314   ref<Expr> getKid(unsigned i) const { return 0; }
00315 
00316   uint64_t getConstantValue() const { return value; }
00317 
00318   int compareContents(const Expr &b) const { 
00319     const ConstantExpr &cb = static_cast<const ConstantExpr&>(b);
00320     if (width != cb.width) return width < cb.width ? -1 : 1;
00321     if (value < cb.value) {
00322       return -1;
00323     } else if (value > cb.value) {
00324       return 1;
00325     } else {
00326       return 0;
00327     }
00328   }
00329 
00330   virtual ref<Expr> rebuild(ref<Expr> kids[]) const { 
00331     assert(0 && "rebuild() on ConstantExpr"); 
00332     return (Expr*) this;
00333   }
00334 
00335   virtual unsigned computeHash();
00336   
00337   static ref<Expr> fromMemory(void *address, Width w);
00338   void toMemory(void *address);
00339 
00340   static ref<ConstantExpr> alloc(uint64_t v, Width w) {
00341     // constructs an "optimized" ConstantExpr
00342     ref<ConstantExpr> r(new ConstantExpr(v, w));
00343     r->computeHash();
00344     return r;
00345   }
00346   
00347   static ref<ConstantExpr> create(uint64_t v, Width w) {
00348     assert(v == bits64::truncateToNBits(v, w) &&
00349            "invalid constant");
00350     return alloc(v, w);
00351   }
00352 
00353   static bool classof(const Expr *E) {
00354     return E->getKind() == Expr::Constant;
00355   }
00356   static bool classof(const ConstantExpr *) { return true; }
00357 };
00358 
00359   
00360 // Utility classes
00361 
00362 class BinaryExpr : public Expr {
00363 public:
00364   ref<Expr> left, right;
00365 
00366 public:
00367   unsigned getNumKids() const { return 2; }
00368   ref<Expr> getKid(unsigned i) const { 
00369     if(i == 0)
00370       return left;
00371     if(i == 1)
00372       return right;
00373     return 0;
00374   }
00375  
00376 protected:
00377   BinaryExpr(const ref<Expr> &l, const ref<Expr> &r) : left(l), right(r) {}
00378 
00379 public:
00380   static bool classof(const Expr *E) {
00381     Kind k = E->getKind();
00382     return Expr::BinaryKindFirst <= k && k <= Expr::BinaryKindLast;
00383   }
00384   static bool classof(const BinaryExpr *) { return true; }
00385 };
00386 
00387 
00388 class CmpExpr : public BinaryExpr {
00389 
00390 protected:
00391   CmpExpr(ref<Expr> l, ref<Expr> r) : BinaryExpr(l,r) {}
00392   
00393 public:                                                       
00394   Width getWidth() const { return Bool; }
00395 
00396   static bool classof(const Expr *E) {
00397     Kind k = E->getKind();
00398     return Expr::CmpKindFirst <= k && k <= Expr::CmpKindLast;
00399   }
00400   static bool classof(const CmpExpr *) { return true; }
00401 };
00402 
00403 // Special
00404 
00405 class NotOptimizedExpr : public Expr {
00406 public:
00407   static const Kind kind = NotOptimized;
00408   static const unsigned numKids = 1;
00409   ref<Expr> src;
00410 
00411   static ref<Expr> alloc(const ref<Expr> &src) {
00412     ref<Expr> r(new NotOptimizedExpr(src));
00413     r->computeHash();
00414     return r;
00415   }
00416   
00417   static ref<Expr> create(ref<Expr> src);
00418   
00419   Width getWidth() const { return src->getWidth(); }
00420   Kind getKind() const { return NotOptimized; }
00421 
00422   unsigned getNumKids() const { return 1; }
00423   ref<Expr> getKid(unsigned i) const { return src; }
00424 
00425   virtual ref<Expr> rebuild(ref<Expr> kids[]) const { return create(kids[0]); }
00426 
00427 private:
00428   NotOptimizedExpr(const ref<Expr> &_src) : src(_src) {}
00429 
00430 public:
00431   static bool classof(const Expr *E) {
00432     return E->getKind() == Expr::NotOptimized;
00433   }
00434   static bool classof(const NotOptimizedExpr *) { return true; }
00435 };
00436 
00437 
00439 class UpdateNode {
00440   friend class UpdateList;
00441   friend class STPBuilder; // for setting STPArray
00442 
00443   mutable unsigned refCount;
00444   // gross
00445   mutable void *stpArray;
00446   // cache instead of recalc
00447   unsigned hashValue;
00448 
00449 public:
00450   const UpdateNode *next;
00451   ref<Expr> index, value;
00452   
00453 private:
00455   unsigned size;
00456   
00457 public:
00458   UpdateNode(const UpdateNode *_next, 
00459              const ref<Expr> &_index, 
00460              const ref<Expr> &_value);
00461 
00462   unsigned getSize() const { return size; }
00463 
00464   int compare(const UpdateNode &b) const;  
00465   unsigned hash() const { return hashValue; }
00466 
00467 private:
00468   UpdateNode() : refCount(0), stpArray(0) {}
00469   ~UpdateNode();
00470 
00471   unsigned computeHash();
00472 };
00473 
00474 class Array {
00475 public:
00476   const MemoryObject *object;
00477   unsigned id;
00478   unsigned size;
00479 
00480   // FIXME: This does not belong here.
00481   mutable void *stpInitialArray;
00482 
00483 public:
00484   // NOTE: id's ***MUST*** be unique to ensure sanity w.r.t. STP,
00485   // which hashes different arrays with the same id to the same
00486   // object! We should probably use the pointer for talking to STP, as
00487   // long as we can guarantee that it won't be a "stale" reference
00488   // once we have freed it.
00489   Array(const MemoryObject *_object, unsigned _id, uint64_t _size) 
00490     : object(_object), id(_id), size(_size), stpInitialArray(0) {}
00491   ~Array() {
00492     // FIXME: This relies on caller to delete the STP array.
00493     assert(!stpInitialArray && "Array must be deleted by caller!");
00494   }
00495 };
00496 
00498 
00501 class UpdateList { 
00502   friend class ReadExpr; // for default constructor
00503 
00504 public:
00505   const Array *root;
00506   
00508   const UpdateNode *head;
00509   
00510   // shouldn't this be part of the ReadExpr? 
00511   bool isRooted;
00512 
00513 public:
00514   UpdateList(const Array *_root, bool isRooted, const UpdateNode *_head);
00515   UpdateList(const UpdateList &b);
00516   ~UpdateList();
00517   
00518   UpdateList &operator=(const UpdateList &b);
00519 
00521   unsigned getSize() const { return (head ? head->getSize() : 0); }
00522   
00523   void extend(const ref<Expr> &index, const ref<Expr> &value);
00524 
00525   int compare(const UpdateList &b) const;
00526   unsigned hash() const;
00527 };
00528 
00530 class ReadExpr : public Expr {
00531 public:
00532   static const Kind kind = Read;
00533   static const unsigned numKids = 1;
00534   
00535 public:
00536   UpdateList updates;
00537   ref<Expr> index;
00538 
00539 public:
00540   static ref<Expr> alloc(const UpdateList &updates, const ref<Expr> &index) {
00541     ref<Expr> r(new ReadExpr(updates, index));
00542     r->computeHash();
00543     return r;
00544   }
00545   
00546   static ref<Expr> create(const UpdateList &updates, ref<Expr> i);
00547   
00548   Width getWidth() const { return Expr::Int8; }
00549   Kind getKind() const { return Read; }
00550   
00551   unsigned getNumKids() const { return numKids; }
00552   ref<Expr> getKid(unsigned i) const { return !i ? index : 0; }  
00553   
00554   int compareContents(const Expr &b) const;
00555 
00556   virtual ref<Expr> rebuild(ref<Expr> kids[]) const { 
00557     return create(updates, kids[0]);
00558   }
00559 
00560   virtual unsigned computeHash();
00561 
00562 private:
00563   ReadExpr(const UpdateList &_updates, const ref<Expr> &_index) : 
00564     updates(_updates), index(_index) {}
00565 
00566 public:
00567   static bool classof(const Expr *E) {
00568     return E->getKind() == Expr::Read;
00569   }
00570   static bool classof(const ReadExpr *) { return true; }
00571 };
00572 
00573 
00575 class SelectExpr : public Expr {
00576 public:
00577   static const Kind kind = Select;
00578   static const unsigned numKids = 3;
00579   
00580 public:
00581   ref<Expr> cond, trueExpr, falseExpr;
00582 
00583 public:
00584   static ref<Expr> alloc(const ref<Expr> &c, const ref<Expr> &t, 
00585                          const ref<Expr> &f) {
00586     ref<Expr> r(new SelectExpr(c, t, f));
00587     r->computeHash();
00588     return r;
00589   }
00590   
00591   static ref<Expr> create(ref<Expr> c, ref<Expr> t, ref<Expr> f);
00592 
00593   Width getWidth() const { return trueExpr->getWidth(); }
00594   Kind getKind() const { return Select; }
00595 
00596   unsigned getNumKids() const { return numKids; }
00597   ref<Expr> getKid(unsigned i) const { 
00598         switch(i) {
00599         case 0: return cond;
00600         case 1: return trueExpr;
00601         case 2: return falseExpr;
00602         default: return 0;
00603         }
00604    }
00605 
00606   static bool isValidKidWidth(unsigned kid, Width w) {
00607     if (kid == 0)
00608       return w == Bool;
00609     else
00610       return true;
00611   }
00612     
00613   virtual ref<Expr> rebuild(ref<Expr> kids[]) const { 
00614     return create(kids[0], kids[1], kids[2]);
00615   }
00616 
00617 private:
00618   SelectExpr(const ref<Expr> &c, const ref<Expr> &t, const ref<Expr> &f) 
00619     : cond(c), trueExpr(t), falseExpr(f) {}
00620 
00621 public:
00622   static bool classof(const Expr *E) {
00623     return E->getKind() == Expr::Select;
00624   }
00625   static bool classof(const SelectExpr *) { return true; }
00626 };
00627 
00628 
00632 class ConcatExpr : public Expr { 
00633 public: 
00634   static const Kind kind = Concat;
00635   static const unsigned numKids = 2;
00636 
00637 private:
00638   Width width;
00639   ref<Expr> left, right;  
00640 
00641 public:
00642   static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) {
00643     ref<Expr> c(new ConcatExpr(l, r));
00644     c->computeHash();
00645     return c;
00646   }
00647   
00648   static ref<Expr> create(const ref<Expr> &l, const ref<Expr> &r);
00649 
00650   Width getWidth() const { return width; }
00651   Kind getKind() const { return kind; }
00652   ref<Expr> getLeft() const { return left; }
00653   ref<Expr> getRight() const { return right; }
00654 
00655   unsigned getNumKids() const { return numKids; }
00656   ref<Expr> getKid(unsigned i) const { 
00657     if (i == 0) return left; 
00658     else if (i == 1) return right;
00659     else return NULL;
00660   }
00661 
00663   static ref<Expr> createN(unsigned nKids, const ref<Expr> kids[]);
00664   static ref<Expr> create4(const ref<Expr> &kid1, const ref<Expr> &kid2,
00665                            const ref<Expr> &kid3, const ref<Expr> &kid4);
00666   static ref<Expr> create8(const ref<Expr> &kid1, const ref<Expr> &kid2,
00667                            const ref<Expr> &kid3, const ref<Expr> &kid4,
00668                            const ref<Expr> &kid5, const ref<Expr> &kid6,
00669                            const ref<Expr> &kid7, const ref<Expr> &kid8);
00670   
00671   virtual ref<Expr> rebuild(ref<Expr> kids[]) const { return create(kids[0], kids[1]); }
00672 
00673 
00674   /* These will be eliminated */
00675   bool is2ByteConcat() const { return false; }
00676   bool is4ByteConcat() const { return false; }
00677   bool is8ByteConcat() const { return false; }
00678   
00679 private:
00680   ConcatExpr(const ref<Expr> &l, const ref<Expr> &r) : left(l), right(r) {
00681     width = l->getWidth() + r->getWidth();
00682   }
00683 
00684 public:
00685   static bool classof(const Expr *E) {
00686     return E->getKind() == Expr::Concat;
00687   }
00688   static bool classof(const ConcatExpr *) { return true; }
00689 };
00690 
00691 
00696 class ExtractExpr : public Expr { 
00697 public:
00698   static const Kind kind = Extract;
00699   static const unsigned numKids = 1;
00700   
00701 public:
00702   ref<Expr> expr;
00703   unsigned offset;
00704   Width width;
00705 
00706 public:  
00707   static ref<Expr> alloc(const ref<Expr> &e, unsigned o, Width w) {
00708     ref<Expr> r(new ExtractExpr(e, o, w));
00709     r->computeHash();
00710     return r;
00711   }
00712   
00714   static ref<Expr> create(ref<Expr> e, unsigned bitOff, Width w);
00715 
00717   static ref<Expr> createByteOff(ref<Expr> e, unsigned byteOff, Width w=Expr::Int8);
00718 
00719   Width getWidth() const { return width; }
00720   Kind getKind() const { return Extract; }
00721 
00722   unsigned getNumKids() const { return numKids; }
00723   ref<Expr> getKid(unsigned i) const { return expr; }
00724 
00725   int compareContents(const Expr &b) const {
00726     const ExtractExpr &eb = static_cast<const ExtractExpr&>(b);
00727     if (offset != eb.offset) return offset < eb.offset ? -1 : 1;
00728     if (width != eb.width) return width < eb.width ? -1 : 1;
00729     return 0;
00730   }
00731 
00732   virtual ref<Expr> rebuild(ref<Expr> kids[]) const { 
00733     return create(kids[0], offset, width);
00734   }
00735 
00736   virtual unsigned computeHash();
00737 
00738 private:
00739   ExtractExpr(const ref<Expr> &e, unsigned b, Width w) 
00740     : expr(e),offset(b),width(w) {}
00741 
00742 public:
00743   static bool classof(const Expr *E) {
00744     return E->getKind() == Expr::Extract;
00745   }
00746   static bool classof(const ExtractExpr *) { return true; }
00747 };
00748 
00749 
00750 // Casting
00751 
00752 class CastExpr : public Expr {
00753 public:
00754   ref<Expr> src;
00755   Width width;
00756 
00757 public:
00758   CastExpr(const ref<Expr> &e, Width w) : src(e), width(w) {}
00759 
00760   Width getWidth() const { return width; }
00761 
00762   unsigned getNumKids() const { return 1; }
00763   ref<Expr> getKid(unsigned i) const { return (i==0) ? src : 0; }
00764   
00765   static bool needsResultType() { return true; }
00766   
00767   int compareContents(const Expr &b) const {
00768     const CastExpr &eb = static_cast<const CastExpr&>(b);
00769     if (width != eb.width) return width < eb.width ? -1 : 1;
00770     return 0;
00771   }
00772 
00773   virtual unsigned computeHash();
00774 
00775   static bool classof(const Expr *E) {
00776     Expr::Kind k = E->getKind();
00777     return Expr::CastKindFirst <= k && k <= Expr::CastKindLast;
00778   }
00779   static bool classof(const CastExpr *) { return true; }
00780 };
00781 
00782 #define CAST_EXPR_CLASS(_class_kind)                             \
00783 class _class_kind ## Expr : public CastExpr {                    \
00784 public:                                                          \
00785   static const Kind kind = _class_kind;                          \
00786   static const unsigned numKids = 1;                             \
00787 public:                                                          \
00788     _class_kind ## Expr(ref<Expr> e, Width w) : CastExpr(e,w) {} \
00789     static ref<Expr> alloc(const ref<Expr> &e, Width w) {        \
00790       ref<Expr> r(new _class_kind ## Expr(e, w));                \
00791       r->computeHash();                                          \
00792       return r;                                                  \
00793     }                                                            \
00794     static ref<Expr> create(const ref<Expr> &e, Width w);        \
00795     Kind getKind() const { return _class_kind; }                 \
00796     virtual ref<Expr> rebuild(ref<Expr> kids[]) const {          \
00797       return create(kids[0], width);                             \
00798     }                                                            \
00799                                                                  \
00800     static bool classof(const Expr *E) {                         \
00801       return E->getKind() == Expr::_class_kind;                  \
00802     }                                                            \
00803     static bool classof(const  _class_kind ## Expr *) {          \
00804       return true;                                               \
00805     }                                                            \
00806 };                                                               \
00807 
00808 CAST_EXPR_CLASS(SExt)
00809 CAST_EXPR_CLASS(ZExt)
00810 
00811 // Arithmetic/Bit Exprs
00812 
00813 #define ARITHMETIC_EXPR_CLASS(_class_kind)                           \
00814 class _class_kind ## Expr : public BinaryExpr {                      \
00815 public:                                                              \
00816   static const Kind kind = _class_kind;                              \
00817   static const unsigned numKids = 2;                                 \
00818 public:                                                              \
00819     _class_kind ## Expr(const ref<Expr> &l,                          \
00820                         const ref<Expr> &r) : BinaryExpr(l,r) {}     \
00821     static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) { \
00822       ref<Expr> res(new _class_kind ## Expr (l, r));                 \
00823       res->computeHash();                                            \
00824       return res;                                                    \
00825     }                                                                \
00826     static ref<Expr> create(const ref<Expr> &l, const ref<Expr> &r); \
00827     Width getWidth() const { return left->getWidth(); }              \
00828     Kind getKind() const { return _class_kind; }                     \
00829     virtual ref<Expr> rebuild(ref<Expr> kids[]) const {              \
00830       return create(kids[0], kids[1]);                               \
00831     }                                                                \
00832                                                                      \
00833     static bool classof(const Expr *E) {                             \
00834       return E->getKind() == Expr::_class_kind;                      \
00835     }                                                                \
00836     static bool classof(const  _class_kind ## Expr *) {              \
00837       return true;                                                   \
00838     }                                                                \
00839 };                                                                   \
00840 
00841 ARITHMETIC_EXPR_CLASS(Add)
00842 ARITHMETIC_EXPR_CLASS(Sub)
00843 ARITHMETIC_EXPR_CLASS(Mul)
00844 ARITHMETIC_EXPR_CLASS(UDiv)
00845 ARITHMETIC_EXPR_CLASS(SDiv)
00846 ARITHMETIC_EXPR_CLASS(URem)
00847 ARITHMETIC_EXPR_CLASS(SRem)
00848 ARITHMETIC_EXPR_CLASS(And)
00849 ARITHMETIC_EXPR_CLASS(Or)
00850 ARITHMETIC_EXPR_CLASS(Xor)
00851 ARITHMETIC_EXPR_CLASS(Shl)
00852 ARITHMETIC_EXPR_CLASS(LShr)
00853 ARITHMETIC_EXPR_CLASS(AShr)
00854 
00855 // Comparison Exprs
00856 
00857 #define COMPARISON_EXPR_CLASS(_class_kind)                           \
00858 class _class_kind ## Expr : public CmpExpr {                         \
00859 public:                                                              \
00860   static const Kind kind = _class_kind;                              \
00861   static const unsigned numKids = 2;                                 \
00862 public:                                                              \
00863     _class_kind ## Expr(const ref<Expr> &l,                          \
00864                         const ref<Expr> &r) : CmpExpr(l,r) {}        \
00865     static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) { \
00866       ref<Expr> res(new _class_kind ## Expr (l, r));                 \
00867       res->computeHash();                                            \
00868       return res;                                                    \
00869     }                                                                \
00870     static ref<Expr> create(const ref<Expr> &l, const ref<Expr> &r); \
00871     Kind getKind() const { return _class_kind; }                     \
00872     virtual ref<Expr> rebuild(ref<Expr> kids[]) const {              \
00873       return create(kids[0], kids[1]);                               \
00874     }                                                                \
00875                                                                      \
00876     static bool classof(const Expr *E) {                             \
00877       return E->getKind() == Expr::_class_kind;                      \
00878     }                                                                \
00879     static bool classof(const  _class_kind ## Expr *) {              \
00880       return true;                                                   \
00881     }                                                                \
00882 };                                                                   \
00883 
00884 COMPARISON_EXPR_CLASS(Eq)
00885 COMPARISON_EXPR_CLASS(Ne)
00886 COMPARISON_EXPR_CLASS(Ult)
00887 COMPARISON_EXPR_CLASS(Ule)
00888 COMPARISON_EXPR_CLASS(Ugt)
00889 COMPARISON_EXPR_CLASS(Uge)
00890 COMPARISON_EXPR_CLASS(Slt)
00891 COMPARISON_EXPR_CLASS(Sle)
00892 COMPARISON_EXPR_CLASS(Sgt)
00893 COMPARISON_EXPR_CLASS(Sge)
00894 
00895 // Implementations
00896 
00897 inline bool Expr::isZero() const {
00898   if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(this))
00899     return CE->getConstantValue() == 0;
00900   return false;
00901 }
00902   
00903 inline bool Expr::isTrue() const {
00904   if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(this))
00905     return (CE->getWidth() == Expr::Bool &&
00906             CE->getConstantValue() == 1);
00907   return false;
00908 }
00909   
00910 inline bool Expr::isFalse() const {
00911   if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(this))
00912     return (CE->getWidth() == Expr::Bool &&
00913             CE->getConstantValue() == 0);
00914   return false;
00915 }
00916 
00917 } // End klee namespace
00918 
00919 #endif

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