blob: 5618a747faefddeba55740fa782e89e37b48b334 [file] [log] [blame]
Chris Lattner8d5a16c2002-03-06 18:00:49 +00001//===- CallGraph.cpp - Build a Module's call graph ------------------------===//
Chris Lattner41fbf302001-09-28 00:08:15 +00002//
3// This file implements call graph construction (from a module), and will
4// eventually implement call graph serialization and deserialization for
5// annotation support.
6//
Chris Lattner9f9e2be2001-10-13 06:33:19 +00007// This call graph represents a dynamic method invocation as a null method node.
8// A call graph may only have up to one null method node that represents all of
9// the dynamic method invocations.
10//
Chris Lattner41fbf302001-09-28 00:08:15 +000011//===----------------------------------------------------------------------===//
12
13#include "llvm/Analysis/CallGraph.h"
Chris Lattner41fbf302001-09-28 00:08:15 +000014#include "llvm/Module.h"
15#include "llvm/Method.h"
16#include "llvm/iOther.h"
Chris Lattner9f9e2be2001-10-13 06:33:19 +000017#include "llvm/iTerminators.h"
Chris Lattner221d6882002-02-12 21:07:25 +000018#include "llvm/Support/InstIterator.h"// FIXME: CallGraph should use method uses
Chris Lattnercee8f9a2001-11-27 00:03:19 +000019#include "Support/STLExtras.h"
Chris Lattner41fbf302001-09-28 00:08:15 +000020#include <algorithm>
Chris Lattner8d5a16c2002-03-06 18:00:49 +000021#include <iostream>
Chris Lattner41fbf302001-09-28 00:08:15 +000022
Chris Lattner4ce0f8a2002-03-06 17:16:43 +000023AnalysisID CallGraph::ID(AnalysisID::create<CallGraph>());
Chris Lattner93193f82002-01-31 00:42:27 +000024
Chris Lattner41fbf302001-09-28 00:08:15 +000025// getNodeFor - Return the node for the specified method or create one if it
26// does not already exist.
27//
Chris Lattner4ce0f8a2002-03-06 17:16:43 +000028CallGraphNode *CallGraph::getNodeFor(Method *M) {
Chris Lattner41fbf302001-09-28 00:08:15 +000029 iterator I = MethodMap.find(M);
30 if (I != MethodMap.end()) return I->second;
31
32 assert(M->getParent() == Mod && "Method not in current module!");
33 CallGraphNode *New = new CallGraphNode(M);
34
Chris Lattner697954c2002-01-20 22:54:45 +000035 MethodMap.insert(std::make_pair(M, New));
Chris Lattner41fbf302001-09-28 00:08:15 +000036 return New;
37}
38
39// addToCallGraph - Add a method to the call graph, and link the node to all of
40// the methods that it calls.
41//
Chris Lattner4ce0f8a2002-03-06 17:16:43 +000042void CallGraph::addToCallGraph(Method *M) {
Chris Lattner41fbf302001-09-28 00:08:15 +000043 CallGraphNode *Node = getNodeFor(M);
44
Chris Lattner25e9cad2001-11-26 18:51:25 +000045 // If this method has external linkage,
46 if (!M->hasInternalLinkage())
47 Root->addCalledMethod(Node);
48
Chris Lattner221d6882002-02-12 21:07:25 +000049 for (inst_iterator I = inst_begin(M), E = inst_end(M); I != E; ++I) {
Chris Lattner9f9e2be2001-10-13 06:33:19 +000050 // Dynamic calls will cause Null nodes to be created
51 if (CallInst *CI = dyn_cast<CallInst>(*I))
Chris Lattner41fbf302001-09-28 00:08:15 +000052 Node->addCalledMethod(getNodeFor(CI->getCalledMethod()));
Chris Lattner9f9e2be2001-10-13 06:33:19 +000053 else if (InvokeInst *II = dyn_cast<InvokeInst>(*I))
54 Node->addCalledMethod(getNodeFor(II->getCalledMethod()));
Chris Lattner41fbf302001-09-28 00:08:15 +000055 }
56}
57
Chris Lattner4ce0f8a2002-03-06 17:16:43 +000058bool CallGraph::run(Module *TheModule) {
Chris Lattner93193f82002-01-31 00:42:27 +000059 destroy();
60
Chris Lattner41fbf302001-09-28 00:08:15 +000061 Mod = TheModule;
62
Chris Lattner25e9cad2001-11-26 18:51:25 +000063 // Create the root node of the module...
64 Root = new CallGraphNode(0);
65
Chris Lattner41fbf302001-09-28 00:08:15 +000066 // Add every method to the call graph...
67 for_each(Mod->begin(), Mod->end(), bind_obj(this,&CallGraph::addToCallGraph));
Chris Lattner93193f82002-01-31 00:42:27 +000068
69 return false;
Chris Lattner41fbf302001-09-28 00:08:15 +000070}
71
Chris Lattner4ce0f8a2002-03-06 17:16:43 +000072void CallGraph::destroy() {
Chris Lattner25e9cad2001-11-26 18:51:25 +000073 for (MethodMapTy::iterator I = MethodMap.begin(), E = MethodMap.end();
74 I != E; ++I) {
75 delete I->second;
76 }
Chris Lattner93193f82002-01-31 00:42:27 +000077 MethodMap.clear();
Chris Lattner25e9cad2001-11-26 18:51:25 +000078}
79
Chris Lattner41fbf302001-09-28 00:08:15 +000080
Chris Lattner4ce0f8a2002-03-06 17:16:43 +000081void WriteToOutput(const CallGraphNode *CGN, std::ostream &o) {
Chris Lattner25e9cad2001-11-26 18:51:25 +000082 if (CGN->getMethod())
83 o << "Call graph node for method: '" << CGN->getMethod()->getName() <<"'\n";
84 else
85 o << "Call graph node null method:\n";
86
Chris Lattner41fbf302001-09-28 00:08:15 +000087 for (unsigned i = 0; i < CGN->size(); ++i)
88 o << " Calls method '" << (*CGN)[i]->getMethod()->getName() << "'\n";
Chris Lattner697954c2002-01-20 22:54:45 +000089 o << "\n";
Chris Lattner41fbf302001-09-28 00:08:15 +000090}
91
Chris Lattner4ce0f8a2002-03-06 17:16:43 +000092void WriteToOutput(const CallGraph &CG, std::ostream &o) {
Chris Lattner25e9cad2001-11-26 18:51:25 +000093 WriteToOutput(CG.getRoot(), o);
Chris Lattner41fbf302001-09-28 00:08:15 +000094 for (CallGraph::const_iterator I = CG.begin(), E = CG.end(); I != E; ++I)
95 o << I->second;
96}
Vikram S. Advea7edb182001-10-22 13:55:46 +000097
98
Chris Lattner25e9cad2001-11-26 18:51:25 +000099//===----------------------------------------------------------------------===//
100// Implementations of public modification methods
101//
102
103// Methods to keep a call graph up to date with a method that has been
104// modified
105//
Chris Lattner4ce0f8a2002-03-06 17:16:43 +0000106void CallGraph::addMethodToModule(Method *Meth) {
Chris Lattner25e9cad2001-11-26 18:51:25 +0000107 assert(0 && "not implemented");
108 abort();
109}
110
111// removeMethodFromModule - Unlink the method from this module, returning it.
112// Because this removes the method from the module, the call graph node is
113// destroyed. This is only valid if the method does not call any other
114// methods (ie, there are no edges in it's CGN). The easiest way to do this
115// is to dropAllReferences before calling this.
116//
Chris Lattner4ce0f8a2002-03-06 17:16:43 +0000117Method *CallGraph::removeMethodFromModule(CallGraphNode *CGN) {
Chris Lattner25e9cad2001-11-26 18:51:25 +0000118 assert(CGN->CalledMethods.empty() && "Cannot remove method from call graph"
119 " if it references other methods!");
120 Method *M = CGN->getMethod(); // Get the method for the call graph node
121 delete CGN; // Delete the call graph node for this method
122 MethodMap.erase(M); // Remove the call graph node from the map
123
124 Mod->getMethodList().remove(M);
125 return M;
126}
127