diff options
author | George Karpenkov <ekarpenkov@apple.com> | 2018-03-23 00:16:01 +0000 |
---|---|---|
committer | George Karpenkov <ekarpenkov@apple.com> | 2018-03-23 00:16:01 +0000 |
commit | 40b42a3ad825cb252b4e23365aabb72d0adab33f (patch) | |
tree | 6e6d149b31ff6b913c4156d6670635f82e67362b /clang/lib/StaticAnalyzer/Core/CoreEngine.cpp | |
parent | c038b2f4415e14cb7f2980e0f4ec8ea3ba55612c (diff) | |
download | bcm5719-llvm-40b42a3ad825cb252b4e23365aabb72d0adab33f.tar.gz bcm5719-llvm-40b42a3ad825cb252b4e23365aabb72d0adab33f.zip |
[analyzer] [NFC] Move worklist implementation to WorkList.cpp
Current location is very confusing, especially because there is already
WorkList.h, and other code in CoreEngine.cpp is not related to work list
implementation.
Differential Revision: https://reviews.llvm.org/D44759
llvm-svn: 328280
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/CoreEngine.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/CoreEngine.cpp | 230 |
1 files changed, 0 insertions, 230 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index 592f0ba621e..416b8e65dc5 100644 --- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -27,21 +27,15 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" -#include "llvm/ADT/PriorityQueue.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include <algorithm> #include <cassert> -#include <deque> #include <memory> #include <utility> -#include <vector> using namespace clang; using namespace ento; @@ -55,230 +49,6 @@ STATISTIC(NumReachedMaxSteps, STATISTIC(NumPathsExplored, "The # of paths explored by the analyzer."); -STATISTIC(MaxQueueSize, "Maximum size of the worklist"); -STATISTIC(MaxReachableSize, "Maximum size of auxiliary worklist set"); - -//===----------------------------------------------------------------------===// -// Worklist classes for exploration of reachable states. -//===----------------------------------------------------------------------===// - -namespace { - -class DFS : public WorkList { - SmallVector<WorkListUnit, 20> Stack; - -public: - bool hasWork() const override { - return !Stack.empty(); - } - - void enqueue(const WorkListUnit& U) override { - Stack.push_back(U); - } - - WorkListUnit dequeue() override { - assert(!Stack.empty()); - const WorkListUnit& U = Stack.back(); - Stack.pop_back(); // This technically "invalidates" U, but we are fine. - return U; - } -}; - -class BFS : public WorkList { - std::deque<WorkListUnit> Queue; - -public: - bool hasWork() const override { - return !Queue.empty(); - } - - void enqueue(const WorkListUnit& U) override { - Queue.push_back(U); - } - - WorkListUnit dequeue() override { - WorkListUnit U = Queue.front(); - Queue.pop_front(); - return U; - } -}; - -} // namespace - -// Place the dstor for WorkList here because it contains virtual member -// functions, and we the code for the dstor generated in one compilation unit. -WorkList::~WorkList() = default; - -std::unique_ptr<WorkList> WorkList::makeDFS() { - return llvm::make_unique<DFS>(); -} - -std::unique_ptr<WorkList> WorkList::makeBFS() { - return llvm::make_unique<BFS>(); -} - -namespace { - - class BFSBlockDFSContents : public WorkList { - std::deque<WorkListUnit> Queue; - SmallVector<WorkListUnit, 20> Stack; - - public: - bool hasWork() const override { - return !Queue.empty() || !Stack.empty(); - } - - void enqueue(const WorkListUnit& U) override { - if (U.getNode()->getLocation().getAs<BlockEntrance>()) - Queue.push_front(U); - else - Stack.push_back(U); - } - - WorkListUnit dequeue() override { - // Process all basic blocks to completion. - if (!Stack.empty()) { - const WorkListUnit& U = Stack.back(); - Stack.pop_back(); // This technically "invalidates" U, but we are fine. - return U; - } - - assert(!Queue.empty()); - // Don't use const reference. The subsequent pop_back() might make it - // unsafe. - WorkListUnit U = Queue.front(); - Queue.pop_front(); - return U; - } - }; - -} // namespace - -std::unique_ptr<WorkList> WorkList::makeBFSBlockDFSContents() { - return llvm::make_unique<BFSBlockDFSContents>(); -} - -namespace { - -class UnexploredFirstStack : public WorkList { - /// Stack of nodes known to have statements we have not traversed yet. - SmallVector<WorkListUnit, 20> StackUnexplored; - - /// Stack of all other nodes. - SmallVector<WorkListUnit, 20> StackOthers; - - using BlockID = unsigned; - using LocIdentifier = std::pair<BlockID, const StackFrameContext *>; - - llvm::DenseSet<LocIdentifier> Reachable; - -public: - bool hasWork() const override { - return !(StackUnexplored.empty() && StackOthers.empty()); - } - - void enqueue(const WorkListUnit &U) override { - const ExplodedNode *N = U.getNode(); - auto BE = N->getLocation().getAs<BlockEntrance>(); - - if (!BE) { - // Assume the choice of the order of the preceeding block entrance was - // correct. - StackUnexplored.push_back(U); - } else { - LocIdentifier LocId = std::make_pair( - BE->getBlock()->getBlockID(), N->getStackFrame()); - auto InsertInfo = Reachable.insert(LocId); - - if (InsertInfo.second) { - StackUnexplored.push_back(U); - } else { - StackOthers.push_back(U); - } - } - MaxReachableSize.updateMax(Reachable.size()); - MaxQueueSize.updateMax(StackUnexplored.size() + StackOthers.size()); - } - - WorkListUnit dequeue() override { - if (!StackUnexplored.empty()) { - WorkListUnit &U = StackUnexplored.back(); - StackUnexplored.pop_back(); - return U; - } else { - WorkListUnit &U = StackOthers.back(); - StackOthers.pop_back(); - return U; - } - } -}; - -} // namespace - -std::unique_ptr<WorkList> WorkList::makeUnexploredFirst() { - return llvm::make_unique<UnexploredFirstStack>(); -} - -class UnexploredFirstPriorityQueue : public WorkList { - using BlockID = unsigned; - using LocIdentifier = std::pair<BlockID, const StackFrameContext *>; - - // How many times each location was visited. - // Is signed because we negate it later in order to have a reversed - // comparison. - using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>; - - // Compare by number of times the location was visited first (negated - // to prefer less often visited locations), then by insertion time (prefer - // expanding nodes inserted sooner first). - using QueuePriority = std::pair<int, unsigned long>; - using QueueItem = std::pair<WorkListUnit, QueuePriority>; - - struct ExplorationComparator { - bool operator() (const QueueItem &LHS, const QueueItem &RHS) { - return LHS.second < RHS.second; - } - }; - - // Number of inserted nodes, used to emulate DFS ordering in the priority - // queue when insertions are equal. - unsigned long Counter = 0; - - // Number of times a current location was reached. - VisitedTimesMap NumReached; - - // The top item is the largest one. - llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, ExplorationComparator> - queue; - -public: - bool hasWork() const override { - return !queue.empty(); - } - - void enqueue(const WorkListUnit &U) override { - const ExplodedNode *N = U.getNode(); - unsigned NumVisited = 0; - if (auto BE = N->getLocation().getAs<BlockEntrance>()) { - LocIdentifier LocId = std::make_pair( - BE->getBlock()->getBlockID(), N->getStackFrame()); - NumVisited = NumReached[LocId]++; - } - - queue.push(std::make_pair(U, std::make_pair(-NumVisited, ++Counter))); - } - - WorkListUnit dequeue() override { - QueueItem U = queue.top(); - queue.pop(); - return U.first; - } -}; - -std::unique_ptr<WorkList> WorkList::makeUnexploredFirstPriorityQueue() { - return llvm::make_unique<UnexploredFirstPriorityQueue>(); -} - //===----------------------------------------------------------------------===// // Core analysis engine. //===----------------------------------------------------------------------===// |