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