blob: e2c4f16a51968589011758033202c6ef82274c9c [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"
19
20namespace clang {
21
22//===----------------------------------------------------------------------===//
23/// DataflowWorkListTy - Data structure representing the worklist used for
24/// dataflow algorithms.
25
26class DataflowWorkListTy {
27 typedef llvm::SmallPtrSet<const CFGBlock*,20> BlockSet;
28 BlockSet wlist;
29public:
30 /// enqueue - Add a block to the worklist. Blocks already on the worklist
31 /// are not added a second time.
32 void enqueue(const CFGBlock* B) { wlist.insert(B); }
33
34 /// dequeue - Remove a block from the worklist.
35 const CFGBlock* dequeue() {
36 assert (!wlist.empty());
37 const CFGBlock* B = *wlist.begin();
38 wlist.erase(B);
39 return B;
40 }
41
42 /// isEmpty - Return true if the worklist is empty.
43 bool isEmpty() const { return wlist.empty(); }
44};
45
46//===----------------------------------------------------------------------===//
47/// DataflowSolverTy - Generic dataflow solver.
48template <typename _DFValuesTy, // Usually a subclass of DataflowValues
49 typename _TransferFuncsTy,
50 typename _MergeOperatorTy >
51class DataflowSolver {
52
53 //===--------------------------------------------------------------------===//
54 // Type declarations.
55 //===--------------------------------------------------------------------===//
56
57public:
58 typedef _DFValuesTy DFValuesTy;
59 typedef _TransferFuncsTy TransferFuncsTy;
60 typedef _MergeOperatorTy MergeOperatorTy;
61
62 typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag;
63 typedef typename _DFValuesTy::ValTy ValTy;
Ted Kremenek2e3e6302007-09-18 18:02:44 +000064 typedef typename _DFValuesTy::EdgeDataMapTy EdgeDataMapTy;
Ted Kremenek7f49f502007-09-14 22:49:21 +000065
66 //===--------------------------------------------------------------------===//
67 // External interface: constructing and running the solver.
68 //===--------------------------------------------------------------------===//
69
70public:
Ted Kremenek3e039752007-09-17 17:14:52 +000071 DataflowSolver(DFValuesTy& d) : D(d) {}
Ted Kremenek7f49f502007-09-14 22:49:21 +000072 ~DataflowSolver() {}
73
74 /// runOnCFG - Computes dataflow values for all blocks in a CFG.
75 void runOnCFG(const CFG& cfg) {
76 // Set initial dataflow values and boundary conditions.
77 D.InitializeValues(cfg);
Ted Kremenek2e3e6302007-09-18 18:02:44 +000078 // Solve the dataflow equations. This will populate D.EdgeDataMap
79 // with dataflow values.
80 SolveDataflowEquations(cfg);
Ted Kremenek7f49f502007-09-14 22:49:21 +000081 }
82
83 /// runOnBlock - Computes dataflow values for a given block.
84 /// This should usually be invoked only after previously computing
85 /// dataflow values using runOnCFG, as runOnBlock is intended to
86 /// only be used for querying the dataflow values within a block with
87 /// and Observer object.
88 void runOnBlock(const CFGBlock* B) {
Ted Kremenek2e3e6302007-09-18 18:02:44 +000089 if (!hasData(B,AnalysisDirTag()))
Ted Kremeneke6148f32007-09-17 21:59:08 +000090 return;
91
Ted Kremenek3e039752007-09-17 17:14:52 +000092 TransferFuncsTy TF (D.getAnalysisData());
Ted Kremenek7f49f502007-09-14 22:49:21 +000093 ProcessBlock(B,TF,AnalysisDirTag());
94 }
95
96 //===--------------------------------------------------------------------===//
97 // Internal solver logic.
98 //===--------------------------------------------------------------------===//
99
100private:
101
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000102 /// SolveDataflowEquations - Perform the actual
Ted Kremenek7f49f502007-09-14 22:49:21 +0000103 /// worklist algorithm to compute dataflow values.
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000104 void SolveDataflowEquations(const CFG& cfg) {
105
106 EnqueueFirstBlock(cfg,AnalysisDirTag());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000107
108 // Create the state for transfer functions.
Ted Kremenek3e039752007-09-17 17:14:52 +0000109 TransferFuncsTy TF(D.getAnalysisData());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000110
111 // Process the worklist until it is empty.
112 while (!WorkList.isEmpty()) {
113 const CFGBlock* B = WorkList.dequeue();
114 // If the dataflow values at the block's entry have changed,
115 // enqueue all predecessor blocks onto the worklist to have
116 // their values updated.
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000117 ProcessBlock(B,TF,AnalysisDirTag());
118 UpdateEdges(B,TF.getVal(),AnalysisDirTag());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000119 }
120 }
121
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000122 void EnqueueFirstBlock(const CFG& cfg, dataflow::forward_analysis_tag) {
123 WorkList.enqueue(&cfg.getEntry());
124 }
125
126 void EnqueueFirstBlock(const CFG& cfg, dataflow::backward_analysis_tag) {
127 WorkList.enqueue(&cfg.getExit());
128 }
129
Ted Kremenek7f49f502007-09-14 22:49:21 +0000130 /// ProcessBlock (FORWARD ANALYSIS) - Process the transfer functions
131 /// for a given block based on a forward analysis.
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000132 void ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
Ted Kremenek7f49f502007-09-14 22:49:21 +0000133 dataflow::forward_analysis_tag) {
134
135 ValTy& V = TF.getVal();
136
137 // Merge dataflow values from all predecessors of this block.
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000138 V.resetValues(D.getAnalysisData());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000139 MergeOperatorTy Merge;
140
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000141 EdgeDataMapTy& M = D.getEdgeDataMap();
Ted Kremeneke6148f32007-09-17 21:59:08 +0000142 bool firstMerge = true;
143
Ted Kremenek7f49f502007-09-14 22:49:21 +0000144 for (CFGBlock::const_pred_iterator I=B->pred_begin(),
Ted Kremeneke6148f32007-09-17 21:59:08 +0000145 E=B->pred_end(); I!=E; ++I) {
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000146 typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(*I,B));
Ted Kremeneke6148f32007-09-17 21:59:08 +0000147 if (BI != M.end()) {
148 if (firstMerge) {
149 firstMerge = false;
150 V.copyValues(BI->second);
151 }
152 else
153 Merge(V,BI->second);
154 }
155 }
Ted Kremenek7f49f502007-09-14 22:49:21 +0000156
157 // Process the statements in the block in the forward direction.
158 for (CFGBlock::const_iterator I=B->begin(), E=B->end(); I!=E; ++I)
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000159 TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
Ted Kremenek7f49f502007-09-14 22:49:21 +0000160 }
161
162 /// ProcessBlock (BACKWARD ANALYSIS) - Process the transfer functions
163 /// for a given block based on a forward analysis.
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000164 void ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
Ted Kremenek7f49f502007-09-14 22:49:21 +0000165 dataflow::backward_analysis_tag) {
166
167 ValTy& V = TF.getVal();
168
169 // Merge dataflow values from all predecessors of this block.
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000170 V.resetValues(D.getAnalysisData());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000171 MergeOperatorTy Merge;
172
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000173 EdgeDataMapTy& M = D.getEdgeDataMap();
Ted Kremeneke6148f32007-09-17 21:59:08 +0000174 bool firstMerge = true;
175
Ted Kremenek7f49f502007-09-14 22:49:21 +0000176 for (CFGBlock::const_succ_iterator I=B->succ_begin(),
Ted Kremeneke6148f32007-09-17 21:59:08 +0000177 E=B->succ_end(); I!=E; ++I) {
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000178 typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(B,*I));
Ted Kremeneke6148f32007-09-17 21:59:08 +0000179 if (BI != M.end()) {
180 if (firstMerge) {
181 firstMerge = false;
182 V.copyValues(BI->second);
183 }
184 else
185 Merge(V,BI->second);
186 }
187 }
Ted Kremenek7f49f502007-09-14 22:49:21 +0000188
189 // Process the statements in the block in the forward direction.
190 for (CFGBlock::const_reverse_iterator I=B->begin(), E=B->end(); I!=E; ++I)
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000191 TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
192 }
193
194 /// UpdateEdges (FORWARD ANALYSIS) - After processing the transfer
195 /// functions for a block, update the dataflow value associated with the
196 /// block's outgoing edges. Enqueue any successor blocks for an
197 /// outgoing edge whose value has changed.
198 void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::forward_analysis_tag) {
199 for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
200 I!=E; ++I) {
201
202 CFG::Edge E(B,*I);
203 UpdateEdgeValue(E,V,*I);
204 }
Ted Kremenek7f49f502007-09-14 22:49:21 +0000205 }
206
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000207 /// UpdateEdges (BACKWARD ANALYSIS) - After processing the transfer
208 /// functions for a block, update the dataflow value associated with the
209 /// block's incoming edges. Enqueue any predecessor blocks for an
210 /// outgoing edge whose value has changed.
211 void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::backward_analysis_tag){
212 for (CFGBlock::const_pred_iterator I=B->succ_begin(), E=B->succ_end();
213 I!=E; ++I) {
214
215 CFG::Edge E(*I,B);
216 UpdateEdgeValue(E,V,*I);
217 }
218 }
219
220 /// UpdateEdgeValue - Update the value associated with a given edge.
221 void UpdateEdgeValue(CFG::Edge& E, ValTy& V, const CFGBlock* TargetBlock) {
222
223 EdgeDataMapTy& M = D.getEdgeDataMap();
224 typename EdgeDataMapTy::iterator I = M.find(E);
225
Ted Kremenek7f49f502007-09-14 22:49:21 +0000226 if (I == M.end()) {
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000227 // First value for this edge.
228 M[E].copyValues(V);
229 WorkList.enqueue(TargetBlock);
Ted Kremenek7f49f502007-09-14 22:49:21 +0000230 }
231 else if (!V.equal(I->second)) {
232 I->second.copyValues(V);
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000233 WorkList.enqueue(TargetBlock);
Ted Kremenek7f49f502007-09-14 22:49:21 +0000234 }
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000235 }
236
237 /// hasData (FORWARD ANALYSIS) - Is there any dataflow values associated
238 /// with the incoming edges of a block?
239 bool hasData(const CFGBlock* B, dataflow::forward_analysis_tag) {
240 EdgeDataMapTy& M = D.getEdgeDataMap();
241
242 for (CFGBlock::const_pred_iterator I=B->pred_begin(), E=B->pred_end();
243 I!=E; ++I)
244 if (M.find(CFG::Edge(*I,B)) != M.end())
245 return true;
246
247 return false;
248 }
249
250 /// hasData (BACKWARD ANALYSIS) - Is there any dataflow values associated
251 /// with the outgoing edges of a block?
252 bool hasData(const CFGBlock* B, dataflow::backward_analysis_tag) {
253 EdgeDataMapTy& M = D.getEdgeDataMap();
254
255 for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
256 I!=E; ++I)
257 if (M.find(CFG::Edge(B,*I)) != M.end())
258 return true;
Ted Kremenek7f49f502007-09-14 22:49:21 +0000259
260 return false;
261 }
262
263private:
264 DFValuesTy& D;
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000265 DataflowWorkListTy WorkList;
Ted Kremenek7f49f502007-09-14 22:49:21 +0000266};
267
268
269} // end namespace clang
270#endif