xref: /openbsd-src/gnu/llvm/llvm/lib/Analysis/CallGraph.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- CallGraph.cpp - Build a Module's call graph ------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "llvm/Analysis/CallGraph.h"
10*d415bd75Srobert #include "llvm/ADT/SCCIterator.h"
1109467b48Spatrick #include "llvm/ADT/STLExtras.h"
1209467b48Spatrick #include "llvm/ADT/SmallVector.h"
1309467b48Spatrick #include "llvm/Config/llvm-config.h"
14097a140dSpatrick #include "llvm/IR/AbstractCallSite.h"
1509467b48Spatrick #include "llvm/IR/Function.h"
16097a140dSpatrick #include "llvm/IR/IntrinsicInst.h"
1709467b48Spatrick #include "llvm/IR/Module.h"
1809467b48Spatrick #include "llvm/IR/PassManager.h"
1909467b48Spatrick #include "llvm/InitializePasses.h"
2009467b48Spatrick #include "llvm/Pass.h"
2109467b48Spatrick #include "llvm/Support/Compiler.h"
2209467b48Spatrick #include "llvm/Support/Debug.h"
2309467b48Spatrick #include "llvm/Support/raw_ostream.h"
2409467b48Spatrick #include <cassert>
2509467b48Spatrick 
2609467b48Spatrick using namespace llvm;
2709467b48Spatrick 
2809467b48Spatrick //===----------------------------------------------------------------------===//
2909467b48Spatrick // Implementations of the CallGraph class methods.
3009467b48Spatrick //
3109467b48Spatrick 
CallGraph(Module & M)3209467b48Spatrick CallGraph::CallGraph(Module &M)
3309467b48Spatrick     : M(M), ExternalCallingNode(getOrInsertFunction(nullptr)),
34097a140dSpatrick       CallsExternalNode(std::make_unique<CallGraphNode>(this, nullptr)) {
35097a140dSpatrick   // Add every interesting function to the call graph.
3609467b48Spatrick   for (Function &F : M)
37097a140dSpatrick     if (!isDbgInfoIntrinsic(F.getIntrinsicID()))
3809467b48Spatrick       addToCallGraph(&F);
3909467b48Spatrick }
4009467b48Spatrick 
CallGraph(CallGraph && Arg)4109467b48Spatrick CallGraph::CallGraph(CallGraph &&Arg)
4209467b48Spatrick     : M(Arg.M), FunctionMap(std::move(Arg.FunctionMap)),
4309467b48Spatrick       ExternalCallingNode(Arg.ExternalCallingNode),
4409467b48Spatrick       CallsExternalNode(std::move(Arg.CallsExternalNode)) {
4509467b48Spatrick   Arg.FunctionMap.clear();
4609467b48Spatrick   Arg.ExternalCallingNode = nullptr;
47097a140dSpatrick 
48097a140dSpatrick   // Update parent CG for all call graph's nodes.
49097a140dSpatrick   CallsExternalNode->CG = this;
50097a140dSpatrick   for (auto &P : FunctionMap)
51097a140dSpatrick     P.second->CG = this;
5209467b48Spatrick }
5309467b48Spatrick 
~CallGraph()5409467b48Spatrick CallGraph::~CallGraph() {
5509467b48Spatrick   // CallsExternalNode is not in the function map, delete it explicitly.
5609467b48Spatrick   if (CallsExternalNode)
5709467b48Spatrick     CallsExternalNode->allReferencesDropped();
5809467b48Spatrick 
5909467b48Spatrick // Reset all node's use counts to zero before deleting them to prevent an
6009467b48Spatrick // assertion from firing.
6109467b48Spatrick #ifndef NDEBUG
6209467b48Spatrick   for (auto &I : FunctionMap)
6309467b48Spatrick     I.second->allReferencesDropped();
6409467b48Spatrick #endif
6509467b48Spatrick }
6609467b48Spatrick 
invalidate(Module &,const PreservedAnalyses & PA,ModuleAnalysisManager::Invalidator &)67097a140dSpatrick bool CallGraph::invalidate(Module &, const PreservedAnalyses &PA,
68097a140dSpatrick                            ModuleAnalysisManager::Invalidator &) {
69097a140dSpatrick   // Check whether the analysis, all analyses on functions, or the function's
70097a140dSpatrick   // CFG have been preserved.
71097a140dSpatrick   auto PAC = PA.getChecker<CallGraphAnalysis>();
72*d415bd75Srobert   return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Module>>());
73097a140dSpatrick }
74097a140dSpatrick 
addToCallGraph(Function * F)7509467b48Spatrick void CallGraph::addToCallGraph(Function *F) {
7609467b48Spatrick   CallGraphNode *Node = getOrInsertFunction(F);
7709467b48Spatrick 
78097a140dSpatrick   // If this function has external linkage or has its address taken and
79097a140dSpatrick   // it is not a callback, then anything could call it.
80097a140dSpatrick   if (!F->hasLocalLinkage() ||
8173471bf0Spatrick       F->hasAddressTaken(nullptr, /*IgnoreCallbackUses=*/true,
8273471bf0Spatrick                          /* IgnoreAssumeLikeCalls */ true,
8373471bf0Spatrick                          /* IgnoreLLVMUsed */ false))
8409467b48Spatrick     ExternalCallingNode->addCalledFunction(nullptr, Node);
8509467b48Spatrick 
86097a140dSpatrick   populateCallGraphNode(Node);
87097a140dSpatrick }
88097a140dSpatrick 
populateCallGraphNode(CallGraphNode * Node)89097a140dSpatrick void CallGraph::populateCallGraphNode(CallGraphNode *Node) {
90097a140dSpatrick   Function *F = Node->getFunction();
91097a140dSpatrick 
9209467b48Spatrick   // If this function is not defined in this translation unit, it could call
9309467b48Spatrick   // anything.
94*d415bd75Srobert   if (F->isDeclaration() && !F->hasFnAttribute(Attribute::NoCallback))
9509467b48Spatrick     Node->addCalledFunction(nullptr, CallsExternalNode.get());
9609467b48Spatrick 
9709467b48Spatrick   // Look for calls by this function.
9809467b48Spatrick   for (BasicBlock &BB : *F)
9909467b48Spatrick     for (Instruction &I : BB) {
10009467b48Spatrick       if (auto *Call = dyn_cast<CallBase>(&I)) {
10109467b48Spatrick         const Function *Callee = Call->getCalledFunction();
102*d415bd75Srobert         if (!Callee)
10309467b48Spatrick           Node->addCalledFunction(Call, CallsExternalNode.get());
104*d415bd75Srobert         else if (!isDbgInfoIntrinsic(Callee->getIntrinsicID()))
10509467b48Spatrick           Node->addCalledFunction(Call, getOrInsertFunction(Callee));
106097a140dSpatrick 
107097a140dSpatrick         // Add reference to callback functions.
108097a140dSpatrick         forEachCallbackFunction(*Call, [=](Function *CB) {
109097a140dSpatrick           Node->addCalledFunction(nullptr, getOrInsertFunction(CB));
110097a140dSpatrick         });
11109467b48Spatrick       }
11209467b48Spatrick     }
11309467b48Spatrick }
11409467b48Spatrick 
print(raw_ostream & OS) const11509467b48Spatrick void CallGraph::print(raw_ostream &OS) const {
11609467b48Spatrick   // Print in a deterministic order by sorting CallGraphNodes by name.  We do
11709467b48Spatrick   // this here to avoid slowing down the non-printing fast path.
11809467b48Spatrick 
11909467b48Spatrick   SmallVector<CallGraphNode *, 16> Nodes;
12009467b48Spatrick   Nodes.reserve(FunctionMap.size());
12109467b48Spatrick 
12209467b48Spatrick   for (const auto &I : *this)
12309467b48Spatrick     Nodes.push_back(I.second.get());
12409467b48Spatrick 
12509467b48Spatrick   llvm::sort(Nodes, [](CallGraphNode *LHS, CallGraphNode *RHS) {
12609467b48Spatrick     if (Function *LF = LHS->getFunction())
12709467b48Spatrick       if (Function *RF = RHS->getFunction())
12809467b48Spatrick         return LF->getName() < RF->getName();
12909467b48Spatrick 
13009467b48Spatrick     return RHS->getFunction() != nullptr;
13109467b48Spatrick   });
13209467b48Spatrick 
13309467b48Spatrick   for (CallGraphNode *CN : Nodes)
13409467b48Spatrick     CN->print(OS);
13509467b48Spatrick }
13609467b48Spatrick 
13709467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const13809467b48Spatrick LLVM_DUMP_METHOD void CallGraph::dump() const { print(dbgs()); }
13909467b48Spatrick #endif
14009467b48Spatrick 
ReplaceExternalCallEdge(CallGraphNode * Old,CallGraphNode * New)141097a140dSpatrick void CallGraph::ReplaceExternalCallEdge(CallGraphNode *Old,
142097a140dSpatrick                                         CallGraphNode *New) {
143097a140dSpatrick   for (auto &CR : ExternalCallingNode->CalledFunctions)
144097a140dSpatrick     if (CR.second == Old) {
145097a140dSpatrick       CR.second->DropRef();
146097a140dSpatrick       CR.second = New;
147097a140dSpatrick       CR.second->AddRef();
148097a140dSpatrick     }
149097a140dSpatrick }
150097a140dSpatrick 
15109467b48Spatrick // removeFunctionFromModule - Unlink the function from this module, returning
15209467b48Spatrick // it.  Because this removes the function from the module, the call graph node
15309467b48Spatrick // is destroyed.  This is only valid if the function does not call any other
15409467b48Spatrick // functions (ie, there are no edges in it's CGN).  The easiest way to do this
15509467b48Spatrick // is to dropAllReferences before calling this.
15609467b48Spatrick //
removeFunctionFromModule(CallGraphNode * CGN)15709467b48Spatrick Function *CallGraph::removeFunctionFromModule(CallGraphNode *CGN) {
15809467b48Spatrick   assert(CGN->empty() && "Cannot remove function from call "
15909467b48Spatrick          "graph if it references other functions!");
16009467b48Spatrick   Function *F = CGN->getFunction(); // Get the function for the call graph node
16109467b48Spatrick   FunctionMap.erase(F);             // Remove the call graph node from the map
16209467b48Spatrick 
16309467b48Spatrick   M.getFunctionList().remove(F);
16409467b48Spatrick   return F;
16509467b48Spatrick }
16609467b48Spatrick 
16709467b48Spatrick // getOrInsertFunction - This method is identical to calling operator[], but
16809467b48Spatrick // it will insert a new CallGraphNode for the specified function if one does
16909467b48Spatrick // not already exist.
getOrInsertFunction(const Function * F)17009467b48Spatrick CallGraphNode *CallGraph::getOrInsertFunction(const Function *F) {
17109467b48Spatrick   auto &CGN = FunctionMap[F];
17209467b48Spatrick   if (CGN)
17309467b48Spatrick     return CGN.get();
17409467b48Spatrick 
17509467b48Spatrick   assert((!F || F->getParent() == &M) && "Function not in current module!");
176097a140dSpatrick   CGN = std::make_unique<CallGraphNode>(this, const_cast<Function *>(F));
17709467b48Spatrick   return CGN.get();
17809467b48Spatrick }
17909467b48Spatrick 
18009467b48Spatrick //===----------------------------------------------------------------------===//
18109467b48Spatrick // Implementations of the CallGraphNode class methods.
18209467b48Spatrick //
18309467b48Spatrick 
print(raw_ostream & OS) const18409467b48Spatrick void CallGraphNode::print(raw_ostream &OS) const {
18509467b48Spatrick   if (Function *F = getFunction())
18609467b48Spatrick     OS << "Call graph node for function: '" << F->getName() << "'";
18709467b48Spatrick   else
18809467b48Spatrick     OS << "Call graph node <<null function>>";
18909467b48Spatrick 
19009467b48Spatrick   OS << "<<" << this << ">>  #uses=" << getNumReferences() << '\n';
19109467b48Spatrick 
19209467b48Spatrick   for (const auto &I : *this) {
19309467b48Spatrick     OS << "  CS<" << I.first << "> calls ";
19409467b48Spatrick     if (Function *FI = I.second->getFunction())
19509467b48Spatrick       OS << "function '" << FI->getName() <<"'\n";
19609467b48Spatrick     else
19709467b48Spatrick       OS << "external node\n";
19809467b48Spatrick   }
19909467b48Spatrick   OS << '\n';
20009467b48Spatrick }
20109467b48Spatrick 
20209467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const20309467b48Spatrick LLVM_DUMP_METHOD void CallGraphNode::dump() const { print(dbgs()); }
20409467b48Spatrick #endif
20509467b48Spatrick 
20609467b48Spatrick /// removeCallEdgeFor - This method removes the edge in the node for the
20709467b48Spatrick /// specified call site.  Note that this method takes linear time, so it
20809467b48Spatrick /// should be used sparingly.
removeCallEdgeFor(CallBase & Call)20909467b48Spatrick void CallGraphNode::removeCallEdgeFor(CallBase &Call) {
21009467b48Spatrick   for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
21109467b48Spatrick     assert(I != CalledFunctions.end() && "Cannot find callsite to remove!");
212097a140dSpatrick     if (I->first && *I->first == &Call) {
21309467b48Spatrick       I->second->DropRef();
21409467b48Spatrick       *I = CalledFunctions.back();
21509467b48Spatrick       CalledFunctions.pop_back();
216097a140dSpatrick 
217097a140dSpatrick       // Remove all references to callback functions if there are any.
218097a140dSpatrick       forEachCallbackFunction(Call, [=](Function *CB) {
219097a140dSpatrick         removeOneAbstractEdgeTo(CG->getOrInsertFunction(CB));
220097a140dSpatrick       });
22109467b48Spatrick       return;
22209467b48Spatrick     }
22309467b48Spatrick   }
22409467b48Spatrick }
22509467b48Spatrick 
22609467b48Spatrick // removeAnyCallEdgeTo - This method removes any call edges from this node to
22709467b48Spatrick // the specified callee function.  This takes more time to execute than
22809467b48Spatrick // removeCallEdgeTo, so it should not be used unless necessary.
removeAnyCallEdgeTo(CallGraphNode * Callee)22909467b48Spatrick void CallGraphNode::removeAnyCallEdgeTo(CallGraphNode *Callee) {
23009467b48Spatrick   for (unsigned i = 0, e = CalledFunctions.size(); i != e; ++i)
23109467b48Spatrick     if (CalledFunctions[i].second == Callee) {
23209467b48Spatrick       Callee->DropRef();
23309467b48Spatrick       CalledFunctions[i] = CalledFunctions.back();
23409467b48Spatrick       CalledFunctions.pop_back();
23509467b48Spatrick       --i; --e;
23609467b48Spatrick     }
23709467b48Spatrick }
23809467b48Spatrick 
23909467b48Spatrick /// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite
24009467b48Spatrick /// from this node to the specified callee function.
removeOneAbstractEdgeTo(CallGraphNode * Callee)24109467b48Spatrick void CallGraphNode::removeOneAbstractEdgeTo(CallGraphNode *Callee) {
24209467b48Spatrick   for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
24309467b48Spatrick     assert(I != CalledFunctions.end() && "Cannot find callee to remove!");
24409467b48Spatrick     CallRecord &CR = *I;
245097a140dSpatrick     if (CR.second == Callee && !CR.first) {
24609467b48Spatrick       Callee->DropRef();
24709467b48Spatrick       *I = CalledFunctions.back();
24809467b48Spatrick       CalledFunctions.pop_back();
24909467b48Spatrick       return;
25009467b48Spatrick     }
25109467b48Spatrick   }
25209467b48Spatrick }
25309467b48Spatrick 
25409467b48Spatrick /// replaceCallEdge - This method replaces the edge in the node for the
25509467b48Spatrick /// specified call site with a new one.  Note that this method takes linear
25609467b48Spatrick /// time, so it should be used sparingly.
replaceCallEdge(CallBase & Call,CallBase & NewCall,CallGraphNode * NewNode)25709467b48Spatrick void CallGraphNode::replaceCallEdge(CallBase &Call, CallBase &NewCall,
25809467b48Spatrick                                     CallGraphNode *NewNode) {
25909467b48Spatrick   for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
26009467b48Spatrick     assert(I != CalledFunctions.end() && "Cannot find callsite to remove!");
261097a140dSpatrick     if (I->first && *I->first == &Call) {
26209467b48Spatrick       I->second->DropRef();
26309467b48Spatrick       I->first = &NewCall;
26409467b48Spatrick       I->second = NewNode;
26509467b48Spatrick       NewNode->AddRef();
266097a140dSpatrick 
26773471bf0Spatrick       // Refresh callback references. Do not resize CalledFunctions if the
26873471bf0Spatrick       // number of callbacks is the same for new and old call sites.
26973471bf0Spatrick       SmallVector<CallGraphNode *, 4u> OldCBs;
27073471bf0Spatrick       SmallVector<CallGraphNode *, 4u> NewCBs;
27173471bf0Spatrick       forEachCallbackFunction(Call, [this, &OldCBs](Function *CB) {
27273471bf0Spatrick         OldCBs.push_back(CG->getOrInsertFunction(CB));
273097a140dSpatrick       });
27473471bf0Spatrick       forEachCallbackFunction(NewCall, [this, &NewCBs](Function *CB) {
27573471bf0Spatrick         NewCBs.push_back(CG->getOrInsertFunction(CB));
276097a140dSpatrick       });
27773471bf0Spatrick       if (OldCBs.size() == NewCBs.size()) {
27873471bf0Spatrick         for (unsigned N = 0; N < OldCBs.size(); ++N) {
27973471bf0Spatrick           CallGraphNode *OldNode = OldCBs[N];
28073471bf0Spatrick           CallGraphNode *NewNode = NewCBs[N];
28173471bf0Spatrick           for (auto J = CalledFunctions.begin();; ++J) {
28273471bf0Spatrick             assert(J != CalledFunctions.end() &&
28373471bf0Spatrick                    "Cannot find callsite to update!");
28473471bf0Spatrick             if (!J->first && J->second == OldNode) {
28573471bf0Spatrick               J->second = NewNode;
28673471bf0Spatrick               OldNode->DropRef();
28773471bf0Spatrick               NewNode->AddRef();
28873471bf0Spatrick               break;
28973471bf0Spatrick             }
29073471bf0Spatrick           }
29173471bf0Spatrick         }
29273471bf0Spatrick       } else {
29373471bf0Spatrick         for (auto *CGN : OldCBs)
29473471bf0Spatrick           removeOneAbstractEdgeTo(CGN);
29573471bf0Spatrick         for (auto *CGN : NewCBs)
29673471bf0Spatrick           addCalledFunction(nullptr, CGN);
29773471bf0Spatrick       }
29809467b48Spatrick       return;
29909467b48Spatrick     }
30009467b48Spatrick   }
30109467b48Spatrick }
30209467b48Spatrick 
30309467b48Spatrick // Provide an explicit template instantiation for the static ID.
30409467b48Spatrick AnalysisKey CallGraphAnalysis::Key;
30509467b48Spatrick 
run(Module & M,ModuleAnalysisManager & AM)30609467b48Spatrick PreservedAnalyses CallGraphPrinterPass::run(Module &M,
30709467b48Spatrick                                             ModuleAnalysisManager &AM) {
30809467b48Spatrick   AM.getResult<CallGraphAnalysis>(M).print(OS);
30909467b48Spatrick   return PreservedAnalyses::all();
31009467b48Spatrick }
31109467b48Spatrick 
run(Module & M,ModuleAnalysisManager & AM)312*d415bd75Srobert PreservedAnalyses CallGraphSCCsPrinterPass::run(Module &M,
313*d415bd75Srobert                                                 ModuleAnalysisManager &AM) {
314*d415bd75Srobert   auto &CG = AM.getResult<CallGraphAnalysis>(M);
315*d415bd75Srobert   unsigned sccNum = 0;
316*d415bd75Srobert   OS << "SCCs for the program in PostOrder:";
317*d415bd75Srobert   for (scc_iterator<CallGraph *> SCCI = scc_begin(&CG); !SCCI.isAtEnd();
318*d415bd75Srobert        ++SCCI) {
319*d415bd75Srobert     const std::vector<CallGraphNode *> &nextSCC = *SCCI;
320*d415bd75Srobert     OS << "\nSCC #" << ++sccNum << ": ";
321*d415bd75Srobert     bool First = true;
322*d415bd75Srobert     for (std::vector<CallGraphNode *>::const_iterator I = nextSCC.begin(),
323*d415bd75Srobert                                                       E = nextSCC.end();
324*d415bd75Srobert          I != E; ++I) {
325*d415bd75Srobert       if (First)
326*d415bd75Srobert         First = false;
327*d415bd75Srobert       else
328*d415bd75Srobert         OS << ", ";
329*d415bd75Srobert       OS << ((*I)->getFunction() ? (*I)->getFunction()->getName()
330*d415bd75Srobert                                  : "external node");
331*d415bd75Srobert     }
332*d415bd75Srobert 
333*d415bd75Srobert     if (nextSCC.size() == 1 && SCCI.hasCycle())
334*d415bd75Srobert       OS << " (Has self-loop).";
335*d415bd75Srobert   }
336*d415bd75Srobert   OS << "\n";
337*d415bd75Srobert   return PreservedAnalyses::all();
338*d415bd75Srobert }
339*d415bd75Srobert 
34009467b48Spatrick //===----------------------------------------------------------------------===//
34109467b48Spatrick // Out-of-line definitions of CallGraphAnalysis class members.
34209467b48Spatrick //
34309467b48Spatrick 
34409467b48Spatrick //===----------------------------------------------------------------------===//
34509467b48Spatrick // Implementations of the CallGraphWrapperPass class methods.
34609467b48Spatrick //
34709467b48Spatrick 
CallGraphWrapperPass()34809467b48Spatrick CallGraphWrapperPass::CallGraphWrapperPass() : ModulePass(ID) {
34909467b48Spatrick   initializeCallGraphWrapperPassPass(*PassRegistry::getPassRegistry());
35009467b48Spatrick }
35109467b48Spatrick 
35209467b48Spatrick CallGraphWrapperPass::~CallGraphWrapperPass() = default;
35309467b48Spatrick 
getAnalysisUsage(AnalysisUsage & AU) const35409467b48Spatrick void CallGraphWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
35509467b48Spatrick   AU.setPreservesAll();
35609467b48Spatrick }
35709467b48Spatrick 
runOnModule(Module & M)35809467b48Spatrick bool CallGraphWrapperPass::runOnModule(Module &M) {
35909467b48Spatrick   // All the real work is done in the constructor for the CallGraph.
36009467b48Spatrick   G.reset(new CallGraph(M));
36109467b48Spatrick   return false;
36209467b48Spatrick }
36309467b48Spatrick 
36409467b48Spatrick INITIALIZE_PASS(CallGraphWrapperPass, "basiccg", "CallGraph Construction",
36509467b48Spatrick                 false, true)
36609467b48Spatrick 
36709467b48Spatrick char CallGraphWrapperPass::ID = 0;
36809467b48Spatrick 
releaseMemory()36909467b48Spatrick void CallGraphWrapperPass::releaseMemory() { G.reset(); }
37009467b48Spatrick 
print(raw_ostream & OS,const Module *) const37109467b48Spatrick void CallGraphWrapperPass::print(raw_ostream &OS, const Module *) const {
37209467b48Spatrick   if (!G) {
37309467b48Spatrick     OS << "No call graph has been built!\n";
37409467b48Spatrick     return;
37509467b48Spatrick   }
37609467b48Spatrick 
37709467b48Spatrick   // Just delegate.
37809467b48Spatrick   G->print(OS);
37909467b48Spatrick }
38009467b48Spatrick 
38109467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
38209467b48Spatrick LLVM_DUMP_METHOD
dump() const38309467b48Spatrick void CallGraphWrapperPass::dump() const { print(dbgs(), nullptr); }
38409467b48Spatrick #endif
38509467b48Spatrick 
38609467b48Spatrick namespace {
38709467b48Spatrick 
38809467b48Spatrick struct CallGraphPrinterLegacyPass : public ModulePass {
38909467b48Spatrick   static char ID; // Pass ID, replacement for typeid
39009467b48Spatrick 
CallGraphPrinterLegacyPass__anoneb90e9e80611::CallGraphPrinterLegacyPass39109467b48Spatrick   CallGraphPrinterLegacyPass() : ModulePass(ID) {
39209467b48Spatrick     initializeCallGraphPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
39309467b48Spatrick   }
39409467b48Spatrick 
getAnalysisUsage__anoneb90e9e80611::CallGraphPrinterLegacyPass39509467b48Spatrick   void getAnalysisUsage(AnalysisUsage &AU) const override {
39609467b48Spatrick     AU.setPreservesAll();
39709467b48Spatrick     AU.addRequiredTransitive<CallGraphWrapperPass>();
39809467b48Spatrick   }
39909467b48Spatrick 
runOnModule__anoneb90e9e80611::CallGraphPrinterLegacyPass40009467b48Spatrick   bool runOnModule(Module &M) override {
40109467b48Spatrick     getAnalysis<CallGraphWrapperPass>().print(errs(), &M);
40209467b48Spatrick     return false;
40309467b48Spatrick   }
40409467b48Spatrick };
40509467b48Spatrick 
40609467b48Spatrick } // end anonymous namespace
40709467b48Spatrick 
40809467b48Spatrick char CallGraphPrinterLegacyPass::ID = 0;
40909467b48Spatrick 
41009467b48Spatrick INITIALIZE_PASS_BEGIN(CallGraphPrinterLegacyPass, "print-callgraph",
41109467b48Spatrick                       "Print a call graph", true, true)
41209467b48Spatrick INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
41309467b48Spatrick INITIALIZE_PASS_END(CallGraphPrinterLegacyPass, "print-callgraph",
41409467b48Spatrick                     "Print a call graph", true, true)
415