00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "klee/Solver.h"
00011
00012 #include "klee/Expr.h"
00013 #include "klee/Constraints.h"
00014 #include "klee/SolverImpl.h"
00015
00016 #include "klee/util/ExprUtil.h"
00017
00018 #include "llvm/Support/Streams.h"
00019
00020 #include <map>
00021 #include <vector>
00022
00023 using namespace klee;
00024 using namespace llvm;
00025
00026 template<class T>
00027 class DenseSet {
00028 typedef std::set<T> set_ty;
00029 set_ty s;
00030
00031 public:
00032 DenseSet() {}
00033
00034 void add(T x) {
00035 s.insert(x);
00036 }
00037 void add(T start, T end) {
00038 for (; start<end; start++)
00039 s.insert(start);
00040 }
00041
00042
00043 bool add(const DenseSet &b) {
00044 bool modified = false;
00045 for (typename set_ty::const_iterator it = b.s.begin(), ie = b.s.end();
00046 it != ie; ++it) {
00047 if (modified || !s.count(*it)) {
00048 modified = true;
00049 s.insert(*it);
00050 }
00051 }
00052 return modified;
00053 }
00054
00055 bool intersects(const DenseSet &b) {
00056 for (typename set_ty::iterator it = s.begin(), ie = s.end();
00057 it != ie; ++it)
00058 if (b.s.count(*it))
00059 return true;
00060 return false;
00061 }
00062
00063 void print(std::ostream &os) const {
00064 bool first = true;
00065 os << "{";
00066 for (typename set_ty::iterator it = s.begin(), ie = s.end();
00067 it != ie; ++it) {
00068 if (first) {
00069 first = false;
00070 } else {
00071 os << ",";
00072 }
00073 os << *it;
00074 }
00075 os << "}";
00076 }
00077 };
00078
00079 template<class T>
00080 inline std::ostream &operator<<(std::ostream &os, const DenseSet<T> &dis) {
00081 dis.print(os);
00082 return os;
00083 }
00084
00085 class IndependentElementSet {
00086 typedef std::map<const Array*, DenseSet<unsigned> > elements_ty;
00087 elements_ty elements;
00088 std::set<const Array*> wholeObjects;
00089
00090 public:
00091 IndependentElementSet() {}
00092 IndependentElementSet(ref<Expr> e) {
00093 std::vector< ref<ReadExpr> > reads;
00094 findReads(e, true, reads);
00095 for (unsigned i = 0; i != reads.size(); ++i) {
00096 ReadExpr *re = reads[i].get();
00097 if (re->updates.isRooted) {
00098 const Array *array = re->updates.root;
00099 if (!wholeObjects.count(array)) {
00100 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(re->index)) {
00101 DenseSet<unsigned> &dis = elements[array];
00102 dis.add((unsigned) CE->getConstantValue());
00103 } else {
00104 elements_ty::iterator it2 = elements.find(array);
00105 if (it2!=elements.end())
00106 elements.erase(it2);
00107 wholeObjects.insert(array);
00108 }
00109 }
00110 }
00111 }
00112 }
00113 IndependentElementSet(const IndependentElementSet &ies) :
00114 elements(ies.elements),
00115 wholeObjects(ies.wholeObjects) {}
00116
00117 IndependentElementSet &operator=(const IndependentElementSet &ies) {
00118 elements = ies.elements;
00119 wholeObjects = ies.wholeObjects;
00120 return *this;
00121 }
00122
00123 void print(std::ostream &os) const {
00124 os << "{";
00125 bool first = true;
00126 for (std::set<const Array*>::iterator it = wholeObjects.begin(),
00127 ie = wholeObjects.end(); it != ie; ++it) {
00128 const Array *array = *it;
00129
00130 if (first) {
00131 first = false;
00132 } else {
00133 os << ", ";
00134 }
00135
00136 os << "MO" << array->id;
00137 }
00138 for (elements_ty::const_iterator it = elements.begin(), ie = elements.end();
00139 it != ie; ++it) {
00140 const Array *array = it->first;
00141 const DenseSet<unsigned> &dis = it->second;
00142
00143 if (first) {
00144 first = false;
00145 } else {
00146 os << ", ";
00147 }
00148
00149 os << "MO" << array->id << " : " << dis;
00150 }
00151 os << "}";
00152 }
00153
00154
00155 bool intersects(const IndependentElementSet &b) {
00156 for (std::set<const Array*>::iterator it = wholeObjects.begin(),
00157 ie = wholeObjects.end(); it != ie; ++it) {
00158 const Array *array = *it;
00159 if (b.wholeObjects.count(array) ||
00160 b.elements.find(array) != b.elements.end())
00161 return true;
00162 }
00163 for (elements_ty::iterator it = elements.begin(), ie = elements.end();
00164 it != ie; ++it) {
00165 const Array *array = it->first;
00166 if (b.wholeObjects.count(array))
00167 return true;
00168 elements_ty::const_iterator it2 = b.elements.find(array);
00169 if (it2 != b.elements.end()) {
00170 if (it->second.intersects(it2->second))
00171 return true;
00172 }
00173 }
00174 return false;
00175 }
00176
00177
00178 bool add(const IndependentElementSet &b) {
00179 bool modified = false;
00180 for (std::set<const Array*>::const_iterator it = b.wholeObjects.begin(),
00181 ie = b.wholeObjects.end(); it != ie; ++it) {
00182 const Array *array = *it;
00183 elements_ty::iterator it2 = elements.find(array);
00184 if (it2!=elements.end()) {
00185 modified = true;
00186 elements.erase(it2);
00187 wholeObjects.insert(array);
00188 } else {
00189 if (!wholeObjects.count(array)) {
00190 modified = true;
00191 wholeObjects.insert(array);
00192 }
00193 }
00194 }
00195 for (elements_ty::const_iterator it = b.elements.begin(),
00196 ie = b.elements.end(); it != ie; ++it) {
00197 const Array *array = it->first;
00198 if (!wholeObjects.count(array)) {
00199 elements_ty::iterator it2 = elements.find(array);
00200 if (it2==elements.end()) {
00201 modified = true;
00202 elements.insert(*it);
00203 } else {
00204 if (it2->second.add(it->second))
00205 modified = true;
00206 }
00207 }
00208 }
00209 return modified;
00210 }
00211 };
00212
00213 inline std::ostream &operator<<(std::ostream &os, const IndependentElementSet &ies) {
00214 ies.print(os);
00215 return os;
00216 }
00217
00218 static
00219 IndependentElementSet getIndependentConstraints(const Query& query,
00220 std::vector< ref<Expr> > &result) {
00221 IndependentElementSet eltsClosure(query.expr);
00222 std::vector< std::pair<ref<Expr>, IndependentElementSet> > worklist;
00223
00224 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00225 ie = query.constraints.end(); it != ie; ++it)
00226 worklist.push_back(std::make_pair(*it, IndependentElementSet(*it)));
00227
00228
00229 bool done = false;
00230 do {
00231 done = true;
00232 std::vector< std::pair<ref<Expr>, IndependentElementSet> > newWorklist;
00233 for (std::vector< std::pair<ref<Expr>, IndependentElementSet> >::iterator
00234 it = worklist.begin(), ie = worklist.end(); it != ie; ++it) {
00235 if (it->second.intersects(eltsClosure)) {
00236 if (eltsClosure.add(it->second))
00237 done = false;
00238 result.push_back(it->first);
00239 } else {
00240 newWorklist.push_back(*it);
00241 }
00242 }
00243 worklist.swap(newWorklist);
00244 } while (!done);
00245
00246 if (0) {
00247 std::set< ref<Expr> > reqset(result.begin(), result.end());
00248 llvm::cerr << "--\n";
00249 llvm::cerr << "Q: " << query.expr << "\n";
00250 llvm::cerr << "\telts: " << IndependentElementSet(query.expr) << "\n";
00251 int i = 0;
00252 for (ConstraintManager::const_iterator it = query.constraints.begin(),
00253 ie = query.constraints.end(); it != ie; ++it) {
00254 llvm::cerr << "C" << i++ << ": " << *it;
00255 llvm::cerr << " " << (reqset.count(*it) ? "(required)" : "(independent)") << "\n";
00256 llvm::cerr << "\telts: " << IndependentElementSet(*it) << "\n";
00257 }
00258 llvm::cerr << "elts closure: " << eltsClosure << "\n";
00259 }
00260
00261 return eltsClosure;
00262 }
00263
00264 class IndependentSolver : public SolverImpl {
00265 private:
00266 Solver *solver;
00267
00268 public:
00269 IndependentSolver(Solver *_solver)
00270 : solver(_solver) {}
00271 ~IndependentSolver() { delete solver; }
00272
00273 bool computeTruth(const Query&, bool &isValid);
00274 bool computeValidity(const Query&, Solver::Validity &result);
00275 bool computeValue(const Query&, ref<Expr> &result);
00276 bool computeInitialValues(const Query& query,
00277 const std::vector<const Array*> &objects,
00278 std::vector< std::vector<unsigned char> > &values,
00279 bool &hasSolution) {
00280 return solver->impl->computeInitialValues(query, objects, values,
00281 hasSolution);
00282 }
00283 };
00284
00285 bool IndependentSolver::computeValidity(const Query& query,
00286 Solver::Validity &result) {
00287 std::vector< ref<Expr> > required;
00288 IndependentElementSet eltsClosure =
00289 getIndependentConstraints(query, required);
00290 ConstraintManager tmp(required);
00291 return solver->impl->computeValidity(Query(tmp, query.expr),
00292 result);
00293 }
00294
00295 bool IndependentSolver::computeTruth(const Query& query, bool &isValid) {
00296 std::vector< ref<Expr> > required;
00297 IndependentElementSet eltsClosure =
00298 getIndependentConstraints(query, required);
00299 ConstraintManager tmp(required);
00300 return solver->impl->computeTruth(Query(tmp, query.expr),
00301 isValid);
00302 }
00303
00304 bool IndependentSolver::computeValue(const Query& query, ref<Expr> &result) {
00305 std::vector< ref<Expr> > required;
00306 IndependentElementSet eltsClosure =
00307 getIndependentConstraints(query, required);
00308 ConstraintManager tmp(required);
00309 return solver->impl->computeValue(Query(tmp, query.expr), result);
00310 }
00311
00312 Solver *klee::createIndependentSolver(Solver *s) {
00313 return new Solver(new IndependentSolver(s));
00314 }