blob: 724b4a4fbb91383cb60c81bf31f91b18f90feb65 [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 Kremenek2a203562007-09-18 18:17:19 +000071 DataflowSolver(DFValuesTy& d) : D(d), TF(d.getAnalysisData()) {}
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 Kremenek2a203562007-09-18 18:17:19 +000089 if (hasData(B,AnalysisDirTag()))
90 ProcessBlock(B,AnalysisDirTag());
Ted Kremenek7f49f502007-09-14 22:49:21 +000091 }
92
93 //===--------------------------------------------------------------------===//
94 // Internal solver logic.
95 //===--------------------------------------------------------------------===//
96
97private:
98
Ted Kremenek2e3e6302007-09-18 18:02:44 +000099 /// SolveDataflowEquations - Perform the actual
Ted Kremenek7f49f502007-09-14 22:49:21 +0000100 /// worklist algorithm to compute dataflow values.
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000101 void SolveDataflowEquations(const CFG& cfg) {
102
103 EnqueueFirstBlock(cfg,AnalysisDirTag());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000104
Ted Kremenek7f49f502007-09-14 22:49:21 +0000105 // Process the worklist until it is empty.
106 while (!WorkList.isEmpty()) {
107 const CFGBlock* B = WorkList.dequeue();
108 // If the dataflow values at the block's entry have changed,
109 // enqueue all predecessor blocks onto the worklist to have
110 // their values updated.
Ted Kremenek2a203562007-09-18 18:17:19 +0000111 ProcessBlock(B,AnalysisDirTag());
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000112 UpdateEdges(B,TF.getVal(),AnalysisDirTag());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000113 }
114 }
115
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000116 void EnqueueFirstBlock(const CFG& cfg, dataflow::forward_analysis_tag) {
117 WorkList.enqueue(&cfg.getEntry());
118 }
119
120 void EnqueueFirstBlock(const CFG& cfg, dataflow::backward_analysis_tag) {
121 WorkList.enqueue(&cfg.getExit());
122 }
123
Ted Kremenek7f49f502007-09-14 22:49:21 +0000124 /// ProcessBlock (FORWARD ANALYSIS) - Process the transfer functions
125 /// for a given block based on a forward analysis.
Ted Kremenek2a203562007-09-18 18:17:19 +0000126 void ProcessBlock(const CFGBlock* B, dataflow::forward_analysis_tag) {
127
Ted Kremenek7f49f502007-09-14 22:49:21 +0000128 // Merge dataflow values from all predecessors of this block.
Ted Kremenek2a203562007-09-18 18:17:19 +0000129 ValTy& V = TF.getVal();
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000130 V.resetValues(D.getAnalysisData());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000131 MergeOperatorTy Merge;
132
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000133 EdgeDataMapTy& M = D.getEdgeDataMap();
Ted Kremeneke6148f32007-09-17 21:59:08 +0000134 bool firstMerge = true;
135
Ted Kremenek7f49f502007-09-14 22:49:21 +0000136 for (CFGBlock::const_pred_iterator I=B->pred_begin(),
Ted Kremeneke6148f32007-09-17 21:59:08 +0000137 E=B->pred_end(); I!=E; ++I) {
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000138 typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(*I,B));
Ted Kremeneke6148f32007-09-17 21:59:08 +0000139 if (BI != M.end()) {
140 if (firstMerge) {
141 firstMerge = false;
142 V.copyValues(BI->second);
143 }
144 else
145 Merge(V,BI->second);
146 }
147 }
Ted Kremenek7f49f502007-09-14 22:49:21 +0000148
149 // Process the statements in the block in the forward direction.
150 for (CFGBlock::const_iterator I=B->begin(), E=B->end(); I!=E; ++I)
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000151 TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
Ted Kremenek7f49f502007-09-14 22:49:21 +0000152 }
153
154 /// ProcessBlock (BACKWARD ANALYSIS) - Process the transfer functions
155 /// for a given block based on a forward analysis.
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000156 void ProcessBlock(const CFGBlock* B, TransferFuncsTy& TF,
Ted Kremenek7f49f502007-09-14 22:49:21 +0000157 dataflow::backward_analysis_tag) {
Ted Kremenek2a203562007-09-18 18:17:19 +0000158
Ted Kremenek7f49f502007-09-14 22:49:21 +0000159 // Merge dataflow values from all predecessors of this block.
Ted Kremenek2a203562007-09-18 18:17:19 +0000160 ValTy& V = TF.getVal();
Ted Kremenek0a03ce62007-09-17 20:49:30 +0000161 V.resetValues(D.getAnalysisData());
Ted Kremenek7f49f502007-09-14 22:49:21 +0000162 MergeOperatorTy Merge;
163
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000164 EdgeDataMapTy& M = D.getEdgeDataMap();
Ted Kremeneke6148f32007-09-17 21:59:08 +0000165 bool firstMerge = true;
166
Ted Kremenek7f49f502007-09-14 22:49:21 +0000167 for (CFGBlock::const_succ_iterator I=B->succ_begin(),
Ted Kremeneke6148f32007-09-17 21:59:08 +0000168 E=B->succ_end(); I!=E; ++I) {
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000169 typename EdgeDataMapTy::iterator BI = M.find(CFG::Edge(B,*I));
Ted Kremeneke6148f32007-09-17 21:59:08 +0000170 if (BI != M.end()) {
171 if (firstMerge) {
172 firstMerge = false;
173 V.copyValues(BI->second);
174 }
175 else
176 Merge(V,BI->second);
177 }
178 }
Ted Kremenek7f49f502007-09-14 22:49:21 +0000179
180 // Process the statements in the block in the forward direction.
181 for (CFGBlock::const_reverse_iterator I=B->begin(), E=B->end(); I!=E; ++I)
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000182 TF.BlockStmt_Visit(const_cast<Stmt*>(*I));
183 }
184
185 /// UpdateEdges (FORWARD ANALYSIS) - After processing the transfer
186 /// functions for a block, update the dataflow value associated with the
187 /// block's outgoing edges. Enqueue any successor blocks for an
188 /// outgoing edge whose value has changed.
189 void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::forward_analysis_tag) {
190 for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
191 I!=E; ++I) {
192
193 CFG::Edge E(B,*I);
194 UpdateEdgeValue(E,V,*I);
195 }
Ted Kremenek7f49f502007-09-14 22:49:21 +0000196 }
197
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000198 /// UpdateEdges (BACKWARD ANALYSIS) - After processing the transfer
199 /// functions for a block, update the dataflow value associated with the
200 /// block's incoming edges. Enqueue any predecessor blocks for an
201 /// outgoing edge whose value has changed.
202 void UpdateEdges(const CFGBlock* B, ValTy& V,dataflow::backward_analysis_tag){
203 for (CFGBlock::const_pred_iterator I=B->succ_begin(), E=B->succ_end();
204 I!=E; ++I) {
205
206 CFG::Edge E(*I,B);
207 UpdateEdgeValue(E,V,*I);
208 }
209 }
210
211 /// UpdateEdgeValue - Update the value associated with a given edge.
212 void UpdateEdgeValue(CFG::Edge& E, ValTy& V, const CFGBlock* TargetBlock) {
213
214 EdgeDataMapTy& M = D.getEdgeDataMap();
215 typename EdgeDataMapTy::iterator I = M.find(E);
216
Ted Kremenek7f49f502007-09-14 22:49:21 +0000217 if (I == M.end()) {
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000218 // First value for this edge.
219 M[E].copyValues(V);
220 WorkList.enqueue(TargetBlock);
Ted Kremenek7f49f502007-09-14 22:49:21 +0000221 }
222 else if (!V.equal(I->second)) {
223 I->second.copyValues(V);
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000224 WorkList.enqueue(TargetBlock);
Ted Kremenek7f49f502007-09-14 22:49:21 +0000225 }
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000226 }
227
228 /// hasData (FORWARD ANALYSIS) - Is there any dataflow values associated
229 /// with the incoming edges of a block?
230 bool hasData(const CFGBlock* B, dataflow::forward_analysis_tag) {
231 EdgeDataMapTy& M = D.getEdgeDataMap();
232
233 for (CFGBlock::const_pred_iterator I=B->pred_begin(), E=B->pred_end();
234 I!=E; ++I)
235 if (M.find(CFG::Edge(*I,B)) != M.end())
236 return true;
237
238 return false;
239 }
240
241 /// hasData (BACKWARD ANALYSIS) - Is there any dataflow values associated
242 /// with the outgoing edges of a block?
243 bool hasData(const CFGBlock* B, dataflow::backward_analysis_tag) {
244 EdgeDataMapTy& M = D.getEdgeDataMap();
245
246 for (CFGBlock::const_succ_iterator I=B->succ_begin(), E=B->succ_end();
247 I!=E; ++I)
248 if (M.find(CFG::Edge(B,*I)) != M.end())
249 return true;
Ted Kremenek7f49f502007-09-14 22:49:21 +0000250
251 return false;
252 }
253
254private:
255 DFValuesTy& D;
Ted Kremenek2e3e6302007-09-18 18:02:44 +0000256 DataflowWorkListTy WorkList;
Ted Kremenek2a203562007-09-18 18:17:19 +0000257 TransferFuncsTy TF;
Ted Kremenek7f49f502007-09-14 22:49:21 +0000258};
259
260
261} // end namespace clang
262#endif