ImpliedValue.cpp

Go to the documentation of this file.
00001 //===-- ImpliedValue.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 "ImpliedValue.h"
00011 
00012 #include "klee/Constraints.h"
00013 #include "klee/Expr.h"
00014 #include "klee/Solver.h"
00015 // FIXME: Use APInt.
00016 #include "klee/Internal/Support/IntEvaluation.h"
00017 
00018 #include "klee/util/ExprUtil.h"
00019 
00020 #include <iostream>
00021 #include <map>
00022 #include <set>
00023 
00024 using namespace klee;
00025 
00026 // XXX we really want to do some sort of canonicalization of exprs
00027 // globally so that cases below become simpler
00028 static void _getImpliedValue(ref<Expr> e,
00029                              uint64_t value,
00030                              ImpliedValueList &results) {
00031   switch (e->getKind()) {
00032   case Expr::Constant: {
00033     assert(value == cast<ConstantExpr>(e)->getConstantValue() && 
00034            "error in implied value calculation");
00035     break;
00036   }
00037 
00038     // Special
00039 
00040   case Expr::NotOptimized: break;
00041 
00042   case Expr::Read: {
00043     // XXX in theory it is possible to descend into a symbolic index
00044     // under certain circumstances (all values known, known value
00045     // unique, or range known, max / min hit). Seems unlikely this
00046     // would work often enough to be worth the effort.
00047     ReadExpr *re = cast<ReadExpr>(e);
00048     results.push_back(std::make_pair(re, 
00049                                      ConstantExpr::create(value, e->getWidth())));
00050     break;
00051   }
00052     
00053   case Expr::Select: {
00054     // not much to do, could improve with range analysis
00055     SelectExpr *se = cast<SelectExpr>(e);
00056     
00057     if (ConstantExpr *TrueCE = dyn_cast<ConstantExpr>(se->trueExpr)) {
00058       if (ConstantExpr *FalseCE = dyn_cast<ConstantExpr>(se->falseExpr)) {
00059         if (TrueCE->getConstantValue() != FalseCE->getConstantValue()) {
00060           if (value == TrueCE->getConstantValue()) {
00061             _getImpliedValue(se->cond, 1, results);
00062           } else {
00063             assert(value == FalseCE->getConstantValue() &&
00064                    "err in implied value calculation");
00065             _getImpliedValue(se->cond, 0, results);
00066           }
00067         }
00068       }
00069     }
00070     break;
00071   }
00072 
00073   case Expr::Concat: {
00074     ConcatExpr *ce = cast<ConcatExpr>(e);
00075     _getImpliedValue(ce->getKid(0), (value >> ce->getKid(1)->getWidth()) & ((1 << ce->getKid(0)->getWidth()) - 1), results);
00076     _getImpliedValue(ce->getKid(1), value & ((1 << ce->getKid(1)->getWidth()) - 1), results);
00077     break;
00078   }
00079     
00080   case Expr::Extract: {
00081     // XXX, could do more here with "some bits" mask
00082     break;
00083   }
00084 
00085     // Casting
00086 
00087   case Expr::ZExt: 
00088   case Expr::SExt: {
00089     CastExpr *ce = cast<CastExpr>(e);
00090     _getImpliedValue(ce->src, 
00091                      bits64::truncateToNBits(value, 
00092                                              ce->src->getWidth()),
00093                      results);
00094     break;
00095   }
00096 
00097     // Arithmetic
00098 
00099   case Expr::Add: { // constants on left
00100     BinaryExpr *be = cast<BinaryExpr>(e);
00101     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(be->left)) {
00102       uint64_t nvalue = ints::sub(value,
00103                                   CE->getConstantValue(),
00104                                   CE->getWidth());
00105       _getImpliedValue(be->right, nvalue, results);
00106     }
00107     break;
00108   }
00109   case Expr::Sub: { // constants on left
00110     BinaryExpr *be = cast<BinaryExpr>(e);
00111     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(be->left)) {
00112       uint64_t nvalue = ints::sub(CE->getConstantValue(),
00113                                   value,
00114                                   CE->getWidth());
00115       _getImpliedValue(be->right, nvalue, results);
00116     }
00117     break;
00118   }
00119   case Expr::Mul: {
00120     // XXX can do stuff here, but need valid mask and other things
00121     // because of bits that might be lost
00122     break;
00123   }
00124 
00125   case Expr::UDiv:
00126   case Expr::SDiv:
00127   case Expr::URem:
00128   case Expr::SRem:
00129     // no, no, no
00130     break;
00131 
00132     // Binary
00133 
00134   case Expr::And: {
00135     BinaryExpr *be = cast<BinaryExpr>(e);
00136     if (be->getWidth() == Expr::Bool) {
00137       if (value) {
00138         _getImpliedValue(be->left, value, results);
00139         _getImpliedValue(be->right, value, results);
00140       }
00141     } else {
00142       // XXX, we can basically propogate a mask here
00143       // where we know "some bits". may or may not be
00144       // useful.
00145     }
00146     break;
00147   }
00148   case Expr::Or: {
00149     BinaryExpr *be = cast<BinaryExpr>(e);
00150     if (!value) {
00151       _getImpliedValue(be->left, 0, results);
00152       _getImpliedValue(be->right, 0, results);
00153     } else {
00154       // XXX, can do more?
00155     }
00156     break;
00157   }
00158   case Expr::Xor: { // constants on left
00159     BinaryExpr *be = cast<BinaryExpr>(e);
00160     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(be->left)) {
00161       _getImpliedValue(be->right, value ^ CE->getConstantValue(), results);
00162     }
00163     break;
00164   }
00165 
00166     // Comparison
00167   case Expr::Ne: 
00168     value = !value;
00169     /* fallthru */
00170   case Expr::Eq: {
00171     EqExpr *ee = cast<EqExpr>(e);
00172     if (value) {
00173       if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left))
00174         _getImpliedValue(ee->right, CE->getConstantValue(), results);
00175     } else {
00176       // look for limited value range, woohoo
00177       //
00178       // in general anytime one side was restricted to two values we
00179       // can apply this trick. the only obvious case where this
00180       // occurs, aside from booleans, is as the result of a select
00181       // expression where the true and false branches are single
00182       // valued and distinct.
00183       
00184       if (ConstantExpr *CE = dyn_cast<ConstantExpr>(ee->left)) {
00185         if (CE->getWidth() == Expr::Bool) {
00186           _getImpliedValue(ee->right, !CE->getConstantValue(), results);
00187         }
00188       }
00189     }
00190     break;
00191   }
00192     
00193   default:
00194     break;
00195   }
00196 }
00197     
00198 void ImpliedValue::getImpliedValues(ref<Expr> e, 
00199                                     ref<ConstantExpr> value, 
00200                                     ImpliedValueList &results) {
00201   _getImpliedValue(e, value->getConstantValue(), results);
00202 }
00203 
00204 void ImpliedValue::checkForImpliedValues(Solver *S, ref<Expr> e, 
00205                                          ref<ConstantExpr> value) {
00206   std::vector<ref<ReadExpr> > reads;
00207   std::map<ref<ReadExpr>, ref<ConstantExpr> > found;
00208   ImpliedValueList results;
00209 
00210   getImpliedValues(e, value, results);
00211 
00212   for (ImpliedValueList::iterator i = results.begin(), ie = results.end();
00213        i != ie; ++i) {
00214     std::map<ref<ReadExpr>, ref<ConstantExpr> >::iterator it = 
00215       found.find(i->first);
00216     if (it != found.end()) {
00217       assert(it->second->getConstantValue() == i->second->getConstantValue() &&
00218              "I don't think so Scott");
00219     } else {
00220       found.insert(std::make_pair(i->first, i->second));
00221     }
00222   }
00223 
00224   findReads(e, false, reads);
00225   std::set< ref<ReadExpr> > readsSet(reads.begin(), reads.end());
00226   reads = std::vector< ref<ReadExpr> >(readsSet.begin(), readsSet.end());
00227 
00228   std::vector<ref<Expr> > assumption;
00229   assumption.push_back(EqExpr::create(e, value));
00230 
00231   // obscure... we need to make sure that all the read indices are
00232   // bounds checked. if we don't do this we can end up constructing
00233   // invalid counterexamples because STP will happily make out of
00234   // bounds indices which will not get picked up. this is of utmost
00235   // importance if we are being backed by the CexCachingSolver.
00236 
00237   for (std::vector< ref<ReadExpr> >::iterator i = reads.begin(), 
00238          ie = reads.end(); i != ie; ++i) {
00239     ReadExpr *re = i->get();
00240     assumption.push_back(UltExpr::create(re->index, 
00241                                          ConstantExpr::alloc(re->updates.root->size, 
00242                                                              kMachinePointerType)));
00243   }
00244 
00245   ConstraintManager assume(assumption);
00246   for (std::vector< ref<ReadExpr> >::iterator i = reads.begin(), 
00247          ie = reads.end(); i != ie; ++i) {
00248     ref<ReadExpr> var = *i;
00249     ref<ConstantExpr> possible;
00250     bool success = S->getValue(Query(assume, var), possible);
00251     assert(success && "FIXME: Unhandled solver failure");    
00252     std::map<ref<ReadExpr>, ref<ConstantExpr> >::iterator it = found.find(var);
00253     bool res;
00254     success = S->mustBeTrue(Query(assume, EqExpr::create(var, possible)), res);
00255     assert(success && "FIXME: Unhandled solver failure");    
00256     if (res) {
00257       if (it != found.end()) {
00258         assert(possible->getConstantValue() == it->second->getConstantValue());
00259         found.erase(it);
00260       }
00261     } else {
00262       if (it!=found.end()) {
00263         ref<Expr> binding = it->second;
00264         llvm::cerr << "checkForImpliedValues: " << e  << " = " << value << "\n"
00265                    << "\t\t implies " << var << " == " << binding
00266                    << " (error)\n";
00267         assert(0);
00268       }
00269     }
00270   }
00271 
00272   assert(found.empty());
00273 }

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