diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/Analysis/CallGraph.h | 59 | ||||
| -rw-r--r-- | llvm/lib/Analysis/IPA/CallGraph.cpp | 203 | 
2 files changed, 57 insertions, 205 deletions
diff --git a/llvm/include/llvm/Analysis/CallGraph.h b/llvm/include/llvm/Analysis/CallGraph.h index 60649f9ed9d..305d43dd758 100644 --- a/llvm/include/llvm/Analysis/CallGraph.h +++ b/llvm/include/llvm/Analysis/CallGraph.h @@ -14,17 +14,20 @@  // callgraph node keeps track of which functions the are called by the function  // corresponding to the node.  // -// A call graph will contain nodes where the function that they correspond to is -// null.  This 'external' node is used to represent control flow that is not -// represented (or analyzable) in the module.  As such, the external node will -// have edges to functions with the following properties: -//   1. All functions in the module without internal linkage, since they could -//      be called by functions outside of the our analysis capability. +// A call graph may contain nodes where the function that they correspond to is +// null.  These 'external' nodes are used to represent control flow that is not +// represented (or analyzable) in the module.  In particular, this analysis +// builds one external node such that: +//   1. All functions in the module without internal linkage will have edges +//      from this external node, indicating that they could be called by +//      functions outside of the module.  //   2. All functions whose address is used for something more than a direct -//      call, for example being stored into a memory location.  Since they may -//      be called by an unknown caller later, they must be tracked as such. +//      call, for example being stored into a memory location will also have an +//      edge from this external node.  Since they may be called by an unknown +//      caller later, they must be tracked as such.  // -// Similarly, functions have a call edge to the external node iff: +// There is a second external node added for calls that leave this module. +// Functions have a call edge to the external node iff:  //   1. The function is external, reflecting the fact that they could call  //      anything without internal linkage or that has its address taken.  //   2. The function contains an indirect function call. @@ -68,9 +71,18 @@ class CallGraph : public Pass {    FunctionMapTy FunctionMap;    // Map from a function to its node    // Root is root of the call graph, or the external node if a 'main' function -  // couldn't be found.  ExternalNode is equivalent to (*this)[0]. +  // couldn't be found.    // -  CallGraphNode *Root, *ExternalNode; +  CallGraphNode *Root; + +  // ExternalCallingNode - This node has edges to all external functions and +  // those internal functions that have their address taken. +  CallGraphNode *ExternalCallingNode; + +  // CallsExternalNode - This node has edges to it from all functions making +  // indirect calls or calling an external function. +  CallGraphNode *CallsExternalNode; +  public:    //===--------------------------------------------------------------------- @@ -79,11 +91,8 @@ public:    typedef FunctionMapTy::iterator iterator;    typedef FunctionMapTy::const_iterator const_iterator; -  // getExternalNode - Return the node that points to all functions that are -  // accessable from outside of the current program. -  // -        CallGraphNode *getExternalNode()       { return ExternalNode; } -  const CallGraphNode *getExternalNode() const { return ExternalNode; } +  CallGraphNode *getExternalCallingNode() const { return ExternalCallingNode; } +  CallGraphNode *getCallsExternalNode()   const { return CallsExternalNode; }    // getRoot - Return the root of the call graph, which is either main, or if    // main cannot be found, the external node. @@ -215,17 +224,19 @@ public:      CalledFunctions.clear();    } -private:                    // Stuff to construct the node, used by CallGraph -  friend class CallGraph; - -  // CallGraphNode ctor - Create a node for the specified function... -  inline CallGraphNode(Function *f) : F(f) {} -      // addCalledFunction add a function to the list of functions called by this    // one    void addCalledFunction(CallGraphNode *M) {      CalledFunctions.push_back(M);    } + +  void removeCallEdgeTo(CallGraphNode *Callee); + +private:                    // Stuff to construct the node, used by CallGraph +  friend class CallGraph; + +  // CallGraphNode ctor - Create a node for the specified function... +  inline CallGraphNode(Function *f) : F(f) {}  }; @@ -257,7 +268,7 @@ template <> struct GraphTraits<const CallGraphNode*> {  template<> struct GraphTraits<CallGraph*> : public GraphTraits<CallGraphNode*> {    static NodeType *getEntryNode(CallGraph *CGN) { -    return CGN->getExternalNode();  // Start at the external node! +    return CGN->getExternalCallingNode();  // Start at the external node!    }    typedef std::pair<const Function*, CallGraphNode*> PairTy;    typedef std::pointer_to_unary_function<PairTy, CallGraphNode&> DerefFun; @@ -279,7 +290,7 @@ template<> struct GraphTraits<CallGraph*> : public GraphTraits<CallGraphNode*> {  template<> struct GraphTraits<const CallGraph*> :    public GraphTraits<const CallGraphNode*> {    static NodeType *getEntryNode(const CallGraph *CGN) { -    return CGN->getExternalNode(); +    return CGN->getExternalCallingNode();    }    // nodes_iterator/begin/end - Allow iteration over all nodes in the graph    typedef CallGraph::const_iterator nodes_iterator; diff --git a/llvm/lib/Analysis/IPA/CallGraph.cpp b/llvm/lib/Analysis/IPA/CallGraph.cpp index 506198c4fa2..8d660b99fb3 100644 --- a/llvm/lib/Analysis/IPA/CallGraph.cpp +++ b/llvm/lib/Analysis/IPA/CallGraph.cpp @@ -7,41 +7,7 @@  //   //===----------------------------------------------------------------------===//  // -// This interface is used to build and manipulate a call graph, which is a very  -// useful tool for interprocedural optimization. -// -// Every function in a module is represented as a node in the call graph.  The -// callgraph node keeps track of which functions the are called by the function -// corresponding to the node. -// -// A call graph will contain nodes where the function that they correspond to is -// null.  This 'external' node is used to represent control flow that is not -// represented (or analyzable) in the module.  As such, the external node will -// have edges to functions with the following properties: -//   1. All functions in the module without internal linkage, since they could -//      be called by functions outside of the our analysis capability. -//   2. All functions whose address is used for something more than a direct -//      call, for example being stored into a memory location.  Since they may -//      be called by an unknown caller later, they must be tracked as such. -// -// Similarly, functions have a call edge to the external node iff: -//   1. The function is external, reflecting the fact that they could call -//      anything without internal linkage or that has its address taken. -//   2. The function contains an indirect function call. -// -// As an extension in the future, there may be multiple nodes with a null -// function.  These will be used when we can prove (through pointer analysis) -// that an indirect call site can call only a specific set of functions. -// -// Because of these properties, the CallGraph captures a conservative superset -// of all of the caller-callee relationships, which is useful for -// transformations. -// -// The CallGraph class also attempts to figure out what the root of the -// CallGraph is, which is currently does by looking for a function named 'main'. -// If no function named 'main' is found, the external node is used as the entry -// node, reflecting the fact that any function without internal linkage could -// be called into (which is common for libraries). +//  This file implements the CallGraph class.  //  //===----------------------------------------------------------------------===// @@ -52,143 +18,10 @@  #include "llvm/iTerminators.h"  #include "llvm/Support/CallSite.h"  #include "Support/STLExtras.h" - -namespace llvm { +using namespace llvm;  static RegisterAnalysis<CallGraph> X("callgraph", "Call Graph Construction"); -static const char * const KnownExternalFunctions[] = { -  // Low-level system calls -  "open", -  "read", -  "write", -  "writev", -  "lseek", -  "poll", -  "ioctl", - -  // Low-level stdc library functions -  "abort", "exit", -  "getenv", "putenv", -   -  // Standard IO functions -  "printf", -  "sprintf", -  "fopen", -  "freopen", -  "fclose", -  "fwrite", -  "puts", -  "fputs", -  "getc", -  "ungetc", -  "putc", -  "putchar", -  "fread", -  "fileno", -  "ftell", -  "fflush", -  "fseek", -  "fileno", -  "ferror", -  "feof", -  "fdopen", -  "__fxstat", -  "setbuf", -  "setbuffer", -  "etlinebuf", -  "setvbuf", - -  // Memory functions -  "malloc", -  "free", -  "realloc", -  "calloc", -  "memalign", -   -  // String functions -  "atoi", -  "memmove", -  "memset", -  "memchr", -  "memcmp", -  "strchr", -  "strncpy", -  "strncmp", -  "strcmp", -  "strtok", -  "__strcoll_l", -  "__strxfrm_l", -  "__strftime_l", -  "__strtol_l", -  "__strtoul_l", -  "__strtoll_l", -  "__strtoull_l", -  "__strtof_l", -  "__strtod_l", -  "__strtold_l", -  "isalpha", - -  // Math functions -  "exp", "sqrt", "cbrt", "hypot", -  "log", "log10", "pow", -  "sin", "cos", "tan", -  "asin", "acos", "atan", "atan2", - -  // Locale functions -  "__uselocale", -  "__newlocale", -  "__freelocale", -  "__duplocale", -  "__nl_langinfo_l", - -  // gettext functions used by libstdc++ -  "gettext", -  "dgettext", -  "dcgettext", -  "textdomain", -  "bindtextdomain", -   -  // Random stuff -  "__assert_fail", -  "__errno_location", -  "clock", "time", -  "__main", -}; - - -/// ExternalFunctionDoesntCallIntoProgram - This hack is used to indicate to the -/// call graph that the specified external function is _KNOWN_ to not call back -/// into the program.  This is important, because otherwise functions which call -/// "printf" for example, end up in a great big SCC that goes from the function -/// through main. -/// -static bool ExternalFunctionDoesntCallIntoProgram(const std::string &Name) { -  static std::vector<std::string> Funcs; - -  // First time this is called? -  if (Funcs.empty()) { -    // Add a whole bunch of functions which are often used... -    Funcs.insert(Funcs.end(), KnownExternalFunctions, -                 KnownExternalFunctions+ -              sizeof(KnownExternalFunctions)/sizeof(KnownExternalFunctions[0])); -    // Sort the list for efficient access -    std::sort(Funcs.begin(), Funcs.end()); -  } - -  if (Name.size() > 7 && !memcmp("__llvm_", Name.c_str(), 7)) -    return true; - -  // Binary search for the function name... -  std::vector<std::string>::iterator I = -    std::lower_bound(Funcs.begin(), Funcs.end(), Name); - -  // Found it? -  return I != Funcs.end() && *I == Name; -} - - -  // getNodeFor - Return the node for the specified function or create one if it  // does not already exist.  // @@ -215,12 +48,12 @@ void CallGraph::addToCallGraph(Function *F) {    // If this function has external linkage, anything could call it...    if (!F->hasInternalLinkage()) { -    ExternalNode->addCalledFunction(Node); +    ExternalCallingNode->addCalledFunction(Node);      // Found the entry point?      if (F->getName() == "main") { -      if (Root) -        Root = ExternalNode;  // Found multiple external mains?  Don't pick one. +      if (Root)    // Found multiple external mains?  Don't pick one. +        Root = ExternalCallingNode;        else          Root = Node;          // Found a main, keep track of it!      } @@ -228,9 +61,8 @@ void CallGraph::addToCallGraph(Function *F) {    // If this function is not defined in this translation unit, it could call    // anything. -  if (F->isExternal() && !F->getIntrinsicID() &&  -      !ExternalFunctionDoesntCallIntoProgram(F->getName())) -    Node->addCalledFunction(ExternalNode); +  if (F->isExternal() && !F->getIntrinsicID()) +    Node->addCalledFunction(CallsExternalNode);    // Loop over all of the users of the function... looking for callers...    // @@ -259,14 +91,14 @@ void CallGraph::addToCallGraph(Function *F) {      }    }    if (isUsedExternally) -    ExternalNode->addCalledFunction(Node); +    ExternalCallingNode->addCalledFunction(Node);    // Look for an indirect function call...    for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB)      for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE; ++II){        CallSite CS = CallSite::get(II);        if (CS.getInstruction() && !CS.getCalledFunction()) -        Node->addCalledFunction(ExternalNode); +        Node->addCalledFunction(CallsExternalNode);      }  } @@ -274,7 +106,8 @@ bool CallGraph::run(Module &M) {    destroy();    Mod = &M; -  ExternalNode = getNodeFor(0); +  ExternalCallingNode = getNodeFor(0); +  CallsExternalNode = new CallGraphNode(0);    Root = 0;    // Add every function to the call graph... @@ -282,7 +115,7 @@ bool CallGraph::run(Module &M) {      addToCallGraph(I);    // If we didn't find a main function, use the external call graph node -  if (Root == 0) Root = ExternalNode; +  if (Root == 0) Root = ExternalCallingNode;    return false;  } @@ -328,7 +161,7 @@ void CallGraph::print(std::ostream &o, const Module *M) const {  // Functions to keep a call graph up to date with a function that has been  // modified  // -void CallGraph::addFunctionToModule(Function *Meth) { +void CallGraph::addFunctionToModule(Function *F) {    assert(0 && "not implemented");    abort();  } @@ -352,4 +185,12 @@ Function *CallGraph::removeFunctionFromModule(CallGraphNode *CGN) {  void CallGraph::stub() {} -} // End llvm namespace +void CallGraphNode::removeCallEdgeTo(CallGraphNode *Callee) { +  for (unsigned i = CalledFunctions.size(); ; --i) { +    assert(i && "Cannot find callee to remove!"); +    if (CalledFunctions[i-1] == Callee) { +      CalledFunctions.erase(CalledFunctions.begin()+i-1); +      return; +    } +  } +}  | 

