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