1*0b57cec5SDimitry Andric //===- CallGraph.cpp - Build a Module's call graph ------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric
9*0b57cec5SDimitry Andric #include "llvm/Analysis/CallGraph.h"
10bdd1243dSDimitry Andric #include "llvm/ADT/SCCIterator.h"
11*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
12*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
13*0b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
145ffd83dbSDimitry Andric #include "llvm/IR/AbstractCallSite.h"
15*0b57cec5SDimitry Andric #include "llvm/IR/Function.h"
165ffd83dbSDimitry Andric #include "llvm/IR/IntrinsicInst.h"
17480093f4SDimitry Andric #include "llvm/IR/Module.h"
18*0b57cec5SDimitry Andric #include "llvm/IR/PassManager.h"
19480093f4SDimitry Andric #include "llvm/InitializePasses.h"
20*0b57cec5SDimitry Andric #include "llvm/Pass.h"
21*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
22*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
23*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
24*0b57cec5SDimitry Andric #include <cassert>
25*0b57cec5SDimitry Andric
26*0b57cec5SDimitry Andric using namespace llvm;
27*0b57cec5SDimitry Andric
28*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
29*0b57cec5SDimitry Andric // Implementations of the CallGraph class methods.
30*0b57cec5SDimitry Andric //
31*0b57cec5SDimitry Andric
CallGraph(Module & M)32*0b57cec5SDimitry Andric CallGraph::CallGraph(Module &M)
33*0b57cec5SDimitry Andric : M(M), ExternalCallingNode(getOrInsertFunction(nullptr)),
345ffd83dbSDimitry Andric CallsExternalNode(std::make_unique<CallGraphNode>(this, nullptr)) {
355ffd83dbSDimitry Andric // Add every interesting function to the call graph.
36*0b57cec5SDimitry Andric for (Function &F : M)
375ffd83dbSDimitry Andric if (!isDbgInfoIntrinsic(F.getIntrinsicID()))
38*0b57cec5SDimitry Andric addToCallGraph(&F);
39*0b57cec5SDimitry Andric }
40*0b57cec5SDimitry Andric
CallGraph(CallGraph && Arg)41*0b57cec5SDimitry Andric CallGraph::CallGraph(CallGraph &&Arg)
42*0b57cec5SDimitry Andric : M(Arg.M), FunctionMap(std::move(Arg.FunctionMap)),
43*0b57cec5SDimitry Andric ExternalCallingNode(Arg.ExternalCallingNode),
44*0b57cec5SDimitry Andric CallsExternalNode(std::move(Arg.CallsExternalNode)) {
45*0b57cec5SDimitry Andric Arg.FunctionMap.clear();
46*0b57cec5SDimitry Andric Arg.ExternalCallingNode = nullptr;
475ffd83dbSDimitry Andric
485ffd83dbSDimitry Andric // Update parent CG for all call graph's nodes.
495ffd83dbSDimitry Andric CallsExternalNode->CG = this;
505ffd83dbSDimitry Andric for (auto &P : FunctionMap)
515ffd83dbSDimitry Andric P.second->CG = this;
52*0b57cec5SDimitry Andric }
53*0b57cec5SDimitry Andric
~CallGraph()54*0b57cec5SDimitry Andric CallGraph::~CallGraph() {
55*0b57cec5SDimitry Andric // CallsExternalNode is not in the function map, delete it explicitly.
56*0b57cec5SDimitry Andric if (CallsExternalNode)
57*0b57cec5SDimitry Andric CallsExternalNode->allReferencesDropped();
58*0b57cec5SDimitry Andric
59*0b57cec5SDimitry Andric // Reset all node's use counts to zero before deleting them to prevent an
60*0b57cec5SDimitry Andric // assertion from firing.
61*0b57cec5SDimitry Andric #ifndef NDEBUG
62*0b57cec5SDimitry Andric for (auto &I : FunctionMap)
63*0b57cec5SDimitry Andric I.second->allReferencesDropped();
64*0b57cec5SDimitry Andric #endif
65*0b57cec5SDimitry Andric }
66*0b57cec5SDimitry Andric
invalidate(Module &,const PreservedAnalyses & PA,ModuleAnalysisManager::Invalidator &)675ffd83dbSDimitry Andric bool CallGraph::invalidate(Module &, const PreservedAnalyses &PA,
685ffd83dbSDimitry Andric ModuleAnalysisManager::Invalidator &) {
695ffd83dbSDimitry Andric // Check whether the analysis, all analyses on functions, or the function's
705ffd83dbSDimitry Andric // CFG have been preserved.
715ffd83dbSDimitry Andric auto PAC = PA.getChecker<CallGraphAnalysis>();
7281ad6265SDimitry Andric return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>());
735ffd83dbSDimitry Andric }
745ffd83dbSDimitry Andric
addToCallGraph(Function * F)75*0b57cec5SDimitry Andric void CallGraph::addToCallGraph(Function *F) {
76*0b57cec5SDimitry Andric CallGraphNode *Node = getOrInsertFunction(F);
77*0b57cec5SDimitry Andric
785ffd83dbSDimitry Andric // If this function has external linkage or has its address taken and
795ffd83dbSDimitry Andric // it is not a callback, then anything could call it.
805ffd83dbSDimitry Andric if (!F->hasLocalLinkage() ||
81fe6060f1SDimitry Andric F->hasAddressTaken(nullptr, /*IgnoreCallbackUses=*/true,
82fe6060f1SDimitry Andric /* IgnoreAssumeLikeCalls */ true,
83fe6060f1SDimitry Andric /* IgnoreLLVMUsed */ false))
84*0b57cec5SDimitry Andric ExternalCallingNode->addCalledFunction(nullptr, Node);
85*0b57cec5SDimitry Andric
865ffd83dbSDimitry Andric populateCallGraphNode(Node);
875ffd83dbSDimitry Andric }
885ffd83dbSDimitry Andric
populateCallGraphNode(CallGraphNode * Node)895ffd83dbSDimitry Andric void CallGraph::populateCallGraphNode(CallGraphNode *Node) {
905ffd83dbSDimitry Andric Function *F = Node->getFunction();
915ffd83dbSDimitry Andric
92*0b57cec5SDimitry Andric // If this function is not defined in this translation unit, it could call
93*0b57cec5SDimitry Andric // anything.
94bdd1243dSDimitry Andric if (F->isDeclaration() && !F->hasFnAttribute(Attribute::NoCallback))
95*0b57cec5SDimitry Andric Node->addCalledFunction(nullptr, CallsExternalNode.get());
96*0b57cec5SDimitry Andric
97*0b57cec5SDimitry Andric // Look for calls by this function.
98*0b57cec5SDimitry Andric for (BasicBlock &BB : *F)
99*0b57cec5SDimitry Andric for (Instruction &I : BB) {
100*0b57cec5SDimitry Andric if (auto *Call = dyn_cast<CallBase>(&I)) {
101*0b57cec5SDimitry Andric const Function *Callee = Call->getCalledFunction();
102bdd1243dSDimitry Andric if (!Callee)
103*0b57cec5SDimitry Andric Node->addCalledFunction(Call, CallsExternalNode.get());
104bdd1243dSDimitry Andric else if (!isDbgInfoIntrinsic(Callee->getIntrinsicID()))
105*0b57cec5SDimitry Andric Node->addCalledFunction(Call, getOrInsertFunction(Callee));
1065ffd83dbSDimitry Andric
1075ffd83dbSDimitry Andric // Add reference to callback functions.
1085ffd83dbSDimitry Andric forEachCallbackFunction(*Call, [=](Function *CB) {
1095ffd83dbSDimitry Andric Node->addCalledFunction(nullptr, getOrInsertFunction(CB));
1105ffd83dbSDimitry Andric });
111*0b57cec5SDimitry Andric }
112*0b57cec5SDimitry Andric }
113*0b57cec5SDimitry Andric }
114*0b57cec5SDimitry Andric
print(raw_ostream & OS) const115*0b57cec5SDimitry Andric void CallGraph::print(raw_ostream &OS) const {
116*0b57cec5SDimitry Andric // Print in a deterministic order by sorting CallGraphNodes by name. We do
117*0b57cec5SDimitry Andric // this here to avoid slowing down the non-printing fast path.
118*0b57cec5SDimitry Andric
119*0b57cec5SDimitry Andric SmallVector<CallGraphNode *, 16> Nodes;
120*0b57cec5SDimitry Andric Nodes.reserve(FunctionMap.size());
121*0b57cec5SDimitry Andric
122*0b57cec5SDimitry Andric for (const auto &I : *this)
123*0b57cec5SDimitry Andric Nodes.push_back(I.second.get());
124*0b57cec5SDimitry Andric
125*0b57cec5SDimitry Andric llvm::sort(Nodes, [](CallGraphNode *LHS, CallGraphNode *RHS) {
126*0b57cec5SDimitry Andric if (Function *LF = LHS->getFunction())
127*0b57cec5SDimitry Andric if (Function *RF = RHS->getFunction())
128*0b57cec5SDimitry Andric return LF->getName() < RF->getName();
129*0b57cec5SDimitry Andric
130*0b57cec5SDimitry Andric return RHS->getFunction() != nullptr;
131*0b57cec5SDimitry Andric });
132*0b57cec5SDimitry Andric
133*0b57cec5SDimitry Andric for (CallGraphNode *CN : Nodes)
134*0b57cec5SDimitry Andric CN->print(OS);
135*0b57cec5SDimitry Andric }
136*0b57cec5SDimitry Andric
137*0b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const138*0b57cec5SDimitry Andric LLVM_DUMP_METHOD void CallGraph::dump() const { print(dbgs()); }
139*0b57cec5SDimitry Andric #endif
140*0b57cec5SDimitry Andric
ReplaceExternalCallEdge(CallGraphNode * Old,CallGraphNode * New)1415ffd83dbSDimitry Andric void CallGraph::ReplaceExternalCallEdge(CallGraphNode *Old,
1425ffd83dbSDimitry Andric CallGraphNode *New) {
1435ffd83dbSDimitry Andric for (auto &CR : ExternalCallingNode->CalledFunctions)
1445ffd83dbSDimitry Andric if (CR.second == Old) {
1455ffd83dbSDimitry Andric CR.second->DropRef();
1465ffd83dbSDimitry Andric CR.second = New;
1475ffd83dbSDimitry Andric CR.second->AddRef();
1485ffd83dbSDimitry Andric }
1495ffd83dbSDimitry Andric }
1505ffd83dbSDimitry Andric
151*0b57cec5SDimitry Andric // removeFunctionFromModule - Unlink the function from this module, returning
152*0b57cec5SDimitry Andric // it. Because this removes the function from the module, the call graph node
153*0b57cec5SDimitry Andric // is destroyed. This is only valid if the function does not call any other
154*0b57cec5SDimitry Andric // functions (ie, there are no edges in it's CGN). The easiest way to do this
155*0b57cec5SDimitry Andric // is to dropAllReferences before calling this.
156*0b57cec5SDimitry Andric //
removeFunctionFromModule(CallGraphNode * CGN)157*0b57cec5SDimitry Andric Function *CallGraph::removeFunctionFromModule(CallGraphNode *CGN) {
158*0b57cec5SDimitry Andric assert(CGN->empty() && "Cannot remove function from call "
159*0b57cec5SDimitry Andric "graph if it references other functions!");
160*0b57cec5SDimitry Andric Function *F = CGN->getFunction(); // Get the function for the call graph node
161*0b57cec5SDimitry Andric FunctionMap.erase(F); // Remove the call graph node from the map
162*0b57cec5SDimitry Andric
163*0b57cec5SDimitry Andric M.getFunctionList().remove(F);
164*0b57cec5SDimitry Andric return F;
165*0b57cec5SDimitry Andric }
166*0b57cec5SDimitry Andric
167*0b57cec5SDimitry Andric // getOrInsertFunction - This method is identical to calling operator[], but
168*0b57cec5SDimitry Andric // it will insert a new CallGraphNode for the specified function if one does
169*0b57cec5SDimitry Andric // not already exist.
getOrInsertFunction(const Function * F)170*0b57cec5SDimitry Andric CallGraphNode *CallGraph::getOrInsertFunction(const Function *F) {
171*0b57cec5SDimitry Andric auto &CGN = FunctionMap[F];
172*0b57cec5SDimitry Andric if (CGN)
173*0b57cec5SDimitry Andric return CGN.get();
174*0b57cec5SDimitry Andric
175*0b57cec5SDimitry Andric assert((!F || F->getParent() == &M) && "Function not in current module!");
1765ffd83dbSDimitry Andric CGN = std::make_unique<CallGraphNode>(this, const_cast<Function *>(F));
177*0b57cec5SDimitry Andric return CGN.get();
178*0b57cec5SDimitry Andric }
179*0b57cec5SDimitry Andric
180*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
181*0b57cec5SDimitry Andric // Implementations of the CallGraphNode class methods.
182*0b57cec5SDimitry Andric //
183*0b57cec5SDimitry Andric
print(raw_ostream & OS) const184*0b57cec5SDimitry Andric void CallGraphNode::print(raw_ostream &OS) const {
185*0b57cec5SDimitry Andric if (Function *F = getFunction())
186*0b57cec5SDimitry Andric OS << "Call graph node for function: '" << F->getName() << "'";
187*0b57cec5SDimitry Andric else
188*0b57cec5SDimitry Andric OS << "Call graph node <<null function>>";
189*0b57cec5SDimitry Andric
190*0b57cec5SDimitry Andric OS << "<<" << this << ">> #uses=" << getNumReferences() << '\n';
191*0b57cec5SDimitry Andric
192*0b57cec5SDimitry Andric for (const auto &I : *this) {
193*0b57cec5SDimitry Andric OS << " CS<" << I.first << "> calls ";
194*0b57cec5SDimitry Andric if (Function *FI = I.second->getFunction())
195*0b57cec5SDimitry Andric OS << "function '" << FI->getName() <<"'\n";
196*0b57cec5SDimitry Andric else
197*0b57cec5SDimitry Andric OS << "external node\n";
198*0b57cec5SDimitry Andric }
199*0b57cec5SDimitry Andric OS << '\n';
200*0b57cec5SDimitry Andric }
201*0b57cec5SDimitry Andric
202*0b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const203*0b57cec5SDimitry Andric LLVM_DUMP_METHOD void CallGraphNode::dump() const { print(dbgs()); }
204*0b57cec5SDimitry Andric #endif
205*0b57cec5SDimitry Andric
206*0b57cec5SDimitry Andric /// removeCallEdgeFor - This method removes the edge in the node for the
207*0b57cec5SDimitry Andric /// specified call site. Note that this method takes linear time, so it
208*0b57cec5SDimitry Andric /// should be used sparingly.
removeCallEdgeFor(CallBase & Call)209*0b57cec5SDimitry Andric void CallGraphNode::removeCallEdgeFor(CallBase &Call) {
210*0b57cec5SDimitry Andric for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
211*0b57cec5SDimitry Andric assert(I != CalledFunctions.end() && "Cannot find callsite to remove!");
2125ffd83dbSDimitry Andric if (I->first && *I->first == &Call) {
213*0b57cec5SDimitry Andric I->second->DropRef();
214*0b57cec5SDimitry Andric *I = CalledFunctions.back();
215*0b57cec5SDimitry Andric CalledFunctions.pop_back();
2165ffd83dbSDimitry Andric
2175ffd83dbSDimitry Andric // Remove all references to callback functions if there are any.
2185ffd83dbSDimitry Andric forEachCallbackFunction(Call, [=](Function *CB) {
2195ffd83dbSDimitry Andric removeOneAbstractEdgeTo(CG->getOrInsertFunction(CB));
2205ffd83dbSDimitry Andric });
221*0b57cec5SDimitry Andric return;
222*0b57cec5SDimitry Andric }
223*0b57cec5SDimitry Andric }
224*0b57cec5SDimitry Andric }
225*0b57cec5SDimitry Andric
226*0b57cec5SDimitry Andric // removeAnyCallEdgeTo - This method removes any call edges from this node to
227*0b57cec5SDimitry Andric // the specified callee function. This takes more time to execute than
228*0b57cec5SDimitry Andric // removeCallEdgeTo, so it should not be used unless necessary.
removeAnyCallEdgeTo(CallGraphNode * Callee)229*0b57cec5SDimitry Andric void CallGraphNode::removeAnyCallEdgeTo(CallGraphNode *Callee) {
230*0b57cec5SDimitry Andric for (unsigned i = 0, e = CalledFunctions.size(); i != e; ++i)
231*0b57cec5SDimitry Andric if (CalledFunctions[i].second == Callee) {
232*0b57cec5SDimitry Andric Callee->DropRef();
233*0b57cec5SDimitry Andric CalledFunctions[i] = CalledFunctions.back();
234*0b57cec5SDimitry Andric CalledFunctions.pop_back();
235*0b57cec5SDimitry Andric --i; --e;
236*0b57cec5SDimitry Andric }
237*0b57cec5SDimitry Andric }
238*0b57cec5SDimitry Andric
239*0b57cec5SDimitry Andric /// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite
240*0b57cec5SDimitry Andric /// from this node to the specified callee function.
removeOneAbstractEdgeTo(CallGraphNode * Callee)241*0b57cec5SDimitry Andric void CallGraphNode::removeOneAbstractEdgeTo(CallGraphNode *Callee) {
242*0b57cec5SDimitry Andric for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
243*0b57cec5SDimitry Andric assert(I != CalledFunctions.end() && "Cannot find callee to remove!");
244*0b57cec5SDimitry Andric CallRecord &CR = *I;
2455ffd83dbSDimitry Andric if (CR.second == Callee && !CR.first) {
246*0b57cec5SDimitry Andric Callee->DropRef();
247*0b57cec5SDimitry Andric *I = CalledFunctions.back();
248*0b57cec5SDimitry Andric CalledFunctions.pop_back();
249*0b57cec5SDimitry Andric return;
250*0b57cec5SDimitry Andric }
251*0b57cec5SDimitry Andric }
252*0b57cec5SDimitry Andric }
253*0b57cec5SDimitry Andric
254*0b57cec5SDimitry Andric /// replaceCallEdge - This method replaces the edge in the node for the
255*0b57cec5SDimitry Andric /// specified call site with a new one. Note that this method takes linear
256*0b57cec5SDimitry Andric /// time, so it should be used sparingly.
replaceCallEdge(CallBase & Call,CallBase & NewCall,CallGraphNode * NewNode)257*0b57cec5SDimitry Andric void CallGraphNode::replaceCallEdge(CallBase &Call, CallBase &NewCall,
258*0b57cec5SDimitry Andric CallGraphNode *NewNode) {
259*0b57cec5SDimitry Andric for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
260*0b57cec5SDimitry Andric assert(I != CalledFunctions.end() && "Cannot find callsite to remove!");
2615ffd83dbSDimitry Andric if (I->first && *I->first == &Call) {
262*0b57cec5SDimitry Andric I->second->DropRef();
263*0b57cec5SDimitry Andric I->first = &NewCall;
264*0b57cec5SDimitry Andric I->second = NewNode;
265*0b57cec5SDimitry Andric NewNode->AddRef();
2665ffd83dbSDimitry Andric
267e8d8bef9SDimitry Andric // Refresh callback references. Do not resize CalledFunctions if the
268e8d8bef9SDimitry Andric // number of callbacks is the same for new and old call sites.
269e8d8bef9SDimitry Andric SmallVector<CallGraphNode *, 4u> OldCBs;
270e8d8bef9SDimitry Andric SmallVector<CallGraphNode *, 4u> NewCBs;
271e8d8bef9SDimitry Andric forEachCallbackFunction(Call, [this, &OldCBs](Function *CB) {
272e8d8bef9SDimitry Andric OldCBs.push_back(CG->getOrInsertFunction(CB));
2735ffd83dbSDimitry Andric });
274e8d8bef9SDimitry Andric forEachCallbackFunction(NewCall, [this, &NewCBs](Function *CB) {
275e8d8bef9SDimitry Andric NewCBs.push_back(CG->getOrInsertFunction(CB));
2765ffd83dbSDimitry Andric });
277e8d8bef9SDimitry Andric if (OldCBs.size() == NewCBs.size()) {
278e8d8bef9SDimitry Andric for (unsigned N = 0; N < OldCBs.size(); ++N) {
279e8d8bef9SDimitry Andric CallGraphNode *OldNode = OldCBs[N];
280e8d8bef9SDimitry Andric CallGraphNode *NewNode = NewCBs[N];
281e8d8bef9SDimitry Andric for (auto J = CalledFunctions.begin();; ++J) {
282e8d8bef9SDimitry Andric assert(J != CalledFunctions.end() &&
283e8d8bef9SDimitry Andric "Cannot find callsite to update!");
284e8d8bef9SDimitry Andric if (!J->first && J->second == OldNode) {
285e8d8bef9SDimitry Andric J->second = NewNode;
286e8d8bef9SDimitry Andric OldNode->DropRef();
287e8d8bef9SDimitry Andric NewNode->AddRef();
288e8d8bef9SDimitry Andric break;
289e8d8bef9SDimitry Andric }
290e8d8bef9SDimitry Andric }
291e8d8bef9SDimitry Andric }
292e8d8bef9SDimitry Andric } else {
293e8d8bef9SDimitry Andric for (auto *CGN : OldCBs)
294e8d8bef9SDimitry Andric removeOneAbstractEdgeTo(CGN);
295e8d8bef9SDimitry Andric for (auto *CGN : NewCBs)
296e8d8bef9SDimitry Andric addCalledFunction(nullptr, CGN);
297e8d8bef9SDimitry Andric }
298*0b57cec5SDimitry Andric return;
299*0b57cec5SDimitry Andric }
300*0b57cec5SDimitry Andric }
301*0b57cec5SDimitry Andric }
302*0b57cec5SDimitry Andric
303*0b57cec5SDimitry Andric // Provide an explicit template instantiation for the static ID.
304*0b57cec5SDimitry Andric AnalysisKey CallGraphAnalysis::Key;
305*0b57cec5SDimitry Andric
run(Module & M,ModuleAnalysisManager & AM)306*0b57cec5SDimitry Andric PreservedAnalyses CallGraphPrinterPass::run(Module &M,
307*0b57cec5SDimitry Andric ModuleAnalysisManager &AM) {
308*0b57cec5SDimitry Andric AM.getResult<CallGraphAnalysis>(M).print(OS);
309*0b57cec5SDimitry Andric return PreservedAnalyses::all();
310*0b57cec5SDimitry Andric }
311*0b57cec5SDimitry Andric
run(Module & M,ModuleAnalysisManager & AM)312bdd1243dSDimitry Andric PreservedAnalyses CallGraphSCCsPrinterPass::run(Module &M,
313bdd1243dSDimitry Andric ModuleAnalysisManager &AM) {
314bdd1243dSDimitry Andric auto &CG = AM.getResult<CallGraphAnalysis>(M);
315bdd1243dSDimitry Andric unsigned sccNum = 0;
316bdd1243dSDimitry Andric OS << "SCCs for the program in PostOrder:";
317bdd1243dSDimitry Andric for (scc_iterator<CallGraph *> SCCI = scc_begin(&CG); !SCCI.isAtEnd();
318bdd1243dSDimitry Andric ++SCCI) {
319bdd1243dSDimitry Andric const std::vector<CallGraphNode *> &nextSCC = *SCCI;
320bdd1243dSDimitry Andric OS << "\nSCC #" << ++sccNum << ": ";
321bdd1243dSDimitry Andric bool First = true;
322bdd1243dSDimitry Andric for (std::vector<CallGraphNode *>::const_iterator I = nextSCC.begin(),
323bdd1243dSDimitry Andric E = nextSCC.end();
324bdd1243dSDimitry Andric I != E; ++I) {
325bdd1243dSDimitry Andric if (First)
326bdd1243dSDimitry Andric First = false;
327bdd1243dSDimitry Andric else
328bdd1243dSDimitry Andric OS << ", ";
329bdd1243dSDimitry Andric OS << ((*I)->getFunction() ? (*I)->getFunction()->getName()
330bdd1243dSDimitry Andric : "external node");
331bdd1243dSDimitry Andric }
332bdd1243dSDimitry Andric
333bdd1243dSDimitry Andric if (nextSCC.size() == 1 && SCCI.hasCycle())
334bdd1243dSDimitry Andric OS << " (Has self-loop).";
335bdd1243dSDimitry Andric }
336bdd1243dSDimitry Andric OS << "\n";
337bdd1243dSDimitry Andric return PreservedAnalyses::all();
338bdd1243dSDimitry Andric }
339bdd1243dSDimitry Andric
340*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
341*0b57cec5SDimitry Andric // Out-of-line definitions of CallGraphAnalysis class members.
342*0b57cec5SDimitry Andric //
343*0b57cec5SDimitry Andric
344*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
345*0b57cec5SDimitry Andric // Implementations of the CallGraphWrapperPass class methods.
346*0b57cec5SDimitry Andric //
347*0b57cec5SDimitry Andric
CallGraphWrapperPass()348*0b57cec5SDimitry Andric CallGraphWrapperPass::CallGraphWrapperPass() : ModulePass(ID) {
349*0b57cec5SDimitry Andric initializeCallGraphWrapperPassPass(*PassRegistry::getPassRegistry());
350*0b57cec5SDimitry Andric }
351*0b57cec5SDimitry Andric
352*0b57cec5SDimitry Andric CallGraphWrapperPass::~CallGraphWrapperPass() = default;
353*0b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const354*0b57cec5SDimitry Andric void CallGraphWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
355*0b57cec5SDimitry Andric AU.setPreservesAll();
356*0b57cec5SDimitry Andric }
357*0b57cec5SDimitry Andric
runOnModule(Module & M)358*0b57cec5SDimitry Andric bool CallGraphWrapperPass::runOnModule(Module &M) {
359*0b57cec5SDimitry Andric // All the real work is done in the constructor for the CallGraph.
360*0b57cec5SDimitry Andric G.reset(new CallGraph(M));
361*0b57cec5SDimitry Andric return false;
362*0b57cec5SDimitry Andric }
363*0b57cec5SDimitry Andric
364*0b57cec5SDimitry Andric INITIALIZE_PASS(CallGraphWrapperPass, "basiccg", "CallGraph Construction",
365*0b57cec5SDimitry Andric false, true)
366*0b57cec5SDimitry Andric
367*0b57cec5SDimitry Andric char CallGraphWrapperPass::ID = 0;
368*0b57cec5SDimitry Andric
releaseMemory()369*0b57cec5SDimitry Andric void CallGraphWrapperPass::releaseMemory() { G.reset(); }
370*0b57cec5SDimitry Andric
print(raw_ostream & OS,const Module *) const371*0b57cec5SDimitry Andric void CallGraphWrapperPass::print(raw_ostream &OS, const Module *) const {
372*0b57cec5SDimitry Andric if (!G) {
373*0b57cec5SDimitry Andric OS << "No call graph has been built!\n";
374*0b57cec5SDimitry Andric return;
375*0b57cec5SDimitry Andric }
376*0b57cec5SDimitry Andric
377*0b57cec5SDimitry Andric // Just delegate.
378*0b57cec5SDimitry Andric G->print(OS);
379*0b57cec5SDimitry Andric }
380*0b57cec5SDimitry Andric
381*0b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
382*0b57cec5SDimitry Andric LLVM_DUMP_METHOD
dump() const383*0b57cec5SDimitry Andric void CallGraphWrapperPass::dump() const { print(dbgs(), nullptr); }
384*0b57cec5SDimitry Andric #endif
385