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