STPBuilder.cpp

Go to the documentation of this file.
00001 //===-- STPBuilder.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 "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 // unclear return
00025 #define vc_bvLeftShiftExpr IAMTHESPAWNOFSATAN
00026 #define vc_bvRightShiftExpr IAMTHESPAWNOFSATAN
00027 // bad refcnt'ng
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> // max, min
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 /* Warning: be careful about what c_interface functions you use. Some of
00070    them look like they cons memory but in fact don't, which is bad when
00071    you call vc_DeleteExpr on them. */
00072 
00073 ::VCExpr STPBuilder::buildVar(const char *name, unsigned width) {
00074   // XXX don't rebuild if this stuff cons's
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   // XXX don't rebuild if this stuff cons's
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 // logical right shift
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 // logical left shift
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     // stp shift does "expr @ [0 x s]" which we then have to extract,
00162     // rolling our own gives slightly smaller exprs
00163     return vc_bvConcatExpr(vc, 
00164                            bvExtract(expr, width - shift - 1, 0),
00165                            bvZero(shift));
00166   }
00167 }
00168 
00169 // left shift by a variable amount on an expression of the specified width
00170 ExprHandle STPBuilder::bvVarLeftShift(ExprHandle expr, ExprHandle amount, unsigned width) {
00171   ExprHandle res = bvZero(width);
00172 
00173   int shiftBits = getShiftBits( width );
00174 
00175   //get the shift amount (looking only at the bits appropriate for the given width)
00176   ExprHandle shift = vc_bvExtract( vc, amount, shiftBits - 1, 0 ); 
00177 
00178   //construct a big if-then-elif-elif-... with one case per possible shift amount
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 // logical right shift by a variable amount on an expression of the specified width
00189 ExprHandle STPBuilder::bvVarRightShift(ExprHandle expr, ExprHandle amount, unsigned width) {
00190   ExprHandle res = bvZero(width);
00191 
00192   int shiftBits = getShiftBits( width );
00193 
00194   //get the shift amount (looking only at the bits appropriate for the given width)
00195   ExprHandle shift = vc_bvExtract( vc, amount, shiftBits - 1, 0 ); 
00196 
00197   //construct a big if-then-elif-elif-... with one case per possible shift amount
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 // arithmetic right shift by a variable amount on an expression of the specified width
00209 ExprHandle STPBuilder::bvVarArithRightShift(ExprHandle expr, ExprHandle amount, unsigned width) {
00210   int shiftBits = getShiftBits( width );
00211 
00212   //get the shift amount (looking only at the bits appropriate for the given width)
00213   ExprHandle shift = vc_bvExtract( vc, amount, shiftBits - 1, 0 );
00214 
00215   //get the sign bit to fill with
00216   ExprHandle signedBool = bvBoolExtract(expr, width-1);
00217 
00218   //start with the result if shifting by width-1
00219   ExprHandle res = constructAShrByConstant(expr, width-1, signedBool, shiftBits);
00220 
00221   //construct a big if-then-elif-elif-... with one case per possible shift amount
00222   // XXX more efficient to move the ite on the sign outside all exprs?
00223   // XXX more efficient to sign extend, right shift, then extract lower bits?
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   // expr*x == expr*(add-sub) == expr*add - expr*sub
00264   ComputeMultConstants64(x, add, sub);
00265 
00266   // legal, these would overflow completely
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  * Compute the 32-bit unsigned integer division of n by a divisor d based on 
00301  * the constants derived from the constant divisor d.
00302  *
00303  * Returns n/d without doing explicit division.  The cost is 2 adds, 3 shifts, 
00304  * and a (64-bit) multiply.
00305  *
00306  * @param n      numerator (dividend) as an expression
00307  * @param width  number of bits used to represent the value
00308  * @param d      the divisor
00309  *
00310  * @return n/d without doing explicit division
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   // Compute the constants needed to compute n/d for constant d w/o
00316   // division by d.
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   // t1  = MULUH(mprime, n) = ( (uint64_t)mprime * (uint64_t)n ) >> 32
00323   ExprHandle expr_n_64   = vc_bvConcatExpr( vc, bvZero(32), expr_n ); //extend to 64 bits
00324   ExprHandle t1_64bits   = constructMulByConstant( expr_n_64, 64, (uint64_t)mprime );
00325   ExprHandle t1          = vc_bvExtract( vc, t1_64bits, 63, 32 ); //upper 32 bits
00326 
00327   // n/d = (((n - t1) >> sh1) + t1) >> sh2;
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  * Compute the 32-bitnsigned integer division of n by a divisor d based on 
00338  * the constants derived from the constant divisor d.
00339  *
00340  * Returns n/d without doing explicit division.  The cost is 3 adds, 3 shifts, 
00341  * a (64-bit) multiply, and an XOR.
00342  *
00343  * @param n      numerator (dividend) as an expression
00344  * @param width  number of bits used to represent the value
00345  * @param d      the divisor
00346  *
00347  * @return n/d without doing explicit division
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   // Compute the constants needed to compute n/d for constant d w/o division by d.
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   // q0 = n + MULSH( mprime, n ) = n + (( (int64_t)mprime * (int64_t)n ) >> 32)
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 ); //upper 32-bits
00364   ExprHandle n_plus_mulsh = vc_bvPlusExpr( vc, width, expr_n, mulsh );
00365 
00366   // Improved variable arithmetic right shift: sign extend, shift,
00367   // extract.
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 ); //lower 32-bits
00371 
00372   // XSIGN(n) is -1 if n is negative, positive one otherwise
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   // q0 = (n_plus_mulsh >> shpost) - XSIGN(n)
00378   ExprHandle q0           = vc_bvMinusExpr( vc, width, shift_shpost, xsign_of_n );
00379   
00380   // n/d = (q0 ^ dsign) - dsign
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     // FIXME: This really needs to be non-recursive.
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   // Special
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     // Casting
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     // Arithmetic
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) //only works for 32-bit division
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) //only works for 32-bit division
00598           return constructSDivByConstant( left, *width_out, divisor);
00599       }
00600     } 
00601 
00602     // XXX need to test for proper handling of sign, not sure I
00603     // trust STP
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         // special case for modding by 1 or else we bvExtract -1:0
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       //use fast division to compute modulo without explicit division for constant divisor
00630       if (optimizeDivides) {
00631         if (*width_out == 32) { //only works for 32-bit division
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         //use fast division to compute modulo without explicit division for constant divisor
00656         if( *width_out == 32 ) { //only works for 32-bit division
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     // XXX implement my fast path and test for proper handling of sign
00667     return vc_sbvModExpr(vc, *width_out, left, right);
00668   }
00669 
00670     // Binary
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       // XXX check for most efficient?
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     // Comparison
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     // unused due to canonicalization
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 }

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