Program Listing for File InterproceduralInfo.h#
↰ Return to documentation for file (src/midend/programAnalysis/staticInterproceduralSlicing/InterproceduralInfo.h)
#ifndef __INTERPROCEDURAL_INFO_H__ // added by HK
#define __INTERPROCEDURAL_INFO_H__ // added by HK
#include <AstInterface.h>
#include <StmtInfoCollect.h>
#include <ReachingDefinition.h>
#include <DefUseChain.h>
#include "CallGraph.h"
#include <ostream>
#include <string>
#include <map>
#include <utility>
#include <set>
#include "DominanceFrontier.h"
#include "SimpleDirectedGraph.h"
// #include "rose.h"
// #include "../newImDomImpl/filteredCFG.h"
#include <virtualCFG.h>
#include "filteredCFG.h"
#include "DominatorTree.h"
#include "DominanceFrontier.h"
// #define VERBOSE_DEBUG
/* ! \class InterproceduralInfo
This class holds information necessary to perform interprocedural slicing.
As specified in the paper by Horowitz et al, every function in a program
requires: - An "entry" node - A "formal-in" node for each parameter - A
"formal-out" node for each return parameter
Similarly, every function call in a procedure requires: - A "call-site"
node - An "actual-in" node for every argument to the function - An
"actual-out" node for every return variable
There should be one InterproceduralInfo object associated with each
procedure in a program. It is initialized by passing in a newly created
object to the constructor of a ControlDependenceGraph. It must then be
passed to the constructor of a DataDependenceGraph. At this point, it
contains all the appropriate intraprocedural edges and nodes as specified
above.
*/
class InterproceduralInfo
{
public:
static SgNode * identifyEntryNode(SgFunctionDeclaration * dec)
{
if (dec->get_definition()!=NULL)
{
return dec->get_definition();
}
else
{
return dec;
}
}
static SgNode * identifyEntryNode(SgFunctionDefinition * def)
{
return def;
}
public:
// ! the nodes required to fully represent a call site in the PDG
struct CallSiteStructure
{
SgNode* sliceImportantNode;
SgNode* sgFunctionCallExpNode;
SgNode* sgCallInterestingNode;
// ! the callsite - one per SgFunctionCallExp
// ! the actual-in nodes - one per argument
std::vector<SgExpression*> actual_in;
// std::vector<SgExpression*
// ! the actual-out nodes - one per argument
// ! a list which records the order of the function arguments
// std::list < SgExpression * >expr_order;
// ! an actual-out node representing the return value of the function
// call
SgNode *actual_return;
};
void setCallInterestingNode(int id,SgNode * node)
{
callSites[id].sgCallInterestingNode=node;
}
SgNode * getCallInterestingNode(int id)
{
return callSites[id].sgCallInterestingNode;
}
SgNode * getActualReturn(int id)
{
return callSites[id].actual_return;
}
SgNode * getActualIn(int id,int varNr)
{
return callSites[id].actual_in[varNr];
}
int getActualInCount(int id)
{
return callSites[id].actual_in.size();
}
void addActualIn(int id,SgExpression * node)
{
callSites[id].actual_in.push_back(node);
}
void setSliceImportantNode(int id,SgNode * node)
{
callSites[id].sliceImportantNode=node;
}
void setActualReturn(int id,SgNode * node)
{
callSites[id].actual_return=node;
}
SgNode * getSliceImportantFunctionCallNode(int i)
{
return callSites[i].sliceImportantNode;
}
std::set<SgNode *> getExitNodes()
{
return exitNodes;
}
void addParameterToFunctionCall(SgNode * functionCall,SgExpression * param)
{
}
int callSiteCount()
{
return callSites.size();
}
SgNode * getFunctionCallExpNode(int i)
{
return callSites[i].sgFunctionCallExpNode;
}
SgNode * getFunctionEntry()
{
return entry;
}
void setEllipse(SgNode * formal)
{
ellipseNode=formal;
}
SgNode* getEllipse()
{
return ellipseNode;
}
protected:
SgFunctionDeclaration * decl;
SgFunctionDefinition * def;
SgNode * entry;
// ! the nodes required to fully represent a procedure entry in the PDG
// ! an entry node - one per function declaration
// ! the formal-in nodes - one per function parameter
// ! the formal-out nodes - one per function parameter
// ! a list which records the order of the parameters
std::list < SgInitializedName * >arg_order;
// ! a formal out node representing the return value of the function
SgNode * formal_return;
std::vector<SgNode*> formal;
SgNode * ellipseNode;
// list containing the nodes from the function that exit...
std::set<SgNode *> exitNodes;
// ! The entry node for a procedure
// ProcedureEntryStructure procedureEntry;
std::vector<CallSiteStructure> callSites;
std::map<SgNode *, int> callSitesMap;
public:
bool isUndefined()
{
if (def==NULL) return true;
else return false;
}
int getFormalCount()
{
return formal.size();
}
SgNode * getFormal(int nr)
{
if (formal.size()>(unsigned int)nr && nr>=0)
return formal[nr];
ROSE_ABORT();
}
void setFormalReturn(SgNode * node)
{
formal_return=node;
}
SgNode * getFormalReturn()
{
return formal_return;
}
// add this DependenceNode to the list of nodes which lead to exiting this function
void addExitNode(SgNode * node)
{
exitNodes.insert(node);
}/*
void createSafeConfiguration()
{
DependenceNode * formalIn,*formalOut,*entry,*formalReturn;
entry=getNode(DependenceNode::ENTRY,getFunctionEntry());
formalReturn=getNode(DependenceNode::FORMALOUT,getFormalReturn());
// this is done for "unknown" functions
for (int i=0;i<getFormalCount();i++)
{
formalIn=getNode(DependenceNode::FORMALIN,getFormal(i));
formalOut=getNode(DependenceNode::FORMALOUT,getFormal(i));
// create connection formalin->return
establishEdge(formalIn,entry,DATA);
establishEdge(formalIn,fornalOut,DATA);
establishEdge(formalIn,formalReturn,DATA);
}
}
*/
InterproceduralInfo(SgFunctionDeclaration* functionDeclaration)
{
#ifdef VERBOSE_DEBUG
std::cout << "creating interprocedural info for " << functionDeclaration->get_name().getString() << "\n";
#endif
decl=functionDeclaration;
def=functionDeclaration->get_definition();
if (def==NULL) entry=decl;
else entry=def;
// create formal stuff
formal_return=functionDeclaration;/*->get_type()->get_return_type();*/
ellipseNode=NULL;
Rose_STL_Container<SgInitializedName*> argList=functionDeclaration->get_args();
for (Rose_STL_Container<SgInitializedName*>::iterator i=argList.begin();i!=argList.end();i++)
{
if (isSgTypeEllipse((*i)->get_type()))
{
ellipseNode=*i;
}
else
{
#ifdef VERBOSE_DEBUG
std::cout << "\tadding formal in "<<*i<<"\n";
#endif
formal.push_back(*i);
}
}
}
/* ! \brief Gets the function declaration that the InterproceduralInfo object is for.
Returns: The SgFunctionDeclaration node that is associated with this object */
SgFunctionDeclaration * foo(){return decl;}
SgFunctionDefinition * getFunctionDefinition()
{ return def;}
SgFunctionDeclaration * getFunctionDeclaration()
{
return decl;
}
// adds an function call to the tracking list, this will alter on be used to analyse the calls site in the ...
// void addFunctionCall(SgNode * sliceImportantNode,SgNode * functionCall,SgNode * actualReturnIdentifier=NULL)
int addFunctionCall(SgNode * functionCall)
{
CallSiteStructure cs;
cs.sliceImportantNode=NULL;//sliceImportantNode;
cs.sgFunctionCallExpNode=functionCall;
// cs.callSiteDepNode=NULL;
cs.actual_return=NULL;
callSites.push_back(cs);
callSitesMap[functionCall]=callSites.size()-1;
return callSites.size()-1;
}
/* static std::list < SgFunctionCallExp * >extractFunctionCalls(SgNode * node)
{
std::list < SgFunctionCallExp * >retval;
std::list < SgNode * >calls = NodeQuery::querySubTree(node, V_SgFunctionCallExp);
for (std::list < SgNode * >::iterator i = calls.begin(); i != calls.end(); i++)
{
SgFunctionCallExp *fce = isSgFunctionCallExp(*i);
ROSE_ASSERT(fce != NULL);
retval.push_back(fce);
}
return retval;
}*/
// ! maps function calls to the call site structure that represents them
// std::map < SgFunctionCallExp *, CallSiteStructure > callsite_map;
};
#endif // #ifndef __INTERPROCEDURAL_INFO_H__ // added by HK