1 //===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===// 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 a '-dot-cfg' analysis pass, which emits the 11 // cfg.<fnname>.dot file for each function in the program, with a graph of the 12 // CFG for that function. 13 // 14 // The other main feature of this file is that it implements the 15 // Function::viewCFG method, which is useful for debugging passes which operate 16 // on the CFG. 17 // 18 //===----------------------------------------------------------------------===// 19 20 #include "llvm/Analysis/CFGPrinter.h" 21 22 #include "llvm/Pass.h" 23 using namespace llvm; 24 25 namespace { 26 struct CFGViewer : public FunctionPass { 27 static char ID; // Pass identifcation, replacement for typeid 28 CFGViewer() : FunctionPass(ID) { 29 initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); 30 } 31 32 virtual bool runOnFunction(Function &F) { 33 F.viewCFG(); 34 return false; 35 } 36 37 void print(raw_ostream &OS, const Module* = 0) const {} 38 39 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 40 AU.setPreservesAll(); 41 } 42 }; 43 } 44 45 char CFGViewer::ID = 0; 46 INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true) 47 48 namespace { 49 struct CFGOnlyViewer : public FunctionPass { 50 static char ID; // Pass identifcation, replacement for typeid 51 CFGOnlyViewer() : FunctionPass(ID) { 52 initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); 53 } 54 55 virtual bool runOnFunction(Function &F) { 56 F.viewCFGOnly(); 57 return false; 58 } 59 60 void print(raw_ostream &OS, const Module* = 0) const {} 61 62 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 63 AU.setPreservesAll(); 64 } 65 }; 66 } 67 68 char CFGOnlyViewer::ID = 0; 69 INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only", 70 "View CFG of function (with no function bodies)", false, true) 71 72 namespace { 73 struct CFGPrinter : public FunctionPass { 74 static char ID; // Pass identification, replacement for typeid 75 CFGPrinter() : FunctionPass(ID) { 76 initializeCFGPrinterPass(*PassRegistry::getPassRegistry()); 77 } 78 79 virtual bool runOnFunction(Function &F) { 80 std::string Filename = "cfg." + F.getName().str() + ".dot"; 81 errs() << "Writing '" << Filename << "'..."; 82 83 std::string ErrorInfo; 84 raw_fd_ostream File(Filename.c_str(), ErrorInfo); 85 86 if (ErrorInfo.empty()) 87 WriteGraph(File, (const Function*)&F); 88 else 89 errs() << " error opening file for writing!"; 90 errs() << "\n"; 91 return false; 92 } 93 94 void print(raw_ostream &OS, const Module* = 0) const {} 95 96 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 97 AU.setPreservesAll(); 98 } 99 }; 100 } 101 102 char CFGPrinter::ID = 0; 103 INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", 104 false, true) 105 106 namespace { 107 struct CFGOnlyPrinter : public FunctionPass { 108 static char ID; // Pass identification, replacement for typeid 109 CFGOnlyPrinter() : FunctionPass(ID) { 110 initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry()); 111 } 112 113 virtual bool runOnFunction(Function &F) { 114 std::string Filename = "cfg." + F.getName().str() + ".dot"; 115 errs() << "Writing '" << Filename << "'..."; 116 117 std::string ErrorInfo; 118 raw_fd_ostream File(Filename.c_str(), ErrorInfo); 119 120 if (ErrorInfo.empty()) 121 WriteGraph(File, (const Function*)&F, true); 122 else 123 errs() << " error opening file for writing!"; 124 errs() << "\n"; 125 return false; 126 } 127 void print(raw_ostream &OS, const Module* = 0) const {} 128 129 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 130 AU.setPreservesAll(); 131 } 132 }; 133 } 134 135 char CFGOnlyPrinter::ID = 0; 136 INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only", 137 "Print CFG of function to 'dot' file (with no function bodies)", 138 false, true) 139 140 /// viewCFG - This function is meant for use from the debugger. You can just 141 /// say 'call F->viewCFG()' and a ghostview window should pop up from the 142 /// program, displaying the CFG of the current function. This depends on there 143 /// being a 'dot' and 'gv' program in your path. 144 /// 145 void Function::viewCFG() const { 146 ViewGraph(this, "cfg" + getName()); 147 } 148 149 /// viewCFGOnly - This function is meant for use from the debugger. It works 150 /// just like viewCFG, but it does not include the contents of basic blocks 151 /// into the nodes, just the label. If you are only interested in the CFG t 152 /// his can make the graph smaller. 153 /// 154 void Function::viewCFGOnly() const { 155 ViewGraph(this, "cfg" + getName(), true); 156 } 157 158 FunctionPass *llvm::createCFGPrinterPass () { 159 return new CFGPrinter(); 160 } 161 162 FunctionPass *llvm::createCFGOnlyPrinterPass () { 163 return new CFGOnlyPrinter(); 164 } 165 166