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