blob: 82e13a9ef2647263213296f0cd9d13351a2d3482 [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"
22
23#include "llvm/Pass.h"
24#include "llvm/Function.h"
25#include "llvm/Analysis/CFGPrinter.h"
26#include "llvm/Analysis/Dominators.h"
27#include "llvm/Analysis/PostDominators.h"
28
29using namespace llvm;
30
31namespace llvm {
32template<>
33struct DOTGraphTraits<DomTreeNode*> : public DefaultDOTGraphTraits {
34 static std::string getNodeLabel(DomTreeNode *Node, DomTreeNode *Graph,
35 bool ShortNames) {
36
37 BasicBlock *BB = Node->getBlock();
38
39 if (!BB)
40 return "Post dominance root node";
41
42 return DOTGraphTraits<const Function*>::getNodeLabel(BB, BB->getParent(),
43 ShortNames);
44 }
45};
46
47template<>
48struct DOTGraphTraits<DominatorTree*> : public DOTGraphTraits<DomTreeNode*> {
49
50 static std::string getGraphName(DominatorTree *DT) {
51 return "Dominator tree";
52 }
53
54 static std::string getNodeLabel(DomTreeNode *Node,
55 DominatorTree *G,
56 bool ShortNames) {
57 return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode(),
58 ShortNames);
59 }
60};
61
62template<>
63struct DOTGraphTraits<PostDominatorTree*>
64 : public DOTGraphTraits<DomTreeNode*> {
65 static std::string getGraphName(PostDominatorTree *DT) {
66 return "Post dominator tree";
67 }
68 static std::string getNodeLabel(DomTreeNode *Node,
69 PostDominatorTree *G,
70 bool ShortNames) {
71 return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node,
72 G->getRootNode(),
73 ShortNames);
74 }
75};
76}
77
78namespace {
79template <class Analysis, bool OnlyBBS>
80struct GenericGraphViewer : public FunctionPass {
Chris Lattnerb839c552009-10-18 04:10:40 +000081 std::string Name;
82
Chris Lattner28717a82009-10-18 04:27:14 +000083 GenericGraphViewer(std::string GraphName, const void *ID) : FunctionPass(ID) {
Chris Lattnerb839c552009-10-18 04:10:40 +000084 Name = GraphName;
85 }
86
87 virtual bool runOnFunction(Function &F) {
88 Analysis *Graph;
89
90 Graph = &getAnalysis<Analysis>();
91 ViewGraph(Graph, Name, OnlyBBS);
92
93 return false;
94 }
95
96 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
97 AU.setPreservesAll();
98 AU.addRequired<Analysis>();
99 }
100};
101
102struct DomViewer
103 : public GenericGraphViewer<DominatorTree, false> {
104 static char ID;
Chris Lattner28717a82009-10-18 04:27:14 +0000105 DomViewer() : GenericGraphViewer<DominatorTree, false>("dom", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000106};
107
108struct DomOnlyViewer
109 : public GenericGraphViewer<DominatorTree, true> {
110 static char ID;
Chris Lattner28717a82009-10-18 04:27:14 +0000111 DomOnlyViewer() : GenericGraphViewer<DominatorTree, true>("domonly", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000112};
113
114struct PostDomViewer
115 : public GenericGraphViewer<PostDominatorTree, false> {
116 static char ID;
117 PostDomViewer() :
Chris Lattner28717a82009-10-18 04:27:14 +0000118 GenericGraphViewer<PostDominatorTree, false>("postdom", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000119};
120
121struct PostDomOnlyViewer
122 : public GenericGraphViewer<PostDominatorTree, true> {
123 static char ID;
124 PostDomOnlyViewer() :
Chris Lattner28717a82009-10-18 04:27:14 +0000125 GenericGraphViewer<PostDominatorTree, true>("postdomonly", &ID){}
Chris Lattnerb839c552009-10-18 04:10:40 +0000126};
127} // end anonymous namespace
128
129char DomViewer::ID = 0;
130RegisterPass<DomViewer> A("view-dom",
131 "View dominance tree of function");
132
133char DomOnlyViewer::ID = 0;
134RegisterPass<DomOnlyViewer> B("view-dom-only",
135 "View dominance tree of function "
136 "(with no function bodies)");
137
138char PostDomViewer::ID = 0;
139RegisterPass<PostDomViewer> C("view-postdom",
140 "View postdominance tree of function");
141
142char PostDomOnlyViewer::ID = 0;
143RegisterPass<PostDomOnlyViewer> D("view-postdom-only",
144 "View postdominance tree of function "
145 "(with no function bodies)");
146
147namespace {
148template <class Analysis, bool OnlyBBS>
149struct GenericGraphPrinter : public FunctionPass {
150
151 static char ID;
152 std::string Name;
153
154 GenericGraphPrinter(std::string GraphName) : FunctionPass(&ID) {
155 Name = GraphName;
156 }
157
158 virtual bool runOnFunction(Function &F) {
159 Analysis *Graph;
160 std::string Filename = Name + "." + F.getNameStr() + ".dot";
161 errs() << "Writing '" << Filename << "'...";
162
163 std::string ErrorInfo;
164 raw_fd_ostream File(Filename.c_str(), ErrorInfo);
165 Graph = &getAnalysis<Analysis>();
166
167 if (ErrorInfo.empty())
168 WriteGraph(File, Graph, OnlyBBS);
169 else
170 errs() << " error opening file for writing!";
171 errs() << "\n";
172 return false;
173 }
174
175 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
176 AU.setPreservesAll();
177 AU.addRequired<Analysis>();
178 }
179};
180
181struct DomPrinter
182 : public GenericGraphPrinter<DominatorTree, false> {
183 static char ID;
184 DomPrinter() : GenericGraphPrinter<DominatorTree, false>("dom"){}
185};
186
187struct DomOnlyPrinter
188 : public GenericGraphPrinter<DominatorTree, true> {
189 static char ID;
190 DomOnlyPrinter() : GenericGraphPrinter<DominatorTree, true>("domonly"){}
191};
192
193struct PostDomPrinter
194 : public GenericGraphPrinter<PostDominatorTree, false> {
195 static char ID;
196 PostDomPrinter() :
197 GenericGraphPrinter<PostDominatorTree, false>("postdom"){}
198};
199
200struct PostDomOnlyPrinter
201 : public GenericGraphPrinter<PostDominatorTree, true> {
202 static char ID;
203 PostDomOnlyPrinter() :
204 GenericGraphPrinter<PostDominatorTree, true>("postdomonly"){}
205};
206} // end anonymous namespace
207
208
209
210char DomPrinter::ID = 0;
211RegisterPass<DomPrinter> E("dot-dom",
212 "Print dominance tree of function "
213 "to 'dot' file");
214
215char DomOnlyPrinter::ID = 0;
216RegisterPass<DomOnlyPrinter> F("dot-dom-only",
217 "Print dominance tree of function "
218 "to 'dot' file "
219 "(with no function bodies)");
220
221char PostDomPrinter::ID = 0;
222RegisterPass<PostDomPrinter> G("dot-postdom",
223 "Print postdominance tree of function "
224 "to 'dot' file");
225
226char PostDomOnlyPrinter::ID = 0;
227RegisterPass<PostDomOnlyPrinter> H("dot-postdom-only",
228 "Print postdominance tree of function "
229 "to 'dot' file "
230 "(with no function bodies)");
231
232// Create methods available outside of this file, to use them
233// "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by
234// the link time optimization.
235
236FunctionPass *llvm::createDomPrinterPass() {
237 return new DomPrinter();
238}
239
240FunctionPass *llvm::createDomOnlyPrinterPass() {
241 return new DomOnlyPrinter();
242}
243
244FunctionPass *llvm::createDomViewerPass() {
245 return new DomViewer();
246}
247
248FunctionPass *llvm::createDomOnlyViewerPass() {
249 return new DomOnlyViewer();
250}
251
252FunctionPass *llvm::createPostDomPrinterPass() {
253 return new PostDomPrinter();
254}
255
256FunctionPass *llvm::createPostDomOnlyPrinterPass() {
257 return new PostDomOnlyPrinter();
258}
259
260FunctionPass *llvm::createPostDomViewerPass() {
261 return new PostDomViewer();
262}
263
264FunctionPass *llvm::createPostDomOnlyViewerPass() {
265 return new PostDomOnlyViewer();
266}