ROSE 0.11.145.147
liveDeadVarAnalysis.h
1#include <featureTests.h>
2#ifdef ROSE_ENABLE_SOURCE_ANALYSIS
3
4#ifndef LIVE_DEAD_VAR_ANALYSIS_H
5#define LIVE_DEAD_VAR_ANALYSIS_H
6
7#include "genericDataflowCommon.h"
8#include "VirtualCFGIterator.h"
9#include "cfgUtils.h"
10#include "CallGraphTraverse.h"
11#include "analysisCommon.h"
12#include "analysis.h"
13#include "dataflow.h"
14#include "latticeFull.h"
15#include "printAnalysisStates.h"
16
17#include <map>
18#include <set>
19#include <vector>
20#include <string>
21#include <iostream>
22
23extern int liveDeadAnalysisDebugLevel;
24
25// Lattice that stores the variables that are live at a given DataflowNode
27{
28 public:
29 std::set<varID> liveVars;
30
31 public:
33 LiveVarsLattice(const varID& var);
34 LiveVarsLattice(const std::set<varID>& liveVars);
35
36 // Initializes this Lattice to its default state, if it is not already initialized
37 void initialize();
38
39 // Returns a copy of this lattice
40 Lattice* copy() const;
41
42 // Overwrites the state of this Lattice with that of that Lattice
43 void copy(Lattice* that);
44
45 // Called by analyses to create a copy of this lattice. However, if this lattice maintains any
46 // information on a per-variable basis, these per-variable mappings must be converted from
47 // the current set of variables to another set. This may be needed during function calls,
48 // when dataflow information from the caller/callee needs to be transferred to the callee/calleer.
49 // We do not force child classes to define their own versions of this function since not all
50 // Lattices have per-variable information.
51 // varNameMap - maps all variable names that have changed, in each mapping pair, pair->first is the
52 // old variable and pair->second is the new variable
53 // func - the function that the copy Lattice will now be associated with
54 void remapVars(const std::map<varID, varID>& varNameMap, const Function& newFunc);
55
56 // Called by analyses to copy over from the that Lattice dataflow information into this Lattice.
57 // that contains data for a set of variables and incorporateVars must overwrite the state of just
58 // those variables, while leaving its state for other variables alone.
59 // We do not force child classes to define their own versions of this function since not all
60 // Lattices have per-variable information.
61 void incorporateVars(Lattice* that_arg);
62
63 // Returns a Lattice that describes the information known within this lattice
64 // about the given expression. By default this could be the entire lattice or any portion of it.
65 // For example, a lattice that maintains lattices for different known variables and expression will
66 // return a lattice for the given expression. Similarly, a lattice that keeps track of constraints
67 // on values of variables and expressions will return the portion of the lattice that relates to
68 // the given expression.
69 // It it legal for this function to return NULL if no information is available.
70 // The function's caller is responsible for deallocating the returned object
71 Lattice* project(SgExpression* expr);
72
73 // The inverse of project(). The call is provided with an expression and a Lattice that describes
74 // the dataflow state that relates to expression. This Lattice must be of the same type as the lattice
75 // returned by project(). unProject() must incorporate this dataflow state into the overall state it holds.
76 // Call must make an internal copy of the passed-in lattice and the caller is responsible for deallocating it.
77 // Returns true if this causes this to change and false otherwise.
78 bool unProject(SgExpression* expr, Lattice* exprState);
79
80 // computes the meet of this and that and saves the result in this
81 // returns true if this causes this to change and false otherwise
82 bool meetUpdate(Lattice* that_arg);
83
84 bool operator==(Lattice* that);
85
86 // Functions used to inform this lattice that a given variable is now in use (e.g. a variable has entered
87 // scope or an expression is being analyzed) or is no longer in use (e.g. a variable has exited scope or
88 // an expression or variable is dead).
89 // It is assumed that a newly-added variable has not been added before and that a variable that is being
90 // removed was previously added
91 // Returns true if this causes the lattice to change and false otherwise.
92 bool addVar(const varID& var);
93 bool remVar(const varID& var);
94
95 // Returns true if the given variable is recorded as live and false otherwise
96 bool isLiveVar(varID var);
97
98 // The string that represents this object
99 // If indent!="", every line of this string must be prefixed by indent
100 // The last character of the returned string should not be '\n', even if it is a multi-line string.
101 std::string str(std::string indent="");
102};
103
104// Virtual class that allows users of the LiveDeadVarsAnalysis to mark certain variables as
105// being used inside a function call if the function's body is not available.
107{
108public:
109 // Returns the set of variables that are used in a call to the given function for which a body has not been provided.
110 // The function is also provided with the DataflowNode where the function was called, as well as its state.
111 virtual std::set<varID> usedVarsInFunc(const Function& func, const DataflowNode& n, NodeState& state)=0;
112};
113
115{
116 std::string indent;
117 LiveVarsLattice* liveLat;
118
119 bool modified;
120 // Expressions that are assigned by the current operation
121 std::set<SgExpression*> assignedExprs;
122 // Variables that are assigned by the current operation
123 std::set<varID> assignedVars;
124 // Variables that are used/read by the current operation
125 std::set<varID> usedVars;
126
127 funcSideEffectUses *fseu;
128
129 friend class LDVAExpressionTransfer;
130
131 // Note that the variable corresponding to this expression is used
132 void used(SgExpression *);
133
134public:
135 LiveDeadVarsTransfer(const Function &f, const DataflowNode &n, NodeState &s, const std::vector<Lattice*> &d, funcSideEffectUses *fseu_)
136 : IntraDFTransferVisitor(f, n, s, d), indent(" "), liveLat(dynamic_cast<LiveVarsLattice*>(*(dfInfo.begin()))), modified(false), fseu(fseu_)
137 {
138 if(liveDeadAnalysisDebugLevel>=1) Dbg::dbg << indent << "liveLat="<<liveLat->str(indent + " ")<<std::endl;
139 // Make sure that all the lattice is initialized
140 liveLat->initialize();
141 }
142
143 bool finish();
144
145 void visit(SgExpression *);
146 void visit(SgInitializedName *);
147 void visit(SgReturnStmt *);
148 void visit(SgExprStatement *);
149 void visit(SgCaseOptionStmt *);
150 void visit(SgIfStmt *);
151 void visit(SgForStatement *);
152 void visit(SgWhileStmt *);
153 void visit(SgDoWhileStmt *);
154};
155
156/* Computes an over-approximation of the set of variables that are live at each DataflowNode. It may consider a given
157 variable as live when in fact it is not. */
158// !!! CURRENTLY THE ANALYSIS IS IMPRECISE BECAUSE:
159// !!! - IF THERE IS A VARIABLE USE WHERE THE IDENTITY OF THE VARIABLE IS COMPUTED THROUGH AN EXPRESSION, WE DO NOT
160// !!! RESPOND BY CONSERVATIVELY MAKING ALL VARIABLES LIVE.
161// !!! - IT DOES NOT CONSIDER INTERNALS OF ARRAYS OR OTHER HEAP MEMORY
163{
164 protected:
165 funcSideEffectUses* fseu;
166
167 public:
169
170 // Generates the initial lattice state for the given dataflow node, in the given function, with the given NodeState
171 void genInitState(const Function& func, const DataflowNode& n, const NodeState& state,
172 std::vector<Lattice*>& initLattices, std::vector<NodeFact*>& initFacts);
173
174 boost::shared_ptr<IntraDFTransferVisitor> getTransferVisitor(const Function& func, const DataflowNode& n,
175 NodeState& state, const std::vector<Lattice*>& dfInfo)
176 { return boost::shared_ptr<IntraDFTransferVisitor>(new LiveDeadVarsTransfer(func, n, state, dfInfo, fseu)); }
177
178 bool transfer(const Function&, const DataflowNode&, NodeState&, const std::vector<Lattice*>&) {
179 ROSE_ABORT();
180 }
181};
182
183// Initialize vars to hold all the variables and expressions that are live at DataflowNode n
184//void getAllLiveVarsAt(LiveDeadVarsAnalysis* ldva, const DataflowNode& n, const NodeState& state, std::set<varID>& vars, std::string indent="");
185void getAllLiveVarsAt(LiveDeadVarsAnalysis* ldva, const NodeState& state, std::set<varID>& vars, std::string indent="");
186
187// Returns the set of variables and expressions that are live at DataflowNode n
188//std::set<varID> getAllLiveVarsAt(LiveDeadVarsAnalysis* ldva, const DataflowNode& n, const NodeState& state, std::string indent="");
189std::set<varID> getAllLiveVarsAt(LiveDeadVarsAnalysis* ldva, const NodeState& state, std::string indent="");
190
191// get Live-In lattice for a control flow graph node generated from a SgNode with an index
192LiveVarsLattice* getLiveInVarsAt(LiveDeadVarsAnalysis* ldva, SgNode* n, unsigned int index = 0);
193
194// get Live-Out lattice for a control flow graph node generated from a SgNode with an index
195LiveVarsLattice* getLiveOutVarsAt(LiveDeadVarsAnalysis* ldva, SgNode* n, unsigned int index = 0);
196
198{
199 protected:
200 // Sample lattice that will be initially associated with every variable (before the analysis)
201 Lattice* perVarLattice;
202
203 // Lattice that corresponds to allVar;
204 Lattice* allVarLattice;
205
206 // Map of lattices that correspond to constant variables
207 std::map<varID, Lattice*> constVarLattices;
208
209 // Maps variables in a given function to the index of their respective Lattice objects in
210 // the ProductLattice::lattice[] array
211 std::map<varID, int> varLatticeIndex;
212
213 // The analysis that identified the variables that are live at this Dataflow node
215
216 bool (*filter) (CFGNode cfgn);
217
218 // Dataflow node that this lattice is associated with and its corresponding node state.
219 DataflowNode n;
220 const NodeState& state;
221
222 protected:
223 // Minimal constructor that initializes just the portions of the object required to make an
224 // initial blank VarsExprsProductLattice
225 VarsExprsProductLattice(const DataflowNode& n, const NodeState& state, bool (*filter) (CFGNode cfgn));
226
227 // Returns a blank instance of a VarsExprsProductLattice that only has the fields n and state set
228 virtual VarsExprsProductLattice* blankVEPL(const DataflowNode& n, const NodeState& state)=0;
229
230 public:
231 // creates a new VarsExprsProductLattice
232 // perVarLattice - sample lattice that will be associated with every variable in scope at node n
233 // it should be assumed that the object pointed to by perVarLattice will be either
234 // used internally by this VarsExprsProductLatticeobject or deallocated
235 // constVarLattices - map of additional variables and their associated lattices, that will be
236 // incorporated into this VarsExprsProductLatticein addition to any other lattices for
237 // currently live variables (these correspond to various useful constant variables like zeroVar)
238 // allVarLattice - the lattice associated with allVar (the variable that represents all of memory)
239 // if allVarLattice==NULL, no support is provided for allVar
240 // ldva - liveness analysis result. This can be set to NULL. Or only live variables at a CFG node will be used to initialize the product lattice
241 // n - the dataflow node that this lattice will be associated with
242 // state - the NodeState at this dataflow node
243 VarsExprsProductLattice(Lattice* perVarLattice,
244 const std::map<varID, Lattice*>& constVarLattices,
245 Lattice* allVarLattice,
247 const DataflowNode& n, const NodeState& state);
248
249 // Create a copy of that. It is assumed that the types of all the lattices in VarsExprsProductLattice that are
250 // the same as in this.
252
254
255 public:
256
257 // Returns the Lattice mapped to the given variable or NULL if nothing is mapped to it
258 Lattice* getVarLattice(const varID& var);
259
260 // Returns the set of all variables mapped by this VarsExprsProductLattice
261 std::set<varID> getAllVars();
262
263 protected:
264
265 // Returns the index of var among the variables associated with func
266 // or -1 otherwise
267 int getVarIndex(const varID& var);
268
269 public:
270
271 // Overwrites the state of this Lattice with that of that Lattice
272 void copy(Lattice* that);
273 // Set this to be a copy of that. It is assumed that the types of all the lattices in VarsExprsProductLattice
274 // that are the same as in this.
275 void copy(const VarsExprsProductLattice* that);
276
277 bool meetUpdate(Lattice *that);
278
279 // Called by analyses to create a copy of this lattice. However, if this lattice maintains any
280 // information on a per-variable basis, these per-variable mappings must be converted from
281 // the current set of variables to another set. This may be needed during function calls,
282 // when dataflow information from the caller/callee needs to be transferred to the callee/calleer.
283 // We do not force child classes to define their own versions of this function since not all
284 // Lattices have per-variable information.
285 // varNameMap - maps all variable names that have changed, in each mapping pair, pair->first is the
286 // old variable and pair->second is the new variable
287 // func - the function that the copy Lattice will now be associated with
288
290 /*Lattice**/void remapVars(const std::map<varID, varID>& varNameMap, const Function& newFunc);
291
292 // Called by analyses to copy over from the that Lattice dataflow information into this Lattice.
293 // that contains data for a set of variables and incorporateVars must overwrite the state of just
294 // those variables, while leaving its state for other variables alone.
295 // We do not force child classes to define their own versions of this function since not all
296 // Lattices have per-variable information.
297 void incorporateVars(Lattice* that);
298
299 // Returns a Lattice that describes the information known within this lattice
300 // about the given expression. By default this could be the entire lattice or any portion of it.
301 // For example, a lattice that maintains lattices for different known variables and expression will
302 // return a lattice for the given expression. Similarly, a lattice that keeps track of constraints
303 // on values of variables and expressions will return the portion of the lattice that relates to
304 // the given expression.
305 // It it legal for this function to return NULL if no information is available.
306 // The function's caller is responsible for deallocating the returned object
307 Lattice* project(SgExpression* expr);
308
309 // The inverse of project(). The call is provided with an expression and a Lattice that describes
310 // the dataflow state that relates to expression. This Lattice must be of the same type as the lattice
311 // returned by project(). unProject() must incorporate this dataflow state into the overall state it holds.
312 // Call must make an internal copy of the passed-in lattice and the caller is responsible for deallocating it.
313 // Returns true if this causes this to change and false otherwise.
314 bool unProject(SgExpression* expr, Lattice* exprState);
315
316 // Functions used to inform this lattice that a given variable is now in use (e.g. a variable has entered
317 // scope or an expression is being analyzed) or is no longer in use (e.g. a variable has exited scope or
318 // an expression or variable is dead).
319 // Returns true if this causes this Lattice to change and false otherwise.
320 bool addVar(const varID& var);
321 bool remVar(const varID& var);
322
323 // Sets the lattice of the given var to be lat.
324 // If the variable is already mapped to some other Lattice,
325 // If *(the current lattice) == *lat, the mapping is not changed
326 // If *(the current lattice) != *lat, the current lattice is deallocated and var is mapped to lat->copy()
327 // Returns true if this causes this Lattice to change and false otherwise.
328 bool addVar(const varID& var, Lattice* lat);
329
330 // The string that represents this object
331 // If indent!="", every line of this string must be prefixed by indent
332 // The last character of the returned string should not be '\n', even if it is a multi-line string.
333 std::string str(std::string indent="");
334};
335
337{
338 protected:
339 // Minimal constructor that initializes just the portions of the object required to make an
340 // initial blank VarsExprsProductLattice
342
343 // Returns a blank instance of a VarsExprsProductLattice that only has the fields n and state set
344 VarsExprsProductLattice* blankVEPL(const DataflowNode& n, const NodeState& state) override;
345
346 public:
347 // creates a new VarsExprsProductLattice
348 // perVarLattice - sample lattice that will be associated with every variable in scope at node n
349 // it should be assumed that the object pointed to by perVarLattice will be either
350 // used internally by this VarsExprsProductLattice object or deallocated
351 // constVarLattices - map of additional variables and their associated lattices, that will be
352 // incorporated into this VarsExprsProductLattice in addition to any other lattices for
353 // currently live variables (these correspond to various useful constant variables like zeroVar)
354 // allVarLattice - the lattice associated with allVar (the variable that represents all of memory)
355 // if allVarLattice==NULL, no support is provided for allVar
356 // func - the current function
357 // n - the dataflow node that this lattice will be associated with
358 // state - the NodeState at this dataflow node
360 const std::map<varID, Lattice*>& constVarLattices,
361 Lattice* allVarLattice,
363 const DataflowNode& n, const NodeState& state);
364
366
367 using VarsExprsProductLattice::copy; // removes warning of hidden overloaded virtual function
368
369 // returns a copy of this lattice
370 Lattice* copy() const override;
371};
372
374{
375 protected:
376 // Minimal constructor that initializes just the portions of the object required to make an
377 // initial blank VarsExprsProductLattice
379
380 // Returns a blank instance of a VarsExprsProductLattice that only has the fields n and state set
381 VarsExprsProductLattice* blankVEPL(const DataflowNode& n, const NodeState& state) override;
382
383 public:
384 // creates a new VarsExprsProductLattice
385 // perVarLattice - sample lattice that will be associated with every variable in scope at node n
386 // it should be assumed that the object pointed to by perVarLattice will be either
387 // used internally by this VarsExprsProductLatticeobject or deallocated
388 // constVarLattices - map of additional variables and their associated lattices, that will be
389 // incorporated into this VarsExprsProductLatticein addition to any other lattices for
390 // currently live variables (these correspond to various useful constant variables like zeroVar)
391 // allVarLattice - the lattice associated with allVar (the variable that represents all of memory)
392 // if allVarLattice==NULL, no support is provided for allVar
393 // func - the current function
394 // n - the dataflow node that this lattice will be associated with
395 // state - the NodeState at this dataflow node
397 const std::map<varID, Lattice*>& constVarLattices,
398 Lattice* allVarLattice,
400 const DataflowNode& n, const NodeState& state);
401
403
404 using VarsExprsProductLattice::copy; // removes warning of hidden overloaded virtual function
405
406 // returns a copy of this lattice
407 Lattice* copy() const override;
408};
409
410// prints the Lattices set by the given LiveDeadVarsAnalysis
411void printLiveDeadVarsAnalysisStates(LiveDeadVarsAnalysis* da, std::string indent="");
412
413#endif
414#endif
Apply an analysis A's transfer function at a particular AST node type.
Definition dataflow.h:88
This class represents the concept of a C and C++ case option (used within a switch statement).
This class represents the concept of a do-while statement.
This class represents the concept of a C or C++ statement which contains a expression.
This class represents the notion of an expression. Expressions are derived from SgLocatedNodes,...
This class represents the concept of a for loop.
This class represents the concept of an "if" construct.
This class represents the notion of a declared variable.
This class represents the base class for all IR nodes within Sage III.
This class represents a source project, with a list of SgFile objects and global information about th...
This class represents the concept of a C Assembler statement (untested).
This class represents the concept of a do-while statement.
void remapVars(const std::map< varID, varID > &varNameMap, const Function &newFunc)
*Lattice**‍/void remapVars(const std::map<varID, varID>& varNameMap, const Function& newFunc,...
A node in the control flow graph.
Definition virtualCFG.h:70