Constraints.cpp

Go to the documentation of this file.
00001 //===-- Constraints.cpp ---------------------------------------------------===//
00002 //
00003 //                     The KLEE Symbolic Virtual Machine
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "klee/Constraints.h"
00011 
00012 #include "klee/util/ExprPPrinter.h"
00013 #include "klee/util/ExprVisitor.h"
00014 
00015 #include <iostream>
00016 #include <map>
00017 
00018 using namespace klee;
00019 
00020 class ExprReplaceVisitor : public ExprVisitor {
00021 private:
00022   ref<Expr> src, dst;
00023 
00024 public:
00025   ExprReplaceVisitor(ref<Expr> _src, ref<Expr> _dst) : src(_src), dst(_dst) {}
00026 
00027   Action visitExpr(const Expr &e) {
00028     if (e == *src.get()) {
00029       return Action::changeTo(dst);
00030     } else {
00031       return Action::doChildren();
00032     }
00033   }
00034 
00035   Action visitExprPost(const Expr &e) {
00036     if (e == *src.get()) {
00037       return Action::changeTo(dst);
00038     } else {
00039       return Action::doChildren();
00040     }
00041   }
00042 };
00043 
00044 class ExprReplaceVisitor2 : public ExprVisitor {
00045 private:
00046   const std::map< ref<Expr>, ref<Expr> > &replacements;
00047 
00048 public:
00049   ExprReplaceVisitor2(const std::map< ref<Expr>, ref<Expr> > &_replacements) 
00050     : ExprVisitor(true),
00051       replacements(_replacements) {}
00052 
00053   Action visitExprPost(const Expr &e) {
00054     std::map< ref<Expr>, ref<Expr> >::const_iterator it =
00055       replacements.find(ref<Expr>((Expr*) &e));
00056     if (it!=replacements.end()) {
00057       return Action::changeTo(it->second);
00058     } else {
00059       return Action::doChildren();
00060     }
00061   }
00062 };
00063 
00064 bool ConstraintManager::rewriteConstraints(ExprVisitor &visitor) {
00065   ConstraintManager::constraints_ty old;
00066   bool changed = false;
00067 
00068   constraints.swap(old);
00069   for (ConstraintManager::constraints_ty::iterator 
00070          it = old.begin(), ie = old.end(); it != ie; ++it) {
00071     ref<Expr> &ce = *it;
00072     ref<Expr> e = visitor.visit(ce);
00073 
00074     if (e!=ce) {
00075       addConstraintInternal(e); // enable further reductions
00076       changed = true;
00077     } else {
00078       constraints.push_back(ce);
00079     }
00080   }
00081 
00082   return changed;
00083 }
00084 
00085 void ConstraintManager::simplifyForValidConstraint(ref<Expr> e) {
00086   // XXX 
00087 }
00088 
00089 ref<Expr> ConstraintManager::simplifyExpr(ref<Expr> e) const {
00090   if (isa<ConstantExpr>(e))
00091     return e;
00092 
00093   std::map< ref<Expr>, ref<Expr> > equalities;
00094   
00095   for (ConstraintManager::constraints_ty::const_iterator 
00096          it = constraints.begin(), ie = constraints.end(); it != ie; ++it) {
00097     if (const EqExpr *ee = dyn_cast<EqExpr>(*it)) {
00098       if (isa<ConstantExpr>(ee->left)) {
00099         equalities.insert(std::make_pair(ee->right,
00100                                          ee->left));
00101       } else {
00102         equalities.insert(std::make_pair(*it,
00103                                          ConstantExpr::alloc(1, Expr::Bool)));
00104       }
00105     } else {
00106       equalities.insert(std::make_pair(*it,
00107                                        ConstantExpr::alloc(1, Expr::Bool)));
00108     }
00109   }
00110 
00111   return ExprReplaceVisitor2(equalities).visit(e);
00112 }
00113 
00114 void ConstraintManager::addConstraintInternal(ref<Expr> e) {
00115   // rewrite any known equalities 
00116 
00117   // XXX should profile the effects of this and the overhead.
00118   // traversing the constraints looking for equalities is hardly the
00119   // slowest thing we do, but it is probably nicer to have a
00120   // ConstraintSet ADT which efficiently remembers obvious patterns
00121   // (byte-constant comparison).
00122 
00123   switch (e->getKind()) {
00124   case Expr::Constant:
00125     assert(cast<ConstantExpr>(e)->getConstantValue() && 
00126            "attempt to add invalid (false) constraint");
00127     break;
00128     
00129     // split to enable finer grained independence and other optimizations
00130   case Expr::And: {
00131     BinaryExpr *be = cast<BinaryExpr>(e);
00132     addConstraintInternal(be->left);
00133     addConstraintInternal(be->right);
00134     break;
00135   }
00136 
00137   case Expr::Eq: {
00138     BinaryExpr *be = cast<BinaryExpr>(e);
00139     if (isa<ConstantExpr>(be->left)) {
00140       ExprReplaceVisitor visitor(be->right, be->left);
00141       rewriteConstraints(visitor);
00142     }
00143     constraints.push_back(e);
00144     break;
00145   }
00146     
00147   default:
00148     constraints.push_back(e);
00149     break;
00150   }
00151 }
00152 
00153 void ConstraintManager::addConstraint(ref<Expr> e) {
00154   e = simplifyExpr(e);
00155   addConstraintInternal(e);
00156 }

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