1 //===- DomPrinter.cpp - DOT printer for the dominance trees    ------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines '-dot-dom' and '-dot-postdom' analysis passes, which emit
10 // a dom.<fnname>.dot or postdom.<fnname>.dot file for each function in the
11 // program, with a graph of the dominance/postdominance tree of that
12 // function.
13 //
14 // There are also passes available to directly call dotty ('-view-dom' or
15 // '-view-postdom'). By appending '-only' like '-dot-dom-only' only the
16 // names of the bbs are printed, but the content is hidden.
17 //
18 //===----------------------------------------------------------------------===//
19 
20 #include "llvm/Analysis/DomPrinter.h"
21 #include "llvm/Analysis/DOTGraphTraitsPass.h"
22 #include "llvm/Analysis/PostDominators.h"
23 #include "llvm/InitializePasses.h"
24 
25 using namespace llvm;
26 
27 namespace llvm {
28 template<>
29 struct DOTGraphTraits<DomTreeNode*> : public DefaultDOTGraphTraits {
30 
31   DOTGraphTraits (bool isSimple=false)
32     : DefaultDOTGraphTraits(isSimple) {}
33 
34   std::string getNodeLabel(DomTreeNode *Node, DomTreeNode *Graph) {
35 
36     BasicBlock *BB = Node->getBlock();
37 
38     if (!BB)
39       return "Post dominance root node";
40 
41 
42     if (isSimple())
43       return DOTGraphTraits<DOTFuncInfo *>
44         ::getSimpleNodeLabel(BB, nullptr);
45     else
46       return DOTGraphTraits<DOTFuncInfo *>
47         ::getCompleteNodeLabel(BB, nullptr);
48   }
49 };
50 
51 template<>
52 struct DOTGraphTraits<DominatorTree*> : public DOTGraphTraits<DomTreeNode*> {
53 
54   DOTGraphTraits (bool isSimple=false)
55     : DOTGraphTraits<DomTreeNode*>(isSimple) {}
56 
57   static std::string getGraphName(DominatorTree *DT) {
58     return "Dominator tree";
59   }
60 
61   std::string getNodeLabel(DomTreeNode *Node, DominatorTree *G) {
62     return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode());
63   }
64 };
65 
66 template<>
67 struct DOTGraphTraits<PostDominatorTree*>
68   : public DOTGraphTraits<DomTreeNode*> {
69 
70   DOTGraphTraits (bool isSimple=false)
71     : DOTGraphTraits<DomTreeNode*>(isSimple) {}
72 
73   static std::string getGraphName(PostDominatorTree *DT) {
74     return "Post dominator tree";
75   }
76 
77   std::string getNodeLabel(DomTreeNode *Node, PostDominatorTree *G ) {
78     return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode());
79   }
80 };
81 }
82 
83 PreservedAnalyses DomTreePrinterPass::run(Function &F,
84                                           FunctionAnalysisManager &AM) {
85   WriteDOTGraphToFile(F, &AM.getResult<DominatorTreeAnalysis>(F), "dom", false);
86   return PreservedAnalyses::all();
87 }
88 
89 PreservedAnalyses DomTreeOnlyPrinterPass::run(Function &F,
90                                               FunctionAnalysisManager &AM) {
91   WriteDOTGraphToFile(F, &AM.getResult<DominatorTreeAnalysis>(F), "domonly",
92                       true);
93   return PreservedAnalyses::all();
94 }
95 
96 void DominatorTree::viewGraph(const Twine &Name, const Twine &Title) {
97 #ifndef NDEBUG
98   ViewGraph(this, Name, false, Title);
99 #else
100   errs() << "DomTree dump not available, build with DEBUG\n";
101 #endif  // NDEBUG
102 }
103 
104 void DominatorTree::viewGraph() {
105 #ifndef NDEBUG
106   this->viewGraph("domtree", "Dominator Tree for function");
107 #else
108   errs() << "DomTree dump not available, build with DEBUG\n";
109 #endif  // NDEBUG
110 }
111 
112 namespace {
113 struct DominatorTreeWrapperPassAnalysisGraphTraits {
114   static DominatorTree *getGraph(DominatorTreeWrapperPass *DTWP) {
115     return &DTWP->getDomTree();
116   }
117 };
118 
119 struct DomViewer : public DOTGraphTraitsViewerWrapperPass<
120                        DominatorTreeWrapperPass, false, DominatorTree *,
121                        DominatorTreeWrapperPassAnalysisGraphTraits> {
122   static char ID;
123   DomViewer()
124       : DOTGraphTraitsViewerWrapperPass<
125             DominatorTreeWrapperPass, false, DominatorTree *,
126             DominatorTreeWrapperPassAnalysisGraphTraits>("dom", ID) {
127     initializeDomViewerPass(*PassRegistry::getPassRegistry());
128   }
129 };
130 
131 struct DomOnlyViewer : public DOTGraphTraitsViewerWrapperPass<
132                            DominatorTreeWrapperPass, true, DominatorTree *,
133                            DominatorTreeWrapperPassAnalysisGraphTraits> {
134   static char ID;
135   DomOnlyViewer()
136       : DOTGraphTraitsViewerWrapperPass<
137             DominatorTreeWrapperPass, true, DominatorTree *,
138             DominatorTreeWrapperPassAnalysisGraphTraits>("domonly", ID) {
139     initializeDomOnlyViewerPass(*PassRegistry::getPassRegistry());
140   }
141 };
142 
143 struct PostDominatorTreeWrapperPassAnalysisGraphTraits {
144   static PostDominatorTree *getGraph(PostDominatorTreeWrapperPass *PDTWP) {
145     return &PDTWP->getPostDomTree();
146   }
147 };
148 
149 struct PostDomViewer
150     : public DOTGraphTraitsViewerWrapperPass<
151           PostDominatorTreeWrapperPass, false, PostDominatorTree *,
152           PostDominatorTreeWrapperPassAnalysisGraphTraits> {
153   static char ID;
154   PostDomViewer()
155       : DOTGraphTraitsViewerWrapperPass<
156             PostDominatorTreeWrapperPass, false, PostDominatorTree *,
157             PostDominatorTreeWrapperPassAnalysisGraphTraits>("postdom", ID) {
158     initializePostDomViewerPass(*PassRegistry::getPassRegistry());
159   }
160 };
161 
162 struct PostDomOnlyViewer
163     : public DOTGraphTraitsViewerWrapperPass<
164           PostDominatorTreeWrapperPass, true, PostDominatorTree *,
165           PostDominatorTreeWrapperPassAnalysisGraphTraits> {
166   static char ID;
167   PostDomOnlyViewer()
168       : DOTGraphTraitsViewerWrapperPass<
169             PostDominatorTreeWrapperPass, true, PostDominatorTree *,
170             PostDominatorTreeWrapperPassAnalysisGraphTraits>("postdomonly",
171                                                              ID) {
172     initializePostDomOnlyViewerPass(*PassRegistry::getPassRegistry());
173   }
174 };
175 } // end anonymous namespace
176 
177 char DomViewer::ID = 0;
178 INITIALIZE_PASS(DomViewer, "view-dom",
179                 "View dominance tree of function", false, false)
180 
181 char DomOnlyViewer::ID = 0;
182 INITIALIZE_PASS(DomOnlyViewer, "view-dom-only",
183                 "View dominance tree of function (with no function bodies)",
184                 false, false)
185 
186 char PostDomViewer::ID = 0;
187 INITIALIZE_PASS(PostDomViewer, "view-postdom",
188                 "View postdominance tree of function", false, false)
189 
190 char PostDomOnlyViewer::ID = 0;
191 INITIALIZE_PASS(PostDomOnlyViewer, "view-postdom-only",
192                 "View postdominance tree of function "
193                 "(with no function bodies)",
194                 false, false)
195 
196 namespace {
197 struct DomPrinter : public DOTGraphTraitsPrinterWrapperPass<
198                         DominatorTreeWrapperPass, false, DominatorTree *,
199                         DominatorTreeWrapperPassAnalysisGraphTraits> {
200   static char ID;
201   DomPrinter()
202       : DOTGraphTraitsPrinterWrapperPass<
203             DominatorTreeWrapperPass, false, DominatorTree *,
204             DominatorTreeWrapperPassAnalysisGraphTraits>("dom", ID) {
205     initializeDomPrinterPass(*PassRegistry::getPassRegistry());
206   }
207 };
208 
209 struct DomOnlyPrinter : public DOTGraphTraitsPrinterWrapperPass<
210                             DominatorTreeWrapperPass, true, DominatorTree *,
211                             DominatorTreeWrapperPassAnalysisGraphTraits> {
212   static char ID;
213   DomOnlyPrinter()
214       : DOTGraphTraitsPrinterWrapperPass<
215             DominatorTreeWrapperPass, true, DominatorTree *,
216             DominatorTreeWrapperPassAnalysisGraphTraits>("domonly", ID) {
217     initializeDomOnlyPrinterPass(*PassRegistry::getPassRegistry());
218   }
219 };
220 
221 struct PostDomPrinter
222     : public DOTGraphTraitsPrinterWrapperPass<
223           PostDominatorTreeWrapperPass, false, PostDominatorTree *,
224           PostDominatorTreeWrapperPassAnalysisGraphTraits> {
225   static char ID;
226   PostDomPrinter()
227       : DOTGraphTraitsPrinterWrapperPass<
228             PostDominatorTreeWrapperPass, false, PostDominatorTree *,
229             PostDominatorTreeWrapperPassAnalysisGraphTraits>("postdom", ID) {
230     initializePostDomPrinterPass(*PassRegistry::getPassRegistry());
231   }
232 };
233 
234 struct PostDomOnlyPrinter
235     : public DOTGraphTraitsPrinterWrapperPass<
236           PostDominatorTreeWrapperPass, true, PostDominatorTree *,
237           PostDominatorTreeWrapperPassAnalysisGraphTraits> {
238   static char ID;
239   PostDomOnlyPrinter()
240       : DOTGraphTraitsPrinterWrapperPass<
241             PostDominatorTreeWrapperPass, true, PostDominatorTree *,
242             PostDominatorTreeWrapperPassAnalysisGraphTraits>("postdomonly",
243                                                              ID) {
244     initializePostDomOnlyPrinterPass(*PassRegistry::getPassRegistry());
245   }
246 };
247 } // end anonymous namespace
248 
249 
250 
251 char DomPrinter::ID = 0;
252 INITIALIZE_PASS(DomPrinter, "dot-dom",
253                 "Print dominance tree of function to 'dot' file",
254                 false, false)
255 
256 char DomOnlyPrinter::ID = 0;
257 INITIALIZE_PASS(DomOnlyPrinter, "dot-dom-only",
258                 "Print dominance tree of function to 'dot' file "
259                 "(with no function bodies)",
260                 false, false)
261 
262 char PostDomPrinter::ID = 0;
263 INITIALIZE_PASS(PostDomPrinter, "dot-postdom",
264                 "Print postdominance tree of function to 'dot' file",
265                 false, false)
266 
267 char PostDomOnlyPrinter::ID = 0;
268 INITIALIZE_PASS(PostDomOnlyPrinter, "dot-postdom-only",
269                 "Print postdominance tree of function to 'dot' file "
270                 "(with no function bodies)",
271                 false, false)
272 
273 // Create methods available outside of this file, to use them
274 // "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by
275 // the link time optimization.
276 
277 FunctionPass *llvm::createDomPrinterPass() {
278   return new DomPrinter();
279 }
280 
281 FunctionPass *llvm::createDomOnlyPrinterPass() {
282   return new DomOnlyPrinter();
283 }
284 
285 FunctionPass *llvm::createDomViewerPass() {
286   return new DomViewer();
287 }
288 
289 FunctionPass *llvm::createDomOnlyViewerPass() {
290   return new DomOnlyViewer();
291 }
292 
293 FunctionPass *llvm::createPostDomPrinterPass() {
294   return new PostDomPrinter();
295 }
296 
297 FunctionPass *llvm::createPostDomOnlyPrinterPass() {
298   return new PostDomOnlyPrinter();
299 }
300 
301 FunctionPass *llvm::createPostDomViewerPass() {
302   return new PostDomViewer();
303 }
304 
305 FunctionPass *llvm::createPostDomOnlyViewerPass() {
306   return new PostDomOnlyViewer();
307 }
308