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/Function.h" 21 #include "llvm/Instructions.h" 22 #include "llvm/Pass.h" 23 #include "llvm/Analysis/CFGPrinter.h" 24 #include "llvm/Assembly/Writer.h" 25 #include "llvm/Support/CFG.h" 26 #include "llvm/Support/Compiler.h" 27 #include "llvm/Support/GraphWriter.h" 28 #include "llvm/Config/config.h" 29 #include <iosfwd> 30 #include <sstream> 31 #include <fstream> 32 using namespace llvm; 33 34 namespace llvm { 35 template<> 36 struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { 37 static std::string getGraphName(const Function *F) { 38 return "CFG for '" + F->getNameStr() + "' function"; 39 } 40 41 static std::string getNodeLabel(const BasicBlock *Node, 42 const Function *Graph, 43 bool ShortNames) { 44 if (ShortNames && !Node->getName().empty()) 45 return Node->getNameStr() + ":"; 46 47 std::ostringstream Out; 48 if (ShortNames) { 49 WriteAsOperand(Out, Node, false); 50 return Out.str(); 51 } 52 53 if (Node->getName().empty()) { 54 WriteAsOperand(Out, Node, false); 55 Out << ":"; 56 } 57 58 Out << *Node; 59 std::string OutStr = Out.str(); 60 if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 61 62 // Process string output to make it nicer... 63 for (unsigned i = 0; i != OutStr.length(); ++i) 64 if (OutStr[i] == '\n') { // Left justify 65 OutStr[i] = '\\'; 66 OutStr.insert(OutStr.begin()+i+1, 'l'); 67 } else if (OutStr[i] == ';') { // Delete comments! 68 unsigned Idx = OutStr.find('\n', i+1); // Find end of line 69 OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); 70 --i; 71 } 72 73 return OutStr; 74 } 75 76 static std::string getEdgeSourceLabel(const BasicBlock *Node, 77 succ_const_iterator I) { 78 // Label source of conditional branches with "T" or "F" 79 if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator())) 80 if (BI->isConditional()) 81 return (I == succ_begin(Node)) ? "T" : "F"; 82 return ""; 83 } 84 }; 85 } 86 87 namespace { 88 struct VISIBILITY_HIDDEN CFGViewer : public FunctionPass { 89 static char ID; // Pass identifcation, replacement for typeid 90 CFGViewer() : FunctionPass(&ID) {} 91 92 virtual bool runOnFunction(Function &F) { 93 F.viewCFG(); 94 return false; 95 } 96 97 void print(std::ostream &OS, const Module* = 0) const {} 98 99 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 100 AU.setPreservesAll(); 101 } 102 }; 103 } 104 105 char CFGViewer::ID = 0; 106 static RegisterPass<CFGViewer> 107 V0("view-cfg", "View CFG of function", false, true); 108 109 namespace { 110 struct VISIBILITY_HIDDEN CFGOnlyViewer : public FunctionPass { 111 static char ID; // Pass identifcation, replacement for typeid 112 CFGOnlyViewer() : FunctionPass(&ID) {} 113 114 virtual bool runOnFunction(Function &F) { 115 F.viewCFG(); 116 return false; 117 } 118 119 void print(std::ostream &OS, const Module* = 0) const {} 120 121 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 122 AU.setPreservesAll(); 123 } 124 }; 125 } 126 127 char CFGOnlyViewer::ID = 0; 128 static RegisterPass<CFGOnlyViewer> 129 V1("view-cfg-only", 130 "View CFG of function (with no function bodies)", false, true); 131 132 namespace { 133 struct VISIBILITY_HIDDEN CFGPrinter : public FunctionPass { 134 static char ID; // Pass identification, replacement for typeid 135 CFGPrinter() : FunctionPass(&ID) {} 136 explicit CFGPrinter(void *pid) : FunctionPass(pid) {} 137 138 virtual bool runOnFunction(Function &F) { 139 std::string Filename = "cfg." + F.getNameStr() + ".dot"; 140 cerr << "Writing '" << Filename << "'..."; 141 std::ofstream File(Filename.c_str()); 142 143 if (File.good()) 144 WriteGraph(File, (const Function*)&F); 145 else 146 cerr << " error opening file for writing!"; 147 cerr << "\n"; 148 return false; 149 } 150 151 void print(std::ostream &OS, const Module* = 0) const {} 152 153 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 154 AU.setPreservesAll(); 155 } 156 }; 157 } 158 159 char CFGPrinter::ID = 0; 160 static RegisterPass<CFGPrinter> 161 P1("dot-cfg", "Print CFG of function to 'dot' file", false, true); 162 163 namespace { 164 struct VISIBILITY_HIDDEN CFGOnlyPrinter : public FunctionPass { 165 static char ID; // Pass identification, replacement for typeid 166 CFGOnlyPrinter() : FunctionPass(&ID) {} 167 explicit CFGOnlyPrinter(void *pid) : FunctionPass(pid) {} 168 virtual bool runOnFunction(Function &F) { 169 std::string Filename = "cfg." + F.getNameStr() + ".dot"; 170 cerr << "Writing '" << Filename << "'..."; 171 std::ofstream File(Filename.c_str()); 172 173 if (File.good()) 174 WriteGraph(File, (const Function*)&F, true); 175 else 176 cerr << " error opening file for writing!"; 177 cerr << "\n"; 178 return false; 179 } 180 void print(std::ostream &OS, const Module* = 0) const {} 181 182 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 183 AU.setPreservesAll(); 184 } 185 }; 186 } 187 188 char CFGOnlyPrinter::ID = 0; 189 static RegisterPass<CFGOnlyPrinter> 190 P2("dot-cfg-only", 191 "Print CFG of function to 'dot' file (with no function bodies)", false, true); 192 193 /// viewCFG - This function is meant for use from the debugger. You can just 194 /// say 'call F->viewCFG()' and a ghostview window should pop up from the 195 /// program, displaying the CFG of the current function. This depends on there 196 /// being a 'dot' and 'gv' program in your path. 197 /// 198 void Function::viewCFG() const { 199 ViewGraph(this, "cfg" + getNameStr()); 200 } 201 202 /// viewCFGOnly - This function is meant for use from the debugger. It works 203 /// just like viewCFG, but it does not include the contents of basic blocks 204 /// into the nodes, just the label. If you are only interested in the CFG t 205 /// his can make the graph smaller. 206 /// 207 void Function::viewCFGOnly() const { 208 ViewGraph(this, "cfg" + getNameStr(), true); 209 } 210 211 FunctionPass *llvm::createCFGPrinterPass () { 212 return new CFGPrinter(); 213 } 214 215 FunctionPass *llvm::createCFGOnlyPrinterPass () { 216 return new CFGOnlyPrinter(); 217 } 218 219