[llvm-commits] [poolalloc] r160291 - in /poolalloc/trunk: include/assistDS/DataStructureCallGraph.h lib/AssistDS/DataStructureCallGraph.cpp

Matthew Wala mttjwl at gmail.com
Mon Jul 16 10:15:24 PDT 2012


Author: wala1
Date: Mon Jul 16 12:15:24 2012
New Revision: 160291

URL: http://llvm.org/viewvc/llvm-project?rev=160291&view=rev
Log:
Add a CallGraph implementation based on DSA.

Added:
    poolalloc/trunk/include/assistDS/DataStructureCallGraph.h
    poolalloc/trunk/lib/AssistDS/DataStructureCallGraph.cpp

Added: poolalloc/trunk/include/assistDS/DataStructureCallGraph.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/DataStructureCallGraph.h?rev=160291&view=auto
==============================================================================
--- poolalloc/trunk/include/assistDS/DataStructureCallGraph.h (added)
+++ poolalloc/trunk/include/assistDS/DataStructureCallGraph.h Mon Jul 16 12:15:24 2012
@@ -0,0 +1,108 @@
+//===- DataStructureCallGraph.h - Provide a CallGraph using DSA -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the DataStructureCallGraph implementation of the
+// CallGraph analysis. Based on llvm/lib/Analysis/IPA/CallGraph.cpp.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _DATA_STRUCTURE_CALLGRAPH_H
+#define _DATA_STRUCTURE_CALLGRAPH_H
+
+#include "dsa/CallTargets.h"
+#include "dsa/DataStructure.h"
+
+#include "llvm/Module.h"
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+class DataStructureCallGraph : public ModulePass, public CallGraph {
+  // Root is root of the call graph, or the external node if a 'main' function
+  // couldn't be found.
+  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;
+
+  typedef dsa::CallTargetFinder<TDDataStructures> CallTargetFinderTy;
+
+public:
+  static char ID;
+  DataStructureCallGraph() :
+    ModulePass(ID), Root(0), ExternalCallingNode(0), CallsExternalNode(0) { }
+
+  virtual bool runOnModule(Module &M);
+
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+    AU.addRequired<TDDataStructures>();
+    AU.addRequired<CallTargetFinderTy>();
+    AU.setPreservesAll();
+  }
+
+  virtual void print(raw_ostream &OS, const Module *) const {
+    OS << "CallGraph Root is: ";
+    if (Function *F = getRoot()->getFunction())
+      OS << F->getName() << "\n";
+    else {
+      OS << "<<null function: 0x" << getRoot() << ">>\n";
+    }
+    
+    CallGraph::print(OS, 0);
+  }
+
+  virtual void releaseMemory() {
+    destroy();
+  }
+  
+  // getAdjustedAnalysisPointer - This method is used when a pass implements an
+  // analysis interface through multiple inheritance. If needed, it should
+  // override this to adjust the this pointer as needed for the specified pass
+  // info.
+  virtual void *getAdjustedAnalysisPointer(AnalysisID PI) {
+    if (PI == &CallGraph::ID)
+      return (CallGraph*)this;
+    return this;
+  }
+  
+  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.
+  CallGraphNode *getRoot()             { return Root; }
+  const CallGraphNode *getRoot() const { return Root; }
+
+private:
+  // addToCallGraph - Add a function to the call graph, and link the node to all
+  // of the functions that it calls.
+  void addToCallGraph(Function *F);
+
+  // destroy - Release memory for the call graph
+  virtual void destroy() {
+    // CallsExternalNode is not in the function map, delete it explicitly.
+    if (CallsExternalNode) {
+      CallsExternalNode->allReferencesDropped();
+      delete CallsExternalNode;
+      CallsExternalNode = 0;
+    }
+    CallGraph::destroy();
+  }
+};
+
+}
+
+#endif // _DATA_STRUCTURE_CALLGRAPH_H

