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