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 DOTGraphTraitsViewer<
120                        DominatorTreeWrapperPass, false, DominatorTree *,
121                        DominatorTreeWrapperPassAnalysisGraphTraits> {
122   static char ID;
123   DomViewer()
124       : DOTGraphTraitsViewer<DominatorTreeWrapperPass, false, DominatorTree *,
125                              DominatorTreeWrapperPassAnalysisGraphTraits>(
126             "dom", ID) {
127     initializeDomViewerPass(*PassRegistry::getPassRegistry());
128   }
129 };
130 
131 struct DomOnlyViewer : public DOTGraphTraitsViewer<
132                            DominatorTreeWrapperPass, true, DominatorTree *,
133                            DominatorTreeWrapperPassAnalysisGraphTraits> {
134   static char ID;
135   DomOnlyViewer()
136       : DOTGraphTraitsViewer<DominatorTreeWrapperPass, true, DominatorTree *,
137                              DominatorTreeWrapperPassAnalysisGraphTraits>(
138             "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 : public DOTGraphTraitsViewer<
150                           PostDominatorTreeWrapperPass, false,
151                           PostDominatorTree *,
152                           PostDominatorTreeWrapperPassAnalysisGraphTraits> {
153   static char ID;
154   PostDomViewer() :
155     DOTGraphTraitsViewer<PostDominatorTreeWrapperPass, false,
156                          PostDominatorTree *,
157                          PostDominatorTreeWrapperPassAnalysisGraphTraits>(
158         "postdom", ID){
159       initializePostDomViewerPass(*PassRegistry::getPassRegistry());
160     }
161 };
162 
163 struct PostDomOnlyViewer : public DOTGraphTraitsViewer<
164                             PostDominatorTreeWrapperPass, true,
165                             PostDominatorTree *,
166                             PostDominatorTreeWrapperPassAnalysisGraphTraits> {
167   static char ID;
168   PostDomOnlyViewer() :
169     DOTGraphTraitsViewer<PostDominatorTreeWrapperPass, true,
170                          PostDominatorTree *,
171                          PostDominatorTreeWrapperPassAnalysisGraphTraits>(
172         "postdomonly", ID){
173       initializePostDomOnlyViewerPass(*PassRegistry::getPassRegistry());
174     }
175 };
176 } // end anonymous namespace
177 
178 char DomViewer::ID = 0;
179 INITIALIZE_PASS(DomViewer, "view-dom",
180                 "View dominance tree of function", false, false)
181 
182 char DomOnlyViewer::ID = 0;
183 INITIALIZE_PASS(DomOnlyViewer, "view-dom-only",
184                 "View dominance tree of function (with no function bodies)",
185                 false, false)
186 
187 char PostDomViewer::ID = 0;
188 INITIALIZE_PASS(PostDomViewer, "view-postdom",
189                 "View postdominance tree of function", false, false)
190 
191 char PostDomOnlyViewer::ID = 0;
192 INITIALIZE_PASS(PostDomOnlyViewer, "view-postdom-only",
193                 "View postdominance tree of function "
194                 "(with no function bodies)",
195                 false, false)
196 
197 namespace {
198 struct DomPrinter : public DOTGraphTraitsPrinter<
199                         DominatorTreeWrapperPass, false, DominatorTree *,
200                         DominatorTreeWrapperPassAnalysisGraphTraits> {
201   static char ID;
202   DomPrinter()
203       : DOTGraphTraitsPrinter<DominatorTreeWrapperPass, false, DominatorTree *,
204                               DominatorTreeWrapperPassAnalysisGraphTraits>(
205             "dom", ID) {
206     initializeDomPrinterPass(*PassRegistry::getPassRegistry());
207   }
208 };
209 
210 struct DomOnlyPrinter : public DOTGraphTraitsPrinter<
211                             DominatorTreeWrapperPass, true, DominatorTree *,
212                             DominatorTreeWrapperPassAnalysisGraphTraits> {
213   static char ID;
214   DomOnlyPrinter()
215       : DOTGraphTraitsPrinter<DominatorTreeWrapperPass, true, DominatorTree *,
216                               DominatorTreeWrapperPassAnalysisGraphTraits>(
217             "domonly", ID) {
218     initializeDomOnlyPrinterPass(*PassRegistry::getPassRegistry());
219   }
220 };
221 
222 struct PostDomPrinter
223   : public DOTGraphTraitsPrinter<
224                             PostDominatorTreeWrapperPass, false,
225                             PostDominatorTree *,
226                             PostDominatorTreeWrapperPassAnalysisGraphTraits> {
227   static char ID;
228   PostDomPrinter() :
229     DOTGraphTraitsPrinter<PostDominatorTreeWrapperPass, false,
230                           PostDominatorTree *,
231                           PostDominatorTreeWrapperPassAnalysisGraphTraits>(
232         "postdom", ID) {
233       initializePostDomPrinterPass(*PassRegistry::getPassRegistry());
234     }
235 };
236 
237 struct PostDomOnlyPrinter
238   : public DOTGraphTraitsPrinter<
239                             PostDominatorTreeWrapperPass, true,
240                             PostDominatorTree *,
241                             PostDominatorTreeWrapperPassAnalysisGraphTraits> {
242   static char ID;
243   PostDomOnlyPrinter() :
244     DOTGraphTraitsPrinter<PostDominatorTreeWrapperPass, true,
245                           PostDominatorTree *,
246                           PostDominatorTreeWrapperPassAnalysisGraphTraits>(
247         "postdomonly", ID) {
248       initializePostDomOnlyPrinterPass(*PassRegistry::getPassRegistry());
249     }
250 };
251 } // end anonymous namespace
252 
253 
254 
255 char DomPrinter::ID = 0;
256 INITIALIZE_PASS(DomPrinter, "dot-dom",
257                 "Print dominance tree of function to 'dot' file",
258                 false, false)
259 
260 char DomOnlyPrinter::ID = 0;
261 INITIALIZE_PASS(DomOnlyPrinter, "dot-dom-only",
262                 "Print dominance tree of function to 'dot' file "
263                 "(with no function bodies)",
264                 false, false)
265 
266 char PostDomPrinter::ID = 0;
267 INITIALIZE_PASS(PostDomPrinter, "dot-postdom",
268                 "Print postdominance tree of function to 'dot' file",
269                 false, false)
270 
271 char PostDomOnlyPrinter::ID = 0;
272 INITIALIZE_PASS(PostDomOnlyPrinter, "dot-postdom-only",
273                 "Print postdominance tree of function to 'dot' file "
274                 "(with no function bodies)",
275                 false, false)
276 
277 // Create methods available outside of this file, to use them
278 // "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by
279 // the link time optimization.
280 
281 FunctionPass *llvm::createDomPrinterPass() {
282   return new DomPrinter();
283 }
284 
285 FunctionPass *llvm::createDomOnlyPrinterPass() {
286   return new DomOnlyPrinter();
287 }
288 
289 FunctionPass *llvm::createDomViewerPass() {
290   return new DomViewer();
291 }
292 
293 FunctionPass *llvm::createDomOnlyViewerPass() {
294   return new DomOnlyViewer();
295 }
296 
297 FunctionPass *llvm::createPostDomPrinterPass() {
298   return new PostDomPrinter();
299 }
300 
301 FunctionPass *llvm::createPostDomOnlyPrinterPass() {
302   return new PostDomOnlyPrinter();
303 }
304 
305 FunctionPass *llvm::createPostDomViewerPass() {
306   return new PostDomViewer();
307 }
308 
309 FunctionPass *llvm::createPostDomOnlyViewerPass() {
310   return new PostDomOnlyViewer();
311 }
312