166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===- GraphPrinters.cpp - DOT printers for various graph types -----------===// 266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// The LLVM Compiler Infrastructure 466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This file is distributed under the University of Illinois Open Source 666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// License. See LICENSE.TXT for details. 766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 1066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This file defines several printers for various different types of graphs used 1166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// by the LLVM infrastructure. It uses the generic graph interface to convert 1266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// the graph into a .dot graph. These graphs can then be processed with the 1366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// "dot" tool to convert them to postscript or some other suitable format. 1466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 1566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 1666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 1766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/GraphWriter.h" 1866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Pass.h" 1966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Value.h" 2066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Analysis/CallGraph.h" 2166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Analysis/Dominators.h" 2266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/ToolOutputFile.h" 2366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanusing namespace llvm; 2466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 2566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumantemplate<typename GraphType> 2666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic void WriteGraphToFile(raw_ostream &O, const std::string &GraphName, 2766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const GraphType >) { 2866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string Filename = GraphName + ".dot"; 2966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman O << "Writing '" << Filename << "'..."; 3066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string ErrInfo; 3166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman tool_output_file F(Filename.c_str(), ErrInfo); 3266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 3366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (ErrInfo.empty()) { 3466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman WriteGraph(F.os(), GT); 3566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman F.os().close(); 3666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!F.os().has_error()) { 3766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman O << "\n"; 3866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman F.keep(); 3966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return; 4066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 4166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 4266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman O << " error opening file for writing!\n"; 4366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman F.os().clear_error(); 4466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 4566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 4866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// Call Graph Printer 4966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 5066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 5166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumannamespace llvm { 5266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman template<> 5366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman struct DOTGraphTraits<CallGraph*> : public DefaultDOTGraphTraits { 5466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 5566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 5666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 5766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman static std::string getGraphName(CallGraph *F) { 5866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return "Call Graph"; 5966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 6066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 6166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman static std::string getNodeLabel(CallGraphNode *Node, CallGraph *Graph) { 6266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Node->getFunction()) 6366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return ((Value*)Node->getFunction())->getName(); 6466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return "external node"; 6566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 6666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman }; 6766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 6866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 6966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 7066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumannamespace { 7166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman struct CallGraphPrinter : public ModulePass { 7266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman static char ID; // Pass ID, replacement for typeid 7366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman CallGraphPrinter() : ModulePass(ID) {} 7466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 7566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman virtual bool runOnModule(Module &M) { 7666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman WriteGraphToFile(llvm::errs(), "callgraph", &getAnalysis<CallGraph>()); 7766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 7866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 7966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 8066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman void print(raw_ostream &OS, const llvm::Module*) const {} 8166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 8266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman virtual void getAnalysisUsage(AnalysisUsage &AU) const { 8366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman AU.addRequired<CallGraph>(); 8466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman AU.setPreservesAll(); 8566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 8666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman }; 8766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 8866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 8966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanchar CallGraphPrinter::ID = 0; 9066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic RegisterPass<CallGraphPrinter> P2("dot-callgraph", 9166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman "Print Call Graph to 'dot' file"); 9266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 9366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 9466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// DomInfoPrinter Pass 9566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 9666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 9766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumannamespace { 9866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman class DomInfoPrinter : public FunctionPass { 9966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman public: 10066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman static char ID; // Pass identification, replacement for typeid 10166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman DomInfoPrinter() : FunctionPass(ID) {} 10266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 10366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman virtual void getAnalysisUsage(AnalysisUsage &AU) const { 10466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman AU.setPreservesAll(); 10566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman AU.addRequired<DominatorTree>(); 10666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 10766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 10866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 10966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman virtual bool runOnFunction(Function &F) { 11066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman getAnalysis<DominatorTree>().dump(); 11166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return false; 11266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 11366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman }; 11466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 11566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 11666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanchar DomInfoPrinter::ID = 0; 11766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic RegisterPass<DomInfoPrinter> 11866b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanDIP("print-dom-info", "Dominator Info Printer", true, true); 119