about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-rw-r--r--lib/Core/Searcher.cpp130
-rw-r--r--lib/Core/Searcher.h114
2 files changed, 156 insertions, 88 deletions
diff --git a/lib/Core/Searcher.cpp b/lib/Core/Searcher.cpp
index f8fd2aea..0dffcf2c 100644
--- a/lib/Core/Searcher.cpp
+++ b/lib/Core/Searcher.cpp
@@ -70,6 +70,15 @@ void DFSSearcher::update(ExecutionState *current,
   }
 }
 
+bool DFSSearcher::empty() {
+  return states.empty();
+}
+
+void DFSSearcher::printName(llvm::raw_ostream &os) {
+  os << "DFSSearcher\n";
+}
+
+
 ///
 
 ExecutionState &BFSSearcher::selectState() {
@@ -115,8 +124,19 @@ void BFSSearcher::update(ExecutionState *current,
   }
 }
 
+bool BFSSearcher::empty() {
+  return states.empty();
+}
+
+void BFSSearcher::printName(llvm::raw_ostream &os) {
+  os << "BFSSearcher\n";
+}
+
+
 ///
 
+RandomSearcher::RandomSearcher(RNG &rng) : theRNG{rng} {}
+
 ExecutionState &RandomSearcher::selectState() {
   return *states[theRNG.getInt32() % states.size()];
 }
@@ -144,6 +164,15 @@ void RandomSearcher::update(ExecutionState *current,
   }
 }
 
+bool RandomSearcher::empty() {
+  return states.empty();
+}
+
+void RandomSearcher::printName(llvm::raw_ostream &os) {
+  os << "RandomSearcher\n";
+}
+
+
 ///
 
 WeightedRandomSearcher::WeightedRandomSearcher(WeightType type, RNG &rng)
@@ -236,12 +265,32 @@ bool WeightedRandomSearcher::empty() {
   return states->empty();
 }
 
+void WeightedRandomSearcher::printName(llvm::raw_ostream &os) {
+  os << "WeightedRandomSearcher::";
+  switch(type) {
+    case Depth              : os << "Depth\n"; return;
+    case RP                 : os << "RandomPath\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 << "<unknown type>\n"; return;
+  }
+}
+
+
 ///
 
 // Check if n is a valid pointer and a node belonging to us
 #define IS_OUR_NODE_VALID(n)                                                   \
   (((n).getPointer() != nullptr) && (((n).getInt() & idBitMask) != 0))
 
