//===-- Searcher.h ----------------------------------------------*- C++ -*-===// // // The KLEE Symbolic Virtual Machine // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef KLEE_SEARCHER_H #define KLEE_SEARCHER_H #include "klee/Internal/System/Time.h" #include "llvm/Support/raw_ostream.h" #include #include #include #include namespace llvm { class BasicBlock; class Function; class Instruction; class raw_ostream; } namespace klee { template class DiscretePDF; class ExecutionState; class Executor; class Searcher { public: virtual ~Searcher(); virtual ExecutionState &selectState() = 0; virtual void update(ExecutionState *current, const std::vector &addedStates, const std::vector &removedStates) = 0; virtual bool empty() = 0; // prints name of searcher as a klee_message() // TODO: could probably make prettier or more flexible virtual void printName(llvm::raw_ostream &os) { os << "\n"; } // pgbovine - to be called when a searcher gets activated and // deactivated, say, by a higher-level searcher; most searchers // don't need this functionality, so don't have to override. virtual void activate() {} virtual void deactivate() {} // utility functions void addState(ExecutionState *es, ExecutionState *current = 0) { std::vector tmp; tmp.push_back(es); update(current, tmp, std::vector()); } void removeState(ExecutionState *es, ExecutionState *current = 0) { std::vector tmp; tmp.push_back(es); update(current, std::vector(), tmp); } enum CoreSearchType { DFS, BFS, RandomState, RandomPath, NURS_CovNew, NURS_MD2U, NURS_Depth, NURS_ICnt, NURS_CPICnt, NURS_QC }; }; class DFSSearcher : public Searcher { std::vector states; public: ExecutionState &selectState(); void update(ExecutionState *current, const std::vector &addedStates, const std::vector &removedStates); bool empty() { return states.empty(); } void printName(llvm::raw_ostream &os) { os << "DFSSearcher\n"; } }; class BFSSearcher : public Searcher { std::deque states; public: ExecutionState &selectState(); void update(ExecutionState *current, const std::vector &addedStates, const std::vector &removedStates); bool empty() { return states.empty(); } void printName(llvm::raw_ostream &os) { os << "BFSSearcher\n"; } }; class RandomSearcher : public Searcher { std::vector states; public: ExecutionState &selectState(); void update(ExecutionState *current, const std::vector &addedStates, const std::vector &removedStates); bool empty() { return states.empty(); } void printName(llvm::raw_ostream &os) { os << "RandomSearcher\n"; } }; class WeightedRandomSearcher : public Searcher { public: enum WeightType { Depth, QueryCost, InstCount, CPInstCount, MinDistToUncovered, CoveringNew }; private: DiscretePDF *states; WeightType type; bool updateWeights; double getWeight(ExecutionState*); public: WeightedRandomSearcher(WeightType type); ~WeightedRandomSearcher(); ExecutionState &selectState(); void update(ExecutionState *current, const std::vector &addedStates, const std::vector &removedStates); bool empty(); void printName(llvm::raw_ostream &os) { os << "WeightedRandomSearcher::"; switch(type) { case Depth : os << "Depth\n"; return; case QueryCost : os << "QueryCost\n"; return; case InstCount : os << "InstCount\n"; return; case CPInstCount : os << "CPInstCount\n"; return; case MinDistToUncovered : os << "MinDistToUncovered\n"; return; case CoveringNew : os << "CoveringNew\n"; return; default : os << "\n"; return; } } }; class RandomPathSearcher : public Searcher { Executor &executor; public: RandomPathSearcher(Executor &_executor); ~RandomPathSearcher(); ExecutionState &selectState(); void update(ExecutionState *current, const std::vector &addedStates, const std::vector &removedStates); bool empty(); void printName(llvm::raw_ostream &os) { os << "RandomPathSearcher\n"; } }; class MergeHandler; class MergingSearcher : public Searcher { friend class MergeHandler; private: Executor &executor; Searcher *baseSearcher; public: MergingSearcher(Executor &executor, Searcher *baseSearcher); ~MergingSearcher(); ExecutionState &selectState(); void update(ExecutionState *current, const std::vector &addedStates, const std::vector &removedStates) { baseSearcher->update(current, addedStates, removedStates); } bool empty() { return baseSearcher->empty(); } void printName(llvm::raw_ostream &os) { os << "MergingSearcher\n"; } }; class BatchingSearcher : public Searcher { Searcher *baseSearcher; time::Span timeBudget; unsigned instructionBudget; ExecutionState *lastState; time::Point lastStartTime; unsigned lastStartInstructions; public: BatchingSearcher(Searcher *baseSearcher, time::Span _timeBudget, unsigned _instructionBudget); ~BatchingSearcher(); ExecutionState &selectState(); void update(ExecutionState *current, const std::vector &addedStates, const std::vector &removedStates); bool empty() { return baseSearcher->empty(); } void printName(llvm::raw_ostream &os) { os << " timeBudget: " << timeBudget << ", instructionBudget: " << instructionBudget << ", baseSearcher:\n"; baseSearcher->printName(os); os << "\n"; } }; class IterativeDeepeningTimeSearcher : public Searcher { Searcher *baseSearcher; time::Point startTime; time::Span time; std::set pausedStates; public: IterativeDeepeningTimeSearcher(Searcher *baseSearcher); ~IterativeDeepeningTimeSearcher(); ExecutionState &selectState(); void update(ExecutionState *current, const std::vector &addedStates, const std::vector &removedStates); bool empty() { return baseSearcher->empty() && pausedStates.empty(); } void printName(llvm::raw_ostream &os) { os << "IterativeDeepeningTimeSearcher\n"; } }; class InterleavedSearcher : public Searcher { typedef std::vector searchers_ty; searchers_ty searchers; unsigned index; public: explicit InterleavedSearcher(const searchers_ty &_searchers); ~InterleavedSearcher(); ExecutionState &selectState(); void update(ExecutionState *current, const std::vector &addedStates, const std::vector &removedStates); bool empty() { return searchers[0]->empty(); } void printName(llvm::raw_ostream &os) { os << " containing " << searchers.size() << " searchers:\n"; for (searchers_ty::iterator it = searchers.begin(), ie = searchers.end(); it != ie; ++it) (*it)->printName(os); os << "\n"; } }; } #endif