14 #include "llvm/ADT/PriorityQueue.h" 15 #include "llvm/ADT/DenseSet.h" 16 #include "llvm/ADT/DenseMap.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/Statistic.h" 22 using namespace clang;
25 #define DEBUG_TYPE "WorkList" 27 STATISTIC(MaxQueueSize,
"Maximum size of the worklist");
28 STATISTIC(MaxReachableSize,
"Maximum size of auxiliary worklist set");
36 class DFS :
public WorkList {
40 bool hasWork()
const override {
41 return !Stack.empty();
44 void enqueue(
const WorkListUnit& U)
override {
48 WorkListUnit dequeue()
override {
49 assert(!Stack.empty());
50 const WorkListUnit& U = Stack.back();
56 class BFS :
public WorkList {
57 std::deque<WorkListUnit> Queue;
60 bool hasWork()
const override {
61 return !Queue.empty();
64 void enqueue(
const WorkListUnit& U)
override {
68 WorkListUnit dequeue()
override {
69 WorkListUnit U = Queue.front();
82 return llvm::make_unique<DFS>();
86 return llvm::make_unique<BFS>();
92 std::deque<WorkListUnit> Queue;
96 bool hasWork()
const override {
97 return !Queue.empty() || !Stack.empty();
109 if (!Stack.empty()) {
115 assert(!Queue.empty());
127 return llvm::make_unique<BFSBlockDFSContents>();
132 class UnexploredFirstStack :
public WorkList {
139 using BlockID = unsigned;
140 using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
145 bool hasWork()
const override {
146 return !(StackUnexplored.empty() && StackOthers.empty());
156 StackUnexplored.push_back(U);
158 LocIdentifier LocId = std::make_pair(
159 BE->getBlock()->getBlockID(),
161 auto InsertInfo = Reachable.insert(LocId);
163 if (InsertInfo.second) {
164 StackUnexplored.push_back(U);
166 StackOthers.push_back(U);
169 MaxReachableSize.updateMax(Reachable.size());
170 MaxQueueSize.updateMax(StackUnexplored.size() + StackOthers.size());
174 if (!StackUnexplored.empty()) {
176 StackUnexplored.pop_back();
180 StackOthers.pop_back();
189 return llvm::make_unique<UnexploredFirstStack>();
193 class UnexploredFirstPriorityQueue :
public WorkList {
194 using BlockID = unsigned;
195 using LocIdentifier = std::pair<BlockID, const StackFrameContext *>;
200 using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>;
205 using QueuePriority = std::pair<int, unsigned long>;
206 using QueueItem = std::pair<WorkListUnit, QueuePriority>;
208 struct ExplorationComparator {
209 bool operator() (
const QueueItem &LHS,
const QueueItem &RHS) {
210 return LHS.second < RHS.second;
216 unsigned long Counter = 0;
219 VisitedTimesMap NumReached;
222 llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, ExplorationComparator>
226 bool hasWork()
const override {
227 return !queue.empty();
232 unsigned NumVisited = 0;
234 LocIdentifier LocId = std::make_pair(
235 BE->getBlock()->getBlockID(),
237 NumVisited = NumReached[LocId]++;
240 queue.push(std::make_pair(U, std::make_pair(-NumVisited, ++Counter)));
244 QueueItem U = queue.top();
252 return llvm::make_unique<UnexploredFirstPriorityQueue>();
256 class UnexploredFirstPriorityLocationQueue :
public WorkList {
257 using LocIdentifier =
const CFGBlock *;
262 using VisitedTimesMap = llvm::DenseMap<LocIdentifier, int>;
267 using QueuePriority = std::pair<int, unsigned long>;
268 using QueueItem = std::pair<WorkListUnit, QueuePriority>;
270 struct ExplorationComparator {
271 bool operator() (
const QueueItem &LHS,
const QueueItem &RHS) {
272 return LHS.second < RHS.second;
278 unsigned long Counter = 0;
281 VisitedTimesMap NumReached;
284 llvm::PriorityQueue<QueueItem, std::vector<QueueItem>, ExplorationComparator>
288 bool hasWork()
const override {
289 return !queue.
empty();
294 unsigned NumVisited = 0;
296 NumVisited = NumReached[BE->getBlock()]++;
298 queue.push(std::make_pair(U, std::make_pair(-NumVisited, ++Counter)));
302 QueueItem U = queue.top();
312 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...