+RandomPathSearcher::RandomPathSearcher(PTree &processTree, RNG &rng)
+  : processTree{processTree},
+    theRNG{rng},
+    idBitMask{processTree.getNextId()} {};
+
 ExecutionState &RandomPathSearcher::selectState() {
   unsigned flips=0, bits=0;
   assert(processTree.root.getInt() & idBitMask &&
@@ -317,8 +366,29 @@ bool RandomPathSearcher::empty() {
   return !IS_OUR_NODE_VALID(processTree.root);
 }
 
+void RandomPathSearcher::printName(llvm::raw_ostream &os) {
+  os << "RandomPathSearcher\n";
+}
+
+
 ///
 
+MergingSearcher::MergingSearcher(Searcher *baseSearcher)
+  : baseSearcher{baseSearcher} {};
+
+void MergingSearcher::pauseState(ExecutionState &state) {
+  assert(std::find(pausedStates.begin(), pausedStates.end(), &state) == pausedStates.end());
+  pausedStates.push_back(&state);
+  baseSearcher->update(nullptr, {}, {&state});
+}
+
+void MergingSearcher::continueState(ExecutionState &state) {
+  auto it = std::find(pausedStates.begin(), pausedStates.end(), &state);
+  assert(it != pausedStates.end());
+  pausedStates.erase(it);
+  baseSearcher->update(nullptr, {&state}, {});
+}
+
 ExecutionState& MergingSearcher::selectState() {
   assert(!baseSearcher->empty() && "base searcher is empty");
 
@@ -348,8 +418,32 @@ ExecutionState& MergingSearcher::selectState() {
   return baseSearcher->selectState();
 }
 
+void MergingSearcher::update(ExecutionState *current,
+            const std::vector<ExecutionState *> &addedStates,
+            const std::vector<ExecutionState *> &removedStates) {
+  // We have to check if the current execution state was just deleted, as to
+  // not confuse the nurs searchers
+  if (std::find(pausedStates.begin(), pausedStates.end(), current) == pausedStates.end()) {
+    baseSearcher->update(current, addedStates, removedStates);
+  }
+}
+
+bool MergingSearcher::empty() {
+  return baseSearcher->empty();
+}
+
+void MergingSearcher::printName(llvm::raw_ostream &os) {
+  os << "MergingSearcher\n";
+}
+
+
 ///
 
+BatchingSearcher::BatchingSearcher(Searcher *baseSearcher, time::Span timeBudget, unsigned instructionBudget)
+  : baseSearcher{baseSearcher},
+    timeBudget{timeBudget},
+    instructionBudget{instructionBudget} {};
+
 ExecutionState &BatchingSearcher::selectState() {
   if (!lastState ||
       (((timeBudget.toSeconds() > 0) &&
@@ -385,8 +479,24 @@ void BatchingSearcher::update(ExecutionState *current,
   baseSearcher->update(current, addedStates, removedStates);
 }
 
+bool BatchingSearcher::empty() {
+  return baseSearcher->empty();
+}
+
+void BatchingSearcher::printName(llvm::raw_ostream &os) {
+  os << "<BatchingSearcher> timeBudget: " << timeBudget
+     << ", instructionBudget: " << instructionBudget
+     << ", baseSearcher:\n";
+  baseSearcher->printName(os);
+  os << "</BatchingSearcher>\n";
+}
+
+
 ///
 
+IterativeDeepeningTimeSearcher::IterativeDeepeningTimeSearcher(Searcher *baseSearcher)
+  : baseSearcher{baseSearcher} {};
+
 ExecutionState &IterativeDeepeningTimeSearcher::selectState() {
   ExecutionState &res = baseSearcher->selectState();
   startTime = time::getWallTime();
@@ -433,6 +543,15 @@ void IterativeDeepeningTimeSearcher::update(
   }
 }
 
+bool IterativeDeepeningTimeSearcher::empty() {
+  return baseSearcher->empty() && pausedStates.empty();
+}
+
+void IterativeDeepeningTimeSearcher::printName(llvm::raw_ostream &os) {
+  os << "IterativeDeepeningTimeSearcher\n";
+}
+
+
 ///
 
 InterleavedSearcher::InterleavedSearcher(const std::vector<Searcher*> &_searchers) {
@@ -455,3 +574,14 @@ void InterleavedSearcher::update(
   for (auto &searcher : searchers)
     searcher->update(current, addedStates, removedStates);
 }
+
+bool InterleavedSearcher::empty() {
+  return searchers[0]->empty();
+}
+
+void InterleavedSearcher::printName(llvm::raw_ostream &os) {
+  os << "<InterleavedSearcher> containing " << searchers.size() << " searchers:\n";
+  for (const auto &searcher : searchers)
+    searcher->printName(os);
+  os << "</InterleavedSearcher>\n";
+}
diff --git a/lib/Core/Searcher.h b/lib/Core/Searcher.h
index e7f146e0..4eda838d 100644
--- a/lib/Core/Searcher.h
+++ b/lib/Core/Searcher.h
@@ -58,9 +58,7 @@ namespace klee {
 
     /// Prints name of searcher as a `klee_message()`.
     // TODO: could probably made prettier or more flexible
-    virtual void printName(llvm::raw_ostream &os) {
-      os << "<unnamed searcher>\n";
-    }
+    virtual void printName(llvm::raw_ostream &os) = 0;
 
     enum CoreSearchType : std::uint8_t {
       DFS,
@@ -87,10 +85,8 @@ namespace klee {
     void update(ExecutionState *current,
                 const std::vector<ExecutionState *> &addedStates,
                 const std::vector<ExecutionState *> &removedStates) override;
-    bool empty() override { return states.empty(); }
-    void printName(llvm::raw_ostream &os) override {
-      os << "DFSSearcher\n";
-    }
+    bool empty() override;
+    void printName(llvm::raw_ostream &os) override;
   };
 
   /// BFSSearcher implements breadth-first exploration. When KLEE branches multiple
@@ -105,10 +101,8 @@ namespace klee {
     void update(ExecutionState *current,
                 const std::vector<ExecutionState *> &addedStates,
                 const std::vector<ExecutionState *> &removedStates) override;
-    bool empty() override { return states.empty(); }
-    void printName(llvm::raw_ostream &os) override {
-      os << "BFSSearcher\n";
-    }
+    bool empty() override;
+    void printName(llvm::raw_ostream &os) override;
   };
 
   /// RandomSearcher picks a state randomly.
@@ -117,15 +111,13 @@ namespace klee {
     RNG &theRNG;
 
   public:
-    explicit RandomSearcher(RNG &rng) : theRNG{rng} {}
+    explicit RandomSearcher(RNG &rng);
     ExecutionState &selectState() override;
     void update(ExecutionState *current,
                 const std::vector<ExecutionState *> &addedStates,
                 const std::vector<ExecutionState *> &removedStates) override;
-    bool empty() override { return states.empty(); }
-    void printName(llvm::raw_ostream &os) override {
-      os << "RandomSearcher\n";
-    }
+    bool empty() override;
+    void printName(llvm::raw_ostream &os) override;
   };
 
   /// The base class for all weighted searchers. Uses DiscretePDF as underlying
@@ -161,19 +153,7 @@ namespace klee {
                 const std::vector<ExecutionState *> &addedStates,
                 const std::vector<ExecutionState *> &removedStates) override;
     bool empty() override;
-    void printName(llvm::raw_ostream &os) override {
-      os << "WeightedRandomSearcher::";
-      switch(type) {
-      case Depth              : os << "Depth\n"; return;
-      case RP                 : os << "RandomPath\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 << "<unknown type>\n"; return;
-      }
-    }
+    void printName(llvm::raw_ostream &os) override;
   };
 
   /// RandomPathSearcher performs a random walk of the PTree to select a state.
@@ -201,10 +181,7 @@ namespace klee {
   public:
     /// \param processTree The process tree.
     /// \param RNG A random number generator.
-    RandomPathSearcher(PTree &processTree, RNG &rng) :
-                         processTree{processTree},
-                         theRNG{rng},
-                         idBitMask{processTree.getNextId()} {};
+    RandomPathSearcher(PTree &processTree, RNG &rng);
     ~RandomPathSearcher() override = default;
 
     ExecutionState &selectState() override;
@@ -212,9 +189,7 @@ namespace klee {
                 const std::vector<ExecutionState *> &addedStates,
                 const std::vector<ExecutionState *> &removedStates) override;
     bool empty() override;
-    void printName(llvm::raw_ostream &os) override {
-      os << "RandomPathSearcher\n";
-    }
+    void printName(llvm::raw_ostream &os) override;
   };
 
 
@@ -232,7 +207,7 @@ namespace klee {
 
     public:
     /// \param baseSearcher The underlying searcher (takes ownership).
-    explicit MergingSearcher(Searcher *baseSearcher) : baseSearcher{baseSearcher} {};
+    explicit MergingSearcher(Searcher *baseSearcher);
     ~MergingSearcher() override = default;
 
     /// ExecutionStates currently paused from scheduling because they are
@@ -249,37 +224,18 @@ namespace klee {
     /// Remove state from the searcher chain, while keeping it in the executor.
     /// This is used here to 'freeze' a state while it is waiting for other
     /// states in its merge group to reach the same instruction.
-    void pauseState(ExecutionState &state) {
-      assert(std::find(pausedStates.begin(), pausedStates.end(), &state) == pausedStates.end());
-      pausedStates.push_back(&state);
-      baseSearcher->update(nullptr, {}, {&state});
-    }
+    void pauseState(ExecutionState &state);
 
     /// Continue a paused state
-    void continueState(ExecutionState &state) {
-      auto it = std::find(pausedStates.begin(), pausedStates.end(), &state);
-      assert(it != pausedStates.end());
-      pausedStates.erase(it);
-      baseSearcher->update(nullptr, {&state}, {});
-    }
+    void continueState(ExecutionState &state);
 
     ExecutionState &selectState() override;
-
     void update(ExecutionState *current,
                 const std::vector<ExecutionState *> &addedStates,
-                const std::vector<ExecutionState *> &removedStates) override {
-      // We have to check if the current execution state was just deleted, as to
-      // not confuse the nurs searchers
-      if (std::find(pausedStates.begin(), pausedStates.end(), current) ==
-          pausedStates.end()) {
-        baseSearcher->update(current, addedStates, removedStates);
-      }
-    }
-
-    bool empty() override { return baseSearcher->empty(); }
-    void printName(llvm::raw_ostream &os) override {
-      os << "MergingSearcher\n";
-    }
+                const std::vector<ExecutionState *> &removedStates) override;
+
+    bool empty() override;
+    void printName(llvm::raw_ostream &os) override;
   };
 
   /// BatchingSearcher selects a state from an underlying searcher and returns
@@ -298,24 +254,15 @@ namespace klee {
     /// \param baseSearcher The underlying searcher (takes ownership).
     /// \param timeBudget Time span a state gets selected before choosing a different one.
     /// \param instructionBudget Number of instructions to re-select a state for.
-    BatchingSearcher(Searcher *baseSearcher, time::Span timeBudget, unsigned instructionBudget) :
-                       baseSearcher{baseSearcher},
-                       timeBudget{timeBudget},
-                       instructionBudget{instructionBudget} {};
+    BatchingSearcher(Searcher *baseSearcher, time::Span timeBudget, unsigned instructionBudget);
     ~BatchingSearcher() override = default;
 
     ExecutionState &selectState() override;
     void update(ExecutionState *current,
                 const std::vector<ExecutionState *> &addedStates,
                 const std::vector<ExecutionState *> &removedStates) override;
-    bool empty() override { return baseSearcher->empty(); }
-    void printName(llvm::raw_ostream &os) override {
-      os << "<BatchingSearcher> timeBudget: " << timeBudget
-         << ", instructionBudget: " << instructionBudget
-         << ", baseSearcher:\n";
-      baseSearcher->printName(os);
-      os << "</BatchingSearcher>\n";
-    }
+    bool empty() override;
+    void printName(llvm::raw_ostream &os) override;
   };
 
   /// IterativeDeepeningTimeSearcher implements time-based deepening. States
@@ -331,18 +278,15 @@ namespace klee {
 
   public:
     /// \param baseSearcher The underlying searcher (takes ownership).
-    explicit IterativeDeepeningTimeSearcher(Searcher *baseSearcher) :
-                                              baseSearcher{baseSearcher} {};
+    explicit IterativeDeepeningTimeSearcher(Searcher *baseSearcher);
     ~IterativeDeepeningTimeSearcher() override = default;
 
     ExecutionState &selectState() override;
     void update(ExecutionState *current,
                 const std::vector<ExecutionState *> &addedStates,
                 const std::vector<ExecutionState *> &removedStates) override;
-    bool empty() override { return baseSearcher->empty() && pausedStates.empty(); }
-    void printName(llvm::raw_ostream &os) override {
-      os << "IterativeDeepeningTimeSearcher\n";
-    }
+    bool empty() override;
+    void printName(llvm::raw_ostream &os) override;
   };
 
   /// InterleavedSearcher selects states from a set of searchers in round-robin
@@ -361,14 +305,8 @@ namespace klee {
     void update(ExecutionState *current,
                 const std::vector<ExecutionState *> &addedStates,
                 const std::vector<ExecutionState *> &removedStates) override;
-    bool empty() override { return searchers[0]->empty(); }
-    void printName(llvm::raw_ostream &os) override {
-      os << "<InterleavedSearcher> containing "
-         << searchers.size() << " searchers:\n";
-      for (const auto &searcher : searchers)
-        searcher->printName(os);
-      os << "</InterleavedSearcher>\n";
-    }
+    bool empty() override;
+    void printName(llvm::raw_ostream &os) override;
   };
 
 } // klee namespace