DomPrinter.cpp revision 199989
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
28using namespace llvm;
29
30namespace llvm {
31template<>
32struct 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
54template<>
55struct 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
69template<>
70struct 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
86namespace {
87template <class Analysis, bool OnlyBBS>
88struct 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
112struct DomViewer
113  : public GenericGraphViewer<DominatorTree, false> {
114  static char ID;
115  DomViewer() : GenericGraphViewer<DominatorTree, false>("dom", &ID){}
116};
117
118struct DomOnlyViewer
119  : public GenericGraphViewer<DominatorTree, true> {
120  static char ID;
121  DomOnlyViewer() : GenericGraphViewer<DominatorTree, true>("domonly", &ID){}
122};
123
124struct PostDomViewer
125  : public GenericGraphViewer<PostDominatorTree, false> {
126  static char ID;
127  PostDomViewer() :
128    GenericGraphViewer<PostDominatorTree, false>("postdom", &ID){}
129};
130
131struct PostDomOnlyViewer
132  : public GenericGraphViewer<PostDominatorTree, true> {
133  static char ID;
134  PostDomOnlyViewer() :
135    GenericGraphViewer<PostDominatorTree, true>("postdomonly", &ID){}
136};
137} // end anonymous namespace
138
139char DomViewer::ID = 0;
140RegisterPass<DomViewer> A("view-dom",
141                          "View dominance tree of function");
142
143char DomOnlyViewer::ID = 0;
144RegisterPass<DomOnlyViewer> B("view-dom-only",
145                              "View dominance tree of function "
146                              "(with no function bodies)");
147
148char PostDomViewer::ID = 0;
149RegisterPass<PostDomViewer> C("view-postdom",
150                              "View postdominance tree of function");
151
152char PostDomOnlyViewer::ID = 0;
153RegisterPass<PostDomOnlyViewer> D("view-postdom-only",
154                                  "View postdominance tree of function "
155                                  "(with no function bodies)");
156
157namespace {
158template <class Analysis, bool OnlyBBS>
159struct 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
195struct DomPrinter
196  : public GenericGraphPrinter<DominatorTree, false> {
197  static char ID;
198  DomPrinter() : GenericGraphPrinter<DominatorTree, false>("dom", &ID) {}
199};
200
201struct DomOnlyPrinter
202  : public GenericGraphPrinter<DominatorTree, true> {
203  static char ID;
204  DomOnlyPrinter() : GenericGraphPrinter<DominatorTree, true>("domonly", &ID) {}
205};
206
207struct PostDomPrinter
208  : public GenericGraphPrinter<PostDominatorTree, false> {
209  static char ID;
210  PostDomPrinter() :
211    GenericGraphPrinter<PostDominatorTree, false>("postdom", &ID) {}
212};
213
214struct 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
224char DomPrinter::ID = 0;
225RegisterPass<DomPrinter> E("dot-dom",
226                           "Print dominance tree of function "
227                           "to 'dot' file");
228
229char DomOnlyPrinter::ID = 0;
230RegisterPass<DomOnlyPrinter> F("dot-dom-only",
231                               "Print dominance tree of function "
232                               "to 'dot' file "
233                               "(with no function bodies)");
234
235char PostDomPrinter::ID = 0;
236RegisterPass<PostDomPrinter> G("dot-postdom",
237                               "Print postdominance tree of function "
238                               "to 'dot' file");
239
240char PostDomOnlyPrinter::ID = 0;
241RegisterPass<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
250FunctionPass *llvm::createDomPrinterPass() {
251  return new DomPrinter();
252}
253
254FunctionPass *llvm::createDomOnlyPrinterPass() {
255  return new DomOnlyPrinter();
256}
257
258FunctionPass *llvm::createDomViewerPass() {
259  return new DomViewer();
260}
261
262FunctionPass *llvm::createDomOnlyViewerPass() {
263  return new DomOnlyViewer();
264}
265
266FunctionPass *llvm::createPostDomPrinterPass() {
267  return new PostDomPrinter();
268}
269
270FunctionPass *llvm::createPostDomOnlyPrinterPass() {
271  return new PostDomOnlyPrinter();
272}
273
274FunctionPass *llvm::createPostDomViewerPass() {
275  return new PostDomViewer();
276}
277
278FunctionPass *llvm::createPostDomOnlyViewerPass() {
279  return new PostDomOnlyViewer();
280}
281