DomPrinter.cpp revision 353358
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 24using namespace llvm; 25 26namespace llvm { 27template<> 28struct 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 50template<> 51struct 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 65template<> 66struct 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 82void 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 90void 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 98namespace { 99struct DominatorTreeWrapperPassAnalysisGraphTraits { 100 static DominatorTree *getGraph(DominatorTreeWrapperPass *DTWP) { 101 return &DTWP->getDomTree(); 102 } 103}; 104 105struct 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 117struct 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 129struct PostDominatorTreeWrapperPassAnalysisGraphTraits { 130 static PostDominatorTree *getGraph(PostDominatorTreeWrapperPass *PDTWP) { 131 return &PDTWP->getPostDomTree(); 132 } 133}; 134 135struct 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 149struct 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 164char DomViewer::ID = 0; 165INITIALIZE_PASS(DomViewer, "view-dom", 166 "View dominance tree of function", false, false) 167 168char DomOnlyViewer::ID = 0; 169INITIALIZE_PASS(DomOnlyViewer, "view-dom-only", 170 "View dominance tree of function (with no function bodies)", 171 false, false) 172 173char PostDomViewer::ID = 0; 174INITIALIZE_PASS(PostDomViewer, "view-postdom", 175 "View postdominance tree of function", false, false) 176 177char PostDomOnlyViewer::ID = 0; 178INITIALIZE_PASS(PostDomOnlyViewer, "view-postdom-only", 179 "View postdominance tree of function " 180 "(with no function bodies)", 181 false, false) 182 183namespace { 184struct 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 196struct 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 208struct 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 223struct 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 241char DomPrinter::ID = 0; 242INITIALIZE_PASS(DomPrinter, "dot-dom", 243 "Print dominance tree of function to 'dot' file", 244 false, false) 245 246char DomOnlyPrinter::ID = 0; 247INITIALIZE_PASS(DomOnlyPrinter, "dot-dom-only", 248 "Print dominance tree of function to 'dot' file " 249 "(with no function bodies)", 250 false, false) 251 252char PostDomPrinter::ID = 0; 253INITIALIZE_PASS(PostDomPrinter, "dot-postdom", 254 "Print postdominance tree of function to 'dot' file", 255 false, false) 256 257char PostDomOnlyPrinter::ID = 0; 258INITIALIZE_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 267FunctionPass *llvm::createDomPrinterPass() { 268 return new DomPrinter(); 269} 270 271FunctionPass *llvm::createDomOnlyPrinterPass() { 272 return new DomOnlyPrinter(); 273} 274 275FunctionPass *llvm::createDomViewerPass() { 276 return new DomViewer(); 277} 278 279FunctionPass *llvm::createDomOnlyViewerPass() { 280 return new DomOnlyViewer(); 281} 282 283FunctionPass *llvm::createPostDomPrinterPass() { 284 return new PostDomPrinter(); 285} 286 287FunctionPass *llvm::createPostDomOnlyPrinterPass() { 288 return new PostDomOnlyPrinter(); 289} 290 291FunctionPass *llvm::createPostDomViewerPass() { 292 return new PostDomViewer(); 293} 294 295FunctionPass *llvm::createPostDomOnlyViewerPass() { 296 return new PostDomOnlyViewer(); 297} 298