blob: 4e7370fac1340f632b0fdcb42db71ac8a0e469c7 [file] [log] [blame]
Ted Kremenek7f49f502007-09-14 22:49:21 +00001//===--- DataflowSolver.h - Skeleton Dataflow Analysis Code -----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Ted Kremenek and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines skeleton code for implementing dataflow analyses.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER
15#define LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER
16
17#include "clang/AST/CFG.h"
18#include "llvm/ADT/SmallPtrSet.h"
Ted Kremenek5b3036e2007-09-18 23:40:51 +000019#include "functional" // STL
Ted Kremenek7f49f502007-09-14 22:49:21 +000020
21namespace clang {
22
23//===----------------------------------------------------------------------===//
24/// DataflowWorkListTy - Data structure representing the worklist used for
25/// dataflow algorithms.
26
27class DataflowWorkListTy {
28 typedef llvm::SmallPtrSet<const CFGBlock*,20> BlockSet;
29 BlockSet wlist;
30public:
31 /// enqueue - Add a block to the worklist. Blocks already on the worklist
32 /// are not added a second time.
33 void enqueue(const CFGBlock* B) { wlist.insert(B); }
34
35 /// dequeue - Remove a block from the worklist.
36 const CFGBlock* dequeue() {
37 assert (!wlist.empty());
38 const CFGBlock* B = *wlist.begin();
39 wlist.erase(B);
40 return B;
41 }
42
43 /// isEmpty - Return true if the worklist is empty.
44 bool isEmpty() const { return wlist.empty(); }
45};
46
47//===----------------------------------------------------------------------===//
48/// DataflowSolverTy - Generic dataflow solver.
49template <typename _DFValuesTy, // Usually a subclass of DataflowValues
50 typename _TransferFuncsTy,
Ted Kremenek5b3036e2007-09-18 23:40:51 +000051 typename _MergeOperatorTy,
52 typename _Equal = std::equal_to<typename _DFValuesTy::ValTy> >
Ted Kremenek7f49f502007-09-14 22:49:21 +000053class DataflowSolver {
54
55 //===--------------------------------------------------------------------===//
56 // Type declarations.
57 //===--------------------------------------------------------------------===//
58
59public:
60 typedef _DFValuesTy DFValuesTy;
61 typedef _TransferFuncsTy TransferFuncsTy;
62 typedef _MergeOperatorTy MergeOperatorTy;
63
64 typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag;
65 typedef typename _DFValuesTy::ValTy ValTy;
Ted Kremenek2e3e6302007-09-18 18:02:44 +000066 typedef typename _DFValuesTy::EdgeDataMapTy EdgeDataMapTy;
Ted Kremenek7f49f502007-09-14 22:49:21 +000067
68 //===--------------------------------------------------------------------===//
69 // External interface: constructing and running the solver.
70 //===--------------------------------------------------------------------===//
71
72public:
Ted Kremenek2a203562007-09-18 18:17:19 +000073 DataflowSolver(DFValuesTy& d) : D(d), TF(d.getAnalysisData()) {}
Ted Kremenek7f49f502007-09-14 22:49:21 +000074 ~DataflowSolver() {}
75
76 /// runOnCFG - Computes dataflow values for all blocks in a CFG.
77 void runOnCFG(const CFG& cfg) {
78 // Set initial dataflow values and boundary conditions.
79 D.InitializeValues(cfg);
Ted Kremenek2e3e6302007-09-18 18:02:44 +000080 // Solve the dataflow equations. This will populate D.EdgeDataMap
81 // with dataflow values.
82 SolveDataflowEquations(cfg);
Ted Kremenek7f49f502007-09-14 22:49:21 +000083 }
84
85 /// runOnBlock - Computes dataflow values for a given block.
86 /// This should usually be invoked only after previously computing
87 /// dataflow values using runOnCFG, as runOnBlock is intended to
88 /// only be used for querying the dataflow values within a block with
89 /// and Observer object.
90 void runOnBlock(const CFGBlock* B) {
Ted Kremenek2a203562007-09-18 18:17:19 +000091 if (hasData(B,AnalysisDirTag()))
92 ProcessBlock(B,AnalysisDirTag());
Ted Kremenek7f49f502007-09-14 22:49:21 +000093 }
94
Ted Kremenek3fa5e092007-09-18 21:08:21 +000095 void runOnBlock(const CFGBlock& B) { runOnBlock(&B); }
96 void runOnBlock(CFG::iterator &I) { runOnBlock(*I); }
97 void runOnBlock(CFG::const_iterator &I) { runOnBlock(*I); }
98
99 void runOnAllBlocks(const CFG& cfg) {
100 for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
101 runOnBlock(I);
102 }
103
Ted Kremenek7f49f502007-09-14 22:49:21 +0000104 //===--------------------------------------------------------------------===//
105 // Internal solver logic.
106 //===--------------------------------------------------------------------===//
107
108private:
109
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000110 /// SolveDataflowEquations - Perform the actual
Ted Kremenek7f49f502007-09-14 22:49:21 +0000111 /// worklist algorithm to compute dataflow values.
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000112 void SolveDataflowEquations(const CFG& cfg) {
113
114 EnqueueFirstBlock(cfg,AnalysisDirTag());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000115
Ted Kremenek7f49f502007-09-14 22:49:21 +0000116 // Process the worklist until it is empty.
117 while (!WorkList.isEmpty()) {
118 const CFGBlock* B = WorkList.dequeue();
119 // If the dataflow values at the block's entry have changed,
120 // enqueue all predecessor blocks onto the worklist to have
121 // their values updated.
Ted Kremenek2a203562007-09-18 18:17:19 +0000122 ProcessBlock(B,AnalysisDirTag());
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000123 UpdateEdges(B,TF.getVal(),AnalysisDirTag());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000124 }
125 }
126
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000127 void EnqueueFirstBlock(const CFG& cfg, dataflow::forward_analysis_tag) {
128 WorkList.enqueue(&cfg.getEntry());
129 }
130
131 void EnqueueFirstBlock(const CFG& cfg, dataflow::backward_analysis_tag) {
132 WorkList.enqueue(&cfg.getExit());
133 }
134
Ted Kremenek7f49f502007-09-14 22:49:21 +0000135 /// ProcessBlock (FORWARD ANALYSIS) - Process the transfer functions
136 /// for a given block based on a forward analysis.
Ted Kremenek2a203562007-09-18 18:17:19 +0000137 void ProcessBlock(const CFGBlock* B, dataflow::forward_analysis_tag) {
138
Ted Kremenek7f49f502007-09-14 22:49:21 +0000139 // Merge dataflow values from all predecessors of this block.
Ted Kremenek2a203562007-09-18 18:17:19 +0000140 ValTy& V = TF.getVal();
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000141 V.resetValues(D.getAnalysisData());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000142 MergeOperatorTy Merge;
143
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000144 EdgeDataMapTy& M = D.getEdgeDataMap();
Ted Kremeneke6148f32007-09-17 21:59:08 +0000145 bool firstMerge = true;
146
Ted Kremenek7f49f502007-09-14 22:49:21 +0000147 for (CFGBlock::const_pred_iterator I=B->pred_begin(),
Ted Kremeneke6148f32007-09-17 21:59:08 +0000148 E=B->pred_end(); I!=E; ++I) {
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000149 typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(*I,B));
Ted Kremeneke6148f32007-09-17 21:59:08 +0000150 if (BI != M.end()) {
151 if (firstMerge) {
152 firstMerge = false;
153 V.copyValues(BI->second);
154 }
155 else
156 Merge(V,BI->second);
157 }
158 }
Ted Kremenek7f49f502007-09-14 22:49:21 +0000159
160 // Process the statements in the block in the forward direction.
161 for (CFGBlock::const_iterator I=B->begin(), E=B->end(); I!=E; ++I)
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000162 TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
Ted Kremenek7f49f502007-09-14 22:49:21 +0000163 }
164
165 /// ProcessBlock (BACKWARD ANALYSIS) - Process the transfer functions
166 /// for a given block based on a forward analysis.
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000167 void ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
Ted Kremenek7f49f502007-09-14 22:49:21 +0000168 dataflow::backward_analysis_tag) {
Ted Kremenek2a203562007-09-18 18:17:19 +0000169
Ted Kremenek7f49f502007-09-14 22:49:21 +0000170 // Merge dataflow values from all predecessors of this block.
Ted Kremenek2a203562007-09-18 18:17:19 +0000171 ValTy& V = TF.getVal();
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000172 V.resetValues(D.getAnalysisData());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000173 MergeOperatorTy Merge;
174
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000175 EdgeDataMapTy& M = D.getEdgeDataMap();
Ted Kremeneke6148f32007-09-17 21:59:08 +0000176 bool firstMerge = true;
177
Ted Kremenek7f49f502007-09-14 22:49:21 +0000178 for (CFGBlock::const_succ_iterator I=B->succ_begin(),
Ted Kremeneke6148f32007-09-17 21:59:08 +0000179 E=B->succ_end(); I!=E; ++I) {
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000180 typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(B,*I));
Ted Kremeneke6148f32007-09-17 21:59:08 +0000181 if (BI != M.end()) {
182 if (firstMerge) {
183 firstMerge = false;
184 V.copyValues(BI->second);
185 }
186 else
187 Merge(V,BI->second);
188 }
189 }
Ted Kremenek7f49f502007-09-14 22:49:21 +0000190
191 // Process the statements in the block in the forward direction.
192 for (CFGBlock::const_reverse_iterator I=B->begin(), E=B->end(); I!=E; ++I)
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000193 TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
194 }
195
196 /// UpdateEdges (FORWARD ANALYSIS) - After processing the transfer
197 /// functions for a block, update the dataflow value associated with the
198 /// block's outgoing edges. Enqueue any successor blocks for an
199 /// outgoing edge whose value has changed.
200 void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::forward_analysis_tag) {
201 for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
202 I!=E; ++I) {
203
Hartmut Kaiser2b606872007-09-20 13:35:09 +0000204 CFG::Edge Edg(B,*I);
205 UpdateEdgeValue(Edg,V,*I);
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000206 }
Ted Kremenek7f49f502007-09-14 22:49:21 +0000207 }
208
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000209 /// UpdateEdges (BACKWARD ANALYSIS) - After processing the transfer
210 /// functions for a block, update the dataflow value associated with the
211 /// block's incoming edges. Enqueue any predecessor blocks for an
212 /// outgoing edge whose value has changed.
213 void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::backward_analysis_tag){
214 for (CFGBlock::const_pred_iterator I=B->succ_begin(), E=B->succ_end();
215 I!=E; ++I) {
216
Hartmut Kaiser2b606872007-09-20 13:35:09 +0000217 CFG::Edge Edg(*I,B);
218 UpdateEdgeValue(Edg,V,*I);
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000219 }
220 }
221
222 /// UpdateEdgeValue - Update the value associated with a given edge.
223 void UpdateEdgeValue(CFG::Edge& E, ValTy& V, const CFGBlock* TargetBlock) {
224
225 EdgeDataMapTy& M = D.getEdgeDataMap();
226 typename EdgeDataMapTy::iterator I = M.find(E);
227
Ted Kremenek7f49f502007-09-14 22:49:21 +0000228 if (I == M.end()) {
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000229 // First value for this edge.
230 M[E].copyValues(V);
231 WorkList.enqueue(TargetBlock);
Ted Kremenek7f49f502007-09-14 22:49:21 +0000232 }
Ted Kremenek5b3036e2007-09-18 23:40:51 +0000233 else if (!_Equal()(V,I->second)) {
Ted Kremenek7f49f502007-09-14 22:49:21 +0000234 I->second.copyValues(V);
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000235 WorkList.enqueue(TargetBlock);
Ted Kremenek7f49f502007-09-14 22:49:21 +0000236 }
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000237 }
238
239 /// hasData (FORWARD ANALYSIS) - Is there any dataflow values associated
240 /// with the incoming edges of a block?
241 bool hasData(const CFGBlock* B, dataflow::forward_analysis_tag) {
242 EdgeDataMapTy& M = D.getEdgeDataMap();
243
244 for (CFGBlock::const_pred_iterator I=B->pred_begin(), E=B->pred_end();
245 I!=E; ++I)
246 if (M.find(CFG::Edge(*I,B)) != M.end())
247 return true;
248
249 return false;
250 }
251
252 /// hasData (BACKWARD ANALYSIS) - Is there any dataflow values associated
253 /// with the outgoing edges of a block?
254 bool hasData(const CFGBlock* B, dataflow::backward_analysis_tag) {
255 EdgeDataMapTy& M = D.getEdgeDataMap();
256
257 for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
258 I!=E; ++I)
259 if (M.find(CFG::Edge(B,*I)) != M.end())
260 return true;
Ted Kremenek7f49f502007-09-14 22:49:21 +0000261
262 return false;
263 }
264
265private:
266 DFValuesTy& D;
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000267 DataflowWorkListTy WorkList;
Ted Kremenek2a203562007-09-18 18:17:19 +0000268 TransferFuncsTy TF;
Ted Kremenek7f49f502007-09-14 22:49:21 +0000269};
270
271
272} // end namespace clang
273#endif