xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/CallPrinter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- CallPrinter.cpp - DOT printer for call graph -----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines '-dot-callgraph', which emit a callgraph.<fnname>.dot
100b57cec5SDimitry Andric // containing the call graph of a module.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric // There is also a pass available to directly call dotty ('-view-callgraph').
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/Analysis/CallPrinter.h"
175ffd83dbSDimitry Andric #include "llvm/ADT/DenseMap.h"
185ffd83dbSDimitry Andric #include "llvm/ADT/SmallSet.h"
1981ad6265SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h"
2081ad6265SDimitry Andric #include "llvm/Analysis/CallGraph.h"
2181ad6265SDimitry Andric #include "llvm/Analysis/HeatUtils.h"
2281ad6265SDimitry Andric #include "llvm/IR/Instructions.h"
23*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h"
2481ad6265SDimitry Andric #include "llvm/InitializePasses.h"
2581ad6265SDimitry Andric #include "llvm/Support/CommandLine.h"
2681ad6265SDimitry Andric #include "llvm/Support/DOTGraphTraits.h"
2781ad6265SDimitry Andric #include "llvm/Support/GraphWriter.h"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric using namespace llvm;
300b57cec5SDimitry Andric 
3181ad6265SDimitry Andric namespace llvm {
3281ad6265SDimitry Andric template <class GraphType> struct GraphTraits;
33*0fca6ea1SDimitry Andric } // namespace llvm
3481ad6265SDimitry Andric 
355ffd83dbSDimitry Andric // This option shows static (relative) call counts.
365ffd83dbSDimitry Andric // FIXME:
375ffd83dbSDimitry Andric // Need to show real counts when profile data is available
385ffd83dbSDimitry Andric static cl::opt<bool> ShowHeatColors("callgraph-heat-colors", cl::init(false),
395ffd83dbSDimitry Andric                                     cl::Hidden,
405ffd83dbSDimitry Andric                                     cl::desc("Show heat colors in call-graph"));
415ffd83dbSDimitry Andric 
425ffd83dbSDimitry Andric static cl::opt<bool>
435ffd83dbSDimitry Andric     ShowEdgeWeight("callgraph-show-weights", cl::init(false), cl::Hidden,
445ffd83dbSDimitry Andric                        cl::desc("Show edges labeled with weights"));
455ffd83dbSDimitry Andric 
465ffd83dbSDimitry Andric static cl::opt<bool>
475ffd83dbSDimitry Andric     CallMultiGraph("callgraph-multigraph", cl::init(false), cl::Hidden,
485ffd83dbSDimitry Andric             cl::desc("Show call-multigraph (do not remove parallel edges)"));
495ffd83dbSDimitry Andric 
505ffd83dbSDimitry Andric static cl::opt<std::string> CallGraphDotFilenamePrefix(
515ffd83dbSDimitry Andric     "callgraph-dot-filename-prefix", cl::Hidden,
525ffd83dbSDimitry Andric     cl::desc("The prefix used for the CallGraph dot file names."));
535ffd83dbSDimitry Andric 
540b57cec5SDimitry Andric namespace llvm {
550b57cec5SDimitry Andric 
565ffd83dbSDimitry Andric class CallGraphDOTInfo {
575ffd83dbSDimitry Andric private:
585ffd83dbSDimitry Andric   Module *M;
595ffd83dbSDimitry Andric   CallGraph *CG;
605ffd83dbSDimitry Andric   DenseMap<const Function *, uint64_t> Freq;
615ffd83dbSDimitry Andric   uint64_t MaxFreq;
620b57cec5SDimitry Andric 
635ffd83dbSDimitry Andric public:
645ffd83dbSDimitry Andric   std::function<BlockFrequencyInfo *(Function &)> LookupBFI;
650b57cec5SDimitry Andric 
665ffd83dbSDimitry Andric   CallGraphDOTInfo(Module *M, CallGraph *CG,
675ffd83dbSDimitry Andric                    function_ref<BlockFrequencyInfo *(Function &)> LookupBFI)
685ffd83dbSDimitry Andric       : M(M), CG(CG), LookupBFI(LookupBFI) {
695ffd83dbSDimitry Andric     MaxFreq = 0;
700b57cec5SDimitry Andric 
71fe6060f1SDimitry Andric     for (Function &F : M->getFunctionList()) {
725ffd83dbSDimitry Andric       uint64_t localSumFreq = 0;
735ffd83dbSDimitry Andric       SmallSet<Function *, 16> Callers;
74fe6060f1SDimitry Andric       for (User *U : F.users())
755ffd83dbSDimitry Andric         if (isa<CallInst>(U))
765ffd83dbSDimitry Andric           Callers.insert(cast<Instruction>(U)->getFunction());
77fe6060f1SDimitry Andric       for (Function *Caller : Callers)
78fe6060f1SDimitry Andric         localSumFreq += getNumOfCalls(*Caller, F);
795ffd83dbSDimitry Andric       if (localSumFreq >= MaxFreq)
805ffd83dbSDimitry Andric         MaxFreq = localSumFreq;
81fe6060f1SDimitry Andric       Freq[&F] = localSumFreq;
825ffd83dbSDimitry Andric     }
835ffd83dbSDimitry Andric     if (!CallMultiGraph)
845ffd83dbSDimitry Andric       removeParallelEdges();
855ffd83dbSDimitry Andric   }
865ffd83dbSDimitry Andric 
875ffd83dbSDimitry Andric   Module *getModule() const { return M; }
885ffd83dbSDimitry Andric 
895ffd83dbSDimitry Andric   CallGraph *getCallGraph() const { return CG; }
905ffd83dbSDimitry Andric 
915ffd83dbSDimitry Andric   uint64_t getFreq(const Function *F) { return Freq[F]; }
925ffd83dbSDimitry Andric 
935ffd83dbSDimitry Andric   uint64_t getMaxFreq() { return MaxFreq; }
945ffd83dbSDimitry Andric 
955ffd83dbSDimitry Andric private:
965ffd83dbSDimitry Andric   void removeParallelEdges() {
975ffd83dbSDimitry Andric     for (auto &I : (*CG)) {
985ffd83dbSDimitry Andric       CallGraphNode *Node = I.second.get();
995ffd83dbSDimitry Andric 
1005ffd83dbSDimitry Andric       bool FoundParallelEdge = true;
1015ffd83dbSDimitry Andric       while (FoundParallelEdge) {
1025ffd83dbSDimitry Andric         SmallSet<Function *, 16> Visited;
1035ffd83dbSDimitry Andric         FoundParallelEdge = false;
1045ffd83dbSDimitry Andric         for (auto CI = Node->begin(), CE = Node->end(); CI != CE; CI++) {
1055ffd83dbSDimitry Andric           if (!(Visited.insert(CI->second->getFunction())).second) {
1065ffd83dbSDimitry Andric             FoundParallelEdge = true;
1075ffd83dbSDimitry Andric             Node->removeCallEdge(CI);
1085ffd83dbSDimitry Andric             break;
1095ffd83dbSDimitry Andric           }
1105ffd83dbSDimitry Andric         }
1115ffd83dbSDimitry Andric       }
1125ffd83dbSDimitry Andric     }
1130b57cec5SDimitry Andric   }
1140b57cec5SDimitry Andric };
1150b57cec5SDimitry Andric 
1165ffd83dbSDimitry Andric template <>
1175ffd83dbSDimitry Andric struct GraphTraits<CallGraphDOTInfo *>
1185ffd83dbSDimitry Andric     : public GraphTraits<const CallGraphNode *> {
1195ffd83dbSDimitry Andric   static NodeRef getEntryNode(CallGraphDOTInfo *CGInfo) {
1205ffd83dbSDimitry Andric     // Start at the external node!
1215ffd83dbSDimitry Andric     return CGInfo->getCallGraph()->getExternalCallingNode();
1225ffd83dbSDimitry Andric   }
1235ffd83dbSDimitry Andric 
1245ffd83dbSDimitry Andric   typedef std::pair<const Function *const, std::unique_ptr<CallGraphNode>>
1255ffd83dbSDimitry Andric       PairTy;
1265ffd83dbSDimitry Andric   static const CallGraphNode *CGGetValuePtr(const PairTy &P) {
1275ffd83dbSDimitry Andric     return P.second.get();
1285ffd83dbSDimitry Andric   }
1295ffd83dbSDimitry Andric 
1305ffd83dbSDimitry Andric   // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
1315ffd83dbSDimitry Andric   typedef mapped_iterator<CallGraph::const_iterator, decltype(&CGGetValuePtr)>
1325ffd83dbSDimitry Andric       nodes_iterator;
1335ffd83dbSDimitry Andric 
1345ffd83dbSDimitry Andric   static nodes_iterator nodes_begin(CallGraphDOTInfo *CGInfo) {
1355ffd83dbSDimitry Andric     return nodes_iterator(CGInfo->getCallGraph()->begin(), &CGGetValuePtr);
1365ffd83dbSDimitry Andric   }
1375ffd83dbSDimitry Andric   static nodes_iterator nodes_end(CallGraphDOTInfo *CGInfo) {
1385ffd83dbSDimitry Andric     return nodes_iterator(CGInfo->getCallGraph()->end(), &CGGetValuePtr);
1395ffd83dbSDimitry Andric   }
1405ffd83dbSDimitry Andric };
1415ffd83dbSDimitry Andric 
1425ffd83dbSDimitry Andric template <>
1435ffd83dbSDimitry Andric struct DOTGraphTraits<CallGraphDOTInfo *> : public DefaultDOTGraphTraits {
1445ffd83dbSDimitry Andric 
1455ffd83dbSDimitry Andric   DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
1465ffd83dbSDimitry Andric 
1475ffd83dbSDimitry Andric   static std::string getGraphName(CallGraphDOTInfo *CGInfo) {
1485ffd83dbSDimitry Andric     return "Call graph: " +
1495ffd83dbSDimitry Andric            std::string(CGInfo->getModule()->getModuleIdentifier());
1505ffd83dbSDimitry Andric   }
1515ffd83dbSDimitry Andric 
152e8d8bef9SDimitry Andric   static bool isNodeHidden(const CallGraphNode *Node,
153e8d8bef9SDimitry Andric                            const CallGraphDOTInfo *CGInfo) {
1545ffd83dbSDimitry Andric     if (CallMultiGraph || Node->getFunction())
1555ffd83dbSDimitry Andric       return false;
1565ffd83dbSDimitry Andric     return true;
1575ffd83dbSDimitry Andric   }
1585ffd83dbSDimitry Andric 
1595ffd83dbSDimitry Andric   std::string getNodeLabel(const CallGraphNode *Node,
1605ffd83dbSDimitry Andric                            CallGraphDOTInfo *CGInfo) {
1615ffd83dbSDimitry Andric     if (Node == CGInfo->getCallGraph()->getExternalCallingNode())
1625ffd83dbSDimitry Andric       return "external caller";
1635ffd83dbSDimitry Andric     if (Node == CGInfo->getCallGraph()->getCallsExternalNode())
1645ffd83dbSDimitry Andric       return "external callee";
1655ffd83dbSDimitry Andric 
1665ffd83dbSDimitry Andric     if (Function *Func = Node->getFunction())
1675ffd83dbSDimitry Andric       return std::string(Func->getName());
1685ffd83dbSDimitry Andric     return "external node";
1695ffd83dbSDimitry Andric   }
1705ffd83dbSDimitry Andric   static const CallGraphNode *CGGetValuePtr(CallGraphNode::CallRecord P) {
1715ffd83dbSDimitry Andric     return P.second;
1725ffd83dbSDimitry Andric   }
1735ffd83dbSDimitry Andric 
1745ffd83dbSDimitry Andric   // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
1755ffd83dbSDimitry Andric   typedef mapped_iterator<CallGraphNode::const_iterator,
1765ffd83dbSDimitry Andric                           decltype(&CGGetValuePtr)>
1775ffd83dbSDimitry Andric       nodes_iterator;
1785ffd83dbSDimitry Andric 
1795ffd83dbSDimitry Andric   std::string getEdgeAttributes(const CallGraphNode *Node, nodes_iterator I,
1805ffd83dbSDimitry Andric                                 CallGraphDOTInfo *CGInfo) {
1815ffd83dbSDimitry Andric     if (!ShowEdgeWeight)
1825ffd83dbSDimitry Andric       return "";
1835ffd83dbSDimitry Andric 
1845ffd83dbSDimitry Andric     Function *Caller = Node->getFunction();
1855ffd83dbSDimitry Andric     if (Caller == nullptr || Caller->isDeclaration())
1865ffd83dbSDimitry Andric       return "";
1875ffd83dbSDimitry Andric 
1885ffd83dbSDimitry Andric     Function *Callee = (*I)->getFunction();
1895ffd83dbSDimitry Andric     if (Callee == nullptr)
1905ffd83dbSDimitry Andric       return "";
1915ffd83dbSDimitry Andric 
1925ffd83dbSDimitry Andric     uint64_t Counter = getNumOfCalls(*Caller, *Callee);
1935ffd83dbSDimitry Andric     double Width =
1945ffd83dbSDimitry Andric         1 + 2 * (double(Counter) / CGInfo->getMaxFreq());
1955ffd83dbSDimitry Andric     std::string Attrs = "label=\"" + std::to_string(Counter) +
1965ffd83dbSDimitry Andric                         "\" penwidth=" + std::to_string(Width);
1975ffd83dbSDimitry Andric     return Attrs;
1985ffd83dbSDimitry Andric   }
1995ffd83dbSDimitry Andric 
2005ffd83dbSDimitry Andric   std::string getNodeAttributes(const CallGraphNode *Node,
2015ffd83dbSDimitry Andric                                 CallGraphDOTInfo *CGInfo) {
2025ffd83dbSDimitry Andric     Function *F = Node->getFunction();
2035ffd83dbSDimitry Andric     if (F == nullptr)
2045ffd83dbSDimitry Andric       return "";
205e8d8bef9SDimitry Andric     std::string attrs;
2065ffd83dbSDimitry Andric     if (ShowHeatColors) {
2075ffd83dbSDimitry Andric       uint64_t freq = CGInfo->getFreq(F);
2085ffd83dbSDimitry Andric       std::string color = getHeatColor(freq, CGInfo->getMaxFreq());
2095ffd83dbSDimitry Andric       std::string edgeColor = (freq <= (CGInfo->getMaxFreq() / 2))
2105ffd83dbSDimitry Andric                                   ? getHeatColor(0)
2115ffd83dbSDimitry Andric                                   : getHeatColor(1);
2125ffd83dbSDimitry Andric       attrs = "color=\"" + edgeColor + "ff\", style=filled, fillcolor=\"" +
2135ffd83dbSDimitry Andric               color + "80\"";
2145ffd83dbSDimitry Andric     }
2155ffd83dbSDimitry Andric     return attrs;
2160b57cec5SDimitry Andric   }
2170b57cec5SDimitry Andric };
2180b57cec5SDimitry Andric 
219*0fca6ea1SDimitry Andric } // namespace llvm
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric namespace {
22281ad6265SDimitry Andric void doCallGraphDOTPrinting(
22381ad6265SDimitry Andric     Module &M, function_ref<BlockFrequencyInfo *(Function &)> LookupBFI) {
22481ad6265SDimitry Andric   std::string Filename;
22581ad6265SDimitry Andric   if (!CallGraphDotFilenamePrefix.empty())
22681ad6265SDimitry Andric     Filename = (CallGraphDotFilenamePrefix + ".callgraph.dot");
22781ad6265SDimitry Andric   else
22881ad6265SDimitry Andric     Filename = (std::string(M.getModuleIdentifier()) + ".callgraph.dot");
22981ad6265SDimitry Andric   errs() << "Writing '" << Filename << "'...";
23081ad6265SDimitry Andric 
23181ad6265SDimitry Andric   std::error_code EC;
23281ad6265SDimitry Andric   raw_fd_ostream File(Filename, EC, sys::fs::OF_Text);
23381ad6265SDimitry Andric 
23481ad6265SDimitry Andric   CallGraph CG(M);
23581ad6265SDimitry Andric   CallGraphDOTInfo CFGInfo(&M, &CG, LookupBFI);
23681ad6265SDimitry Andric 
23781ad6265SDimitry Andric   if (!EC)
23881ad6265SDimitry Andric     WriteGraph(File, &CFGInfo);
23981ad6265SDimitry Andric   else
24081ad6265SDimitry Andric     errs() << "  error opening file for writing!";
24181ad6265SDimitry Andric   errs() << "\n";
24281ad6265SDimitry Andric }
24381ad6265SDimitry Andric 
24481ad6265SDimitry Andric void viewCallGraph(Module &M,
24581ad6265SDimitry Andric                    function_ref<BlockFrequencyInfo *(Function &)> LookupBFI) {
24681ad6265SDimitry Andric   CallGraph CG(M);
24781ad6265SDimitry Andric   CallGraphDOTInfo CFGInfo(&M, &CG, LookupBFI);
24881ad6265SDimitry Andric 
24981ad6265SDimitry Andric   std::string Title =
25081ad6265SDimitry Andric       DOTGraphTraits<CallGraphDOTInfo *>::getGraphName(&CFGInfo);
25181ad6265SDimitry Andric   ViewGraph(&CFGInfo, "callgraph", true, Title);
25281ad6265SDimitry Andric }
25381ad6265SDimitry Andric } // namespace
25481ad6265SDimitry Andric 
25581ad6265SDimitry Andric namespace llvm {
25681ad6265SDimitry Andric PreservedAnalyses CallGraphDOTPrinterPass::run(Module &M,
25781ad6265SDimitry Andric                                                ModuleAnalysisManager &AM) {
25881ad6265SDimitry Andric   FunctionAnalysisManager &FAM =
25981ad6265SDimitry Andric       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
26081ad6265SDimitry Andric 
26181ad6265SDimitry Andric   auto LookupBFI = [&FAM](Function &F) {
26281ad6265SDimitry Andric     return &FAM.getResult<BlockFrequencyAnalysis>(F);
26381ad6265SDimitry Andric   };
26481ad6265SDimitry Andric 
26581ad6265SDimitry Andric   doCallGraphDOTPrinting(M, LookupBFI);
26681ad6265SDimitry Andric 
26781ad6265SDimitry Andric   return PreservedAnalyses::all();
26881ad6265SDimitry Andric }
26981ad6265SDimitry Andric 
27081ad6265SDimitry Andric PreservedAnalyses CallGraphViewerPass::run(Module &M,
27181ad6265SDimitry Andric                                            ModuleAnalysisManager &AM) {
27281ad6265SDimitry Andric 
27381ad6265SDimitry Andric   FunctionAnalysisManager &FAM =
27481ad6265SDimitry Andric       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
27581ad6265SDimitry Andric 
27681ad6265SDimitry Andric   auto LookupBFI = [&FAM](Function &F) {
27781ad6265SDimitry Andric     return &FAM.getResult<BlockFrequencyAnalysis>(F);
27881ad6265SDimitry Andric   };
27981ad6265SDimitry Andric 
28081ad6265SDimitry Andric   viewCallGraph(M, LookupBFI);
28181ad6265SDimitry Andric 
28281ad6265SDimitry Andric   return PreservedAnalyses::all();
28381ad6265SDimitry Andric }
28481ad6265SDimitry Andric } // namespace llvm
28581ad6265SDimitry Andric 
28681ad6265SDimitry Andric namespace {
2875ffd83dbSDimitry Andric // Viewer
2885ffd83dbSDimitry Andric class CallGraphViewer : public ModulePass {
2895ffd83dbSDimitry Andric public:
2900b57cec5SDimitry Andric   static char ID;
2915ffd83dbSDimitry Andric   CallGraphViewer() : ModulePass(ID) {}
2920b57cec5SDimitry Andric 
2935ffd83dbSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
2945ffd83dbSDimitry Andric   bool runOnModule(Module &M) override;
2950b57cec5SDimitry Andric };
2960b57cec5SDimitry Andric 
2975ffd83dbSDimitry Andric void CallGraphViewer::getAnalysisUsage(AnalysisUsage &AU) const {
2985ffd83dbSDimitry Andric   ModulePass::getAnalysisUsage(AU);
2995ffd83dbSDimitry Andric   AU.addRequired<BlockFrequencyInfoWrapperPass>();
3005ffd83dbSDimitry Andric   AU.setPreservesAll();
3010b57cec5SDimitry Andric }
3025ffd83dbSDimitry Andric 
3035ffd83dbSDimitry Andric bool CallGraphViewer::runOnModule(Module &M) {
3045ffd83dbSDimitry Andric   auto LookupBFI = [this](Function &F) {
3055ffd83dbSDimitry Andric     return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
3060b57cec5SDimitry Andric   };
3070b57cec5SDimitry Andric 
30881ad6265SDimitry Andric   viewCallGraph(M, LookupBFI);
3095ffd83dbSDimitry Andric 
3105ffd83dbSDimitry Andric   return false;
3115ffd83dbSDimitry Andric }
3125ffd83dbSDimitry Andric 
3135ffd83dbSDimitry Andric // DOT Printer
3145ffd83dbSDimitry Andric 
3155ffd83dbSDimitry Andric class CallGraphDOTPrinter : public ModulePass {
3165ffd83dbSDimitry Andric public:
3175ffd83dbSDimitry Andric   static char ID;
3185ffd83dbSDimitry Andric   CallGraphDOTPrinter() : ModulePass(ID) {}
3195ffd83dbSDimitry Andric 
3205ffd83dbSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
3215ffd83dbSDimitry Andric   bool runOnModule(Module &M) override;
3225ffd83dbSDimitry Andric };
3235ffd83dbSDimitry Andric 
3245ffd83dbSDimitry Andric void CallGraphDOTPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
3255ffd83dbSDimitry Andric   ModulePass::getAnalysisUsage(AU);
3265ffd83dbSDimitry Andric   AU.addRequired<BlockFrequencyInfoWrapperPass>();
3275ffd83dbSDimitry Andric   AU.setPreservesAll();
3285ffd83dbSDimitry Andric }
3295ffd83dbSDimitry Andric 
3305ffd83dbSDimitry Andric bool CallGraphDOTPrinter::runOnModule(Module &M) {
3315ffd83dbSDimitry Andric   auto LookupBFI = [this](Function &F) {
3325ffd83dbSDimitry Andric     return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
3335ffd83dbSDimitry Andric   };
3345ffd83dbSDimitry Andric 
33581ad6265SDimitry Andric   doCallGraphDOTPrinting(M, LookupBFI);
3365ffd83dbSDimitry Andric 
3375ffd83dbSDimitry Andric   return false;
3385ffd83dbSDimitry Andric }
3395ffd83dbSDimitry Andric 
3400b57cec5SDimitry Andric } // end anonymous namespace
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric char CallGraphViewer::ID = 0;
3430b57cec5SDimitry Andric INITIALIZE_PASS(CallGraphViewer, "view-callgraph", "View call graph", false,
3440b57cec5SDimitry Andric                 false)
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric char CallGraphDOTPrinter::ID = 0;
3470b57cec5SDimitry Andric INITIALIZE_PASS(CallGraphDOTPrinter, "dot-callgraph",
3480b57cec5SDimitry Andric                 "Print call graph to 'dot' file", false, false)
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric // Create methods available outside of this file, to use them
3510b57cec5SDimitry Andric // "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by
3520b57cec5SDimitry Andric // the link time optimization.
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric ModulePass *llvm::createCallGraphViewerPass() { return new CallGraphViewer(); }
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric ModulePass *llvm::createCallGraphDOTPrinterPass() {
3570b57cec5SDimitry Andric   return new CallGraphDOTPrinter();
3580b57cec5SDimitry Andric }
359