add function passes for printing various dominator datastructures
[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
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
29 using namespace llvm;
30
31 namespace llvm {
32 template<>
33 struct 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
47 template<>
48 struct 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
62 template<>
63 struct 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
78 namespace {
79 template <class Analysis, bool OnlyBBS>
80 struct 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
104 struct DomViewer
105   : public GenericGraphViewer<DominatorTree, false> {
106   static char ID;
107   DomViewer() : GenericGraphViewer<DominatorTree, false>("dom"){}
108 };
109
110 struct DomOnlyViewer
111   : public GenericGraphViewer<DominatorTree, true> {
112   static char ID;
113   DomOnlyViewer() : GenericGraphViewer<DominatorTree, true>("domonly"){}
114 };
115
116 struct PostDomViewer
117   : public GenericGraphViewer<PostDominatorTree, false> {
118   static char ID;
119   PostDomViewer() :
120     GenericGraphViewer<PostDominatorTree, false>("postdom"){}
121 };
122
123 struct PostDomOnlyViewer
124   : public GenericGraphViewer<PostDominatorTree, true> {
125   static char ID;
126   PostDomOnlyViewer() :
127     GenericGraphViewer<PostDominatorTree, true>("postdomonly"){}
128 };
129 } // end anonymous namespace
130
131 char DomViewer::ID = 0;
132 RegisterPass<DomViewer> A("view-dom",
133                           "View dominance tree of function");
134
135 char DomOnlyViewer::ID = 0;
136 RegisterPass<DomOnlyViewer> B("view-dom-only",
137                               "View dominance tree of function "
138                               "(with no function bodies)");
139
140 char PostDomViewer::ID = 0;
141 RegisterPass<PostDomViewer> C("view-postdom",
142                               "View postdominance tree of function");
143
144 char PostDomOnlyViewer::ID = 0;
145 RegisterPass<PostDomOnlyViewer> D("view-postdom-only",
146                                   "View postdominance tree of function "
147                                   "(with no function bodies)");
148
149 namespace {
150 template <class Analysis, bool OnlyBBS>
151 struct 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
183 struct DomPrinter
184   : public GenericGraphPrinter<DominatorTree, false> {
185   static char ID;
186   DomPrinter() : GenericGraphPrinter<DominatorTree, false>("dom"){}
187 };
188
189 struct DomOnlyPrinter
190   : public GenericGraphPrinter<DominatorTree, true> {
191   static char ID;
192   DomOnlyPrinter() : GenericGraphPrinter<DominatorTree, true>("domonly"){}
193 };
194
195 struct PostDomPrinter
196   : public GenericGraphPrinter<PostDominatorTree, false> {
197   static char ID;
198   PostDomPrinter() :
199     GenericGraphPrinter<PostDominatorTree, false>("postdom"){}
200 };
201
202 struct 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
212 char DomPrinter::ID = 0;
213 RegisterPass<DomPrinter> E("dot-dom",
214                            "Print dominance tree of function "
215                            "to 'dot' file");
216
217 char DomOnlyPrinter::ID = 0;
218 RegisterPass<DomOnlyPrinter> F("dot-dom-only",
219                                "Print dominance tree of function "
220                                "to 'dot' file "
221                                "(with no function bodies)");
222
223 char PostDomPrinter::ID = 0;
224 RegisterPass<PostDomPrinter> G("dot-postdom",
225                                "Print postdominance tree of function "
226                                "to 'dot' file");
227
228 char PostDomOnlyPrinter::ID = 0;
229 RegisterPass<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
238 FunctionPass *llvm::createDomPrinterPass() {
239   return new DomPrinter();
240 }
241
242 FunctionPass *llvm::createDomOnlyPrinterPass() {
243   return new DomOnlyPrinter();
244 }
245
246 FunctionPass *llvm::createDomViewerPass() {
247   return new DomViewer();
248 }
249
250 FunctionPass *llvm::createDomOnlyViewerPass() {
251   return new DomOnlyViewer();
252 }
253
254 FunctionPass *llvm::createPostDomPrinterPass() {
255   return new PostDomPrinter();
256 }
257
258 FunctionPass *llvm::createPostDomOnlyPrinterPass() {
259   return new PostDomOnlyPrinter();
260 }
261
262 FunctionPass *llvm::createPostDomViewerPass() {
263   return new PostDomViewer();
264 }
265
266 FunctionPass *llvm::createPostDomOnlyViewerPass() {
267   return new PostDomOnlyViewer();
268 }