ROSE
0.9.6a
|
Static single assignment analysis. More...
#include <staticSingleAssignment.h>
Public Types | |
typedef std::vector < SgInitializedName * > | VarName |
A compound variable name as used by the variable renaming. More... | |
typedef boost::unordered_map < SgNode *, std::set< VarName > > | LocalDefUseTable |
Describes the defs or uses at each node. More... | |
typedef FilteredCFGNode < ssa_private::DataflowCfgFilter > | FilteredCfgNode |
A filtered CFGNode that is used for DefUse traversal. More... | |
typedef FilteredCFGEdge < ssa_private::DataflowCfgFilter > | FilteredCfgEdge |
A filtered CFGEdge that is used for DefUse traversal. More... | |
typedef boost::shared_ptr < ReachingDef > | ReachingDefPtr |
typedef std::map< VarName, ReachingDefPtr > | NodeReachingDefTable |
A map from each variable to its reaching definitions at the current node. More... | |
typedef boost::unordered_map < SgNode *, std::pair < NodeReachingDefTable, NodeReachingDefTable > > | GlobalReachingDefTable |
The first table is the IN table. More... | |
typedef boost::unordered_map < SgNode *, NodeReachingDefTable > | UseTable |
Map from each node to the variables used at that node and their reaching definitions. More... | |
Public Member Functions | |
StaticSingleAssignment (SgProject *proj) | |
~StaticSingleAssignment () | |
void | run (bool interprocedural, bool treatPointersAsStructures) |
Run the analysis. More... | |
void | toDOT (const std::string fileName) |
Print the CFG with any UniqueNames and Def/Use information visible. More... | |
void | toFilteredDOT (const std::string fileName) |
Print the CFG with any UniqueNames and Def/Use information visible. More... | |
void | printOriginalDefs (SgNode *node) |
void | printOriginalDefTable () |
LocalDefUseTable & | getOriginalDefTable () |
Get the table of definitions for every node. More... | |
LocalDefUseTable & | getLocalUsesTable () |
const NodeReachingDefTable & | getOutgoingDefsAtNode (SgNode *node) const |
Returns the definitions of all the variables right after the given node has executed. More... | |
const NodeReachingDefTable & | getReachingDefsAtNode_ (SgNode *node) const |
Returns the definitions of all the variables immediately before the given node has executed. More... | |
const NodeReachingDefTable & | getUsesAtNode (SgNode *node) const |
Returns a list of all the variables used at this node. More... | |
const NodeReachingDefTable & | getDefsAtNode (SgNode *node) const |
Returns a list of all the variables defined at the given node. More... | |
std::set< VarName > | getVarsUsedInSubtree (SgNode *root) const |
Returns a set of all the variables names that have uses in the subtree. More... | |
std::set< VarName > | getVarsDefinedInSubtree (SgNode *root) const |
Given a node, traverses all its children in the AST and collects all the variable names that have definitions in the subtree. More... | |
std::set< VarName > | getOriginalVarsDefinedInSubtree (SgNode *root) const |
Given a node, traverses all its children in the AST and collects all the variable names that have original definitions in the subtree. More... | |
NodeReachingDefTable | getLastVersions (SgFunctionDeclaration *func) const |
Returns the last encountered definition of every variable. More... | |
Static Public Member Functions | |
static bool | getDebug () |
static bool | getDebugExtra () |
static bool | isPrefixOfName (VarName name, VarName prefix) |
Find if the given prefix is a prefix of the given name. More... | |
static ssa_private::VarUniqueName * | getUniqueName (SgNode *node) |
Get the uniqueName attribute for the given node. More... | |
static const VarName & | getVarName (SgNode *node) |
Get the variable name of the given node. More... | |
static const VarName & | getVarForExpression (SgNode *node) |
If an expression evaluates to a reference of a variable, returns that variable. More... | |
static SgExpression * | buildVariableReference (const VarName &var, SgScopeStatement *scope=NULL) |
Get an AST fragment containing the appropriate varRefs and Dot/Arrow ops to access the given variable. More... | |
static bool | isVarInScope (const VarName &var, SgNode *scope) |
Finds the scope of the given node, and returns true if the given variable is accessible there. More... | |
static std::string | varnameToString (const VarName &vec) |
Get a string representation of a varName. More... | |
static void | printLocalDefUseTable (const LocalDefUseTable &table) |
Static Public Attributes | |
static VarName | emptyName |
Private Member Functions | |
void | runDefUseDataFlow (SgFunctionDefinition *func) |
Once all the local definitions have been inserted in the ssaLocalDefsTable and phi functions have been inserted in the reaching defs table, propagate reaching definitions along the CFG. More... | |
void | expandParentMemberDefinitions (SgFunctionDeclaration *function) |
Expand all member definitions (chained names) to define every name in the chain that is shorter than the originally defined name. More... | |
void | expandParentMemberUses (SgFunctionDeclaration *function) |
Expand all member uses (chained names) to explicitly use every name in the chain that is a parent of the original use. More... | |
void | insertDefsForChildMemberUses (SgFunctionDeclaration *function) |
Find all uses of compound variable names and insert expanded defs for them when their parents are defined. More... | |
void | insertDefsForExternalVariables (SgFunctionDeclaration *function) |
Insert defs for functions that are declared outside the function scope. More... | |
std::multimap< FilteredCfgNode, std::pair< FilteredCfgNode, FilteredCfgEdge > > | insertPhiFunctions (SgFunctionDefinition *function, const std::vector< FilteredCfgNode > &cfgNodesInPostOrder) |
Find where phi functions need to be inserted and insert empty phi functions at those nodes. More... | |
void | populateLocalDefsTable (SgFunctionDeclaration *function) |
Create ReachingDef objects for each local def and insert them in the local def table. More... | |
void | renumberAllDefinitions (SgFunctionDefinition *func, const std::vector< FilteredCfgNode > &cfgNodesInPostOrder) |
Give numbers to all the reachingDef objects. More... | |
void | updateIncomingPropagatedDefs (FilteredCfgNode cfgNode) |
Take all the outgoing defs from previous nodes and merge them as the incoming defs of the current node. More... | |
bool | propagateDefs (FilteredCfgNode cfgNode) |
Performs the data-flow update for one individual node, populating the reachingDefsTable for that node. More... | |
void | buildUseTable (const std::vector< FilteredCfgNode > &cfgNodes) |
Once all the reaching def information has been propagated, uses the reaching def information and the local use information to match uses to their reaching defs. More... | |
void | interproceduralDefPropagation (const boost::unordered_set< SgFunctionDefinition * > &interestingFunctions) |
Insert definitions at function call sites for all variables defined interprocedurally. More... | |
std::vector < SgFunctionDefinition * > | calculateInterproceduralProcessingOrder (const boost::unordered_set< SgFunctionDefinition * > &interestingFunctions) |
This function returns the order in which functions should be processed so that callees are processed before callers whenever possible (this is sometimes not possible due to recursion). More... | |
void | processCalleesThenFunction (SgFunctionDefinition *targetFunction, SgIncidenceDirectedGraph *callGraph, const boost::unordered_map< SgFunctionDefinition *, SgGraphNode * > &graphNodeToFunction, std::vector< SgFunctionDefinition * > &processingOrder, std::set< SgFunctionDefinition * > visited) |
Add all the callees of the function to the processing list, then add the function itself. More... | |
bool | insertInterproceduralDefs (SgFunctionDefinition *funcDef, const boost::unordered_set< SgFunctionDefinition * > &processed, ClassHierarchyWrapper *classHierarchy) |
Add definitions at function call expressions for variables that are modified interprocedurally. More... | |
void | processOneCallSite (SgExpression *callSite, SgFunctionDeclaration *callee, const boost::unordered_set< SgFunctionDefinition * > &processed, ClassHierarchyWrapper *classHierarchy) |
Insert the interprocedural defs at a particular call site for a particular callee. More... | |
void | printToDOT (SgSourceFile *file, std::ofstream &outFile) |
void | printToFilteredDOT (SgSourceFile *file, std::ofstream &outFile) |
Static Private Member Functions | |
static bool | isBuiltinVar (const VarName &var) |
Returns true if the variable is implicitly defined at the function entry by the compiler. More... | |
static std::vector < FilteredCfgNode > | getCfgNodesInPostorder (SgFunctionDefinition *func) |
Iterates all the CFG nodes in the function and returns them in postorder, according to depth-first search. More... | |
static bool | isVarAccessibleFromCaller (const VarName &var, SgExpression *callSite, SgFunctionDeclaration *callee) |
Given a variable that is in a callee's scope, returns true if the caller can access the same variable, false otherwise. More... | |
static bool | varRequiresThisPointer (const VarName &var) |
Returns true if the variable is a nonstatic class variable, so it hass to be accessed by the "this" pointer. More... | |
static bool | isThisPointerSameInCallee (SgFunctionCallExp *callSite, SgMemberFunctionDeclaration *callee) |
Returns true if the callee is acting on the same object instance as the caller. More... | |
static bool | isThisPointer (SgExpression *expression) |
Returns true of the given expression evaluates to the 'this' pointer. More... | |
static bool | isDeepConstPointer (SgType *type) |
True if the type is a const pointer pointing to a const object. More... | |
static bool | isPointerToDeepConst (SgType *type) |
True if the type is a pointer pointing to a const object. More... | |
static bool | isArgumentNonConstReferenceOrPointer (SgInitializedName *formalArgument) |
Returns true if the given formal parameter is a reference or a nonconst pointer, so that it its value is aliased between function calls. More... | |
Private Attributes | |
SgProject * | project |
The project to perform SSA Analysis on. More... | |
LocalDefUseTable | originalDefTable |
This is the table of variable definition locations that is generated by the VarDefUseTraversal. More... | |
LocalDefUseTable | expandedDefTable |
This is the table of definitions that is expanded from the original table. More... | |
GlobalReachingDefTable | reachingDefsTable |
Maps each node to the reaching definitions at that node. More... | |
LocalDefUseTable | localUsesTable |
This is the table that is populated with all the use information for all the variables at all the nodes. More... | |
UseTable | useTable |
Map from each node to the variables used at that node and their reaching definitions. More... | |
boost::unordered_map< SgNode *, NodeReachingDefTable > | ssaLocalDefTable |
Local definitions (actual definitions, not phi definitions). More... | |
Static single assignment analysis.
Contains all the functionality to implement variable renaming on a given program. For this class, we do not actually transform the AST directly, rather we perform the analysis and add attributes to the AST nodes so that later optimizations can access the results of this analysis while still preserving the original AST.
Definition at line 62 of file staticSingleAssignment.h.
typedef std::vector<SgInitializedName*> StaticSingleAssignment::VarName |
A compound variable name as used by the variable renaming.
Definition at line 71 of file staticSingleAssignment.h.
typedef boost::unordered_map<SgNode*, std::set<VarName> > StaticSingleAssignment::LocalDefUseTable |
Describes the defs or uses at each node.
This is for local, rather than propagated, information.
Definition at line 74 of file staticSingleAssignment.h.
typedef FilteredCFGNode<ssa_private::DataflowCfgFilter> StaticSingleAssignment::FilteredCfgNode |
A filtered CFGNode that is used for DefUse traversal.
Definition at line 77 of file staticSingleAssignment.h.
typedef FilteredCFGEdge<ssa_private::DataflowCfgFilter> StaticSingleAssignment::FilteredCfgEdge |
A filtered CFGEdge that is used for DefUse traversal.
Definition at line 80 of file staticSingleAssignment.h.
typedef boost::shared_ptr<ReachingDef> StaticSingleAssignment::ReachingDefPtr |
Definition at line 82 of file staticSingleAssignment.h.
typedef std::map<VarName, ReachingDefPtr> StaticSingleAssignment::NodeReachingDefTable |
A map from each variable to its reaching definitions at the current node.
Definition at line 85 of file staticSingleAssignment.h.
typedef boost::unordered_map<SgNode*, std::pair<NodeReachingDefTable, NodeReachingDefTable> > StaticSingleAssignment::GlobalReachingDefTable |
The first table is the IN table.
The second table is the OUT table.
Definition at line 88 of file staticSingleAssignment.h.
typedef boost::unordered_map<SgNode*, NodeReachingDefTable> StaticSingleAssignment::UseTable |
Map from each node to the variables used at that node and their reaching definitions.
Definition at line 91 of file staticSingleAssignment.h.
|
inline |
Definition at line 131 of file staticSingleAssignment.h.
|
inline |
Definition at line 135 of file staticSingleAssignment.h.
void StaticSingleAssignment::run | ( | bool | interprocedural, |
bool | treatPointersAsStructures | ||
) |
Run the analysis.
If interprocedural analysis is not enabled, functionc all expressions (SgFunctionCallExp) will not count as definitions of any variables.
interprocedural | true to enable interprocedural analysis, false to perform no interprocedural analysis. |
treatPointersAsStructures | if true, p->x is versioned as if it were the variable p.x. |
|
inlinestatic |
Definition at line 145 of file staticSingleAssignment.h.
References SgProject::get_verbose().
|
inlinestatic |
Definition at line 150 of file staticSingleAssignment.h.
References SgProject::get_verbose().
Referenced by ssa_private::calculateControlDependence().
|
private |
Once all the local definitions have been inserted in the ssaLocalDefsTable and phi functions have been inserted in the reaching defs table, propagate reaching definitions along the CFG.
|
staticprivate |
Returns true if the variable is implicitly defined at the function entry by the compiler.
|
private |
Expand all member definitions (chained names) to define every name in the chain that is shorter than the originally defined name.
When a member of a struct/class is referenced, this will insert definitions for every member referenced to access the currently referenced one.
ex. Obj o; //Declare o of type Obj o.a.b = 5; //Def for o.a.b
In the second line, this function will insert the following:
o.a.b = 5; //Def for o.a.b, o.a, o
|
private |
Expand all member uses (chained names) to explicitly use every name in the chain that is a parent of the original use.
When a member of a struct/class is used, this will insert uses for every member referenced to access the currently used one.
ex. Obj o; //Declare o of type Obj int i; //Declare i of type int i = o.a.b; //Def for i, use for o.a.b
In the third line, this function will insert the following:
i = o.a.b; //Def for i, use for o.a.b, o.a, o
curNode |
|
private |
Find all uses of compound variable names and insert expanded defs for them when their parents are defined.
E.g. for a.x, all defs of a will have a def of a.x inserted. Note that there might be other child expansions of a, such as a.y, that we do not insert since they have no uses.
|
private |
Insert defs for functions that are declared outside the function scope.
|
private |
Find where phi functions need to be inserted and insert empty phi functions at those nodes.
This updates the IN part of the reaching def table with Phi functions.
cfgNodesInPostOrder | all the CFG nodes of the function |
|
private |
Create ReachingDef objects for each local def and insert them in the local def table.
|
private |
Give numbers to all the reachingDef objects.
Should be called after phi functions are inserted and the local def table is populated, but before dataflow propagates the definitions.
cfgNodesInPostOrder | a list of all the CFG nodes in the function, in postorder. |
|
private |
Take all the outgoing defs from previous nodes and merge them as the incoming defs of the current node.
|
private |
Performs the data-flow update for one individual node, populating the reachingDefsTable for that node.
|
private |
Once all the reaching def information has been propagated, uses the reaching def information and the local use information to match uses to their reaching defs.
cfgNodesInPostOrder | all the nodes for which uses should be matched to defs |
|
staticprivate |
Iterates all the CFG nodes in the function and returns them in postorder, according to depth-first search.
Reverse postorder is the most efficient order for dataflow propagation.
|
private |
Insert definitions at function call sites for all variables defined interprocedurally.
Iterates on the call graph until the definitions converge (hence it works with recursion).
interestinFunctions | all functions that should be analyzed. |
|
private |
This function returns the order in which functions should be processed so that callees are processed before callers whenever possible (this is sometimes not possible due to recursion).
Internally, it builds a call graph and constructs a depth-first ordering of it.
|
private |
Add all the callees of the function to the processing list, then add the function itself.
Does nothing if the function is already in the list.
|
private |
Add definitions at function call expressions for variables that are modified interprocedurally.
The definitions are inserted in the original def table.
funcDef | function whose body should be queries for function calls |
processed | all the functions completely processed by SSA. If a callee is one of these functions, we can use exact information. |
|
private |
Insert the interprocedural defs at a particular call site for a particular callee.
This function may be called multiple times for the same call site with different callees (e.g. in the case of virtual functions). The call site should either be a SgFunctionCallExp or SgConstructorInitializer
processed | functions already processed by SSA |
|
staticprivate |
Given a variable that is in a callee's scope, returns true if the caller can access the same variable, false otherwise.
callSite | either a SgFunctionCallExp or SgConstructorInitializer. |
|
staticprivate |
Returns true if the variable is a nonstatic class variable, so it hass to be accessed by the "this" pointer.
|
staticprivate |
Returns true if the callee is acting on the same object instance as the caller.
|
staticprivate |
Returns true of the given expression evaluates to the 'this' pointer.
False otherwise. This function is conservative; it will return false if it cannot statically determine that the expression is equivalent to the 'This' pointe.
|
staticprivate |
True if the type is a const pointer pointing to a const object.
Expanded recursively
|
staticprivate |
True if the type is a pointer pointing to a const object.
Expanded recursively.
|
staticprivate |
Returns true if the given formal parameter is a reference or a nonconst pointer, so that it its value is aliased between function calls.
|
private |
|
private |
void StaticSingleAssignment::toDOT | ( | const std::string | fileName) |
Print the CFG with any UniqueNames and Def/Use information visible.
fileName | The filename to save graph as. Filenames will be prepended. |
void StaticSingleAssignment::toFilteredDOT | ( | const std::string | fileName) |
Print the CFG with any UniqueNames and Def/Use information visible.
This will only print the nodes that are of interest to the filter function used by the def/use traversal.
fileName | The filename to save graph as. Filenames will be prepended. |
void StaticSingleAssignment::printOriginalDefs | ( | SgNode * | node) |
void StaticSingleAssignment::printOriginalDefTable | ( | ) |
|
inline |
Get the table of definitions for every node.
These definitions are NOT propagated.
Definition at line 342 of file staticSingleAssignment.h.
|
inline |
Definition at line 347 of file staticSingleAssignment.h.
const NodeReachingDefTable& StaticSingleAssignment::getOutgoingDefsAtNode | ( | SgNode * | node) | const |
Returns the definitions of all the variables right after the given node has executed.
This function does not work correctly for "container" nodes such as SgBasicBlock, SgCommaOp, SgExprStmt. If there is a definition at the node itself, e.g. SgAssignOp, it is included in the outgoing defs.
const NodeReachingDefTable& StaticSingleAssignment::getReachingDefsAtNode_ | ( | SgNode * | node) | const |
Returns the definitions of all the variables immediately before the given node has executed.
If there is a definition at the node itself, e.g. SgAssignOp, it is not included in the reaching defs.
const NodeReachingDefTable& StaticSingleAssignment::getUsesAtNode | ( | SgNode * | node) | const |
Returns a list of all the variables used at this node.
Note that uses don't propagate past an SgStatement. Each use is mapped to the reaching definition to which the use corresponds.
const NodeReachingDefTable& StaticSingleAssignment::getDefsAtNode | ( | SgNode * | node) | const |
Returns a list of all the variables defined at the given node.
Note that this will return an empty collections for nodes that do not modify any variables. Compare this function to getReachingDefsAtNode.
Returns a set of all the variables names that have uses in the subtree.
Given a node, traverses all its children in the AST and collects all the variable names that have definitions in the subtree.
Given a node, traverses all its children in the AST and collects all the variable names that have original definitions in the subtree.
Expanded definitions are not included - for example if p.x is defined, p is not included.
NodeReachingDefTable StaticSingleAssignment::getLastVersions | ( | SgFunctionDeclaration * | func) | const |
Returns the last encountered definition of every variable.
Variables go out of scope, so quering for reaching definitions at the end of a function doesn't return the last versions of all variables.
Find if the given prefix is a prefix of the given name.
This will return whether the given name has the given prefix inside it.
ex. a.b.c has prefix a.b, but not a.c
name | The name to search. |
prefix | The prefix to search for. |
|
static |
Get the uniqueName attribute for the given node.
node | Node to get the attribute from. |
Get the variable name of the given node.
node | The node to get the name for. |
If an expression evaluates to a reference of a variable, returns that variable.
Handles casts, comma ops, address of ops, etc. For example, Given the expression (...., &a), this method would return the VarName for a.
|
static |
Get an AST fragment containing the appropriate varRefs and Dot/Arrow ops to access the given variable.
var | The variable to construct access for. |
scope | The scope within which to construct the access. |
Finds the scope of the given node, and returns true if the given variable is accessible there.
False if the variable is not accessible.
|
static |
Get a string representation of a varName.
vec | varName to get string for. |
|
static |
|
private |
The project to perform SSA Analysis on.
Definition at line 66 of file staticSingleAssignment.h.
|
private |
This is the table of variable definition locations that is generated by the VarDefUseTraversal.
It is later used to populate the actual def/use table. It maps each node to the variable names that are defined inside that node.
Definition at line 100 of file staticSingleAssignment.h.
|
private |
This is the table of definitions that is expanded from the original table.
It is used to populate the actual def/use table. It maps each node to the variable names that are defined inside that node.
Definition at line 106 of file staticSingleAssignment.h.
|
private |
Maps each node to the reaching definitions at that node.
The table is populated with phi functions using iterated dominance frontiers, and then is filled through dataflow.
Definition at line 111 of file staticSingleAssignment.h.
|
private |
This is the table that is populated with all the use information for all the variables at all the nodes.
It is populated during the runDefUse function, and is done with the steady-state dataflow algorithm. For each node, the table contains all the variables that were used at that node, and maps them to the reaching definitions for each use.
Definition at line 119 of file staticSingleAssignment.h.
|
private |
Map from each node to the variables used at that node and their reaching definitions.
Definition at line 122 of file staticSingleAssignment.h.
|
private |
Local definitions (actual definitions, not phi definitions).
This table does not get populated until AFTER interprocedural propagation; hence the values here cannot be used during interprocedural analysis.
Definition at line 127 of file staticSingleAssignment.h.
|
static |
Definition at line 310 of file staticSingleAssignment.h.