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