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 &GT) {
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