blob: f7918177ccaa3b4dcef5feb95bce70a952b81be2 [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 {
81
82 static char ID;
83 std::string Name;
84
85 GenericGraphViewer(std::string GraphName) : FunctionPass(&ID) {
86 Name = GraphName;
87 }
88
89 virtual bool runOnFunction(Function &F) {
90 Analysis *Graph;
91
92 Graph = &getAnalysis<Analysis>();
93 ViewGraph(Graph, Name, OnlyBBS);
94
95 return false;
96 }
97
98 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
99 AU.setPreservesAll();
100 AU.addRequired<Analysis>();
101 }
102};
103
104struct DomViewer
105 : public GenericGraphViewer<DominatorTree, false> {
106 static char ID;
107 DomViewer() : GenericGraphViewer<DominatorTree, false>("dom"){}
108};
109
110struct DomOnlyViewer
111 : public GenericGraphViewer<DominatorTree, true> {
112 static char ID;
113 DomOnlyViewer() : GenericGraphViewer<DominatorTree, true>("domonly"){}
114};
115
116struct PostDomViewer
117 : public GenericGraphViewer<PostDominatorTree, false> {
118 static char ID;
119 PostDomViewer() :
120 GenericGraphViewer<PostDominatorTree, false>("postdom"){}
121};
122
123struct PostDomOnlyViewer
124 : public GenericGraphViewer<PostDominatorTree, true> {
125 static char ID;
126 PostDomOnlyViewer() :
127 GenericGraphViewer<PostDominatorTree, true>("postdomonly"){}
128};
129} // end anonymous namespace
130
131char DomViewer::ID = 0;
132RegisterPass<DomViewer> A("view-dom",
133 "View dominance tree of function");
134
135char DomOnlyViewer::ID = 0;
136RegisterPass<DomOnlyViewer> B("view-dom-only",
137 "View dominance tree of function "
138 "(with no function bodies)");
139
140char PostDomViewer::ID = 0;
141RegisterPass<PostDomViewer> C("view-postdom",
142 "View postdominance tree of function");
143
144char PostDomOnlyViewer::ID = 0;
145RegisterPass<PostDomOnlyViewer> D("view-postdom-only",
146 "View postdominance tree of function "
147 "(with no function bodies)");
148
149namespace {
150template <class Analysis, bool OnlyBBS>
151struct GenericGraphPrinter : public FunctionPass {
152
153 static char ID;
154 std::string Name;
155
156 GenericGraphPrinter(std::string GraphName) : FunctionPass(&ID) {
157 Name = GraphName;
158 }
159
160 virtual bool runOnFunction(Function &F) {
161 Analysis *Graph;
162 std::string Filename = Name + "." + F.getNameStr() + ".dot";
163 errs() << "Writing '" << Filename << "'...";
164
165 std::string ErrorInfo;
166 raw_fd_ostream File(Filename.c_str(), ErrorInfo);
167 Graph = &getAnalysis<Analysis>();
168
169 if (ErrorInfo.empty())
170 WriteGraph(File, Graph, OnlyBBS);
171 else
172 errs() << " error opening file for writing!";
173 errs() << "\n";
174 return false;
175 }
176
177 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
178 AU.setPreservesAll();
179 AU.addRequired<Analysis>();
180 }
181};
182
183struct DomPrinter
184 : public GenericGraphPrinter<DominatorTree, false> {
185 static char ID;
186 DomPrinter() : GenericGraphPrinter<DominatorTree, false>("dom"){}
187};
188
189struct DomOnlyPrinter
190 : public GenericGraphPrinter<DominatorTree, true> {
191 static char ID;
192 DomOnlyPrinter() : GenericGraphPrinter<DominatorTree, true>("domonly"){}
193};
194
195struct PostDomPrinter
196 : public GenericGraphPrinter<PostDominatorTree, false> {
197 static char ID;
198 PostDomPrinter() :
199 GenericGraphPrinter<PostDominatorTree, false>("postdom"){}
200};
201
202struct PostDomOnlyPrinter
203 : public GenericGraphPrinter<PostDominatorTree, true> {
204 static char ID;
205 PostDomOnlyPrinter() :
206 GenericGraphPrinter<PostDominatorTree, true>("postdomonly"){}
207};
208} // end anonymous namespace
209
210
211
212char DomPrinter::ID = 0;
213RegisterPass<DomPrinter> E("dot-dom",
214 "Print dominance tree of function "
215 "to 'dot' file");
216
217char DomOnlyPrinter::ID = 0;
218RegisterPass<DomOnlyPrinter> F("dot-dom-only",
219 "Print dominance tree of function "
220 "to 'dot' file "
221 "(with no function bodies)");
222
223char PostDomPrinter::ID = 0;
224RegisterPass<PostDomPrinter> G("dot-postdom",
225 "Print postdominance tree of function "
226 "to 'dot' file");
227
228char PostDomOnlyPrinter::ID = 0;
229RegisterPass<PostDomOnlyPrinter> H("dot-postdom-only",
230 "Print postdominance tree of function "
231 "to 'dot' file "
232 "(with no function bodies)");
233
234// Create methods available outside of this file, to use them
235// "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by
236// the link time optimization.
237
238FunctionPass *llvm::createDomPrinterPass() {
239 return new DomPrinter();
240}
241
242FunctionPass *llvm::createDomOnlyPrinterPass() {
243 return new DomOnlyPrinter();
244}
245
246FunctionPass *llvm::createDomViewerPass() {
247 return new DomViewer();
248}
249
250FunctionPass *llvm::createDomOnlyViewerPass() {
251 return new DomOnlyViewer();
252}
253
254FunctionPass *llvm::createPostDomPrinterPass() {
255 return new PostDomPrinter();
256}
257
258FunctionPass *llvm::createPostDomOnlyPrinterPass() {
259 return new PostDomOnlyPrinter();
260}
261
262FunctionPass *llvm::createPostDomViewerPass() {
263 return new PostDomViewer();
264}
265
266FunctionPass *llvm::createPostDomOnlyViewerPass() {
267 return new PostDomOnlyViewer();
268}