blob: 762cd9f6bcb504e51bdc4516b979015b1c7486d0 [file] [log] [blame]
Chris Lattnerb839c552009-10-18 04:10:40 +00001//===- DomPrinter.cpp - DOT printer for the dominance trees ------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines '-dot-dom' and '-dot-postdom' analysis passes, which emit
11// a dom.<fnname>.dot or postdom.<fnname>.dot file for each function in the
12// program, with a graph of the dominance/postdominance tree of that
13// function.
14//
15// There are also passes available to directly call dotty ('-view-dom' or
16// '-view-postdom'). By appending '-only' like '-dot-dom-only' only the
17// names of the bbs are printed, but the content is hidden.
18//
19//===----------------------------------------------------------------------===//
20
21#include "llvm/Analysis/DomPrinter.h"
Chris Lattnerb839c552009-10-18 04:10:40 +000022#include "llvm/Pass.h"
23#include "llvm/Function.h"
24#include "llvm/Analysis/CFGPrinter.h"
25#include "llvm/Analysis/Dominators.h"
26#include "llvm/Analysis/PostDominators.h"
27
28using namespace llvm;
29
30namespace llvm {
31template<>
32struct DOTGraphTraits<DomTreeNode*> : public DefaultDOTGraphTraits {
Tobias Grossera10d5982009-11-30 12:38:13 +000033
34 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
35
Chris Lattnerb839c552009-10-18 04:10:40 +000036 static std::string getNodeLabel(DomTreeNode *Node, DomTreeNode *Graph,
37 bool ShortNames) {
38
39 BasicBlock *BB = Node->getBlock();
40
41 if (!BB)
42 return "Post dominance root node";
43
44 return DOTGraphTraits<const Function*>::getNodeLabel(BB, BB->getParent(),
45 ShortNames);
46 }
47};
48
49template<>
50struct DOTGraphTraits<DominatorTree*> : public DOTGraphTraits<DomTreeNode*> {
51
Tobias Grossera10d5982009-11-30 12:38:13 +000052 DOTGraphTraits (bool isSimple=false)
53 : DOTGraphTraits<DomTreeNode*>(isSimple) {}
54
Chris Lattnerb839c552009-10-18 04:10:40 +000055 static std::string getGraphName(DominatorTree *DT) {
56 return "Dominator tree";
57 }
58
59 static std::string getNodeLabel(DomTreeNode *Node,
60 DominatorTree *G,
61 bool ShortNames) {
62 return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode(),
63 ShortNames);
64 }
65};
66
67template<>
68struct DOTGraphTraits<PostDominatorTree*>
69 : public DOTGraphTraits<DomTreeNode*> {
Tobias Grossera10d5982009-11-30 12:38:13 +000070
71 DOTGraphTraits (bool isSimple=false)
72 : DOTGraphTraits<DomTreeNode*>(isSimple) {}
73
Chris Lattnerb839c552009-10-18 04:10:40 +000074 static std::string getGraphName(PostDominatorTree *DT) {
75 return "Post dominator tree";
76 }
77 static std::string getNodeLabel(DomTreeNode *Node,
78 PostDominatorTree *G,
79 bool ShortNames) {
80 return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node,
81 G->getRootNode(),
82 ShortNames);
83 }
84};
85}
86
87namespace {
88template <class Analysis, bool OnlyBBS>
89struct GenericGraphViewer : public FunctionPass {
Chris Lattnerb839c552009-10-18 04:10:40 +000090 std::string Name;
91
Chris Lattner28717a82009-10-18 04:27:14 +000092 GenericGraphViewer(std::string GraphName, const void *ID) : FunctionPass(ID) {
Chris Lattnerb839c552009-10-18 04:10:40 +000093 Name = GraphName;
94 }
95
96 virtual bool runOnFunction(Function &F) {
97 Analysis *Graph;
Tobias Grosser2833fac2009-11-30 12:06:37 +000098 std::string Title, GraphName;
Chris Lattnerb839c552009-10-18 04:10:40 +000099 Graph = &getAnalysis<Analysis>();
Tobias Grosser2833fac2009-11-30 12:06:37 +0000100 GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
101 Title = GraphName + " for '" + F.getNameStr() + "' function";
102 ViewGraph(Graph, Name, OnlyBBS, Title);
Chris Lattnerb839c552009-10-18 04:10:40 +0000103
104 return false;
105 }
106
107 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
108 AU.setPreservesAll();
109 AU.addRequired<Analysis>();
110 }
111};
112
113struct DomViewer
114 : public GenericGraphViewer<DominatorTree, false> {
115 static char ID;
Chris Lattner28717a82009-10-18 04:27:14 +0000116 DomViewer() : GenericGraphViewer<DominatorTree, false>("dom", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000117};
118
119struct DomOnlyViewer
120 : public GenericGraphViewer<DominatorTree, true> {
121 static char ID;
Chris Lattner28717a82009-10-18 04:27:14 +0000122 DomOnlyViewer() : GenericGraphViewer<DominatorTree, true>("domonly", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000123};
124
125struct PostDomViewer
126 : public GenericGraphViewer<PostDominatorTree, false> {
127 static char ID;
128 PostDomViewer() :
Chris Lattner28717a82009-10-18 04:27:14 +0000129 GenericGraphViewer<PostDominatorTree, false>("postdom", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000130};
131
132struct PostDomOnlyViewer
133 : public GenericGraphViewer<PostDominatorTree, true> {
134 static char ID;
135 PostDomOnlyViewer() :
Chris Lattner28717a82009-10-18 04:27:14 +0000136 GenericGraphViewer<PostDominatorTree, true>("postdomonly", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000137};
138} // end anonymous namespace
139
140char DomViewer::ID = 0;
141RegisterPass<DomViewer> A("view-dom",
142 "View dominance tree of function");
143
144char DomOnlyViewer::ID = 0;
145RegisterPass<DomOnlyViewer> B("view-dom-only",
146 "View dominance tree of function "
147 "(with no function bodies)");
148
149char PostDomViewer::ID = 0;
150RegisterPass<PostDomViewer> C("view-postdom",
151 "View postdominance tree of function");
152
153char PostDomOnlyViewer::ID = 0;
154RegisterPass<PostDomOnlyViewer> D("view-postdom-only",
155 "View postdominance tree of function "
156 "(with no function bodies)");
157
158namespace {
159template <class Analysis, bool OnlyBBS>
160struct GenericGraphPrinter : public FunctionPass {
161
Chris Lattnerb839c552009-10-18 04:10:40 +0000162 std::string Name;
163
Chris Lattner0ec5c322009-10-18 04:58:34 +0000164 GenericGraphPrinter(std::string GraphName, const void *ID)
165 : FunctionPass(ID) {
Chris Lattnerb839c552009-10-18 04:10:40 +0000166 Name = GraphName;
167 }
168
169 virtual bool runOnFunction(Function &F) {
170 Analysis *Graph;
171 std::string Filename = Name + "." + F.getNameStr() + ".dot";
172 errs() << "Writing '" << Filename << "'...";
173
174 std::string ErrorInfo;
175 raw_fd_ostream File(Filename.c_str(), ErrorInfo);
176 Graph = &getAnalysis<Analysis>();
177
Tobias Grosser2833fac2009-11-30 12:06:37 +0000178 std::string Title, GraphName;
179 GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
180 Title = GraphName + " for '" + F.getNameStr() + "' function";
181
Chris Lattnerb839c552009-10-18 04:10:40 +0000182 if (ErrorInfo.empty())
Tobias Grosser2833fac2009-11-30 12:06:37 +0000183 WriteGraph(File, Graph, OnlyBBS, Name, Title);
Chris Lattnerb839c552009-10-18 04:10:40 +0000184 else
185 errs() << " error opening file for writing!";
186 errs() << "\n";
187 return false;
188 }
189
190 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
191 AU.setPreservesAll();
192 AU.addRequired<Analysis>();
193 }
194};
195
196struct DomPrinter
197 : public GenericGraphPrinter<DominatorTree, false> {
198 static char ID;
Chris Lattner0ec5c322009-10-18 04:58:34 +0000199 DomPrinter() : GenericGraphPrinter<DominatorTree, false>("dom", &ID) {}
Chris Lattnerb839c552009-10-18 04:10:40 +0000200};
201
202struct DomOnlyPrinter
203 : public GenericGraphPrinter<DominatorTree, true> {
204 static char ID;
Chris Lattner0ec5c322009-10-18 04:58:34 +0000205 DomOnlyPrinter() : GenericGraphPrinter<DominatorTree, true>("domonly", &ID) {}
Chris Lattnerb839c552009-10-18 04:10:40 +0000206};
207
208struct PostDomPrinter
209 : public GenericGraphPrinter<PostDominatorTree, false> {
210 static char ID;
211 PostDomPrinter() :
Chris Lattner0ec5c322009-10-18 04:58:34 +0000212 GenericGraphPrinter<PostDominatorTree, false>("postdom", &ID) {}
Chris Lattnerb839c552009-10-18 04:10:40 +0000213};
214
215struct PostDomOnlyPrinter
216 : public GenericGraphPrinter<PostDominatorTree, true> {
217 static char ID;
218 PostDomOnlyPrinter() :
Chris Lattner0ec5c322009-10-18 04:58:34 +0000219 GenericGraphPrinter<PostDominatorTree, true>("postdomonly", &ID) {}
Chris Lattnerb839c552009-10-18 04:10:40 +0000220};
221} // end anonymous namespace
222
223
224
225char DomPrinter::ID = 0;
226RegisterPass<DomPrinter> E("dot-dom",
227 "Print dominance tree of function "
228 "to 'dot' file");
229
230char DomOnlyPrinter::ID = 0;
231RegisterPass<DomOnlyPrinter> F("dot-dom-only",
232 "Print dominance tree of function "
233 "to 'dot' file "
234 "(with no function bodies)");
235
236char PostDomPrinter::ID = 0;
237RegisterPass<PostDomPrinter> G("dot-postdom",
238 "Print postdominance tree of function "
239 "to 'dot' file");
240
241char PostDomOnlyPrinter::ID = 0;
242RegisterPass<PostDomOnlyPrinter> H("dot-postdom-only",
243 "Print postdominance tree of function "
244 "to 'dot' file "
245 "(with no function bodies)");
246
247// Create methods available outside of this file, to use them
248// "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by
249// the link time optimization.
250
251FunctionPass *llvm::createDomPrinterPass() {
252 return new DomPrinter();
253}
254
255FunctionPass *llvm::createDomOnlyPrinterPass() {
256 return new DomOnlyPrinter();
257}
258
259FunctionPass *llvm::createDomViewerPass() {
260 return new DomViewer();
261}
262
263FunctionPass *llvm::createDomOnlyViewerPass() {
264 return new DomOnlyViewer();
265}
266
267FunctionPass *llvm::createPostDomPrinterPass() {
268 return new PostDomPrinter();
269}
270
271FunctionPass *llvm::createPostDomOnlyPrinterPass() {
272 return new PostDomOnlyPrinter();
273}
274
275FunctionPass *llvm::createPostDomViewerPass() {
276 return new PostDomViewer();
277}
278
279FunctionPass *llvm::createPostDomOnlyViewerPass() {
280 return new PostDomOnlyViewer();
281}