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 24 using namespace llvm; 25 26 namespace llvm { 27 template<> 28 struct DOTGraphTraits<DomTreeNode*> : public DefaultDOTGraphTraits { 29 30 DOTGraphTraits (bool isSimple=false) 31 : DefaultDOTGraphTraits(isSimple) {} 32 33 std::string getNodeLabel(DomTreeNode *Node, DomTreeNode *Graph) { 34 35 BasicBlock *BB = Node->getBlock(); 36 37 if (!BB) 38 return "Post dominance root node"; 39 40 41 if (isSimple()) 42 return DOTGraphTraits<const Function*> 43 ::getSimpleNodeLabel(BB, BB->getParent()); 44 else 45 return DOTGraphTraits<const Function*> 46 ::getCompleteNodeLabel(BB, BB->getParent()); 47 } 48 }; 49 50 template<> 51 struct DOTGraphTraits<DominatorTree*> : public DOTGraphTraits<DomTreeNode*> { 52 53 DOTGraphTraits (bool isSimple=false) 54 : DOTGraphTraits<DomTreeNode*>(isSimple) {} 55 56 static std::string getGraphName(DominatorTree *DT) { 57 return "Dominator tree"; 58 } 59 60 std::string getNodeLabel(DomTreeNode *Node, DominatorTree *G) { 61 return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode()); 62 } 63 }; 64 65 template<> 66 struct DOTGraphTraits<PostDominatorTree*> 67 : public DOTGraphTraits<DomTreeNode*> { 68 69 DOTGraphTraits (bool isSimple=false) 70 : DOTGraphTraits<DomTreeNode*>(isSimple) {} 71 72 static std::string getGraphName(PostDominatorTree *DT) { 73 return "Post dominator tree"; 74 } 75 76 std::string getNodeLabel(DomTreeNode *Node, PostDominatorTree *G ) { 77 return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode()); 78 } 79 }; 80 } 81 82 void DominatorTree::viewGraph(const Twine &Name, const Twine &Title) { 83 #ifndef NDEBUG 84 ViewGraph(this, Name, false, Title); 85 #else 86 errs() << "DomTree dump not available, build with DEBUG\n"; 87 #endif // NDEBUG 88 } 89 90 void DominatorTree::viewGraph() { 91 #ifndef NDEBUG 92 this->viewGraph("domtree", "Dominator Tree for function"); 93 #else 94 errs() << "DomTree dump not available, build with DEBUG\n"; 95 #endif // NDEBUG 96 } 97 98 namespace { 99 struct DominatorTreeWrapperPassAnalysisGraphTraits { 100 static DominatorTree *getGraph(DominatorTreeWrapperPass *DTWP) { 101 return &DTWP->getDomTree(); 102 } 103 }; 104 105 struct DomViewer : public DOTGraphTraitsViewer< 106 DominatorTreeWrapperPass, false, DominatorTree *, 107 DominatorTreeWrapperPassAnalysisGraphTraits> { 108 static char ID; 109 DomViewer() 110 : DOTGraphTraitsViewer<DominatorTreeWrapperPass, false, DominatorTree *, 111 DominatorTreeWrapperPassAnalysisGraphTraits>( 112 "dom", ID) { 113 initializeDomViewerPass(*PassRegistry::getPassRegistry()); 114 } 115 }; 116 117 struct DomOnlyViewer : public DOTGraphTraitsViewer< 118 DominatorTreeWrapperPass, true, DominatorTree *, 119 DominatorTreeWrapperPassAnalysisGraphTraits> { 120 static char ID; 121 DomOnlyViewer() 122 : DOTGraphTraitsViewer<DominatorTreeWrapperPass, true, DominatorTree *, 123 DominatorTreeWrapperPassAnalysisGraphTraits>( 124 "domonly", ID) { 125 initializeDomOnlyViewerPass(*PassRegistry::getPassRegistry()); 126 } 127 }; 128 129 struct PostDominatorTreeWrapperPassAnalysisGraphTraits { 130 static PostDominatorTree *getGraph(PostDominatorTreeWrapperPass *PDTWP) { 131 return &PDTWP->getPostDomTree(); 132 } 133 }; 134 135 struct PostDomViewer : public DOTGraphTraitsViewer< 136 PostDominatorTreeWrapperPass, false, 137 PostDominatorTree *, 138 PostDominatorTreeWrapperPassAnalysisGraphTraits> { 139 static char ID; 140 PostDomViewer() : 141 DOTGraphTraitsViewer<PostDominatorTreeWrapperPass, false, 142 PostDominatorTree *, 143 PostDominatorTreeWrapperPassAnalysisGraphTraits>( 144 "postdom", ID){ 145 initializePostDomViewerPass(*PassRegistry::getPassRegistry()); 146 } 147 }; 148 149 struct PostDomOnlyViewer : public DOTGraphTraitsViewer< 150 PostDominatorTreeWrapperPass, true, 151 PostDominatorTree *, 152 PostDominatorTreeWrapperPassAnalysisGraphTraits> { 153 static char ID; 154 PostDomOnlyViewer() : 155 DOTGraphTraitsViewer<PostDominatorTreeWrapperPass, true, 156 PostDominatorTree *, 157 PostDominatorTreeWrapperPassAnalysisGraphTraits>( 158 "postdomonly", ID){ 159 initializePostDomOnlyViewerPass(*PassRegistry::getPassRegistry()); 160 } 161 }; 162 } // end anonymous namespace 163 164 char DomViewer::ID = 0; 165 INITIALIZE_PASS(DomViewer, "view-dom", 166 "View dominance tree of function", false, false) 167 168 char DomOnlyViewer::ID = 0; 169 INITIALIZE_PASS(DomOnlyViewer, "view-dom-only", 170 "View dominance tree of function (with no function bodies)", 171 false, false) 172 173 char PostDomViewer::ID = 0; 174 INITIALIZE_PASS(PostDomViewer, "view-postdom", 175 "View postdominance tree of function", false, false) 176 177 char PostDomOnlyViewer::ID = 0; 178 INITIALIZE_PASS(PostDomOnlyViewer, "view-postdom-only", 179 "View postdominance tree of function " 180 "(with no function bodies)", 181 false, false) 182 183 namespace { 184 struct DomPrinter : public DOTGraphTraitsPrinter< 185 DominatorTreeWrapperPass, false, DominatorTree *, 186 DominatorTreeWrapperPassAnalysisGraphTraits> { 187 static char ID; 188 DomPrinter() 189 : DOTGraphTraitsPrinter<DominatorTreeWrapperPass, false, DominatorTree *, 190 DominatorTreeWrapperPassAnalysisGraphTraits>( 191 "dom", ID) { 192 initializeDomPrinterPass(*PassRegistry::getPassRegistry()); 193 } 194 }; 195 196 struct DomOnlyPrinter : public DOTGraphTraitsPrinter< 197 DominatorTreeWrapperPass, true, DominatorTree *, 198 DominatorTreeWrapperPassAnalysisGraphTraits> { 199 static char ID; 200 DomOnlyPrinter() 201 : DOTGraphTraitsPrinter<DominatorTreeWrapperPass, true, DominatorTree *, 202 DominatorTreeWrapperPassAnalysisGraphTraits>( 203 "domonly", ID) { 204 initializeDomOnlyPrinterPass(*PassRegistry::getPassRegistry()); 205 } 206 }; 207 208 struct PostDomPrinter 209 : public DOTGraphTraitsPrinter< 210 PostDominatorTreeWrapperPass, false, 211 PostDominatorTree *, 212 PostDominatorTreeWrapperPassAnalysisGraphTraits> { 213 static char ID; 214 PostDomPrinter() : 215 DOTGraphTraitsPrinter<PostDominatorTreeWrapperPass, false, 216 PostDominatorTree *, 217 PostDominatorTreeWrapperPassAnalysisGraphTraits>( 218 "postdom", ID) { 219 initializePostDomPrinterPass(*PassRegistry::getPassRegistry()); 220 } 221 }; 222 223 struct PostDomOnlyPrinter 224 : public DOTGraphTraitsPrinter< 225 PostDominatorTreeWrapperPass, true, 226 PostDominatorTree *, 227 PostDominatorTreeWrapperPassAnalysisGraphTraits> { 228 static char ID; 229 PostDomOnlyPrinter() : 230 DOTGraphTraitsPrinter<PostDominatorTreeWrapperPass, true, 231 PostDominatorTree *, 232 PostDominatorTreeWrapperPassAnalysisGraphTraits>( 233 "postdomonly", ID) { 234 initializePostDomOnlyPrinterPass(*PassRegistry::getPassRegistry()); 235 } 236 }; 237 } // end anonymous namespace 238 239 240 241 char DomPrinter::ID = 0; 242 INITIALIZE_PASS(DomPrinter, "dot-dom", 243 "Print dominance tree of function to 'dot' file", 244 false, false) 245 246 char DomOnlyPrinter::ID = 0; 247 INITIALIZE_PASS(DomOnlyPrinter, "dot-dom-only", 248 "Print dominance tree of function to 'dot' file " 249 "(with no function bodies)", 250 false, false) 251 252 char PostDomPrinter::ID = 0; 253 INITIALIZE_PASS(PostDomPrinter, "dot-postdom", 254 "Print postdominance tree of function to 'dot' file", 255 false, false) 256 257 char PostDomOnlyPrinter::ID = 0; 258 INITIALIZE_PASS(PostDomOnlyPrinter, "dot-postdom-only", 259 "Print postdominance tree of function to 'dot' file " 260 "(with no function bodies)", 261 false, false) 262 263 // Create methods available outside of this file, to use them 264 // "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by 265 // the link time optimization. 266 267 FunctionPass *llvm::createDomPrinterPass() { 268 return new DomPrinter(); 269 } 270 271 FunctionPass *llvm::createDomOnlyPrinterPass() { 272 return new DomOnlyPrinter(); 273 } 274 275 FunctionPass *llvm::createDomViewerPass() { 276 return new DomViewer(); 277 } 278 279 FunctionPass *llvm::createDomOnlyViewerPass() { 280 return new DomOnlyViewer(); 281 } 282 283 FunctionPass *llvm::createPostDomPrinterPass() { 284 return new PostDomPrinter(); 285 } 286 287 FunctionPass *llvm::createPostDomOnlyPrinterPass() { 288 return new PostDomOnlyPrinter(); 289 } 290 291 FunctionPass *llvm::createPostDomViewerPass() { 292 return new PostDomViewer(); 293 } 294 295 FunctionPass *llvm::createPostDomOnlyViewerPass() { 296 return new PostDomOnlyViewer(); 297 } 298