00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "STPBuilder.h"
00011
00012 #include "klee/Expr.h"
00013 #include "klee/Solver.h"
00014 #include "klee/util/Bits.h"
00015
00016 #include "ConstantDivision.h"
00017 #include "SolverStats.h"
00018
00019 #include "llvm/Support/CommandLine.h"
00020
00021 #include <cstdio>
00022
00023 #define vc_bvBoolExtract IAMTHESPAWNOFSATAN
00024
00025 #define vc_bvLeftShiftExpr IAMTHESPAWNOFSATAN
00026 #define vc_bvRightShiftExpr IAMTHESPAWNOFSATAN
00027
00028 #define vc_bvVar32LeftShiftExpr IAMTHESPAWNOFSATAN
00029 #define vc_bvVar32RightShiftExpr IAMTHESPAWNOFSATAN
00030 #define vc_bvVar32DivByPowOfTwoExpr IAMTHESPAWNOFSATAN
00031 #define vc_bvCreateMemoryArray IAMTHESPAWNOFSATAN
00032 #define vc_bvReadMemoryArray IAMTHESPAWNOFSATAN
00033 #define vc_bvWriteToMemoryArray IAMTHESPAWNOFSATAN
00034
00035 #include <algorithm>
00036 #include <cassert>
00037 #include <iostream>
00038 #include <map>
00039 #include <sstream>
00040 #include <vector>
00041
00042 using namespace klee;
00043
00044 namespace {
00045 llvm::cl::opt<bool>
00046 UseConstructHash("use-construct-hash",
00047 llvm::cl::desc("Use hash-consing during STP query construction."),
00048 llvm::cl::init(true));
00049 }
00050
00052
00053
00054
00055 STPBuilder::STPBuilder(::VC _vc, bool _optimizeDivides)
00056 : vc(_vc), optimizeDivides(_optimizeDivides)
00057 {
00058 tempVars[0] = buildVar("__tmpInt8", 8);
00059 tempVars[1] = buildVar("__tmpInt16", 16);
00060 tempVars[2] = buildVar("__tmpInt32", 32);
00061 tempVars[3] = buildVar("__tmpInt64", 64);
00062 }
00063
00064 STPBuilder::~STPBuilder() {
00065 }
00066
00068
00069
00070
00071
00072
00073 ::VCExpr STPBuilder::buildVar(const char *name, unsigned width) {
00074
00075 ::Type t = (width==1) ? vc_boolType(vc) : vc_bvType(vc, width);
00076 ::VCExpr res = vc_varExpr(vc, (char*) name, t);
00077 vc_DeleteExpr(t);
00078 return res;
00079 }
00080
00081 ::VCExpr STPBuilder::buildArray(const char *name, unsigned indexWidth, unsigned valueWidth) {
00082
00083 ::Type t1 = vc_bvType(vc, indexWidth);
00084 ::Type t2 = vc_bvType(vc, valueWidth);
00085 ::Type t = vc_arrayType(vc, t1, t2);
00086 ::VCExpr res = vc_varExpr(vc, (char*) name, t);
00087 vc_DeleteExpr(t);
00088 vc_DeleteExpr(t2);
00089 vc_DeleteExpr(t1);
00090 return res;
00091 }
00092
00093 ExprHandle STPBuilder::getTempVar(Expr::Width w) {
00094 switch (w) {
00095 default: assert(0 && "invalid type");
00096 case Expr::Int8: return tempVars[0];
00097 case Expr::Int16: return tempVars[1];
00098 case Expr::Int32: return tempVars[2];
00099 case Expr::Int64: return tempVars[3];
00100 }
00101 }
00102
00103 ExprHandle STPBuilder::getTrue() {
00104 return vc_trueExpr(vc);
00105 }
00106 ExprHandle STPBuilder::getFalse() {
00107 return vc_falseExpr(vc);
00108 }
00109 ExprHandle STPBuilder::bvOne(unsigned width) {
00110 return bvConst32(width, 1);
00111 }
00112 ExprHandle STPBuilder::bvZero(unsigned width) {
00113 return bvConst32(width, 0);
00114 }
00115 ExprHandle STPBuilder::bvMinusOne(unsigned width) {
00116 return bvConst64(width, (int64_t) -1);
00117 }
00118 ExprHandle STPBuilder::bvConst32(unsigned width, uint32_t value) {
00119 return vc_bvConstExprFromInt(vc, width, value);
00120 }
00121 ExprHandle STPBuilder::bvConst64(unsigned width, uint64_t value) {
00122 return vc_bvConstExprFromLL(vc, width, value);
00123 }
00124
00125 ExprHandle STPBuilder::bvBoolExtract(ExprHandle expr, int bit) {
00126 return vc_eqExpr(vc, bvExtract(expr, bit, bit), bvOne(1));
00127 }
00128 ExprHandle STPBuilder::bvExtract(ExprHandle expr, unsigned top, unsigned bottom) {
00129 return vc_bvExtract(vc, expr, top, bottom);
00130 }
00131 ExprHandle STPBuilder::eqExpr(ExprHandle a, ExprHandle b) {
00132 return vc_eqExpr(vc, a, b);
00133 }
00134
00135
00136 ExprHandle STPBuilder::bvRightShift(ExprHandle expr, unsigned amount, unsigned shiftBits) {
00137 unsigned width = vc_getBVLength(vc, expr);
00138 unsigned shift = amount & ((1<<shiftBits) - 1);
00139
00140 if (shift==0) {
00141 return expr;
00142 } else if (shift>=width) {
00143 return bvZero(width);
00144 } else {
00145 return vc_bvConcatExpr(vc,
00146 bvZero(shift),
00147 bvExtract(expr, width - 1, shift));
00148 }
00149 }
00150
00151
00152 ExprHandle STPBuilder::bvLeftShift(ExprHandle expr, unsigned amount, unsigned shiftBits) {
00153 unsigned width = vc_getBVLength(vc, expr);
00154 unsigned shift = amount & ((1<<shiftBits) - 1);
00155
00156 if (shift==0) {
00157 return expr;
00158 } else if (shift>=width) {
00159 return bvZero(width);
00160 } else {
00161
00162
00163 return vc_bvConcatExpr(vc,
00164 bvExtract(expr, width - shift - 1, 0),
00165 bvZero(shift));
00166 }
00167 }
00168
00169
00170 ExprHandle STPBuilder::bvVarLeftShift(ExprHandle expr, ExprHandle amount, unsigned width) {
00171 ExprHandle res = bvZero(width);
00172
00173 int shiftBits = getShiftBits( width );
00174
00175
00176 ExprHandle shift = vc_bvExtract( vc, amount, shiftBits - 1, 0 );
00177
00178
00179 for( int i=width-1; i>=0; i-- ) {
00180 res = vc_iteExpr(vc,
00181 eqExpr(shift, bvConst32(shiftBits, i)),
00182 bvLeftShift(expr, i, shiftBits),
00183 res);
00184 }
00185 return res;
00186 }
00187
00188
00189 ExprHandle STPBuilder::bvVarRightShift(ExprHandle expr, ExprHandle amount, unsigned width) {
00190 ExprHandle res = bvZero(width);
00191
00192 int shiftBits = getShiftBits( width );
00193
00194
00195 ExprHandle shift = vc_bvExtract( vc, amount, shiftBits - 1, 0 );
00196
00197
00198 for( int i=width-1; i>=0; i-- ) {
00199 res = vc_iteExpr(vc,
00200 eqExpr(shift, bvConst32(shiftBits, i)),
00201 bvRightShift(expr, i, shiftBits),
00202 res);
00203 }
00204
00205 return res;
00206 }
00207
00208
00209 ExprHandle STPBuilder::bvVarArithRightShift(ExprHandle expr, ExprHandle amount, unsigned width) {
00210 int shiftBits = getShiftBits( width );
00211
00212
00213 ExprHandle shift = vc_bvExtract( vc, amount, shiftBits - 1, 0 );
00214
00215
00216 ExprHandle signedBool = bvBoolExtract(expr, width-1);
00217
00218
00219 ExprHandle res = constructAShrByConstant(expr, width-1, signedBool, shiftBits);
00220
00221
00222
00223
00224 for( int i=width-2; i>=0; i-- ) {
00225 res = vc_iteExpr(vc,
00226 eqExpr(shift, bvConst32(shiftBits,i)),
00227 constructAShrByConstant(expr,
00228 i,
00229 signedBool,
00230 shiftBits),
00231 res);
00232 }
00233
00234 return res;
00235 }
00236
00237 ExprHandle STPBuilder::constructAShrByConstant(ExprHandle expr,
00238 unsigned amount,
00239 ExprHandle isSigned,
00240 unsigned shiftBits) {
00241 unsigned width = vc_getBVLength(vc, expr);
00242 unsigned shift = amount & ((1<<shiftBits) - 1);
00243
00244 if (shift==0) {
00245 return expr;
00246 } else if (shift>=width-1) {
00247 return vc_iteExpr(vc, isSigned, bvMinusOne(width), bvZero(width));
00248 } else {
00249 return vc_iteExpr(vc,
00250 isSigned,
00251 ExprHandle(vc_bvConcatExpr(vc,
00252 bvMinusOne(shift),
00253 bvExtract(expr, width - 1, shift))),
00254 bvRightShift(expr, shift, shiftBits));
00255 }
00256 }
00257
00258 ExprHandle STPBuilder::constructMulByConstant(ExprHandle expr, unsigned width, uint64_t x) {
00259 unsigned shiftBits = getShiftBits(width);
00260 uint64_t add, sub;
00261 ExprHandle res = 0;
00262
00263
00264 ComputeMultConstants64(x, add, sub);
00265
00266
00267 add = bits64::truncateToNBits(add, width);
00268 sub = bits64::truncateToNBits(sub, width);
00269
00270 for (int j=63; j>=0; j--) {
00271 uint64_t bit = 1LL << j;
00272
00273 if ((add&bit) || (sub&bit)) {
00274 assert(!((add&bit) && (sub&bit)) && "invalid mult constants");
00275 ExprHandle op = bvLeftShift(expr, j, shiftBits);
00276
00277 if (add&bit) {
00278 if (res) {
00279 res = vc_bvPlusExpr(vc, width, res, op);
00280 } else {
00281 res = op;
00282 }
00283 } else {
00284 if (res) {
00285 res = vc_bvMinusExpr(vc, width, res, op);
00286 } else {
00287 res = vc_bvUMinusExpr(vc, op);
00288 }
00289 }
00290 }
00291 }
00292
00293 if (!res)
00294 res = bvZero(width);
00295
00296 return res;
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 ExprHandle STPBuilder::constructUDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d) {
00313 assert(width==32 && "can only compute udiv constants for 32-bit division");
00314
00315
00316
00317 uint32_t mprime, sh1, sh2;
00318 ComputeUDivConstants32(d, mprime, sh1, sh2);
00319 ExprHandle expr_sh1 = bvConst32( 32, sh1);
00320 ExprHandle expr_sh2 = bvConst32( 32, sh2);
00321
00322
00323 ExprHandle expr_n_64 = vc_bvConcatExpr( vc, bvZero(32), expr_n );
00324 ExprHandle t1_64bits = constructMulByConstant( expr_n_64, 64, (uint64_t)mprime );
00325 ExprHandle t1 = vc_bvExtract( vc, t1_64bits, 63, 32 );
00326
00327
00328 ExprHandle n_minus_t1 = vc_bvMinusExpr( vc, width, expr_n, t1 );
00329 ExprHandle shift_sh1 = bvVarRightShift( n_minus_t1, expr_sh1, 32 );
00330 ExprHandle plus_t1 = vc_bvPlusExpr( vc, width, shift_sh1, t1 );
00331 ExprHandle res = bvVarRightShift( plus_t1, expr_sh2, 32 );
00332
00333 return res;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 ExprHandle STPBuilder::constructSDivByConstant(ExprHandle expr_n, unsigned width, uint64_t d) {
00350 assert(width==32 && "can only compute udiv constants for 32-bit division");
00351
00352
00353 int32_t mprime, dsign, shpost;
00354 ComputeSDivConstants32(d, mprime, dsign, shpost);
00355 ExprHandle expr_dsign = bvConst32( 32, dsign);
00356 ExprHandle expr_shpost = bvConst32( 32, shpost);
00357
00358
00359 int64_t mprime_64 = (int64_t)mprime;
00360
00361 ExprHandle expr_n_64 = vc_bvSignExtend( vc, expr_n, 64 );
00362 ExprHandle mult_64 = constructMulByConstant( expr_n_64, 64, mprime_64 );
00363 ExprHandle mulsh = vc_bvExtract( vc, mult_64, 63, 32 );
00364 ExprHandle n_plus_mulsh = vc_bvPlusExpr( vc, width, expr_n, mulsh );
00365
00366
00367
00368 ExprHandle extend_npm = vc_bvSignExtend( vc, n_plus_mulsh, 64 );
00369 ExprHandle shift_npm = bvVarRightShift( extend_npm, expr_shpost, 64 );
00370 ExprHandle shift_shpost = vc_bvExtract( vc, shift_npm, 31, 0 );
00371
00372
00373 ExprHandle is_signed = bvBoolExtract( expr_n, 31 );
00374 ExprHandle neg_one = bvMinusOne(32);
00375 ExprHandle xsign_of_n = vc_iteExpr( vc, is_signed, neg_one, bvZero(32) );
00376
00377
00378 ExprHandle q0 = vc_bvMinusExpr( vc, width, shift_shpost, xsign_of_n );
00379
00380
00381 ExprHandle q0_xor_dsign = vc_bvXorExpr( vc, q0, expr_dsign );
00382 ExprHandle res = vc_bvMinusExpr( vc, width, q0_xor_dsign, expr_dsign );
00383
00384 return res;
00385 }
00386
00387 ::VCExpr STPBuilder::getInitialArray(const Array *root) {
00388 if (root->stpInitialArray) {
00389 return root->stpInitialArray;
00390 } else {
00391 char buf[32];
00392 sprintf(buf, "arr%d", root->id);
00393 root->stpInitialArray = buildArray(buf, 32, 8);
00394 return root->stpInitialArray;
00395 }
00396 }
00397
00398 ExprHandle STPBuilder::getInitialRead(const Array *root, unsigned index) {
00399 return vc_readExpr(vc, getInitialArray(root), bvConst32(32, index));
00400 }
00401
00402 ::VCExpr STPBuilder::getArrayForUpdate(const Array *root,
00403 const UpdateNode *un) {
00404 if (!un) {
00405 return getInitialArray(root);
00406 } else {
00407
00408 if (!un->stpArray)
00409 un->stpArray = vc_writeExpr(vc,
00410 getArrayForUpdate(root, un->next),
00411 construct(un->index, 0),
00412 construct(un->value, 0));
00413
00414 return un->stpArray;
00415 }
00416 }
00417
00420 ExprHandle STPBuilder::construct(ref<Expr> e, int *width_out) {
00421 if (!UseConstructHash || isa<ConstantExpr>(e)) {
00422 return constructActual(e, width_out);
00423 } else {
00424 ExprHashMap< std::pair<ExprHandle, unsigned> >::iterator it =
00425 constructed.find(e);
00426 if (it!=constructed.end()) {
00427 if (width_out)
00428 *width_out = it->second.second;
00429 return it->second.first;
00430 } else {
00431 int width;
00432 if (!width_out) width_out = &width;
00433 ExprHandle res = constructActual(e, width_out);
00434 constructed.insert(std::make_pair(e, std::make_pair(res, *width_out)));
00435 return res;
00436 }
00437 }
00438 }
00439
00440
00443 ExprHandle STPBuilder::constructActual(ref<Expr> e, int *width_out) {
00444 int width;
00445 if (!width_out) width_out = &width;
00446
00447 ++stats::queryConstructs;
00448
00449 switch (e->getKind()) {
00450 case Expr::Constant: {
00451 uint64_t asUInt64 = cast<ConstantExpr>(e)->getConstantValue();
00452 *width_out = e->getWidth();
00453
00454 if (*width_out > 64)
00455 assert(0 && "constructActual: width > 64");
00456
00457 if (*width_out == 1)
00458 return asUInt64 ? getTrue() : getFalse();
00459 else if (*width_out <= 32)
00460 return bvConst32(*width_out, asUInt64);
00461 else return bvConst64(*width_out, asUInt64);
00462 }
00463
00464
00465 case Expr::NotOptimized: {
00466 NotOptimizedExpr *noe = cast<NotOptimizedExpr>(e);
00467 return construct(noe->src, width_out);
00468 }
00469
00470 case Expr::Read: {
00471 ReadExpr *re = cast<ReadExpr>(e);
00472 *width_out = 8;
00473 return vc_readExpr(vc,
00474 getArrayForUpdate(re->updates.root, re->updates.head),
00475 construct(re->index, 0));
00476 }
00477
00478 case Expr::Select: {
00479 SelectExpr *se = cast<SelectExpr>(e);
00480 ExprHandle cond = construct(se->cond, 0);
00481 ExprHandle tExpr = construct(se->trueExpr, width_out);
00482 ExprHandle fExpr = construct(se->falseExpr, width_out);
00483 return vc_iteExpr(vc, cond, tExpr, fExpr);
00484 }
00485
00486 case Expr::Concat: {
00487 ConcatExpr *ce = cast<ConcatExpr>(e);
00488 unsigned numKids = ce->getNumKids();
00489 ExprHandle res = construct(ce->getKid(numKids-1), 0);
00490 for (int i=numKids-2; i>=0; i--) {
00491 res = vc_bvConcatExpr(vc, construct(ce->getKid(i), 0), res);
00492 }
00493 *width_out = ce->getWidth();
00494 return res;
00495 }
00496
00497 case Expr::Extract: {
00498 ExtractExpr *ee = cast<ExtractExpr>(e);
00499 ExprHandle src = construct(ee->expr, width_out);
00500 *width_out = ee->getWidth();
00501 if (*width_out==1) {
00502 return bvBoolExtract(src, 0);
00503 } else {
00504 return vc_bvExtract(vc, src, ee->offset + *width_out - 1, ee->offset);
00505 }
00506 }
00507
00508
00509
00510 case Expr::ZExt: {
00511 int srcWidth;
00512 CastExpr *ce = cast<CastExpr>(e);
00513 ExprHandle src = construct(ce->src, &srcWidth);
00514 *width_out = ce->getWidth();
00515 if (srcWidth==1) {
00516 return vc_iteExpr(vc, src, bvOne(*width_out), bvZero(*width_out));
00517 } else {
00518 return vc_bvConcatExpr(vc, bvZero(*width_out-srcWidth), src);
00519 }
00520 }
00521
00522 case Expr::SExt: {
00523 int srcWidth;
00524 CastExpr *ce = cast<CastExpr>(e);
00525 ExprHandle src = construct(ce->src, &srcWidth);
00526 *width_out = ce->getWidth();
00527 if (srcWidth==1) {
00528 return vc_iteExpr(vc, src, bvMinusOne(*width_out), bvZero(*width_out));
00529 } else {
00530 return vc_bvSignExtend(vc, src, *width_out);
00531 }
00532 }
00533
00534
00535
00536 case Expr::Add: {
00537 AddExpr *ae = cast<AddExpr>(e);
00538 ExprHandle left = construct(ae->left, width_out);
00539 ExprHandle right = construct(ae->right, width_out);
00540 assert(*width_out!=1 && "uncanonicalized add");
00541 return vc_bvPlusExpr(vc, *width_out, left, right);
00542 }
00543
00544 case Expr::Sub: {
00545 SubExpr *se = cast<SubExpr>(e);
00546 ExprHandle left = construct(se->left, width_out);
00547 ExprHandle right = construct(se->right, width_out);
00548 assert(*width_out!=1 && "uncanonicalized sub");
00549 return vc_bvMinusExpr(vc, *width_out, left, right);
00550 }
00551
00552 case Expr::Mul: {
00553 MulExpr *me = cast<MulExpr>(e);
00554 ExprHandle right = construct(me->right, width_out);
00555 assert(*width_out!=1 && "uncanonicalized mul");
00556
00557 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(me->left)) {
00558 return constructMulByConstant(right, *width_out,
00559 CE->getConstantValue());
00560 } else {
00561 ExprHandle left = construct(me->left, width_out);
00562 return vc_bvMultExpr(vc, *width_out, left, right);
00563 }
00564 }
00565
00566 case Expr::UDiv: {
00567 UDivExpr *de = cast<UDivExpr>(e);
00568 ExprHandle left = construct(de->left, width_out);
00569 assert(*width_out!=1 && "uncanonicalized udiv");
00570
00571 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
00572 uint64_t divisor = CE->getConstantValue();
00573
00574 if (bits64::isPowerOfTwo(divisor)) {
00575 return bvRightShift(left,
00576 bits64::indexOfSingleBit(divisor),
00577 getShiftBits(*width_out));
00578 } else if (optimizeDivides) {
00579 if (*width_out == 32)
00580 return constructUDivByConstant( left, *width_out, (uint32_t)divisor );
00581 }
00582 }
00583
00584 ExprHandle right = construct(de->right, width_out);
00585 return vc_bvDivExpr(vc, *width_out, left, right);
00586 }
00587
00588 case Expr::SDiv: {
00589 SDivExpr *de = cast<SDivExpr>(e);
00590 ExprHandle left = construct(de->left, width_out);
00591 assert(*width_out!=1 && "uncanonicalized sdiv");
00592
00593 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
00594 uint64_t divisor = CE->getConstantValue();
00595
00596 if (optimizeDivides) {
00597 if (*width_out == 32)
00598 return constructSDivByConstant( left, *width_out, divisor);
00599 }
00600 }
00601
00602
00603
00604 ExprHandle right = construct(de->right, width_out);
00605 return vc_sbvDivExpr(vc, *width_out, left, right);
00606 }
00607
00608 case Expr::URem: {
00609 URemExpr *de = cast<URemExpr>(e);
00610 ExprHandle left = construct(de->left, width_out);
00611 assert(*width_out!=1 && "uncanonicalized urem");
00612
00613 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(de->right)) {
00614 uint64_t divisor = CE->getConstantValue();
00615
00616 if (bits64::isPowerOfTwo(divisor)) {
00617 unsigned bits = bits64::indexOfSingleBit(divisor);
00618
00619
00620 if (bits == 0) {
00621 return bvZero(*width_out);
00622 } else {
00623 return vc_bvConcatExpr(vc,
00624 bvZero(*width_out - bits),
00625 bvExtract(left, bits - 1, 0));
00626 }
00627 }
00628
00629
00630 if (optimizeDivides) {
00631 if (*width_out == 32) {
00632 ExprHandle quotient = constructUDivByConstant( left, *width_out, (uint32_t)divisor );
00633 ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor );
00634 ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor );
00635 return rem;
00636 }
00637 }
00638 }
00639
00640 ExprHandle right = construct(de->right, width_out);
00641 return vc_bvModExpr(vc, *width_out, left, right);
00642 }
00643
00644 case Expr::SRem: {
00645 SRemExpr *de = cast<SRemExpr>(e);
00646 ExprHandle left = construct(de->left, width_out);
00647 ExprHandle right = construct(de->right, width_out);
00648 assert(*width_out!=1 && "uncanonicalized srem");
00649
00650 #if 0 //not faster per first benchmark
00651 if (optimizeDivides) {
00652 if (ConstantExpr *cre = de->right->asConstant()) {
00653 uint64_t divisor = cre->asUInt64;
00654
00655
00656 if( *width_out == 32 ) {
00657 ExprHandle quotient = constructSDivByConstant( left, *width_out, divisor );
00658 ExprHandle quot_times_divisor = constructMulByConstant( quotient, *width_out, divisor );
00659 ExprHandle rem = vc_bvMinusExpr( vc, *width_out, left, quot_times_divisor );
00660 return rem;
00661 }
00662 }
00663 }
00664 #endif
00665
00666
00667 return vc_sbvModExpr(vc, *width_out, left, right);
00668 }
00669
00670
00671
00672 case Expr::And: {
00673 AndExpr *ae = cast<AndExpr>(e);
00674 ExprHandle left = construct(ae->left, width_out);
00675 ExprHandle right = construct(ae->right, width_out);
00676 if (*width_out==1) {
00677 return vc_andExpr(vc, left, right);
00678 } else {
00679 return vc_bvAndExpr(vc, left, right);
00680 }
00681 }
00682 case Expr::Or: {
00683 OrExpr *oe = cast<OrExpr>(e);
00684 ExprHandle left = construct(oe->left, width_out);
00685 ExprHandle right = construct(oe->right, width_out);
00686 if (*width_out==1) {
00687 return vc_orExpr(vc, left, right);
00688 } else {
00689 return vc_bvOrExpr(vc, left, right);
00690 }
00691 }
00692
00693 case Expr::Xor: {
00694 XorExpr *xe = cast<XorExpr>(e);
00695 ExprHandle left = construct(xe->left, width_out);
00696 ExprHandle right = construct(xe->right, width_out);
00697
00698 if (*width_out==1) {
00699
00700 return vc_iteExpr(vc, left,
00701 ExprHandle(vc_notExpr(vc, right)), right);
00702 } else {
00703 return vc_bvXorExpr(vc, left, right);
00704 }
00705 }
00706
00707 case Expr::Shl: {
00708 ShlExpr *se = cast<ShlExpr>(e);
00709 ExprHandle left = construct(se->left, width_out);
00710 assert(*width_out!=1 && "uncanonicalized shl");
00711
00712 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(se->right)) {
00713 return bvLeftShift(left, CE->getConstantValue(),
00714 getShiftBits(*width_out));
00715 } else {
00716 int shiftWidth;
00717 ExprHandle amount = construct(se->right, &shiftWidth);
00718 return bvVarLeftShift( left, amount, *width_out );
00719 }
00720 }
00721
00722 case Expr::LShr: {
00723 LShrExpr *lse = cast<LShrExpr>(e);
00724 ExprHandle left = construct(lse->left, width_out);
00725 unsigned shiftBits = getShiftBits(*width_out);
00726 assert(*width_out!=1 && "uncanonicalized lshr");
00727
00728 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(lse->right)) {
00729 return bvRightShift(left, (unsigned) CE->getConstantValue(),
00730 shiftBits);
00731 } else {
00732 int shiftWidth;
00733 ExprHandle amount = construct(lse->right, &shiftWidth);
00734 return bvVarRightShift( left, amount, *width_out );
00735 }
00736 }
00737
00738 case Expr::AShr: {
00739 AShrExpr *ase = cast<AShrExpr>(e);
00740 ExprHandle left = construct(ase->left, width_out);
00741 assert(*width_out!=1 && "uncanonicalized ashr");
00742
00743 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ase->right)) {
00744 unsigned shift = (unsigned) CE->getConstantValue();
00745 ExprHandle signedBool = bvBoolExtract(left, *width_out-1);
00746 return constructAShrByConstant(left, shift, signedBool,
00747 getShiftBits(*width_out));
00748 } else {
00749 int shiftWidth;
00750 ExprHandle amount = construct(ase->right, &shiftWidth);
00751 return bvVarArithRightShift( left, amount, *width_out );
00752 }
00753 }
00754
00755
00756
00757 case Expr::Eq: {
00758 EqExpr *ee = cast<EqExpr>(e);
00759 ExprHandle left = construct(ee->left, width_out);
00760 ExprHandle right = construct(ee->right, width_out);
00761 if (*width_out==1) {
00762 if (isa<ConstantExpr>(ee->left)) {
00763 assert(!cast<ConstantExpr>(ee->left)->getConstantValue() &&
00764 "uncanonicalized eq");
00765 return vc_notExpr(vc, right);
00766 } else {
00767 return vc_iffExpr(vc, left, right);
00768 }
00769 } else {
00770 *width_out = 1;
00771 return vc_eqExpr(vc, left, right);
00772 }
00773 }
00774
00775 case Expr::Ult: {
00776 UltExpr *ue = cast<UltExpr>(e);
00777 ExprHandle left = construct(ue->left, width_out);
00778 ExprHandle right = construct(ue->right, width_out);
00779 assert(*width_out!=1 && "uncanonicalized ult");
00780 *width_out = 1;
00781 return vc_bvLtExpr(vc, left, right);
00782 }
00783
00784 case Expr::Ule: {
00785 UleExpr *ue = cast<UleExpr>(e);
00786 ExprHandle left = construct(ue->left, width_out);
00787 ExprHandle right = construct(ue->right, width_out);
00788 assert(*width_out!=1 && "uncanonicalized ule");
00789 *width_out = 1;
00790 return vc_bvLeExpr(vc, left, right);
00791 }
00792
00793 case Expr::Slt: {
00794 SltExpr *se = cast<SltExpr>(e);
00795 ExprHandle left = construct(se->left, width_out);
00796 ExprHandle right = construct(se->right, width_out);
00797 assert(*width_out!=1 && "uncanonicalized slt");
00798 *width_out = 1;
00799 return vc_sbvLtExpr(vc, left, right);
00800 }
00801
00802 case Expr::Sle: {
00803 SleExpr *se = cast<SleExpr>(e);
00804 ExprHandle left = construct(se->left, width_out);
00805 ExprHandle right = construct(se->right, width_out);
00806 assert(*width_out!=1 && "uncanonicalized sle");
00807 *width_out = 1;
00808 return vc_sbvLeExpr(vc, left, right);
00809 }
00810
00811
00812 #if 0
00813 case Expr::Ne:
00814 case Expr::Ugt:
00815 case Expr::Uge:
00816 case Expr::Sgt:
00817 case Expr::Sge:
00818 #endif
00819
00820 default:
00821 assert(0 && "unhandled Expr type");
00822 return vc_trueExpr(vc);
00823 }
00824 }