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