15 #include "llvm/ADT/PriorityQueue.h" 16 #include "llvm/ADT/DenseSet.h" 17 #include "llvm/ADT/DenseMap.h" 18 #include "llvm/ADT/STLExtras.h" 19 #include "llvm/ADT/Statistic.h" 23 using namespace clang;
26 #define DEBUG_TYPE "WorkList" 28 STATISTIC(MaxQueueSize,
"Maximum size of the worklist");
29 STATISTIC(MaxReachableSize,
"Maximum size of auxiliary worklist set");
37 class DFS :
public WorkList {
41 bool hasWork()
const override {
42 return !Stack.empty();
45 void enqueue(
const WorkListUnit& U)
override {
49 WorkListUnit dequeue()
override {
50 assert(!Stack.empty());
51 const WorkListUnit& U = Stack.back();
57 class BFS :
public WorkList {
58 std::deque<WorkListUnit> Queue;
61 bool hasWork()
const override {
62 return !Queue.empty();
65 void enqueue(
const WorkListUnit& U)
override {
69 WorkListUnit dequeue()
override {
70 WorkListUnit U = Queue.front();
83 return llvm::make_unique<DFS>();
87 return llvm::make_unique<BFS>();
93 std::deque<WorkListUnit> Queue;
97 bool hasWork()
const override {
98 return !Queue.empty() || !Stack.empty();
110 if (!Stack.empty()) {
116 assert(!Queue.empty());
128 return llvm::make_unique<BFSBlockDFSContents>();
133 class UnexploredFirstStack :
public WorkList {
140 using BlockID = unsigned;
141 using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
146 bool hasWork()
const override {
147 return !(StackUnexplored.empty() && StackOthers.empty());
157 StackUnexplored.push_back(U);
159 LocIdentifier LocId = std::make_pair(
160 BE->getBlock()->getBlockID(),
162 auto InsertInfo = Reachable.insert(LocId);
164 if (InsertInfo.second) {
165 StackUnexplored.push_back(U);
167 StackOthers.push_back(U);
170 MaxReachableSize.updateMax(Reachable.size());
171 MaxQueueSize.updateMax(StackUnexplored.size() + StackOthers.size());
175 if (!StackUnexplored.empty()) {
177 StackUnexplored.pop_back();
181 StackOthers.pop_back();
190 return llvm::make_unique<UnexploredFirstStack>();
194 class UnexploredFirstPriorityQueue :
public WorkList {
195 using BlockID = unsigned;
196 using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
201 using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>;
206 using QueuePriority = std::pair<int, unsigned long>;
207 using QueueItem = std::pair<WorkListUnit, QueuePriority>;
209 struct ExplorationComparator {
210 bool operator() (
const QueueItem &LHS,
const QueueItem &RHS) {
211 return LHS.second < RHS.second;
217 unsigned long Counter = 0;
220 VisitedTimesMap NumReached;
223 llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, ExplorationComparator>
227 bool hasWork()
const override {
228 return !queue.empty();
233 unsigned NumVisited = 0;
235 LocIdentifier LocId = std::make_pair(
236 BE->getBlock()->getBlockID(),
238 NumVisited = NumReached[LocId]++;
241 queue.push(std::make_pair(U, std::make_pair(-NumVisited, ++Counter)));
245 QueueItem U = queue.top();
253 return llvm::make_unique<UnexploredFirstPriorityQueue>();
257 class UnexploredFirstPriorityLocationQueue :
public WorkList {
258 using LocIdentifier =
const CFGBlock *;
263 using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>;
268 using QueuePriority = std::pair<int, unsigned long>;
269 using QueueItem = std::pair<WorkListUnit, QueuePriority>;
271 struct ExplorationComparator {
272 bool operator() (
const QueueItem &LHS,
const QueueItem &RHS) {
273 return LHS.second < RHS.second;
279 unsigned long Counter = 0;
282 VisitedTimesMap NumReached;
285 llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, ExplorationComparator>
289 bool hasWork()
const override {
290 return !queue.
empty();
295 unsigned NumVisited = 0;
297 NumVisited = NumReached[BE->getBlock()]++;
299 queue.push(std::make_pair(U, std::make_pair(-NumVisited, ++Counter)));
303 QueueItem U = queue.top();
313 return llvm::make_unique<UnexploredFirstPriorityLocationQueue>();
static std::unique_ptr< WorkList > makeUnexploredFirstPriorityQueue()
static std::unique_ptr< WorkList > makeDFS()
const LocationContext * getLocationContext() const
static std::unique_ptr< WorkList > makeBFS()
Represents a single basic block in a source-level CFG.
STATISTIC(MaxQueueSize, "Maximum size of the worklist")
ExplodedNode * getNode() const
Returns the node associated with the worklist unit.
static std::unique_ptr< WorkList > makeUnexploredFirstPriorityLocationQueue()
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
static std::unique_ptr< WorkList > makeBFSBlockDFSContents()
Dataflow Directional Tag Classes.
const StackFrameContext * getStackFrame() const
static std::unique_ptr< WorkList > makeUnexploredFirst()
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...