Expr.cpp

Go to the documentation of this file.
00001 //===-- Expr.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/Expr.h"
00011 
00012 
00013 #include "klee/Machine.h"
00014 // FIXME: This shouldn't be here.
00015 //#include "klee/Memory.h"
00016 #include "llvm/Type.h"
00017 #include "llvm/DerivedTypes.h"
00018 #include "llvm/Support/CommandLine.h"
00019 #include "llvm/Support/Streams.h"
00020 // FIXME: We shouldn't need this once fast constant support moves into
00021 // Core. If we need to do arithmetic, we probably want to use APInt.
00022 #include "klee/Internal/Support/IntEvaluation.h"
00023 
00024 #include "klee/util/ExprPPrinter.h"
00025 
00026 using namespace klee;
00027 using namespace llvm;
00028 
00029 namespace {
00030   cl::opt<bool>
00031   ConstArrayOpt("const-array-opt",
00032          cl::init(false),
00033          cl::desc("Enable various optimizations involving all-constant arrays."));
00034 }
00035 
00036 /***/
00037 
00038 unsigned Expr::count = 0;
00039 
00040 ref<Expr> Expr::createTempRead(const Array *array, Expr::Width w) {
00041   UpdateList ul(array, true, 0);
00042 
00043   switch (w) {
00044   default: assert(0 && "invalid width");
00045   case Expr::Bool: 
00046     return ZExtExpr::create(ReadExpr::create(ul, 
00047                                              ConstantExpr::alloc(0,kMachinePointerType)),
00048                             Expr::Bool);
00049   case Expr::Int8: 
00050     return ReadExpr::create(ul, 
00051                             ConstantExpr::alloc(0,kMachinePointerType));
00052   case Expr::Int16: 
00053     return ConcatExpr::create(ReadExpr::create(ul, 
00054                                                ConstantExpr::alloc(1,kMachinePointerType)),
00055                               ReadExpr::create(ul, 
00056                                                ConstantExpr::alloc(0,kMachinePointerType)));
00057   case Expr::Int32: 
00058     return ConcatExpr::create4(ReadExpr::create(ul, 
00059                                                 ConstantExpr::alloc(3,kMachinePointerType)),
00060                                ReadExpr::create(ul, 
00061                                                 ConstantExpr::alloc(2,kMachinePointerType)),
00062                                ReadExpr::create(ul, 
00063                                                 ConstantExpr::alloc(1,kMachinePointerType)),
00064                                ReadExpr::create(ul, 
00065                                                 ConstantExpr::alloc(0,kMachinePointerType)));
00066   case Expr::Int64: 
00067     return ConcatExpr::create8(ReadExpr::create(ul, 
00068                                                 ConstantExpr::alloc(7,kMachinePointerType)),
00069                                ReadExpr::create(ul, 
00070                                                 ConstantExpr::alloc(6,kMachinePointerType)),
00071                                ReadExpr::create(ul, 
00072                                                 ConstantExpr::alloc(5,kMachinePointerType)),
00073                                ReadExpr::create(ul, 
00074                                                 ConstantExpr::alloc(4,kMachinePointerType)),
00075                                ReadExpr::create(ul, 
00076                                                 ConstantExpr::alloc(3,kMachinePointerType)),
00077                                ReadExpr::create(ul, 
00078                                                 ConstantExpr::alloc(2,kMachinePointerType)),
00079                                ReadExpr::create(ul, 
00080                                                 ConstantExpr::alloc(1,kMachinePointerType)),
00081                                ReadExpr::create(ul, 
00082                                                 ConstantExpr::alloc(0,kMachinePointerType)));
00083   }
00084 }
00085 
00086 // returns 0 if b is structurally equal to *this
00087 int Expr::compare(const Expr &b) const {
00088   if (this == &b) return 0;
00089 
00090   Kind ak = getKind(), bk = b.getKind();
00091   if (ak!=bk)
00092     return (ak < bk) ? -1 : 1;
00093 
00094   if (hashValue != b.hashValue) 
00095     return (hashValue < b.hashValue) ? -1 : 1;
00096 
00097   if (int res = compareContents(b)) 
00098     return res;
00099 
00100   unsigned aN = getNumKids();
00101   for (unsigned i=0; i<aN; i++)
00102     if (int res = getKid(i).compare(b.getKid(i)))
00103       return res;
00104 
00105   return 0;
00106 }
00107 
00108 void Expr::printKind(std::ostream &os, Kind k) {
00109   switch(k) {
00110 #define X(C) case C: os << #C; break
00111     X(Constant);
00112     X(NotOptimized);
00113     X(Read);
00114     X(Select);
00115     X(Concat);
00116     X(Extract);
00117     X(ZExt);
00118     X(SExt);
00119     X(Add);
00120     X(Sub);
00121     X(Mul);
00122     X(UDiv);
00123     X(SDiv);
00124     X(URem);
00125     X(SRem);
00126     X(And);
00127     X(Or);
00128     X(Xor);
00129     X(Shl);
00130     X(LShr);
00131     X(AShr);
00132     X(Eq);
00133     X(Ne);
00134     X(Ult);
00135     X(Ule);
00136     X(Ugt);
00137     X(Uge);
00138     X(Slt);
00139     X(Sle);
00140     X(Sgt);
00141     X(Sge);
00142 #undef X
00143   default:
00144     assert(0 && "invalid kind");
00145     }
00146 }
00147 
00149 //
00150 // Simple hash functions for various kinds of Exprs
00151 //
00153 
00154 unsigned Expr::computeHash() {
00155   unsigned res = getKind() * Expr::MAGIC_HASH_CONSTANT;
00156 
00157   int n = getNumKids();
00158   for (int i = 0; i < n; i++) {
00159     res <<= 1;
00160     res ^= getKid(i)->hash() * Expr::MAGIC_HASH_CONSTANT;
00161   }
00162   
00163   hashValue = res;
00164   return hashValue;
00165 }
00166 
00167 unsigned ConstantExpr::computeHash() {
00168   hashValue = value ^ (width * MAGIC_HASH_CONSTANT);
00169   return hashValue;
00170 }
00171 
00172 unsigned CastExpr::computeHash() {
00173   unsigned res = getWidth() * Expr::MAGIC_HASH_CONSTANT;
00174   hashValue = res ^ src->hash() * Expr::MAGIC_HASH_CONSTANT;
00175   return hashValue;
00176 }
00177 
00178 unsigned ExtractExpr::computeHash() {
00179   unsigned res = offset * Expr::MAGIC_HASH_CONSTANT;
00180   res ^= getWidth() * Expr::MAGIC_HASH_CONSTANT;
00181   hashValue = res ^ expr->hash() * Expr::MAGIC_HASH_CONSTANT;
00182   return hashValue;
00183 }
00184 
00185 unsigned ReadExpr::computeHash() {
00186   unsigned res = index->hash() * Expr::MAGIC_HASH_CONSTANT;
00187   res ^= updates.hash();
00188   hashValue = res;
00189   return hashValue;
00190 }
00191 
00192 ref<Expr> Expr::createFromKind(Kind k, std::vector<CreateArg> args) {
00193   unsigned numArgs = args.size();
00194   (void) numArgs;
00195 
00196   switch(k) {
00197     case Constant:
00198     case Extract:
00199     case Read:
00200     default:
00201       assert(0 && "invalid kind");
00202 
00203     case NotOptimized:
00204       assert(numArgs == 1 && args[0].isExpr() &&
00205              "invalid args array for given opcode");
00206       return NotOptimizedExpr::create(args[0].expr);
00207       
00208     case Select:
00209       assert(numArgs == 3 && args[0].isExpr() &&
00210              args[1].isExpr() && args[2].isExpr() &&
00211              "invalid args array for Select opcode");
00212       return SelectExpr::create(args[0].expr,
00213                                 args[1].expr,
00214                                 args[2].expr);
00215 
00216     case Concat: {
00217       assert(numArgs == 2 && args[0].isExpr() && args[1].isExpr() && 
00218              "invalid args array for Concat opcode");
00219       
00220       return ConcatExpr::create(args[0].expr, args[1].expr);
00221     }
00222       
00223 #define CAST_EXPR_CASE(T)                                    \
00224       case T:                                                \
00225         assert(numArgs == 2 &&                               \
00226                args[0].isExpr() && args[1].isWidth() &&      \
00227                "invalid args array for given opcode");       \
00228       return T ## Expr::create(args[0].expr, args[1].width); \
00229       
00230 #define BINARY_EXPR_CASE(T)                                 \
00231       case T:                                               \
00232         assert(numArgs == 2 &&                              \
00233                args[0].isExpr() && args[1].isExpr() &&      \
00234                "invalid args array for given opcode");      \
00235       return T ## Expr::create(args[0].expr, args[1].expr); \
00236 
00237       CAST_EXPR_CASE(ZExt);
00238       CAST_EXPR_CASE(SExt);
00239       
00240       BINARY_EXPR_CASE(Add);
00241       BINARY_EXPR_CASE(Sub);
00242       BINARY_EXPR_CASE(Mul);
00243       BINARY_EXPR_CASE(UDiv);
00244       BINARY_EXPR_CASE(SDiv);
00245       BINARY_EXPR_CASE(URem);
00246       BINARY_EXPR_CASE(SRem);
00247       BINARY_EXPR_CASE(And);
00248       BINARY_EXPR_CASE(Or);
00249       BINARY_EXPR_CASE(Xor);
00250       BINARY_EXPR_CASE(Shl);
00251       BINARY_EXPR_CASE(LShr);
00252       BINARY_EXPR_CASE(AShr);
00253       
00254       BINARY_EXPR_CASE(Eq);
00255       BINARY_EXPR_CASE(Ne);
00256       BINARY_EXPR_CASE(Ult);
00257       BINARY_EXPR_CASE(Ule);
00258       BINARY_EXPR_CASE(Ugt);
00259       BINARY_EXPR_CASE(Uge);
00260       BINARY_EXPR_CASE(Slt);
00261       BINARY_EXPR_CASE(Sle);
00262       BINARY_EXPR_CASE(Sgt);
00263       BINARY_EXPR_CASE(Sge);
00264   }
00265 }
00266 
00267 
00268 void Expr::printWidth(std::ostream &os, Width width) {
00269   switch(width) {
00270   case Expr::Bool: os << "Expr::Bool"; break;
00271   case Expr::Int8: os << "Expr::Int8"; break;
00272   case Expr::Int16: os << "Expr::Int16"; break;
00273   case Expr::Int32: os << "Expr::Int32"; break;
00274   case Expr::Int64: os << "Expr::Int64"; break;
00275   default: os << "<invalid type: " << (unsigned) width << ">";
00276   }
00277 }
00278 
00279 Expr::Width Expr::getWidthForLLVMType(const llvm::Type *t) {
00280   switch (t->getTypeID()) {
00281   case llvm::Type::IntegerTyID: {
00282     Width w = cast<IntegerType>(t)->getBitWidth();
00283 
00284     // should remove this limitation soon
00285     if (w == 1 || w == 8 || w == 16 || w == 32 || w == 64)
00286       return w;
00287     else {
00288       assert(0 && "XXX arbitrary bit widths unsupported");
00289       abort();
00290     }
00291   }
00292   case llvm::Type::FloatTyID: return Expr::Int32;
00293   case llvm::Type::DoubleTyID: return Expr::Int64;
00294   case llvm::Type::X86_FP80TyID: return Expr::Int64; // XXX: needs to be fixed
00295   case llvm::Type::PointerTyID: return kMachinePointerType;
00296   default:
00297     cerr << "non-primitive type argument to Expr::getTypeForLLVMType()\n";
00298     abort();
00299   }
00300 }
00301 
00302 ref<Expr> Expr::createImplies(ref<Expr> hyp, ref<Expr> conc) {
00303   return OrExpr::create(Expr::createNot(hyp), conc);
00304 }
00305 
00306 ref<Expr> Expr::createIsZero(ref<Expr> e) {
00307   return EqExpr::create(e, ConstantExpr::create(0, e->getWidth()));
00308 }
00309 
00310 ref<Expr> Expr::createCoerceToPointerType(ref<Expr> e) {
00311   return ZExtExpr::create(e, kMachinePointerType);
00312 }
00313 
00314 ref<Expr> Expr::createNot(ref<Expr> e) {
00315   return createIsZero(e);
00316 }
00317 
00318 ref<Expr> Expr::createPointer(uint64_t v) {
00319   return ConstantExpr::create(v, kMachinePointerType);
00320 }
00321 
00322 void Expr::print(std::ostream &os) const {
00323   ExprPPrinter::printSingleExpr(os, (Expr*)this);
00324 }
00325 
00326 /***/
00327 
00328 ref<Expr> ConstantExpr::fromMemory(void *address, Width width) {
00329   switch (width) {
00330   default: assert(0 && "invalid type");
00331   case  Expr::Bool: return ConstantExpr::create(*(( uint8_t*) address), width);
00332   case  Expr::Int8: return ConstantExpr::create(*(( uint8_t*) address), width);
00333   case Expr::Int16: return ConstantExpr::create(*((uint16_t*) address), width);
00334   case Expr::Int32: return ConstantExpr::create(*((uint32_t*) address), width);
00335   case Expr::Int64: return ConstantExpr::create(*((uint64_t*) address), width);
00336   }
00337 }
00338 
00339 void ConstantExpr::toMemory(void *address) {
00340   switch (width) {
00341   default: assert(0 && "invalid type");
00342   case  Expr::Bool: *(( uint8_t*) address) = value; break;
00343   case  Expr::Int8: *(( uint8_t*) address) = value; break;
00344   case Expr::Int16: *((uint16_t*) address) = value; break;
00345   case Expr::Int32: *((uint32_t*) address) = value; break;
00346   case Expr::Int64: *((uint64_t*) address) = value; break;
00347   }
00348 }
00349 
00350 /***/
00351 
00352 ref<Expr>  NotOptimizedExpr::create(ref<Expr> src) {
00353   return NotOptimizedExpr::alloc(src);
00354 }
00355 
00356 ref<Expr> ReadExpr::create(const UpdateList &ul, ref<Expr> index) {
00357   // rollback index when possible... 
00358 
00359   // XXX this doesn't really belong here... there are basically two
00360   // cases, one is rebuild, where we want to optimistically try various
00361   // optimizations when the index has changed, and the other is 
00362   // initial creation, where we expect the ObjectState to have constructed
00363   // a smart UpdateList so it is not worth rescanning.
00364 
00365   const UpdateNode *un = ul.head;
00366   for (; un; un=un->next) {
00367     ref<Expr> cond = EqExpr::create(index, un->index);
00368     
00369     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(cond)) {
00370       if (CE->getConstantValue())
00371         return un->value;
00372     } else {
00373       break;
00374     }
00375   }
00376 
00377   return ReadExpr::alloc(ul, index);
00378 }
00379 
00380 int ReadExpr::compareContents(const Expr &b) const { 
00381   return updates.compare(static_cast<const ReadExpr&>(b).updates);
00382 }
00383 
00384 ref<Expr> SelectExpr::create(ref<Expr> c, ref<Expr> t, ref<Expr> f) {
00385   Expr::Width kt = t->getWidth();
00386 
00387   assert(c->getWidth()==Bool && "type mismatch");
00388   assert(kt==f->getWidth() && "type mismatch");
00389 
00390   if (ConstantExpr *CE = dyn_cast<ConstantExpr>(c)) {
00391     return CE->getConstantValue() ? t : f;
00392   } else if (t==f) {
00393     return t;
00394   } else if (kt==Expr::Bool) { // c ? t : f  <=> (c and t) or (not c and f)
00395     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(t)) {      
00396       if (CE->getConstantValue()) {
00397         return OrExpr::create(c, f);
00398       } else {
00399         return AndExpr::create(Expr::createNot(c), f);
00400       }
00401     } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(f)) {
00402       if (CE->getConstantValue()) {
00403         return OrExpr::create(Expr::createNot(c), t);
00404       } else {
00405         return AndExpr::create(c, t);
00406       }
00407     }
00408   }
00409   
00410   return SelectExpr::alloc(c, t, f);
00411 }
00412 
00413 /***/
00414 
00415 
00416 ref<Expr> ConcatExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
00417   Expr::Width w = l->getWidth() + r->getWidth();
00418   
00419   // Fold concatenation of constants.
00420   //
00421   // FIXME: concat 0 x -> zext x ?
00422   if (ConstantExpr *lCE = dyn_cast<ConstantExpr>(l)) {
00423     if (ConstantExpr *rCE = dyn_cast<ConstantExpr>(r)) {
00424       assert(w <= 64 && "ConcatExpr::create(): don't support concats describing constants greater than 64 bits yet");
00425       
00426       uint64_t res = (lCE->getConstantValue() << rCE->getWidth()) + 
00427         rCE->getConstantValue();
00428       return ConstantExpr::create(res, w);
00429     }
00430   }
00431 
00432   // Merge contiguous Extracts
00433   if (ExtractExpr *ee_left = dyn_cast<ExtractExpr>(l)) {
00434     if (ExtractExpr *ee_right = dyn_cast<ExtractExpr>(r)) {
00435       if (ee_left->expr == ee_right->expr &&
00436           ee_right->offset + ee_right->width == ee_left->offset) {
00437         return ExtractExpr::create(ee_left->expr, ee_right->offset, w);
00438       }
00439     }
00440   }
00441 
00442   return ConcatExpr::alloc(l, r);
00443 }
00444 
00446 ref<Expr> ConcatExpr::createN(unsigned n_kids, const ref<Expr> kids[]) {
00447   assert(n_kids > 0);
00448   if (n_kids == 1)
00449     return kids[0];
00450   
00451   ref<Expr> r = ConcatExpr::create(kids[n_kids-2], kids[n_kids-1]);
00452   for (int i=n_kids-3; i>=0; i--)
00453     r = ConcatExpr::create(kids[i], r);
00454   return r;
00455 }
00456 
00458 ref<Expr> ConcatExpr::create4(const ref<Expr> &kid1, const ref<Expr> &kid2,
00459                                      const ref<Expr> &kid3, const ref<Expr> &kid4) {
00460   return ConcatExpr::create(kid1, ConcatExpr::create(kid2, ConcatExpr::create(kid3, kid4)));
00461 }
00462 
00464 ref<Expr> ConcatExpr::create8(const ref<Expr> &kid1, const ref<Expr> &kid2,
00465                               const ref<Expr> &kid3, const ref<Expr> &kid4,
00466                               const ref<Expr> &kid5, const ref<Expr> &kid6,
00467                               const ref<Expr> &kid7, const ref<Expr> &kid8) {
00468   return ConcatExpr::create(kid1, ConcatExpr::create(kid2, ConcatExpr::create(kid3, 
00469                               ConcatExpr::create(kid4, ConcatExpr::create4(kid5, kid6, kid7, kid8)))));
00470 }
00471 
00472 /***/
00473 
00474 ref<Expr> ExtractExpr::create(ref<Expr> expr, unsigned off, Width w) {
00475   unsigned kw = expr->getWidth();
00476   assert(w > 0 && off + w <= kw && "invalid extract");
00477   
00478   if (w == kw) {
00479     return expr;
00480   } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(expr)) {
00481     return ConstantExpr::create(ints::trunc(CE->getConstantValue() >> off, w, 
00482                                             kw), w);
00483   } else {
00484     // Extract(Concat)
00485     if (ConcatExpr *ce = dyn_cast<ConcatExpr>(expr)) {
00486       // if the extract skips the right side of the concat
00487       if (off >= ce->getRight()->getWidth())
00488         return ExtractExpr::create(ce->getLeft(), off - ce->getRight()->getWidth(), w);
00489       
00490       // if the extract skips the left side of the concat
00491       if (off + w <= ce->getRight()->getWidth())
00492         return ExtractExpr::create(ce->getRight(), off, w);
00493 
00494       // E(C(x,y)) = C(E(x), E(y))
00495       return ConcatExpr::create(ExtractExpr::create(ce->getKid(0), 0, w - ce->getKid(1)->getWidth() + off),
00496                                 ExtractExpr::create(ce->getKid(1), off, ce->getKid(1)->getWidth() - off));
00497     }
00498   }
00499   
00500   return ExtractExpr::alloc(expr, off, w);
00501 }
00502 
00503 
00504 ref<Expr> ExtractExpr::createByteOff(ref<Expr> expr, unsigned offset, Width bits) {
00505   return ExtractExpr::create(expr, 8*offset, bits);
00506 }
00507 
00508 /***/
00509 
00510 ref<Expr> ZExtExpr::create(const ref<Expr> &e, Width w) {
00511   unsigned kBits = e->getWidth();
00512   if (w == kBits) {
00513     return e;
00514   } else if (w < kBits) { // trunc
00515     return ExtractExpr::createByteOff(e, 0, w);
00516   } else {
00517     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(e))
00518       return ConstantExpr::create(ints::zext(CE->getConstantValue(), w, kBits),
00519                                   w);
00520     
00521     return ZExtExpr::alloc(e, w);
00522   }
00523 }
00524 
00525 ref<Expr> SExtExpr::create(const ref<Expr> &e, Width w) {
00526   unsigned kBits = e->getWidth();
00527   if (w == kBits) {
00528     return e;
00529   } else if (w < kBits) { // trunc
00530     return ExtractExpr::createByteOff(e, 0, w);
00531   } else {
00532     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(e))
00533       return ConstantExpr::create(ints::sext(CE->getConstantValue(), w, kBits),
00534                                   w);
00535     
00536     return SExtExpr::alloc(e, w);
00537   }
00538 }
00539 
00540 /***/
00541 
00542 static ref<Expr> AndExpr_create(Expr *l, Expr *r);
00543 static ref<Expr> XorExpr_create(Expr *l, Expr *r);
00544 
00545 static ref<Expr> EqExpr_createPartial(Expr *l, const ref<ConstantExpr> &cr);
00546 static ref<Expr> AndExpr_createPartialR(const ref<ConstantExpr> &cl, Expr *r);
00547 static ref<Expr> SubExpr_createPartialR(const ref<ConstantExpr> &cl, Expr *r);
00548 static ref<Expr> XorExpr_createPartialR(const ref<ConstantExpr> &cl, Expr *r);
00549 
00550 static ref<Expr> AddExpr_createPartialR(const ref<ConstantExpr> &cl, Expr *r) {
00551   uint64_t value = cl->getConstantValue();
00552   Expr::Width type = cl->getWidth();
00553 
00554   if (type==Expr::Bool) {
00555     return XorExpr_createPartialR(cl, r);
00556   } else if (!value) {
00557     return r;
00558   } else {
00559     Expr::Kind rk = r->getKind();
00560     if (rk==Expr::Add && isa<ConstantExpr>(r->getKid(0))) { // A + (B+c) == (A+B) + c
00561       return AddExpr::create(AddExpr::create(cl, r->getKid(0)),
00562                              r->getKid(1));
00563     } else if (rk==Expr::Sub && isa<ConstantExpr>(r->getKid(0))) { // A + (B-c) == (A+B) - c
00564       return SubExpr::create(AddExpr::create(cl, r->getKid(0)),
00565                              r->getKid(1));
00566     } else {
00567       return AddExpr::alloc(cl, r);
00568     }
00569   }
00570 }
00571 static ref<Expr> AddExpr_createPartial(Expr *l, const ref<ConstantExpr> &cr) {
00572   return AddExpr_createPartialR(cr, l);
00573 }
00574 static ref<Expr> AddExpr_create(Expr *l, Expr *r) {
00575   Expr::Width type = l->getWidth();
00576 
00577   if (type == Expr::Bool) {
00578     return XorExpr_create(l, r);
00579   } else {
00580     Expr::Kind lk = l->getKind(), rk = r->getKind();
00581     if (lk==Expr::Add && isa<ConstantExpr>(l->getKid(0))) { // (k+a)+b = k+(a+b)
00582       return AddExpr::create(l->getKid(0),
00583                              AddExpr::create(l->getKid(1), r));
00584     } else if (lk==Expr::Sub && isa<ConstantExpr>(l->getKid(0))) { // (k-a)+b = k+(b-a)
00585       return AddExpr::create(l->getKid(0),
00586                              SubExpr::create(r, l->getKid(1)));
00587     } else if (rk==Expr::Add && isa<ConstantExpr>(r->getKid(0))) { // a + (k+b) = k+(a+b)
00588       return AddExpr::create(r->getKid(0),
00589                              AddExpr::create(l, r->getKid(1)));
00590     } else if (rk==Expr::Sub && isa<ConstantExpr>(r->getKid(0))) { // a + (k-b) = k+(a-b)
00591       return AddExpr::create(r->getKid(0),
00592                              SubExpr::create(l, r->getKid(1)));
00593     } else {
00594       return AddExpr::alloc(l, r);
00595     }
00596   }  
00597 }
00598 
00599 static ref<Expr> SubExpr_createPartialR(const ref<ConstantExpr> &cl, Expr *r) {
00600   Expr::Width type = cl->getWidth();
00601 
00602   if (type==Expr::Bool) {
00603     return XorExpr_createPartialR(cl, r);
00604   } else {
00605     Expr::Kind rk = r->getKind();
00606     if (rk==Expr::Add && isa<ConstantExpr>(r->getKid(0))) { // A - (B+c) == (A-B) - c
00607       return SubExpr::create(SubExpr::create(cl, r->getKid(0)),
00608                              r->getKid(1));
00609     } else if (rk==Expr::Sub && isa<ConstantExpr>(r->getKid(0))) { // A - (B-c) == (A-B) + c
00610       return AddExpr::create(SubExpr::create(cl, r->getKid(0)),
00611                              r->getKid(1));
00612     } else {
00613       return SubExpr::alloc(cl, r);
00614     }
00615   }
00616 }
00617 static ref<Expr> SubExpr_createPartial(Expr *l, const ref<ConstantExpr> &cr) {
00618   uint64_t value = cr->getConstantValue();
00619   Expr::Width width = cr->getWidth();
00620   uint64_t nvalue = ints::sub(0, value, width);
00621 
00622   return AddExpr_createPartial(l, ConstantExpr::create(nvalue, width));
00623 }
00624 static ref<Expr> SubExpr_create(Expr *l, Expr *r) {
00625   Expr::Width type = l->getWidth();
00626 
00627   if (type == Expr::Bool) {
00628     return XorExpr_create(l, r);
00629   } else if (*l==*r) {
00630     return ConstantExpr::alloc(0, type);
00631   } else {
00632     Expr::Kind lk = l->getKind(), rk = r->getKind();
00633     if (lk==Expr::Add && isa<ConstantExpr>(l->getKid(0))) { // (k+a)-b = k+(a-b)
00634       return AddExpr::create(l->getKid(0),
00635                              SubExpr::create(l->getKid(1), r));
00636     } else if (lk==Expr::Sub && isa<ConstantExpr>(l->getKid(0))) { // (k-a)-b = k-(a+b)
00637       return SubExpr::create(l->getKid(0),
00638                              AddExpr::create(l->getKid(1), r));
00639     } else if (rk==Expr::Add && isa<ConstantExpr>(r->getKid(0))) { // a - (k+b) = (a-c) - k
00640       return SubExpr::create(SubExpr::create(l, r->getKid(1)),
00641                              r->getKid(0));
00642     } else if (rk==Expr::Sub && isa<ConstantExpr>(r->getKid(0))) { // a - (k-b) = (a+b) - k
00643       return SubExpr::create(AddExpr::create(l, r->getKid(1)),
00644                              r->getKid(0));
00645     } else {
00646       return SubExpr::alloc(l, r);
00647     }
00648   }  
00649 }
00650 
00651 static ref<Expr> MulExpr_createPartialR(const ref<ConstantExpr> &cl, Expr *r) {
00652   uint64_t value = cl->getConstantValue();
00653   Expr::Width type = cl->getWidth();
00654 
00655   if (type == Expr::Bool) {
00656     return AndExpr_createPartialR(cl, r);
00657   } else if (value == 1) {
00658     return r;
00659   } else if (!value) {
00660     return cl;
00661   } else {
00662     return MulExpr::alloc(cl, r);
00663   }
00664 }
00665 static ref<Expr> MulExpr_createPartial(Expr *l, const ref<ConstantExpr> &cr) {
00666   return MulExpr_createPartialR(cr, l);
00667 }
00668 static ref<Expr> MulExpr_create(Expr *l, Expr *r) {
00669   Expr::Width type = l->getWidth();
00670   
00671   if (type == Expr::Bool) {
00672     return AndExpr::alloc(l, r);
00673   } else {
00674     return MulExpr::alloc(l, r);
00675   }
00676 }
00677 
00678 static ref<Expr> AndExpr_createPartial(Expr *l, const ref<ConstantExpr> &cr) {
00679   uint64_t value = cr->getConstantValue();
00680   Expr::Width width = cr->getWidth();
00681 
00682   if (value==ints::sext(1, width, 1)) {
00683     return l;
00684   } else if (!value) {
00685     return cr;
00686   } else {
00687     return AndExpr::alloc(l, cr);
00688   }
00689 }
00690 static ref<Expr> AndExpr_createPartialR(const ref<ConstantExpr> &cl, Expr *r) {
00691   return AndExpr_createPartial(r, cl);
00692 }
00693 static ref<Expr> AndExpr_create(Expr *l, Expr *r) {
00694   return AndExpr::alloc(l, r);
00695 }
00696 
00697 static ref<Expr> OrExpr_createPartial(Expr *l, const ref<ConstantExpr> &cr) {
00698   uint64_t value = cr->getConstantValue();
00699   Expr::Width width = cr->getWidth();
00700 
00701   if (value == ints::sext(1, width, 1)) {
00702     return cr;
00703   } else if (!value) {
00704     return l;
00705   } else {
00706     return OrExpr::alloc(l, cr);
00707   }
00708 }
00709 static ref<Expr> OrExpr_createPartialR(const ref<ConstantExpr> &cl, Expr *r) {
00710   return OrExpr_createPartial(r, cl);
00711 }
00712 static ref<Expr> OrExpr_create(Expr *l, Expr *r) {
00713   return OrExpr::alloc(l, r);
00714 }
00715 
00716 static ref<Expr> XorExpr_createPartialR(const ref<ConstantExpr> &cl, Expr *r) {
00717   uint64_t value = cl->getConstantValue();
00718   Expr::Width type = cl->getWidth();
00719 
00720   if (type==Expr::Bool) {
00721     if (value) {
00722       return EqExpr_createPartial(r, ConstantExpr::create(0, Expr::Bool));
00723     } else {
00724       return r;
00725     }
00726   } else if (!value) {
00727     return r;
00728   } else {
00729     return XorExpr::alloc(cl, r);
00730   }
00731 }
00732 
00733 static ref<Expr> XorExpr_createPartial(Expr *l, const ref<ConstantExpr> &cr) {
00734   return XorExpr_createPartialR(cr, l);
00735 }
00736 static ref<Expr> XorExpr_create(Expr *l, Expr *r) {
00737   return XorExpr::alloc(l, r);
00738 }
00739 
00740 static ref<Expr> UDivExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
00741   if (l->getWidth() == Expr::Bool) { // r must be 1
00742     return l;
00743   } else{
00744     return UDivExpr::alloc(l, r);
00745   }
00746 }
00747 
00748 static ref<Expr> SDivExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
00749   if (l->getWidth() == Expr::Bool) { // r must be 1
00750     return l;
00751   } else{
00752     return SDivExpr::alloc(l, r);
00753   }
00754 }
00755 
00756 static ref<Expr> URemExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
00757   if (l->getWidth() == Expr::Bool) { // r must be 1
00758     return ConstantExpr::create(0, Expr::Bool);
00759   } else{
00760     return URemExpr::alloc(l, r);
00761   }
00762 }
00763 
00764 static ref<Expr> SRemExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
00765   if (l->getWidth() == Expr::Bool) { // r must be 1
00766     return ConstantExpr::create(0, Expr::Bool);
00767   } else{
00768     return SRemExpr::alloc(l, r);
00769   }
00770 }
00771 
00772 static ref<Expr> ShlExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
00773   if (l->getWidth() == Expr::Bool) { // l & !r
00774     return AndExpr::create(l, Expr::createNot(r));
00775   } else{
00776     return ShlExpr::alloc(l, r);
00777   }
00778 }
00779 
00780 static ref<Expr> LShrExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
00781   if (l->getWidth() == Expr::Bool) { // l & !r
00782     return AndExpr::create(l, Expr::createNot(r));
00783   } else{
00784     return LShrExpr::alloc(l, r);
00785   }
00786 }
00787 
00788 static ref<Expr> AShrExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
00789   if (l->getWidth() == Expr::Bool) { // l
00790     return l;
00791   } else{
00792     return AShrExpr::alloc(l, r);
00793   }
00794 }
00795 
00796 #define BCREATE_R(_e_op, _op, partialL, partialR) \
00797 ref<Expr>  _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) { \
00798   assert(l->getWidth()==r->getWidth() && "type mismatch");              \
00799   if (ConstantExpr *cl = dyn_cast<ConstantExpr>(l)) {                   \
00800     if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) {                 \
00801       Expr::Width width = l->getWidth();                                \
00802       uint64_t val = ints::_op(cl->getConstantValue(),                  \
00803                                cr->getConstantValue(), width);          \
00804       return ConstantExpr::create(val, width);                          \
00805     } else {                                                            \
00806       return _e_op ## _createPartialR(cl, r.get());                     \
00807     }                                                                   \
00808   } else if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) {            \
00809     return _e_op ## _createPartial(l.get(), cr);                        \
00810   }                                                                     \
00811   return _e_op ## _create(l.get(), r.get());                            \
00812 }
00813 
00814 #define BCREATE(_e_op, _op) \
00815 ref<Expr>  _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) { \
00816   assert(l->getWidth()==r->getWidth() && "type mismatch");          \
00817   if (ConstantExpr *cl = dyn_cast<ConstantExpr>(l)) {               \
00818     if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) {             \
00819       Expr::Width width = l->getWidth();                            \
00820       uint64_t val = ints::_op(cl->getConstantValue(),              \
00821                                cr->getConstantValue(), width);      \
00822       return ConstantExpr::create(val, width);                      \
00823     }                                                               \
00824   }                                                                 \
00825   return _e_op ## _create(l, r);                                    \
00826 }
00827 
00828 BCREATE_R(AddExpr, add, AddExpr_createPartial, AddExpr_createPartialR)
00829 BCREATE_R(SubExpr, sub, SubExpr_createPartial, SubExpr_createPartialR)
00830 BCREATE_R(MulExpr, mul, MulExpr_createPartial, MulExpr_createPartialR)
00831 BCREATE_R(AndExpr, land, AndExpr_createPartial, AndExpr_createPartialR)
00832 BCREATE_R(OrExpr, lor, OrExpr_createPartial, OrExpr_createPartialR)
00833 BCREATE_R(XorExpr, lxor, XorExpr_createPartial, XorExpr_createPartialR)
00834 BCREATE(UDivExpr, udiv)
00835 BCREATE(SDivExpr, sdiv)
00836 BCREATE(URemExpr, urem)
00837 BCREATE(SRemExpr, srem)
00838 BCREATE(ShlExpr, shl)
00839 BCREATE(LShrExpr, lshr)
00840 BCREATE(AShrExpr, ashr)
00841 
00842 #define CMPCREATE(_e_op, _op) \
00843 ref<Expr>  _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) { \
00844   assert(l->getWidth()==r->getWidth() && "type mismatch");              \
00845   if (ConstantExpr *cl = dyn_cast<ConstantExpr>(l)) {                   \
00846     if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) {                 \
00847       Expr::Width width = cl->getWidth();                               \
00848       uint64_t val = ints::_op(cl->getConstantValue(),                  \
00849                                cr->getConstantValue(), width);          \
00850       return ConstantExpr::create(val, Expr::Bool);                     \
00851     }                                                                   \
00852   }                                                                     \
00853   return _e_op ## _create(l, r);                                        \
00854 }
00855 
00856 #define CMPCREATE_T(_e_op, _op, _reflexive_e_op, partialL, partialR) \
00857 ref<Expr>  _e_op ::create(const ref<Expr> &l, const ref<Expr> &r) {    \
00858   assert(l->getWidth()==r->getWidth() && "type mismatch");             \
00859   if (ConstantExpr *cl = dyn_cast<ConstantExpr>(l)) {                  \
00860     if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) {                \
00861       Expr::Width width = cl->getWidth();                              \
00862       uint64_t val = ints::_op(cl->getConstantValue(),                 \
00863                                cr->getConstantValue(), width);         \
00864       return ConstantExpr::create(val, Expr::Bool);                    \
00865     } else {                                                           \
00866       return partialR(cl, r.get());                                    \
00867     }                                                                  \
00868   } else if (ConstantExpr *cr = dyn_cast<ConstantExpr>(r)) {           \
00869     return partialL(l.get(), cr);                                      \
00870   } else {                                                             \
00871     return _e_op ## _create(l.get(), r.get());                         \
00872   }                                                                    \
00873 }
00874   
00875 
00876 static ref<Expr> EqExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
00877   if (l == r) {
00878     return ConstantExpr::alloc(1, Expr::Bool);
00879   } else {
00880     return EqExpr::alloc(l, r);
00881   }
00882 }
00883 
00884 
00889 static ref<Expr> TryConstArrayOpt(const ref<ConstantExpr> &cl, 
00890                                   ReadExpr *rd) {
00891   assert(rd->getKind() == Expr::Read && "read expression required");
00892   
00893   uint64_t ct = cl->getConstantValue();
00894   ref<Expr> first_idx_match;
00895 
00896   // number of positions in the array that contain value ct
00897   unsigned matches = 0;
00898 
00899   //llvm::cerr << "Size updates/root: " << rd->updates.getSize() << " / " << (rd->updates.root)->size << "\n";
00900 
00901   // for now, just assume standard "flushing" of a concrete array,
00902   // where the concrete array has one update for each index, in order
00903   bool all_const = true;
00904   if (rd->updates.getSize() == rd->updates.root->size) {
00905     unsigned k = rd->updates.getSize();
00906     for (const UpdateNode *un = rd->updates.head; un; un = un->next) {
00907       assert(k > 0);
00908       k--;
00909 
00910       ref<Expr> idx = un->index;
00911       ref<Expr> val = un->value;
00912       ConstantExpr *idxCE = dyn_cast<ConstantExpr>(idx);
00913       ConstantExpr *valCE = dyn_cast<ConstantExpr>(val);
00914       if (!idxCE || !valCE) {
00915         all_const = false;
00916         break;
00917       }
00918 
00919       if (idxCE->getConstantValue() != k) {
00920         all_const = false;
00921         break;
00922       }
00923       if (valCE->getConstantValue() == ct) {
00924         matches++;
00925         if (matches == 1)
00926           first_idx_match = un->index;
00927       }
00928     }
00929   }
00930   else all_const = false;
00931   
00932   if (all_const && matches <= 100) {
00933     // apply optimization
00934     //llvm::cerr << "\n\n=== Applying const array optimization ===\n\n";
00935 
00936     if (matches == 0)
00937       return ConstantExpr::alloc(0, Expr::Bool);
00938 
00939     ref<Expr> res = EqExpr::create(first_idx_match, rd->index);
00940     if (matches == 1)
00941       return res;
00942     
00943     for (const UpdateNode *un = rd->updates.head; un; un = un->next) {
00944       if (un->index != first_idx_match && 
00945           cast<ConstantExpr>(un->value)->getConstantValue() == ct) {
00946         ref<Expr> curr_eq = EqExpr::create(un->index, rd->index);
00947         res = OrExpr::create(curr_eq, res);
00948       }
00949     }
00950     
00951     return res;
00952   }
00953 
00954   return EqExpr_create(cl, ref<Expr>(rd));
00955 }
00956 
00957 
00958 static ref<Expr> EqExpr_createPartialR(const ref<ConstantExpr> &cl, Expr *r) {  
00959   uint64_t value = cl->getConstantValue();
00960   Expr::Width width = cl->getWidth();
00961 
00962   Expr::Kind rk = r->getKind();
00963   if (width == Expr::Bool) {
00964     if (value) {
00965       return r;
00966     } else {
00967       // 0 != ...
00968       
00969       if (rk == Expr::Eq) {
00970         const EqExpr *ree = cast<EqExpr>(r);
00971 
00972         // eliminate double negation
00973         if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ree->left)) {
00974           if (CE->getWidth() == Expr::Bool) {
00975             assert(!CE->getConstantValue());
00976             return ree->right;
00977           }
00978         }
00979       } else if (rk == Expr::Or) {
00980         const OrExpr *roe = cast<OrExpr>(r);
00981 
00982         // transform not(or(a,b)) to and(not a, not b)
00983         return AndExpr::create(Expr::createNot(roe->left),
00984                                Expr::createNot(roe->right));
00985       }
00986     }
00987   } else if (rk == Expr::SExt) {
00988     // (sext(a,T)==c) == (a==c)
00989     const SExtExpr *see = cast<SExtExpr>(r);
00990     Expr::Width fromBits = see->src->getWidth();
00991     uint64_t trunc = bits64::truncateToNBits(value, fromBits);
00992 
00993     // pathological check, make sure it is possible to
00994     // sext to this value *from any value*
00995     if (value == ints::sext(trunc, width, fromBits)) {
00996       return EqExpr::create(see->src, ConstantExpr::create(trunc, fromBits));
00997     } else {
00998       return ConstantExpr::create(0, Expr::Bool);
00999     }
01000   } else if (rk == Expr::ZExt) {
01001     // (zext(a,T)==c) == (a==c)
01002     const ZExtExpr *zee = cast<ZExtExpr>(r);
01003     Expr::Width fromBits = zee->src->getWidth();
01004     uint64_t trunc = bits64::truncateToNBits(value, fromBits);
01005     
01006     // pathological check, make sure it is possible to
01007     // zext to this value *from any value*
01008     if (value == ints::zext(trunc, width, fromBits)) {
01009       return EqExpr::create(zee->src, ConstantExpr::create(trunc, fromBits));
01010     } else {
01011       return ConstantExpr::create(0, Expr::Bool);
01012     }
01013   } else if (rk==Expr::Add) {
01014     const AddExpr *ae = cast<AddExpr>(r);
01015     if (isa<ConstantExpr>(ae->left)) {
01016       // c0 = c1 + b => c0 - c1 = b
01017       return EqExpr_createPartialR(cast<ConstantExpr>(SubExpr::create(cl, 
01018                                                                       ae->left)),
01019                                    ae->right.get());
01020     }
01021   } else if (rk==Expr::Sub) {
01022     const SubExpr *se = cast<SubExpr>(r);
01023     if (isa<ConstantExpr>(se->left)) {
01024       // c0 = c1 - b => c1 - c0 = b
01025       return EqExpr_createPartialR(cast<ConstantExpr>(SubExpr::create(se->left, 
01026                                                                       cl)),
01027                                    se->right.get());
01028     }
01029   } else if (rk == Expr::Read && ConstArrayOpt) {
01030     return TryConstArrayOpt(cl, static_cast<ReadExpr*>(r));
01031   }
01032     
01033   return EqExpr_create(cl, r);
01034 }
01035 
01036 static ref<Expr> EqExpr_createPartial(Expr *l, const ref<ConstantExpr> &cr) {  
01037   return EqExpr_createPartialR(cr, l);
01038 }
01039   
01040 ref<Expr> NeExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
01041   return EqExpr::create(ConstantExpr::create(0, Expr::Bool),
01042                         EqExpr::create(l, r));
01043 }
01044 
01045 ref<Expr> UgtExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
01046   return UltExpr::create(r, l);
01047 }
01048 ref<Expr> UgeExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
01049   return UleExpr::create(r, l);
01050 }
01051 
01052 ref<Expr> SgtExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
01053   return SltExpr::create(r, l);
01054 }
01055 ref<Expr> SgeExpr::create(const ref<Expr> &l, const ref<Expr> &r) {
01056   return SleExpr::create(r, l);
01057 }
01058 
01059 static ref<Expr> UltExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
01060   Expr::Width t = l->getWidth();
01061   if (t == Expr::Bool) { // !l && r
01062     return AndExpr::create(Expr::createNot(l), r);
01063   } else {
01064     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(r)) {      
01065       uint64_t value = CE->getConstantValue();
01066       if (value <= 8) {
01067         ref<Expr> res = ConstantExpr::alloc(0, Expr::Bool);
01068         for (unsigned i=0; i<value; i++) {
01069           res = OrExpr::create(EqExpr::create(l, 
01070                                               ConstantExpr::alloc(i, t)), res);
01071         }
01072         return res;
01073       }
01074     }
01075     return UltExpr::alloc(l, r);
01076   }
01077 }
01078 
01079 static ref<Expr> UleExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
01080   if (l->getWidth() == Expr::Bool) { // !(l && !r)
01081     return OrExpr::create(Expr::createNot(l), r);
01082   } else {
01083     return UleExpr::alloc(l, r);
01084   }
01085 }
01086 
01087 static ref<Expr> SltExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
01088   if (l->getWidth() == Expr::Bool) { // l && !r
01089     return AndExpr::create(l, Expr::createNot(r));
01090   } else {
01091     return SltExpr::alloc(l, r);
01092   }
01093 }
01094 
01095 static ref<Expr> SleExpr_create(const ref<Expr> &l, const ref<Expr> &r) {
01096   if (l->getWidth() == Expr::Bool) { // !(!l && r)
01097     return OrExpr::create(l, Expr::createNot(r));
01098   } else {
01099     return SleExpr::alloc(l, r);
01100   }
01101 }
01102 
01103 CMPCREATE_T(EqExpr, eq, EqExpr, EqExpr_createPartial, EqExpr_createPartialR)
01104 CMPCREATE(UltExpr, ult)
01105 CMPCREATE(UleExpr, ule)
01106 CMPCREATE(SltExpr, slt)
01107 CMPCREATE(SleExpr, sle)

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