Added: poolalloc/trunk/lib/AssistDS/DataStructureCallGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/DataStructureCallGraph.cpp?rev=160291&view=auto
==============================================================================
--- poolalloc/trunk/lib/AssistDS/DataStructureCallGraph.cpp (added)
+++ poolalloc/trunk/lib/AssistDS/DataStructureCallGraph.cpp Mon Jul 16 12:15:24 2012
@@ -0,0 +1,123 @@
+//===- DataStructureCallGraph.cpp - Provide a CallGraph using DSA ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the DataStructureCallGraph implementation of the
+// CallGraph analysis. Based on llvm/lib/Analysis/IPA/CallGraph.cpp.
+//
+//===----------------------------------------------------------------------===//
+
+#include "assistDS/DataStructureCallGraph.h"
+#include "dsa/DSGraph.h"
+#include "dsa/DSNode.h"
+
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Support/CallSite.h"
+#include "llvm/Support/InstIterator.h"
+
+using namespace llvm;
+
+char DataStructureCallGraph::ID;
+
+static RegisterPass<DataStructureCallGraph>
+X("dsa-cg", "DSA-based CallGraph implementation");
+
+RegisterAnalysisGroup<CallGraph> Y(X); 
+
+bool DataStructureCallGraph::runOnModule(Module &M) {
+  CallGraph::initialize(M);
+
+  ExternalCallingNode = getOrInsertFunction(0);
+  CallsExternalNode = new CallGraphNode(0);
+  Root = 0;
+
+  // Add every function to the call graph.
+  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
+    addToCallGraph(I);
+
+  // If we didn't find a main function, use the external call graph node
+  if (Root == 0) Root = ExternalCallingNode;
+  
+  return false;
+}
+
+// Add a function to the call graph, and link the node to all of the functions
+// that it calls.
+void DataStructureCallGraph::addToCallGraph(Function *F) {
+  CallGraphNode *Node = getOrInsertFunction(F);
+
+  if (!F->hasLocalLinkage()) {
+    ExternalCallingNode->addCalledFunction(CallSite(), Node);
+
+    // Found the entry point?
+    if (F->getName() == "main") {
+      if (Root)    // Found multiple external mains?  Don't pick one.
+        Root = ExternalCallingNode;
+      else
+        Root = Node; // Found a main, keep track of it!
+    }
+  }
+
+  // If this function is not defined in this translation unit, it could call
+  // anything.
+  if (F->isDeclaration() && !F->isIntrinsic()) {
+    Node->addCalledFunction(CallSite(), CallsExternalNode);
+    return;
+  }
+
+  TDDataStructures &DS = getAnalysis<TDDataStructures>();
+  DSGraph &GG = *DS.getGlobalsGraph();
+  CallTargetFinderTy &CTF = getAnalysis<CallTargetFinderTy>();
+
+  // Determine if the function can be called by external code by looking up
+  // its DSNode in the globals graph. A node marked External, Unknown, or
+  // Incomplete has the possibility of being called from external code.
+  DSNode *N = GG.getNodeForValue(F).getNode();
+
+  if (N &&
+      (N->isExternalNode() ||
+       N->isUnknownNode() ||
+       N->isIncompleteNode())) {
+    ExternalCallingNode->addCalledFunction(CallSite(), Node);
+  }
+
+  // Go over the instructions in the function and determine the call targets
+  // for each call site.
+  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
+    CallSite CS(&*I);
+
+    // Only look through valid call sites that are not calls to intrinsics.
+    if (!CS || isa<IntrinsicInst>(&*I))
+      continue;
+
+    if (const Function *F = 
+        dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts())) {
+      // Direct call: Don't use DSA, just add the function we discovered as
+      // the call target.
+
+      Node->addCalledFunction(CS, getOrInsertFunction(F));
+    } else {
+      // Indirect call: Use CallTargetFinder to determine the set of targets to
+      // the indirect call site. Be conservative about incomplete call sites.
+
+      if (!CTF.isComplete(CS)) {
+        // Add CallsExternalNode as a target of incomplete call sites.
+        Node->addCalledFunction(CS, CallsExternalNode);
+      }
+
+      SmallPtrSet<const Function *, 16> Targets(CTF.begin(CS), CTF.end(CS));
+
+      for (SmallPtrSet<const Function *, 16>::const_iterator
+           TI = Targets.begin(), TE = Targets.end(); TI != TE; ++TI) {
+        Node->addCalledFunction(CS, getOrInsertFunction(*TI));
+      }
+    }
+  }
+}





More information about the llvm-commits mailing list