DomPrinter.cpp revision 199989
1//===- DomPrinter.cpp - DOT printer for the dominance trees ------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines '-dot-dom' and '-dot-postdom' analysis passes, which emit 11// a dom.<fnname>.dot or postdom.<fnname>.dot file for each function in the 12// program, with a graph of the dominance/postdominance tree of that 13// function. 14// 15// There are also passes available to directly call dotty ('-view-dom' or 16// '-view-postdom'). By appending '-only' like '-dot-dom-only' only the 17// names of the bbs are printed, but the content is hidden. 18// 19//===----------------------------------------------------------------------===// 20 21#include "llvm/Analysis/DomPrinter.h" 22#include "llvm/Pass.h" 23#include "llvm/Function.h" 24#include "llvm/Analysis/CFGPrinter.h" 25#include "llvm/Analysis/Dominators.h" 26#include "llvm/Analysis/PostDominators.h" 27 28using namespace llvm; 29 30namespace llvm { 31template<> 32struct DOTGraphTraits<DomTreeNode*> : public DefaultDOTGraphTraits { 33 34 DOTGraphTraits (bool isSimple=false) 35 : DefaultDOTGraphTraits(isSimple) {} 36 37 std::string getNodeLabel(DomTreeNode *Node, DomTreeNode *Graph) { 38 39 BasicBlock *BB = Node->getBlock(); 40 41 if (!BB) 42 return "Post dominance root node"; 43 44 45 if (isSimple()) 46 return DOTGraphTraits<const Function*> 47 ::getSimpleNodeLabel(BB, BB->getParent()); 48 else 49 return DOTGraphTraits<const Function*> 50 ::getCompleteNodeLabel(BB, BB->getParent()); 51 } 52}; 53 54template<> 55struct DOTGraphTraits<DominatorTree*> : public DOTGraphTraits<DomTreeNode*> { 56 57 DOTGraphTraits (bool isSimple=false) 58 : DOTGraphTraits<DomTreeNode*>(isSimple) {} 59 60 static std::string getGraphName(DominatorTree *DT) { 61 return "Dominator tree"; 62 } 63 64 std::string getNodeLabel(DomTreeNode *Node, DominatorTree *G) { 65 return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode()); 66 } 67}; 68 69template<> 70struct DOTGraphTraits<PostDominatorTree*> 71 : public DOTGraphTraits<DomTreeNode*> { 72 73 DOTGraphTraits (bool isSimple=false) 74 : DOTGraphTraits<DomTreeNode*>(isSimple) {} 75 76 static std::string getGraphName(PostDominatorTree *DT) { 77 return "Post dominator tree"; 78 } 79 80 std::string getNodeLabel(DomTreeNode *Node, PostDominatorTree *G ) { 81 return DOTGraphTraits<DomTreeNode*>::getNodeLabel(Node, G->getRootNode()); 82 } 83}; 84} 85 86namespace { 87template <class Analysis, bool OnlyBBS> 88struct GenericGraphViewer : public FunctionPass { 89 std::string Name; 90 91 GenericGraphViewer(std::string GraphName, const void *ID) : FunctionPass(ID) { 92 Name = GraphName; 93 } 94 95 virtual bool runOnFunction(Function &F) { 96 Analysis *Graph; 97 std::string Title, GraphName; 98 Graph = &getAnalysis<Analysis>(); 99 GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph); 100 Title = GraphName + " for '" + F.getNameStr() + "' function"; 101 ViewGraph(Graph, Name, OnlyBBS, Title); 102 103 return false; 104 } 105 106 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 107 AU.setPreservesAll(); 108 AU.addRequired<Analysis>(); 109 } 110}; 111 112struct DomViewer 113 : public GenericGraphViewer<DominatorTree, false> { 114 static char ID; 115 DomViewer() : GenericGraphViewer<DominatorTree, false>("dom", &ID){} 116}; 117 118struct DomOnlyViewer 119 : public GenericGraphViewer<DominatorTree, true> { 120 static char ID; 121 DomOnlyViewer() : GenericGraphViewer<DominatorTree, true>("domonly", &ID){} 122}; 123 124struct PostDomViewer 125 : public GenericGraphViewer<PostDominatorTree, false> { 126 static char ID; 127 PostDomViewer() : 128 GenericGraphViewer<PostDominatorTree, false>("postdom", &ID){} 129}; 130 131struct PostDomOnlyViewer 132 : public GenericGraphViewer<PostDominatorTree, true> { 133 static char ID; 134 PostDomOnlyViewer() : 135 GenericGraphViewer<PostDominatorTree, true>("postdomonly", &ID){} 136}; 137} // end anonymous namespace 138 139char DomViewer::ID = 0; 140RegisterPass<DomViewer> A("view-dom", 141 "View dominance tree of function"); 142 143char DomOnlyViewer::ID = 0; 144RegisterPass<DomOnlyViewer> B("view-dom-only", 145 "View dominance tree of function " 146 "(with no function bodies)"); 147 148char PostDomViewer::ID = 0; 149RegisterPass<PostDomViewer> C("view-postdom", 150 "View postdominance tree of function"); 151 152char PostDomOnlyViewer::ID = 0; 153RegisterPass<PostDomOnlyViewer> D("view-postdom-only", 154 "View postdominance tree of function " 155 "(with no function bodies)"); 156 157namespace { 158template <class Analysis, bool OnlyBBS> 159struct GenericGraphPrinter : public FunctionPass { 160 161 std::string Name; 162 163 GenericGraphPrinter(std::string GraphName, const void *ID) 164 : FunctionPass(ID) { 165 Name = GraphName; 166 } 167 168 virtual bool runOnFunction(Function &F) { 169 Analysis *Graph; 170 std::string Filename = Name + "." + F.getNameStr() + ".dot"; 171 errs() << "Writing '" << Filename << "'..."; 172 173 std::string ErrorInfo; 174 raw_fd_ostream File(Filename.c_str(), ErrorInfo); 175 Graph = &getAnalysis<Analysis>(); 176 177 std::string Title, GraphName; 178 GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph); 179 Title = GraphName + " for '" + F.getNameStr() + "' function"; 180 181 if (ErrorInfo.empty()) 182 WriteGraph(File, Graph, OnlyBBS, Name, Title); 183 else 184 errs() << " error opening file for writing!"; 185 errs() << "\n"; 186 return false; 187 } 188 189 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 190 AU.setPreservesAll(); 191 AU.addRequired<Analysis>(); 192 } 193}; 194 195struct DomPrinter 196 : public GenericGraphPrinter<DominatorTree, false> { 197 static char ID; 198 DomPrinter() : GenericGraphPrinter<DominatorTree, false>("dom", &ID) {} 199}; 200 201struct DomOnlyPrinter 202 : public GenericGraphPrinter<DominatorTree, true> { 203 static char ID; 204 DomOnlyPrinter() : GenericGraphPrinter<DominatorTree, true>("domonly", &ID) {} 205}; 206 207struct PostDomPrinter 208 : public GenericGraphPrinter<PostDominatorTree, false> { 209 static char ID; 210 PostDomPrinter() : 211 GenericGraphPrinter<PostDominatorTree, false>("postdom", &ID) {} 212}; 213 214struct PostDomOnlyPrinter 215 : public GenericGraphPrinter<PostDominatorTree, true> { 216 static char ID; 217 PostDomOnlyPrinter() : 218 GenericGraphPrinter<PostDominatorTree, true>("postdomonly", &ID) {} 219}; 220} // end anonymous namespace 221 222 223 224char DomPrinter::ID = 0; 225RegisterPass<DomPrinter> E("dot-dom", 226 "Print dominance tree of function " 227 "to 'dot' file"); 228 229char DomOnlyPrinter::ID = 0; 230RegisterPass<DomOnlyPrinter> F("dot-dom-only", 231 "Print dominance tree of function " 232 "to 'dot' file " 233 "(with no function bodies)"); 234 235char PostDomPrinter::ID = 0; 236RegisterPass<PostDomPrinter> G("dot-postdom", 237 "Print postdominance tree of function " 238 "to 'dot' file"); 239 240char PostDomOnlyPrinter::ID = 0; 241RegisterPass<PostDomOnlyPrinter> H("dot-postdom-only", 242 "Print postdominance tree of function " 243 "to 'dot' file " 244 "(with no function bodies)"); 245 246// Create methods available outside of this file, to use them 247// "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by 248// the link time optimization. 249 250FunctionPass *llvm::createDomPrinterPass() { 251 return new DomPrinter(); 252} 253 254FunctionPass *llvm::createDomOnlyPrinterPass() { 255 return new DomOnlyPrinter(); 256} 257 258FunctionPass *llvm::createDomViewerPass() { 259 return new DomViewer(); 260} 261 262FunctionPass *llvm::createDomOnlyViewerPass() { 263 return new DomOnlyViewer(); 264} 265 266FunctionPass *llvm::createPostDomPrinterPass() { 267 return new PostDomPrinter(); 268} 269 270FunctionPass *llvm::createPostDomOnlyPrinterPass() { 271 return new PostDomOnlyPrinter(); 272} 273 274FunctionPass *llvm::createPostDomViewerPass() { 275 return new PostDomViewer(); 276} 277 278FunctionPass *llvm::createPostDomOnlyViewerPass() { 279 return new PostDomOnlyViewer(); 280} 281