blob: 32b8994f0289bb0338eacfc2deeea97d1e2f41f4 [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
Tobias Grosser56f4ef32009-11-30 12:38:47 +000034 DOTGraphTraits (bool isSimple=false)
35 : DefaultDOTGraphTraits(isSimple) {}
Tobias Grossera10d5982009-11-30 12:38:13 +000036
Tobias Grosser56f4ef32009-11-30 12:38:47 +000037 std::string getNodeLabel(DomTreeNode *Node, DomTreeNode *Graph) {
Chris Lattnerb839c552009-10-18 04:10:40 +000038
39 BasicBlock *BB = Node->getBlock();
40
41 if (!BB)
42 return "Post dominance root node";
43
Tobias Grosser56f4ef32009-11-30 12:38:47 +000044
45 if (isSimple())
46 return DOTGraphTraits<const Function*>
47 ::getSimpleNodeLabel(BB, BB->getParent());
48 else
49 return DOTGraphTraits<const Function*>
50 ::getCompleteNodeLabel(BB, BB->getParent());
Chris Lattnerb839c552009-10-18 04:10:40 +000051 }
52};
53
54template<>
55struct DOTGraphTraits<DominatorTree*> : public DOTGraphTraits<DomTreeNode*> {
56
Tobias Grossera10d5982009-11-30 12:38:13 +000057 DOTGraphTraits (bool isSimple=false)
58 : DOTGraphTraits<DomTreeNode*>(isSimple) {}
59
Chris Lattnerb839c552009-10-18 04:10:40 +000060 static std::string getGraphName(DominatorTree *DT) {
61 return "Dominator tree";
62 }
63
Tobias Grosser56f4ef32009-11-30 12:38:47 +000064 std::string getNodeLabel(DomTreeNode *Node, DominatorTree *G) {
65 return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode());
Chris Lattnerb839c552009-10-18 04:10:40 +000066 }
67};
68
69template<>
70struct DOTGraphTraits<PostDominatorTree*>
71 : public DOTGraphTraits<DomTreeNode*> {
Tobias Grossera10d5982009-11-30 12:38:13 +000072
73 DOTGraphTraits (bool isSimple=false)
74 : DOTGraphTraits<DomTreeNode*>(isSimple) {}
75
Chris Lattnerb839c552009-10-18 04:10:40 +000076 static std::string getGraphName(PostDominatorTree *DT) {
77 return "Post dominator tree";
78 }
Tobias Grosser56f4ef32009-11-30 12:38:47 +000079
80 std::string getNodeLabel(DomTreeNode *Node, PostDominatorTree *G ) {
81 return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode());
Chris Lattnerb839c552009-10-18 04:10:40 +000082 }
83};
84}
85
86namespace {
87template <class Analysis, bool OnlyBBS>
88struct GenericGraphViewer : public FunctionPass {
Chris Lattnerb839c552009-10-18 04:10:40 +000089 std::string Name;
90
Chris Lattner28717a82009-10-18 04:27:14 +000091 GenericGraphViewer(std::string GraphName, const void *ID) : FunctionPass(ID) {
Chris Lattnerb839c552009-10-18 04:10:40 +000092 Name = GraphName;
93 }
94
95 virtual bool runOnFunction(Function &F) {
96 Analysis *Graph;
Tobias Grosser2833fac2009-11-30 12:06:37 +000097 std::string Title, GraphName;
Chris Lattnerb839c552009-10-18 04:10:40 +000098 Graph = &getAnalysis<Analysis>();
Tobias Grosser2833fac2009-11-30 12:06:37 +000099 GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
100 Title = GraphName + " for '" + F.getNameStr() + "' function";
101 ViewGraph(Graph, Name, OnlyBBS, Title);
Chris Lattnerb839c552009-10-18 04:10:40 +0000102
103 return false;
104 }
105
106 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
107 AU.setPreservesAll();
108 AU.addRequired<Analysis>();
109 }
110};
111
112struct DomViewer
113 : public GenericGraphViewer<DominatorTree, false> {
114 static char ID;
Chris Lattner28717a82009-10-18 04:27:14 +0000115 DomViewer() : GenericGraphViewer<DominatorTree, false>("dom", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000116};
117
118struct DomOnlyViewer
119 : public GenericGraphViewer<DominatorTree, true> {
120 static char ID;
Chris Lattner28717a82009-10-18 04:27:14 +0000121 DomOnlyViewer() : GenericGraphViewer<DominatorTree, true>("domonly", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000122};
123
124struct PostDomViewer
125 : public GenericGraphViewer<PostDominatorTree, false> {
126 static char ID;
127 PostDomViewer() :
Chris Lattner28717a82009-10-18 04:27:14 +0000128 GenericGraphViewer<PostDominatorTree, false>("postdom", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000129};
130
131struct PostDomOnlyViewer
132 : public GenericGraphViewer<PostDominatorTree, true> {
133 static char ID;
134 PostDomOnlyViewer() :
Chris Lattner28717a82009-10-18 04:27:14 +0000135 GenericGraphViewer<PostDominatorTree, true>("postdomonly", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000136};
137} // end anonymous namespace
138
139char DomViewer::ID = 0;
140RegisterPass<DomViewer> A("view-dom",
141 "View dominance tree of function");
142
143char DomOnlyViewer::ID = 0;
144RegisterPass<DomOnlyViewer> B("view-dom-only",
145 "View dominance tree of function "
146 "(with no function bodies)");
147
148char PostDomViewer::ID = 0;
149RegisterPass<PostDomViewer> C("view-postdom",
150 "View postdominance tree of function");
151
152char PostDomOnlyViewer::ID = 0;
153RegisterPass<PostDomOnlyViewer> D("view-postdom-only",
154 "View postdominance tree of function "
155 "(with no function bodies)");
156
157namespace {
158template <class Analysis, bool OnlyBBS>
159struct GenericGraphPrinter : public FunctionPass {
160
Chris Lattnerb839c552009-10-18 04:10:40 +0000161 std::string Name;
162
Chris Lattner0ec5c322009-10-18 04:58:34 +0000163 GenericGraphPrinter(std::string GraphName, const void *ID)
164 : FunctionPass(ID) {
Chris Lattnerb839c552009-10-18 04:10:40 +0000165 Name = GraphName;
166 }
167
168 virtual bool runOnFunction(Function &F) {
169 Analysis *Graph;
170 std::string Filename = Name + "." + F.getNameStr() + ".dot";
171 errs() << "Writing '" << Filename << "'...";
172
173 std::string ErrorInfo;
174 raw_fd_ostream File(Filename.c_str(), ErrorInfo);
175 Graph = &getAnalysis<Analysis>();
176
Tobias Grosser2833fac2009-11-30 12:06:37 +0000177 std::string Title, GraphName;
178 GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
179 Title = GraphName + " for '" + F.getNameStr() + "' function";
180
Chris Lattnerb839c552009-10-18 04:10:40 +0000181 if (ErrorInfo.empty())
Tobias Grosser2833fac2009-11-30 12:06:37 +0000182 WriteGraph(File, Graph, OnlyBBS, Name, Title);
Chris Lattnerb839c552009-10-18 04:10:40 +0000183 else
184 errs() << " error opening file for writing!";
185 errs() << "\n";
186 return false;
187 }
188
189 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
190 AU.setPreservesAll();
191 AU.addRequired<Analysis>();
192 }
193};
194
195struct DomPrinter
196 : public GenericGraphPrinter<DominatorTree, false> {
197 static char ID;
Chris Lattner0ec5c322009-10-18 04:58:34 +0000198 DomPrinter() : GenericGraphPrinter<DominatorTree, false>("dom", &ID) {}
Chris Lattnerb839c552009-10-18 04:10:40 +0000199};
200
201struct DomOnlyPrinter
202 : public GenericGraphPrinter<DominatorTree, true> {
203 static char ID;
Chris Lattner0ec5c322009-10-18 04:58:34 +0000204 DomOnlyPrinter() : GenericGraphPrinter<DominatorTree, true>("domonly", &ID) {}
Chris Lattnerb839c552009-10-18 04:10:40 +0000205};
206
207struct PostDomPrinter
208 : public GenericGraphPrinter<PostDominatorTree, false> {
209 static char ID;
210 PostDomPrinter() :
Chris Lattner0ec5c322009-10-18 04:58:34 +0000211 GenericGraphPrinter<PostDominatorTree, false>("postdom", &ID) {}
Chris Lattnerb839c552009-10-18 04:10:40 +0000212};
213
214struct PostDomOnlyPrinter
215 : public GenericGraphPrinter<PostDominatorTree, true> {
216 static char ID;
217 PostDomOnlyPrinter() :
Chris Lattner0ec5c322009-10-18 04:58:34 +0000218 GenericGraphPrinter<PostDominatorTree, true>("postdomonly", &ID) {}
Chris Lattnerb839c552009-10-18 04:10:40 +0000219};
220} // end anonymous namespace
221
222
223
224char DomPrinter::ID = 0;
225RegisterPass<DomPrinter> E("dot-dom",
226 "Print dominance tree of function "
227 "to 'dot' file");
228
229char DomOnlyPrinter::ID = 0;
230RegisterPass<DomOnlyPrinter> F("dot-dom-only",
231 "Print dominance tree of function "
232 "to 'dot' file "
233 "(with no function bodies)");
234
235char PostDomPrinter::ID = 0;
236RegisterPass<PostDomPrinter> G("dot-postdom",
237 "Print postdominance tree of function "
238 "to 'dot' file");
239
240char PostDomOnlyPrinter::ID = 0;
241RegisterPass<PostDomOnlyPrinter> H("dot-postdom-only",
242 "Print postdominance tree of function "
243 "to 'dot' file "
244 "(with no function bodies)");
245
246// Create methods available outside of this file, to use them
247// "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by
248// the link time optimization.
249
250FunctionPass *llvm::createDomPrinterPass() {
251 return new DomPrinter();
252}
253
254FunctionPass *llvm::createDomOnlyPrinterPass() {
255 return new DomOnlyPrinter();
256}
257
258FunctionPass *llvm::createDomViewerPass() {
259 return new DomViewer();
260}
261
262FunctionPass *llvm::createDomOnlyViewerPass() {
263 return new DomOnlyViewer();
264}
265
266FunctionPass *llvm::createPostDomPrinterPass() {
267 return new PostDomPrinter();
268}
269
270FunctionPass *llvm::createPostDomOnlyPrinterPass() {
271 return new PostDomOnlyPrinter();
272}
273
274FunctionPass *llvm::createPostDomViewerPass() {
275 return new PostDomViewer();
276}
277
278FunctionPass *llvm::createPostDomOnlyViewerPass() {
279 return new PostDomOnlyViewer();
280}