17adc3a2bSChandler Carruth //===- CallPrinter.cpp - DOT printer for call graph -----------------------===//
27adc3a2bSChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67adc3a2bSChandler Carruth //
77adc3a2bSChandler Carruth //===----------------------------------------------------------------------===//
87adc3a2bSChandler Carruth //
97adc3a2bSChandler Carruth // This file defines '-dot-callgraph', which emit a callgraph.<fnname>.dot
107adc3a2bSChandler Carruth // containing the call graph of a module.
117adc3a2bSChandler Carruth //
127adc3a2bSChandler Carruth // There is also a pass available to directly call dotty ('-view-callgraph').
137adc3a2bSChandler Carruth //
147adc3a2bSChandler Carruth //===----------------------------------------------------------------------===//
157adc3a2bSChandler Carruth 
167adc3a2bSChandler Carruth #include "llvm/Analysis/CallPrinter.h"
170128b950SSimon Pilgrim #include "llvm/ADT/DenseMap.h"
180128b950SSimon Pilgrim #include "llvm/ADT/SmallSet.h"
1971c3a551Sserge-sans-paille #include "llvm/Analysis/BlockFrequencyInfo.h"
2071c3a551Sserge-sans-paille #include "llvm/Analysis/CallGraph.h"
2171c3a551Sserge-sans-paille #include "llvm/Analysis/HeatUtils.h"
2271c3a551Sserge-sans-paille #include "llvm/IR/Instructions.h"
2371c3a551Sserge-sans-paille #include "llvm/InitializePasses.h"
2471c3a551Sserge-sans-paille #include "llvm/Support/CommandLine.h"
2571c3a551Sserge-sans-paille #include "llvm/Support/DOTGraphTraits.h"
2671c3a551Sserge-sans-paille #include "llvm/Support/GraphWriter.h"
277adc3a2bSChandler Carruth 
287adc3a2bSChandler Carruth using namespace llvm;
297adc3a2bSChandler Carruth 
3071c3a551Sserge-sans-paille namespace llvm {
3171c3a551Sserge-sans-paille template <class GraphType> struct GraphTraits;
3271c3a551Sserge-sans-paille }
3371c3a551Sserge-sans-paille 
34369d00dfSKirill Naumov // This option shows static (relative) call counts.
35369d00dfSKirill Naumov // FIXME:
36369d00dfSKirill Naumov // Need to show real counts when profile data is available
37369d00dfSKirill Naumov static cl::opt<bool> ShowHeatColors("callgraph-heat-colors", cl::init(false),
38369d00dfSKirill Naumov                                     cl::Hidden,
39369d00dfSKirill Naumov                                     cl::desc("Show heat colors in call-graph"));
40369d00dfSKirill Naumov 
41369d00dfSKirill Naumov static cl::opt<bool>
42369d00dfSKirill Naumov     ShowEdgeWeight("callgraph-show-weights", cl::init(false), cl::Hidden,
43369d00dfSKirill Naumov                        cl::desc("Show edges labeled with weights"));
44369d00dfSKirill Naumov 
45369d00dfSKirill Naumov static cl::opt<bool>
46369d00dfSKirill Naumov     CallMultiGraph("callgraph-multigraph", cl::init(false), cl::Hidden,
47369d00dfSKirill Naumov             cl::desc("Show call-multigraph (do not remove parallel edges)"));
48369d00dfSKirill Naumov 
49369d00dfSKirill Naumov static cl::opt<std::string> CallGraphDotFilenamePrefix(
50369d00dfSKirill Naumov     "callgraph-dot-filename-prefix", cl::Hidden,
51369d00dfSKirill Naumov     cl::desc("The prefix used for the CallGraph dot file names."));
52369d00dfSKirill Naumov 
537adc3a2bSChandler Carruth namespace llvm {
547adc3a2bSChandler Carruth 
55369d00dfSKirill Naumov class CallGraphDOTInfo {
56369d00dfSKirill Naumov private:
57369d00dfSKirill Naumov   Module *M;
58369d00dfSKirill Naumov   CallGraph *CG;
59369d00dfSKirill Naumov   DenseMap<const Function *, uint64_t> Freq;
60369d00dfSKirill Naumov   uint64_t MaxFreq;
617adc3a2bSChandler Carruth 
62369d00dfSKirill Naumov public:
63369d00dfSKirill Naumov   std::function<BlockFrequencyInfo *(Function &)> LookupBFI;
647adc3a2bSChandler Carruth 
CallGraphDOTInfo(Module * M,CallGraph * CG,function_ref<BlockFrequencyInfo * (Function &)> LookupBFI)65369d00dfSKirill Naumov   CallGraphDOTInfo(Module *M, CallGraph *CG,
66369d00dfSKirill Naumov                    function_ref<BlockFrequencyInfo *(Function &)> LookupBFI)
67369d00dfSKirill Naumov       : M(M), CG(CG), LookupBFI(LookupBFI) {
68369d00dfSKirill Naumov     MaxFreq = 0;
697adc3a2bSChandler Carruth 
7028d31320SKazu Hirata     for (Function &F : M->getFunctionList()) {
71369d00dfSKirill Naumov       uint64_t localSumFreq = 0;
72369d00dfSKirill Naumov       SmallSet<Function *, 16> Callers;
7328d31320SKazu Hirata       for (User *U : F.users())
74369d00dfSKirill Naumov         if (isa<CallInst>(U))
75369d00dfSKirill Naumov           Callers.insert(cast<Instruction>(U)->getFunction());
7628d31320SKazu Hirata       for (Function *Caller : Callers)
7728d31320SKazu Hirata         localSumFreq += getNumOfCalls(*Caller, F);
78369d00dfSKirill Naumov       if (localSumFreq >= MaxFreq)
79369d00dfSKirill Naumov         MaxFreq = localSumFreq;
8028d31320SKazu Hirata       Freq[&F] = localSumFreq;
81369d00dfSKirill Naumov     }
82369d00dfSKirill Naumov     if (!CallMultiGraph)
83369d00dfSKirill Naumov       removeParallelEdges();
84369d00dfSKirill Naumov   }
85369d00dfSKirill Naumov 
getModule() const86369d00dfSKirill Naumov   Module *getModule() const { return M; }
87369d00dfSKirill Naumov 
getCallGraph() const88369d00dfSKirill Naumov   CallGraph *getCallGraph() const { return CG; }
89369d00dfSKirill Naumov 
getFreq(const Function * F)90369d00dfSKirill Naumov   uint64_t getFreq(const Function *F) { return Freq[F]; }
91369d00dfSKirill Naumov 
getMaxFreq()92369d00dfSKirill Naumov   uint64_t getMaxFreq() { return MaxFreq; }
93369d00dfSKirill Naumov 
94369d00dfSKirill Naumov private:
removeParallelEdges()95369d00dfSKirill Naumov   void removeParallelEdges() {
96369d00dfSKirill Naumov     for (auto &I : (*CG)) {
97369d00dfSKirill Naumov       CallGraphNode *Node = I.second.get();
98369d00dfSKirill Naumov 
99369d00dfSKirill Naumov       bool FoundParallelEdge = true;
100369d00dfSKirill Naumov       while (FoundParallelEdge) {
101369d00dfSKirill Naumov         SmallSet<Function *, 16> Visited;
102369d00dfSKirill Naumov         FoundParallelEdge = false;
103369d00dfSKirill Naumov         for (auto CI = Node->begin(), CE = Node->end(); CI != CE; CI++) {
104369d00dfSKirill Naumov           if (!(Visited.insert(CI->second->getFunction())).second) {
105369d00dfSKirill Naumov             FoundParallelEdge = true;
106369d00dfSKirill Naumov             Node->removeCallEdge(CI);
107369d00dfSKirill Naumov             break;
108369d00dfSKirill Naumov           }
109369d00dfSKirill Naumov         }
110369d00dfSKirill Naumov       }
111369d00dfSKirill Naumov     }
1127adc3a2bSChandler Carruth   }
113cd0d7634SSean Fertile };
1147adc3a2bSChandler Carruth 
115369d00dfSKirill Naumov template <>
116369d00dfSKirill Naumov struct GraphTraits<CallGraphDOTInfo *>
117369d00dfSKirill Naumov     : public GraphTraits<const CallGraphNode *> {
getEntryNodellvm::GraphTraits118369d00dfSKirill Naumov   static NodeRef getEntryNode(CallGraphDOTInfo *CGInfo) {
119369d00dfSKirill Naumov     // Start at the external node!
120369d00dfSKirill Naumov     return CGInfo->getCallGraph()->getExternalCallingNode();
121369d00dfSKirill Naumov   }
122369d00dfSKirill Naumov 
123369d00dfSKirill Naumov   typedef std::pair<const Function *const, std::unique_ptr<CallGraphNode>>
124369d00dfSKirill Naumov       PairTy;
CGGetValuePtrllvm::GraphTraits125369d00dfSKirill Naumov   static const CallGraphNode *CGGetValuePtr(const PairTy &P) {
126369d00dfSKirill Naumov     return P.second.get();
127369d00dfSKirill Naumov   }
128369d00dfSKirill Naumov 
129369d00dfSKirill Naumov   // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
130369d00dfSKirill Naumov   typedef mapped_iterator<CallGraph::const_iterator, decltype(&CGGetValuePtr)>
131369d00dfSKirill Naumov       nodes_iterator;
132369d00dfSKirill Naumov 
nodes_beginllvm::GraphTraits133369d00dfSKirill Naumov   static nodes_iterator nodes_begin(CallGraphDOTInfo *CGInfo) {
134369d00dfSKirill Naumov     return nodes_iterator(CGInfo->getCallGraph()->begin(), &CGGetValuePtr);
135369d00dfSKirill Naumov   }
nodes_endllvm::GraphTraits136369d00dfSKirill Naumov   static nodes_iterator nodes_end(CallGraphDOTInfo *CGInfo) {
137369d00dfSKirill Naumov     return nodes_iterator(CGInfo->getCallGraph()->end(), &CGGetValuePtr);
138369d00dfSKirill Naumov   }
139369d00dfSKirill Naumov };
140369d00dfSKirill Naumov 
141369d00dfSKirill Naumov template <>
142369d00dfSKirill Naumov struct DOTGraphTraits<CallGraphDOTInfo *> : public DefaultDOTGraphTraits {
143369d00dfSKirill Naumov 
DOTGraphTraitsllvm::DOTGraphTraits144369d00dfSKirill Naumov   DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
145369d00dfSKirill Naumov 
getGraphNamellvm::DOTGraphTraits146369d00dfSKirill Naumov   static std::string getGraphName(CallGraphDOTInfo *CGInfo) {
147369d00dfSKirill Naumov     return "Call graph: " +
148369d00dfSKirill Naumov            std::string(CGInfo->getModule()->getModuleIdentifier());
149369d00dfSKirill Naumov   }
150369d00dfSKirill Naumov 
isNodeHiddenllvm::DOTGraphTraits1516eff1278SBardia Mahjour   static bool isNodeHidden(const CallGraphNode *Node,
1526eff1278SBardia Mahjour                            const CallGraphDOTInfo *CGInfo) {
153369d00dfSKirill Naumov     if (CallMultiGraph || Node->getFunction())
154369d00dfSKirill Naumov       return false;
155369d00dfSKirill Naumov     return true;
156369d00dfSKirill Naumov   }
157369d00dfSKirill Naumov 
getNodeLabelllvm::DOTGraphTraits158369d00dfSKirill Naumov   std::string getNodeLabel(const CallGraphNode *Node,
159369d00dfSKirill Naumov                            CallGraphDOTInfo *CGInfo) {
160369d00dfSKirill Naumov     if (Node == CGInfo->getCallGraph()->getExternalCallingNode())
161369d00dfSKirill Naumov       return "external caller";
162369d00dfSKirill Naumov     if (Node == CGInfo->getCallGraph()->getCallsExternalNode())
163369d00dfSKirill Naumov       return "external callee";
164369d00dfSKirill Naumov 
165369d00dfSKirill Naumov     if (Function *Func = Node->getFunction())
166369d00dfSKirill Naumov       return std::string(Func->getName());
167369d00dfSKirill Naumov     return "external node";
168369d00dfSKirill Naumov   }
CGGetValuePtrllvm::DOTGraphTraits169369d00dfSKirill Naumov   static const CallGraphNode *CGGetValuePtr(CallGraphNode::CallRecord P) {
170369d00dfSKirill Naumov     return P.second;
171369d00dfSKirill Naumov   }
172369d00dfSKirill Naumov 
173369d00dfSKirill Naumov   // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
174369d00dfSKirill Naumov   typedef mapped_iterator<CallGraphNode::const_iterator,
175369d00dfSKirill Naumov                           decltype(&CGGetValuePtr)>
176369d00dfSKirill Naumov       nodes_iterator;
177369d00dfSKirill Naumov 
getEdgeAttributesllvm::DOTGraphTraits178369d00dfSKirill Naumov   std::string getEdgeAttributes(const CallGraphNode *Node, nodes_iterator I,
179369d00dfSKirill Naumov                                 CallGraphDOTInfo *CGInfo) {
180369d00dfSKirill Naumov     if (!ShowEdgeWeight)
181369d00dfSKirill Naumov       return "";
182369d00dfSKirill Naumov 
183369d00dfSKirill Naumov     Function *Caller = Node->getFunction();
184369d00dfSKirill Naumov     if (Caller == nullptr || Caller->isDeclaration())
185369d00dfSKirill Naumov       return "";
186369d00dfSKirill Naumov 
187369d00dfSKirill Naumov     Function *Callee = (*I)->getFunction();
188369d00dfSKirill Naumov     if (Callee == nullptr)
189369d00dfSKirill Naumov       return "";
190369d00dfSKirill Naumov 
191369d00dfSKirill Naumov     uint64_t Counter = getNumOfCalls(*Caller, *Callee);
192369d00dfSKirill Naumov     double Width =
193369d00dfSKirill Naumov         1 + 2 * (double(Counter) / CGInfo->getMaxFreq());
194369d00dfSKirill Naumov     std::string Attrs = "label=\"" + std::to_string(Counter) +
195369d00dfSKirill Naumov                         "\" penwidth=" + std::to_string(Width);
196369d00dfSKirill Naumov     return Attrs;
197369d00dfSKirill Naumov   }
198369d00dfSKirill Naumov 
getNodeAttributesllvm::DOTGraphTraits199369d00dfSKirill Naumov   std::string getNodeAttributes(const CallGraphNode *Node,
200369d00dfSKirill Naumov                                 CallGraphDOTInfo *CGInfo) {
201369d00dfSKirill Naumov     Function *F = Node->getFunction();
202369d00dfSKirill Naumov     if (F == nullptr)
203369d00dfSKirill Naumov       return "";
20412fc9ca3SKazu Hirata     std::string attrs;
205369d00dfSKirill Naumov     if (ShowHeatColors) {
206369d00dfSKirill Naumov       uint64_t freq = CGInfo->getFreq(F);
207369d00dfSKirill Naumov       std::string color = getHeatColor(freq, CGInfo->getMaxFreq());
208369d00dfSKirill Naumov       std::string edgeColor = (freq <= (CGInfo->getMaxFreq() / 2))
209369d00dfSKirill Naumov                                   ? getHeatColor(0)
210369d00dfSKirill Naumov                                   : getHeatColor(1);
211369d00dfSKirill Naumov       attrs = "color=\"" + edgeColor + "ff\", style=filled, fillcolor=\"" +
212369d00dfSKirill Naumov               color + "80\"";
213369d00dfSKirill Naumov     }
214369d00dfSKirill Naumov     return attrs;
2157adc3a2bSChandler Carruth   }
2167adc3a2bSChandler Carruth };
2177adc3a2bSChandler Carruth 
218cd0d7634SSean Fertile } // end llvm namespace
2197adc3a2bSChandler Carruth 
2207adc3a2bSChandler Carruth namespace {
doCallGraphDOTPrinting(Module & M,function_ref<BlockFrequencyInfo * (Function &)> LookupBFI)221*a7e20a8aSArthur Eubanks void doCallGraphDOTPrinting(
222*a7e20a8aSArthur Eubanks     Module &M, function_ref<BlockFrequencyInfo *(Function &)> LookupBFI) {
223*a7e20a8aSArthur Eubanks   std::string Filename;
224*a7e20a8aSArthur Eubanks   if (!CallGraphDotFilenamePrefix.empty())
225*a7e20a8aSArthur Eubanks     Filename = (CallGraphDotFilenamePrefix + ".callgraph.dot");
226*a7e20a8aSArthur Eubanks   else
227*a7e20a8aSArthur Eubanks     Filename = (std::string(M.getModuleIdentifier()) + ".callgraph.dot");
228*a7e20a8aSArthur Eubanks   errs() << "Writing '" << Filename << "'...";
229*a7e20a8aSArthur Eubanks 
230*a7e20a8aSArthur Eubanks   std::error_code EC;
231*a7e20a8aSArthur Eubanks   raw_fd_ostream File(Filename, EC, sys::fs::OF_Text);
232*a7e20a8aSArthur Eubanks 
233*a7e20a8aSArthur Eubanks   CallGraph CG(M);
234*a7e20a8aSArthur Eubanks   CallGraphDOTInfo CFGInfo(&M, &CG, LookupBFI);
235*a7e20a8aSArthur Eubanks 
236*a7e20a8aSArthur Eubanks   if (!EC)
237*a7e20a8aSArthur Eubanks     WriteGraph(File, &CFGInfo);
238*a7e20a8aSArthur Eubanks   else
239*a7e20a8aSArthur Eubanks     errs() << "  error opening file for writing!";
240*a7e20a8aSArthur Eubanks   errs() << "\n";
241*a7e20a8aSArthur Eubanks }
242*a7e20a8aSArthur Eubanks 
viewCallGraph(Module & M,function_ref<BlockFrequencyInfo * (Function &)> LookupBFI)243*a7e20a8aSArthur Eubanks void viewCallGraph(Module &M,
244*a7e20a8aSArthur Eubanks                    function_ref<BlockFrequencyInfo *(Function &)> LookupBFI) {
245*a7e20a8aSArthur Eubanks   CallGraph CG(M);
246*a7e20a8aSArthur Eubanks   CallGraphDOTInfo CFGInfo(&M, &CG, LookupBFI);
247*a7e20a8aSArthur Eubanks 
248*a7e20a8aSArthur Eubanks   std::string Title =
249*a7e20a8aSArthur Eubanks       DOTGraphTraits<CallGraphDOTInfo *>::getGraphName(&CFGInfo);
250*a7e20a8aSArthur Eubanks   ViewGraph(&CFGInfo, "callgraph", true, Title);
251*a7e20a8aSArthur Eubanks }
252*a7e20a8aSArthur Eubanks } // namespace
253*a7e20a8aSArthur Eubanks 
254*a7e20a8aSArthur Eubanks namespace llvm {
run(Module & M,ModuleAnalysisManager & AM)255*a7e20a8aSArthur Eubanks PreservedAnalyses CallGraphDOTPrinterPass::run(Module &M,
256*a7e20a8aSArthur Eubanks                                                ModuleAnalysisManager &AM) {
257*a7e20a8aSArthur Eubanks   FunctionAnalysisManager &FAM =
258*a7e20a8aSArthur Eubanks       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
259*a7e20a8aSArthur Eubanks 
260*a7e20a8aSArthur Eubanks   auto LookupBFI = [&FAM](Function &F) {
261*a7e20a8aSArthur Eubanks     return &FAM.getResult<BlockFrequencyAnalysis>(F);
262*a7e20a8aSArthur Eubanks   };
263*a7e20a8aSArthur Eubanks 
264*a7e20a8aSArthur Eubanks   doCallGraphDOTPrinting(M, LookupBFI);
265*a7e20a8aSArthur Eubanks 
266*a7e20a8aSArthur Eubanks   return PreservedAnalyses::all();
267*a7e20a8aSArthur Eubanks }
268*a7e20a8aSArthur Eubanks 
run(Module & M,ModuleAnalysisManager & AM)269*a7e20a8aSArthur Eubanks PreservedAnalyses CallGraphViewerPass::run(Module &M,
270*a7e20a8aSArthur Eubanks                                            ModuleAnalysisManager &AM) {
271*a7e20a8aSArthur Eubanks 
272*a7e20a8aSArthur Eubanks   FunctionAnalysisManager &FAM =
273*a7e20a8aSArthur Eubanks       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
274*a7e20a8aSArthur Eubanks 
275*a7e20a8aSArthur Eubanks   auto LookupBFI = [&FAM](Function &F) {
276*a7e20a8aSArthur Eubanks     return &FAM.getResult<BlockFrequencyAnalysis>(F);
277*a7e20a8aSArthur Eubanks   };
278*a7e20a8aSArthur Eubanks 
279*a7e20a8aSArthur Eubanks   viewCallGraph(M, LookupBFI);
280*a7e20a8aSArthur Eubanks 
281*a7e20a8aSArthur Eubanks   return PreservedAnalyses::all();
282*a7e20a8aSArthur Eubanks }
283*a7e20a8aSArthur Eubanks } // namespace llvm
284*a7e20a8aSArthur Eubanks 
285*a7e20a8aSArthur Eubanks namespace {
286369d00dfSKirill Naumov // Viewer
287369d00dfSKirill Naumov class CallGraphViewer : public ModulePass {
288369d00dfSKirill Naumov public:
2893b0535b4SSean Fertile   static char ID;
CallGraphViewer()290369d00dfSKirill Naumov   CallGraphViewer() : ModulePass(ID) {}
2913b0535b4SSean Fertile 
292369d00dfSKirill Naumov   void getAnalysisUsage(AnalysisUsage &AU) const override;
293369d00dfSKirill Naumov   bool runOnModule(Module &M) override;
2947adc3a2bSChandler Carruth };
2957adc3a2bSChandler Carruth 
getAnalysisUsage(AnalysisUsage & AU) const296369d00dfSKirill Naumov void CallGraphViewer::getAnalysisUsage(AnalysisUsage &AU) const {
297369d00dfSKirill Naumov   ModulePass::getAnalysisUsage(AU);
298369d00dfSKirill Naumov   AU.addRequired<BlockFrequencyInfoWrapperPass>();
299369d00dfSKirill Naumov   AU.setPreservesAll();
3003b0535b4SSean Fertile }
301369d00dfSKirill Naumov 
runOnModule(Module & M)302369d00dfSKirill Naumov bool CallGraphViewer::runOnModule(Module &M) {
303369d00dfSKirill Naumov   auto LookupBFI = [this](Function &F) {
304369d00dfSKirill Naumov     return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
3053b0535b4SSean Fertile   };
3063b0535b4SSean Fertile 
307*a7e20a8aSArthur Eubanks   viewCallGraph(M, LookupBFI);
308369d00dfSKirill Naumov 
309369d00dfSKirill Naumov   return false;
310369d00dfSKirill Naumov }
311369d00dfSKirill Naumov 
312369d00dfSKirill Naumov // DOT Printer
313369d00dfSKirill Naumov 
314369d00dfSKirill Naumov class CallGraphDOTPrinter : public ModulePass {
315369d00dfSKirill Naumov public:
316369d00dfSKirill Naumov   static char ID;
CallGraphDOTPrinter()317369d00dfSKirill Naumov   CallGraphDOTPrinter() : ModulePass(ID) {}
318369d00dfSKirill Naumov 
319369d00dfSKirill Naumov   void getAnalysisUsage(AnalysisUsage &AU) const override;
320369d00dfSKirill Naumov   bool runOnModule(Module &M) override;
321369d00dfSKirill Naumov };
322369d00dfSKirill Naumov 
getAnalysisUsage(AnalysisUsage & AU) const323369d00dfSKirill Naumov void CallGraphDOTPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
324369d00dfSKirill Naumov   ModulePass::getAnalysisUsage(AU);
325369d00dfSKirill Naumov   AU.addRequired<BlockFrequencyInfoWrapperPass>();
326369d00dfSKirill Naumov   AU.setPreservesAll();
327369d00dfSKirill Naumov }
328369d00dfSKirill Naumov 
runOnModule(Module & M)329369d00dfSKirill Naumov bool CallGraphDOTPrinter::runOnModule(Module &M) {
330369d00dfSKirill Naumov   auto LookupBFI = [this](Function &F) {
331369d00dfSKirill Naumov     return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
332369d00dfSKirill Naumov   };
333369d00dfSKirill Naumov 
334*a7e20a8aSArthur Eubanks   doCallGraphDOTPrinting(M, LookupBFI);
335369d00dfSKirill Naumov 
336369d00dfSKirill Naumov   return false;
337369d00dfSKirill Naumov }
338369d00dfSKirill Naumov 
3397adc3a2bSChandler Carruth } // end anonymous namespace
3407adc3a2bSChandler Carruth 
3417adc3a2bSChandler Carruth char CallGraphViewer::ID = 0;
3427adc3a2bSChandler Carruth INITIALIZE_PASS(CallGraphViewer, "view-callgraph", "View call graph", false,
3437adc3a2bSChandler Carruth                 false)
3447adc3a2bSChandler Carruth 
3455f432292SChandler Carruth char CallGraphDOTPrinter::ID = 0;
3465f432292SChandler Carruth INITIALIZE_PASS(CallGraphDOTPrinter, "dot-callgraph",
3477adc3a2bSChandler Carruth                 "Print call graph to 'dot' file", false, false)
3487adc3a2bSChandler Carruth 
349e2024d72SArthur Eubanks // Create methods available outside of this file, to use them
350e2024d72SArthur Eubanks // "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by
351e2024d72SArthur Eubanks // the link time optimization.
352e2024d72SArthur Eubanks 
createCallGraphViewerPass()3537adc3a2bSChandler Carruth ModulePass *llvm::createCallGraphViewerPass() { return new CallGraphViewer(); }
3547adc3a2bSChandler Carruth 
createCallGraphDOTPrinterPass()3555f432292SChandler Carruth ModulePass *llvm::createCallGraphDOTPrinterPass() {
3565f432292SChandler Carruth   return new CallGraphDOTPrinter();
3577adc3a2bSChandler Carruth }
358