32b8994f0289bb0338eacfc2deeea97d1e2f41f4
[oota-llvm.git] / lib / Analysis / DomPrinter.cpp
1 //===- 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 #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
28 using namespace llvm;
29
30 namespace llvm {
31 template<>
32 struct DOTGraphTraits<DomTreeNode*> : public DefaultDOTGraphTraits {
33
34   DOTGraphTraits (bool isSimple=false)
35     : DefaultDOTGraphTraits(isSimple) {}
36
37   std::string getNodeLabel(DomTreeNode *Node, DomTreeNode *Graph) {
38
39     BasicBlock *BB = Node->getBlock();
40
41     if (!BB)
42       return "Post dominance root node";
43
44
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());
51   }
52 };
53
54 template<>
55 struct DOTGraphTraits<DominatorTree*> : public DOTGraphTraits<DomTreeNode*> {
56
57   DOTGraphTraits (bool isSimple=false)
58     : DOTGraphTraits<DomTreeNode*>(isSimple) {}
59
60   static std::string getGraphName(DominatorTree *DT) {
61     return "Dominator tree";
62   }
63
64   std::string getNodeLabel(DomTreeNode *Node, DominatorTree *G) {
65     return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode());
66   }
67 };
68
69 template<>
70 struct DOTGraphTraits<PostDominatorTree*>
71   : public DOTGraphTraits<DomTreeNode*> {
72
73   DOTGraphTraits (bool isSimple=false)
74     : DOTGraphTraits<DomTreeNode*>(isSimple) {}
75
76   static std::string getGraphName(PostDominatorTree *DT) {
77     return "Post dominator tree";
78   }
79
80   std::string getNodeLabel(DomTreeNode *Node, PostDominatorTree *G ) {
81     return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode());
82   }
83 };
84 }
85
86 namespace {
87 template <class Analysis, bool OnlyBBS>
88 struct GenericGraphViewer : public FunctionPass {
89   std::string Name;
90
91   GenericGraphViewer(std::string GraphName, const void *ID) : FunctionPass(ID) {
92     Name = GraphName;
93   }
94
95   virtual bool runOnFunction(Function &F) {
96     Analysis *Graph;
97     std::string Title, GraphName;
98     Graph = &getAnalysis<Analysis>();
99     GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
100     Title = GraphName + " for '" + F.getNameStr() + "' function";
101     ViewGraph(Graph, Name, OnlyBBS, Title);
102
103     return false;
104   }
105
106   virtual void getAnalysisUsage(AnalysisUsage &AU) const {
107     AU.setPreservesAll();
108     AU.addRequired<Analysis>();
109   }
110 };
111
112 struct DomViewer
113   : public GenericGraphViewer<DominatorTree, false> {
114   static char ID;
115   DomViewer() : GenericGraphViewer<DominatorTree, false>("dom", &ID){}
116 };
117
118 struct DomOnlyViewer
119   : public GenericGraphViewer<DominatorTree, true> {
120   static char ID;
121   DomOnlyViewer() : GenericGraphViewer<DominatorTree, true>("domonly", &ID){}
122 };
123
124 struct PostDomViewer
125   : public GenericGraphViewer<PostDominatorTree, false> {
126   static char ID;
127   PostDomViewer() :
128     GenericGraphViewer<PostDominatorTree, false>("postdom", &ID){}
129 };
130
131 struct PostDomOnlyViewer
132   : public GenericGraphViewer<PostDominatorTree, true> {
133   static char ID;
134   PostDomOnlyViewer() :
135     GenericGraphViewer<PostDominatorTree, true>("postdomonly", &ID){}
136 };
137 } // end anonymous namespace
138
139 char DomViewer::ID = 0;
140 RegisterPass<DomViewer> A("view-dom",
141                           "View dominance tree of function");
142
143 char DomOnlyViewer::ID = 0;
144 RegisterPass<DomOnlyViewer> B("view-dom-only",
145                               "View dominance tree of function "
146                               "(with no function bodies)");
147
148 char PostDomViewer::ID = 0;
149 RegisterPass<PostDomViewer> C("view-postdom",
150                               "View postdominance tree of function");
151
152 char PostDomOnlyViewer::ID = 0;
153 RegisterPass<PostDomOnlyViewer> D("view-postdom-only",
154                                   "View postdominance tree of function "
155                                   "(with no function bodies)");
156
157 namespace {
158 template <class Analysis, bool OnlyBBS>
159 struct GenericGraphPrinter : public FunctionPass {
160
161   std::string Name;
162
163   GenericGraphPrinter(std::string GraphName, const void *ID)
164     : FunctionPass(ID) {
165     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
177     std::string Title, GraphName;
178     GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
179     Title = GraphName + " for '" + F.getNameStr() + "' function";
180
181     if (ErrorInfo.empty())
182       WriteGraph(File, Graph, OnlyBBS, Name, Title);
183     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
195 struct DomPrinter
196   : public GenericGraphPrinter<DominatorTree, false> {
197   static char ID;
198   DomPrinter() : GenericGraphPrinter<DominatorTree, false>("dom", &ID) {}
199 };
200
201 struct DomOnlyPrinter
202   : public GenericGraphPrinter<DominatorTree, true> {
203   static char ID;
204   DomOnlyPrinter() : GenericGraphPrinter<DominatorTree, true>("domonly", &ID) {}
205 };
206
207 struct PostDomPrinter
208   : public GenericGraphPrinter<PostDominatorTree, false> {
209   static char ID;
210   PostDomPrinter() :
211     GenericGraphPrinter<PostDominatorTree, false>("postdom", &ID) {}
212 };
213
214 struct PostDomOnlyPrinter
215   : public GenericGraphPrinter<PostDominatorTree, true> {
216   static char ID;
217   PostDomOnlyPrinter() :
218     GenericGraphPrinter<PostDominatorTree, true>("postdomonly", &ID) {}
219 };
220 } // end anonymous namespace
221
222
223
224 char DomPrinter::ID = 0;
225 RegisterPass<DomPrinter> E("dot-dom",
226                            "Print dominance tree of function "
227                            "to 'dot' file");
228
229 char DomOnlyPrinter::ID = 0;
230 RegisterPass<DomOnlyPrinter> F("dot-dom-only",
231                                "Print dominance tree of function "
232                                "to 'dot' file "
233                                "(with no function bodies)");
234
235 char PostDomPrinter::ID = 0;
236 RegisterPass<PostDomPrinter> G("dot-postdom",
237                                "Print postdominance tree of function "
238                                "to 'dot' file");
239
240 char PostDomOnlyPrinter::ID = 0;
241 RegisterPass<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
250 FunctionPass *llvm::createDomPrinterPass() {
251   return new DomPrinter();
252 }
253
254 FunctionPass *llvm::createDomOnlyPrinterPass() {
255   return new DomOnlyPrinter();
256 }
257
258 FunctionPass *llvm::createDomViewerPass() {
259   return new DomViewer();
260 }
261
262 FunctionPass *llvm::createDomOnlyViewerPass() {
263   return new DomOnlyViewer();
264 }
265
266 FunctionPass *llvm::createPostDomPrinterPass() {
267   return new PostDomPrinter();
268 }
269
270 FunctionPass *llvm::createPostDomOnlyPrinterPass() {
271   return new PostDomOnlyPrinter();
272 }
273
274 FunctionPass *llvm::createPostDomViewerPass() {
275   return new PostDomViewer();
276 }
277
278 FunctionPass *llvm::createPostDomOnlyViewerPass() {
279   return new PostDomOnlyViewer();
280 }