ExprUtil.cpp

Go to the documentation of this file.
00001 //===-- ExprUtil.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/util/ExprUtil.h"
00011 #include "klee/util/ExprHashMap.h"
00012 
00013 #include "klee/Expr.h"
00014 
00015 #include "klee/util/ExprVisitor.h"
00016 
00017 #include <set>
00018 
00019 using namespace klee;
00020 
00021 void klee::findReads(ref<Expr> e, 
00022                      bool visitUpdates,
00023                      std::vector< ref<ReadExpr> > &results) {
00024   // Invariant: \forall_{i \in stack} !i.isConstant() && i \in visited 
00025   std::vector< ref<Expr> > stack;
00026   ExprHashSet visited;
00027   std::set<const UpdateNode *> updates;
00028   
00029   if (!isa<ConstantExpr>(e)) {
00030     visited.insert(e);
00031     stack.push_back(e);
00032   }
00033 
00034   while (!stack.empty()) {
00035     ref<Expr> top = stack.back();
00036     stack.pop_back();
00037 
00038     if (ReadExpr *re = dyn_cast<ReadExpr>(top)) {
00039       // We memoized so can just add to list without worrying about
00040       // repeats.
00041       results.push_back(re);
00042 
00043       if (!isa<ConstantExpr>(re->index) &&
00044           visited.insert(re->index).second)
00045         stack.push_back(re->index);
00046       
00047       if (visitUpdates) {
00048         // XXX this is probably suboptimal. We want to avoid a potential
00049         // explosion traversing update lists which can be quite
00050         // long. However, it seems silly to hash all of the update nodes
00051         // especially since we memoize all the expr results anyway. So
00052         // we take a simple approach of memoizing the results for the
00053         // head, which often will be shared among multiple nodes.
00054         if (updates.insert(re->updates.head).second) {
00055           for (const UpdateNode *un=re->updates.head; un; un=un->next) {
00056             if (!isa<ConstantExpr>(un->index) &&
00057                 visited.insert(un->index).second)
00058               stack.push_back(un->index);
00059             if (!isa<ConstantExpr>(un->value) &&
00060                 visited.insert(un->value).second)
00061               stack.push_back(un->value);
00062           }
00063         }
00064       }
00065     } else if (!isa<ConstantExpr>(top)) {
00066       Expr *e = top.get();
00067       for (unsigned i=0; i<e->getNumKids(); i++) {
00068         ref<Expr> k = e->getKid(i);
00069         if (!isa<ConstantExpr>(k) &&
00070             visited.insert(k).second)
00071           stack.push_back(k);
00072       }
00073     }
00074   }
00075 }
00076 
00078 
00079 namespace klee {
00080 
00081 class SymbolicObjectFinder : public ExprVisitor {
00082 protected:
00083   Action visitRead(const ReadExpr &re) {
00084     const UpdateList &ul = re.updates;
00085 
00086     // XXX should we memo better than what ExprVisitor is doing for us?
00087     for (const UpdateNode *un=ul.head; un; un=un->next) {
00088       visit(un->index);
00089       visit(un->value);
00090     }
00091 
00092     if (ul.isRooted)
00093       if (results.insert(ul.root).second)
00094         objects.push_back(ul.root);
00095 
00096     return Action::doChildren();
00097   }
00098 
00099 public:
00100   std::set<const Array*> results;
00101   std::vector<const Array*> &objects;
00102   
00103   SymbolicObjectFinder(std::vector<const Array*> &_objects)
00104     : objects(_objects) {}
00105 };
00106 
00107 }
00108 
00109 template<typename InputIterator>
00110 void klee::findSymbolicObjects(InputIterator begin, 
00111                                InputIterator end,
00112                                std::vector<const Array*> &results) {
00113   SymbolicObjectFinder of(results);
00114   for (; begin!=end; ++begin)
00115     of.visit(*begin);
00116 }
00117 
00118 void klee::findSymbolicObjects(ref<Expr> e,
00119                                std::vector<const Array*> &results) {
00120   findSymbolicObjects(&e, &e+1, results);
00121 }
00122 
00123 typedef std::vector< ref<Expr> >::iterator A;
00124 template void klee::findSymbolicObjects<A>(A, A, std::vector<const Array*> &);
00125 
00126 typedef std::set< ref<Expr> >::iterator B;
00127 template void klee::findSymbolicObjects<B>(B, B, std::vector<const Array*> &);

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