[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