28b18d1480eb57d8ae6289219a9375b6c117c9a7
[oota-llvm.git] / tools / analyze / GraphPrinters.cpp
1 //===- GraphPrinters.cpp - DOT printers for various graph types -----------===//
2 //
3 // This file defines several printers for various different types of graphs used
4 // by the LLVM infrastructure.  It uses the generic graph interface to convert
5 // the graph into a .dot graph.  These graphs can then be processed with the
6 // "dot" tool to convert them to postscript or some other suitable format.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "Support/GraphWriter.h"
11 #include "llvm/Pass.h"
12 #include "llvm/iTerminators.h"
13 #include "llvm/Analysis/CallGraph.h"
14 #include "llvm/Support/CFG.h"
15 #include <sstream>
16 #include <fstream>
17
18 //===----------------------------------------------------------------------===//
19 //                         Control Flow Graph Printer
20 //===----------------------------------------------------------------------===//
21
22 template<>
23 struct DOTGraphTraits<Function*> : public DefaultDOTGraphTraits {
24   static std::string getGraphName(Function *F) {
25     return "CFG for '" + F->getName() + "' function";
26   }
27
28   static std::string getNodeLabel(BasicBlock *Node, Function *Graph) {
29     std::ostringstream Out;
30     Out << Node;
31     std::string OutStr = Out.str();
32     if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
33
34     // Process string output to make it nicer...
35     for (unsigned i = 0; i != OutStr.length(); ++i)
36       if (OutStr[i] == '\n') {                            // Left justify
37         OutStr[i] = '\\';
38         OutStr.insert(OutStr.begin()+i+1, 'l');
39       } else if (OutStr[i] == ';') {                      // Delete comments!
40         unsigned Idx = OutStr.find('\n', i+1);            // Find end of line
41         OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx);
42         --i;
43       }
44
45     return OutStr;
46   }
47
48   static std::string getNodeAttributes(BasicBlock *N) {
49     return "fontname=Courier";
50   }
51   
52   static std::string getEdgeSourceLabel(BasicBlock *Node, succ_iterator I) {
53     // Label source of conditional branches with "T" or "F"
54     if (BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator()))
55       if (BI->isConditional())
56         return (I == succ_begin(Node)) ? "T" : "F";
57     return "";
58   }
59 };
60
61 template<typename GraphType>
62 static void WriteGraphToFile(std::ostream &O, const std::string &GraphName,
63                              const GraphType &GT) {
64   std::string Filename = GraphName + ".dot";
65   O << "Writing '" << Filename << "'...";
66   std::ofstream F(Filename.c_str());
67   
68   if (F.good())
69     WriteGraph(F, GT);
70   else
71     O << "  error opening file for writing!";
72   O << "\n";
73 }
74
75
76 namespace {
77   struct CFGPrinter : public FunctionPass {
78     virtual bool runOnFunction(Function &Func) {
79       WriteGraphToFile(std::cerr, "cfg."+Func.getName(), &Func);
80       return false;
81     }
82
83     void print(std::ostream &OS) const {}
84     
85     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
86       AU.setPreservesAll();
87     }
88   };
89
90   RegisterAnalysis<CFGPrinter> P1("print-cfg",
91                                   "Print CFG of function to 'dot' file");
92 };
93
94
95
96 //===----------------------------------------------------------------------===//
97 //                              Call Graph Printer
98 //===----------------------------------------------------------------------===//
99
100 template<>
101 struct DOTGraphTraits<CallGraph*> : public DefaultDOTGraphTraits {
102   static std::string getGraphName(CallGraph *F) {
103     return "Call Graph";
104   }
105
106   static std::string getNodeLabel(CallGraphNode *Node, CallGraph *Graph) {
107     if (Node->getFunction())
108       return Node->getFunction()->getName();
109     else
110       return "Indirect call node";
111   }
112 };
113
114
115 namespace {
116   struct CallGraphPrinter : public Pass {
117     virtual bool run(Module &M) {
118       WriteGraphToFile(std::cerr, "callgraph", &getAnalysis<CallGraph>());
119       return false;
120     }
121
122     void print(std::ostream &OS) const {}
123     
124     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
125       AU.addRequired<CallGraph>();
126       AU.setPreservesAll();
127     }
128   };
129
130   RegisterAnalysis<CallGraphPrinter> P2("print-callgraph",
131                                         "Print Call Graph to 'dot' file");
132 };