00001
00002
00003
00004
00005
00006
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
00105
00106 Constant = 0,
00107
00108
00109
00113 NotOptimized,
00114
00116 Read=NotOptimized+2,
00117 Select,
00118 Concat,
00119 Extract,
00120
00121
00122 ZExt,
00123 SExt,
00124
00125
00126
00127
00128 Add,
00129 Sub,
00130 Mul,
00131 UDiv,
00132 SDiv,
00133 URem,
00134 SRem,
00135
00136
00137 And,
00138 Or,
00139 Xor,
00140 Shl,
00141 LShr,
00142 AShr,
00143
00144
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
00195
00196 virtual ref<Expr> rebuild(ref<Expr> kids[]) const = 0;
00197
00198
00199
00201 bool isZero() const;
00202
00204 bool isTrue() const;
00205
00207 bool isFalse() const;
00208
00209
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
00221
00222
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
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
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
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
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
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
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;
00442
00443 mutable unsigned refCount;
00444
00445 mutable void *stpArray;
00446
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
00481 mutable void *stpInitialArray;
00482
00483 public:
00484
00485
00486
00487
00488
00489 Array(const MemoryObject *_object, unsigned _id, uint64_t _size)
00490 : object(_object), id(_id), size(_size), stpInitialArray(0) {}
00491 ~Array() {
00492
00493 assert(!stpInitialArray && "Array must be deleted by caller!");
00494 }
00495 };
00496
00498
00501 class UpdateList {
00502 friend class ReadExpr;
00503
00504 public:
00505 const Array *root;
00506
00508 const UpdateNode *head;
00509
00510
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
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
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
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
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
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 }
00918
00919 #endif