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 void DominatorTree::viewGraph(const Twine &Name, const Twine &Title) { 84 #ifndef NDEBUG 85 ViewGraph(this, Name, false, Title); 86 #else 87 errs() << "DomTree dump not available, build with DEBUG\n"; 88 #endif // NDEBUG 89 } 90 91 void DominatorTree::viewGraph() { 92 #ifndef NDEBUG 93 this->viewGraph("domtree", "Dominator Tree for function"); 94 #else 95 errs() << "DomTree dump not available, build with DEBUG\n"; 96 #endif // NDEBUG 97 } 98 99 namespace { 100 struct DominatorTreeWrapperPassAnalysisGraphTraits { 101 static DominatorTree *getGraph(DominatorTreeWrapperPass *DTWP) { 102 return &DTWP->getDomTree(); 103 } 104 }; 105 106 struct DomViewer : public DOTGraphTraitsViewer< 107 DominatorTreeWrapperPass, false, DominatorTree *, 108 DominatorTreeWrapperPassAnalysisGraphTraits> { 109 static char ID; 110 DomViewer() 111 : DOTGraphTraitsViewer<DominatorTreeWrapperPass, false, DominatorTree *, 112 DominatorTreeWrapperPassAnalysisGraphTraits>( 113 "dom", ID) { 114 initializeDomViewerPass(*PassRegistry::getPassRegistry()); 115 } 116 }; 117 118 struct DomOnlyViewer : public DOTGraphTraitsViewer< 119 DominatorTreeWrapperPass, true, DominatorTree *, 120 DominatorTreeWrapperPassAnalysisGraphTraits> { 121 static char ID; 122 DomOnlyViewer() 123 : DOTGraphTraitsViewer<DominatorTreeWrapperPass, true, DominatorTree *, 124 DominatorTreeWrapperPassAnalysisGraphTraits>( 125 "domonly", ID) { 126 initializeDomOnlyViewerPass(*PassRegistry::getPassRegistry()); 127 } 128 }; 129 130 struct PostDominatorTreeWrapperPassAnalysisGraphTraits { 131 static PostDominatorTree *getGraph(PostDominatorTreeWrapperPass *PDTWP) { 132 return &PDTWP->getPostDomTree(); 133 } 134 }; 135 136 struct PostDomViewer : public DOTGraphTraitsViewer< 137 PostDominatorTreeWrapperPass, false, 138 PostDominatorTree *, 139 PostDominatorTreeWrapperPassAnalysisGraphTraits> { 140 static char ID; 141 PostDomViewer() : 142 DOTGraphTraitsViewer<PostDominatorTreeWrapperPass, false, 143 PostDominatorTree *, 144 PostDominatorTreeWrapperPassAnalysisGraphTraits>( 145 "postdom", ID){ 146 initializePostDomViewerPass(*PassRegistry::getPassRegistry()); 147 } 148 }; 149 150 struct PostDomOnlyViewer : public DOTGraphTraitsViewer< 151 PostDominatorTreeWrapperPass, true, 152 PostDominatorTree *, 153 PostDominatorTreeWrapperPassAnalysisGraphTraits> { 154 static char ID; 155 PostDomOnlyViewer() : 156 DOTGraphTraitsViewer<PostDominatorTreeWrapperPass, true, 157 PostDominatorTree *, 158 PostDominatorTreeWrapperPassAnalysisGraphTraits>( 159 "postdomonly", ID){ 160 initializePostDomOnlyViewerPass(*PassRegistry::getPassRegistry()); 161 } 162 }; 163 } // end anonymous namespace 164 165 char DomViewer::ID = 0; 166 INITIALIZE_PASS(DomViewer, "view-dom", 167 "View dominance tree of function", false, false) 168 169 char DomOnlyViewer::ID = 0; 170 INITIALIZE_PASS(DomOnlyViewer, "view-dom-only", 171 "View dominance tree of function (with no function bodies)", 172 false, false) 173 174 char PostDomViewer::ID = 0; 175 INITIALIZE_PASS(PostDomViewer, "view-postdom", 176 "View postdominance tree of function", false, false) 177 178 char PostDomOnlyViewer::ID = 0; 179 INITIALIZE_PASS(PostDomOnlyViewer, "view-postdom-only", 180 "View postdominance tree of function " 181 "(with no function bodies)", 182 false, false) 183 184 namespace { 185 struct DomPrinter : public DOTGraphTraitsPrinter< 186 DominatorTreeWrapperPass, false, DominatorTree *, 187 DominatorTreeWrapperPassAnalysisGraphTraits> { 188 static char ID; 189 DomPrinter() 190 : DOTGraphTraitsPrinter<DominatorTreeWrapperPass, false, DominatorTree *, 191 DominatorTreeWrapperPassAnalysisGraphTraits>( 192 "dom", ID) { 193 initializeDomPrinterPass(*PassRegistry::getPassRegistry()); 194 } 195 }; 196 197 struct DomOnlyPrinter : public DOTGraphTraitsPrinter< 198 DominatorTreeWrapperPass, true, DominatorTree *, 199 DominatorTreeWrapperPassAnalysisGraphTraits> { 200 static char ID; 201 DomOnlyPrinter() 202 : DOTGraphTraitsPrinter<DominatorTreeWrapperPass, true, DominatorTree *, 203 DominatorTreeWrapperPassAnalysisGraphTraits>( 204 "domonly", ID) { 205 initializeDomOnlyPrinterPass(*PassRegistry::getPassRegistry()); 206 } 207 }; 208 209 struct PostDomPrinter 210 : public DOTGraphTraitsPrinter< 211 PostDominatorTreeWrapperPass, false, 212 PostDominatorTree *, 213 PostDominatorTreeWrapperPassAnalysisGraphTraits> { 214 static char ID; 215 PostDomPrinter() : 216 DOTGraphTraitsPrinter<PostDominatorTreeWrapperPass, false, 217 PostDominatorTree *, 218 PostDominatorTreeWrapperPassAnalysisGraphTraits>( 219 "postdom", ID) { 220 initializePostDomPrinterPass(*PassRegistry::getPassRegistry()); 221 } 222 }; 223 224 struct PostDomOnlyPrinter 225 : public DOTGraphTraitsPrinter< 226 PostDominatorTreeWrapperPass, true, 227 PostDominatorTree *, 228 PostDominatorTreeWrapperPassAnalysisGraphTraits> { 229 static char ID; 230 PostDomOnlyPrinter() : 231 DOTGraphTraitsPrinter<PostDominatorTreeWrapperPass, true, 232 PostDominatorTree *, 233 PostDominatorTreeWrapperPassAnalysisGraphTraits>( 234 "postdomonly", ID) { 235 initializePostDomOnlyPrinterPass(*PassRegistry::getPassRegistry()); 236 } 237 }; 238 } // end anonymous namespace 239 240 241 242 char DomPrinter::ID = 0; 243 INITIALIZE_PASS(DomPrinter, "dot-dom", 244 "Print dominance tree of function to 'dot' file", 245 false, false) 246 247 char DomOnlyPrinter::ID = 0; 248 INITIALIZE_PASS(DomOnlyPrinter, "dot-dom-only", 249 "Print dominance tree of function to 'dot' file " 250 "(with no function bodies)", 251 false, false) 252 253 char PostDomPrinter::ID = 0; 254 INITIALIZE_PASS(PostDomPrinter, "dot-postdom", 255 "Print postdominance tree of function to 'dot' file", 256 false, false) 257 258 char PostDomOnlyPrinter::ID = 0; 259 INITIALIZE_PASS(PostDomOnlyPrinter, "dot-postdom-only", 260 "Print postdominance tree of function to 'dot' file " 261 "(with no function bodies)", 262 false, false) 263 264 // Create methods available outside of this file, to use them 265 // "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by 266 // the link time optimization. 267 268 FunctionPass *llvm::createDomPrinterPass() { 269 return new DomPrinter(); 270 } 271 272 FunctionPass *llvm::createDomOnlyPrinterPass() { 273 return new DomOnlyPrinter(); 274 } 275 276 FunctionPass *llvm::createDomViewerPass() { 277 return new DomViewer(); 278 } 279 280 FunctionPass *llvm::createDomOnlyViewerPass() { 281 return new DomOnlyViewer(); 282 } 283 284 FunctionPass *llvm::createPostDomPrinterPass() { 285 return new PostDomPrinter(); 286 } 287 288 FunctionPass *llvm::createPostDomOnlyPrinterPass() { 289 return new PostDomOnlyPrinter(); 290 } 291 292 FunctionPass *llvm::createPostDomViewerPass() { 293 return new PostDomViewer(); 294 } 295 296 FunctionPass *llvm::createPostDomOnlyViewerPass() { 297 return new PostDomOnlyViewer(); 298 } 299