00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "klee/Expr.h"
00011
00012
00013 #include "klee/Machine.h"
00014
00015
00016 #include "llvm/Type.h"
00017 #include "llvm/DerivedTypes.h"
00018 #include "llvm/Support/CommandLine.h"
00019 #include "llvm/Support/Streams.h"
00020
00021
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
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
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
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;
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
00358
00359
00360
00361
00362
00363
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) {
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
00420
00421
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
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
00485 if (ConcatExpr *ce = dyn_cast<ConcatExpr>(expr)) {
00486
00487 if (off >= ce->getRight()->getWidth())
00488 return ExtractExpr::create(ce->getLeft(), off - ce->getRight()->getWidth(), w);
00489
00490
00491 if (off + w <= ce->getRight()->getWidth())
00492 return ExtractExpr::create(ce->getRight(), off, w);
00493
00494
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) {
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) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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))) {
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) {
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) {
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) {
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) {
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) {
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) {
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) {
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
00897 unsigned matches = 0;
00898
00899
00900
00901
00902
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
00934
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
00968
00969 if (rk == Expr::Eq) {
00970 const EqExpr *ree = cast<EqExpr>(r);
00971
00972
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
00983 return AndExpr::create(Expr::createNot(roe->left),
00984 Expr::createNot(roe->right));
00985 }
00986 }
00987 } else if (rk == Expr::SExt) {
00988
00989 const SExtExpr *see = cast<SExtExpr>(r);
00990 Expr::Width fromBits = see->src->getWidth();
00991 uint64_t trunc = bits64::truncateToNBits(value, fromBits);
00992
00993
00994
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
01002 const ZExtExpr *zee = cast<ZExtExpr>(r);
01003 Expr::Width fromBits = zee->src->getWidth();
01004 uint64_t trunc = bits64::truncateToNBits(value, fromBits);
01005
01006
01007
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
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
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) {
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) {
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) {
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) {
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)