CFGPrinter.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
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" 22using namespace llvm; 23 24namespace { 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 bool runOnFunction(Function &F) override { 32 F.viewCFG(); 33 return false; 34 } 35 36 void print(raw_ostream &OS, const Module* = 0) const override {} 37 38 void getAnalysisUsage(AnalysisUsage &AU) const override { 39 AU.setPreservesAll(); 40 } 41 }; 42} 43 44char CFGViewer::ID = 0; 45INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true) 46 47namespace { 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 bool runOnFunction(Function &F) override { 55 F.viewCFGOnly(); 56 return false; 57 } 58 59 void print(raw_ostream &OS, const Module* = 0) const override {} 60 61 void getAnalysisUsage(AnalysisUsage &AU) const override { 62 AU.setPreservesAll(); 63 } 64 }; 65} 66 67char CFGOnlyViewer::ID = 0; 68INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only", 69 "View CFG of function (with no function bodies)", false, true) 70 71namespace { 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 bool runOnFunction(Function &F) override { 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, sys::fs::F_Text); 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 override {} 94 95 void getAnalysisUsage(AnalysisUsage &AU) const override { 96 AU.setPreservesAll(); 97 } 98 }; 99} 100 101char CFGPrinter::ID = 0; 102INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", 103 false, true) 104 105namespace { 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 bool runOnFunction(Function &F) override { 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, sys::fs::F_Text); 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 override {} 127 128 void getAnalysisUsage(AnalysisUsage &AU) const override { 129 AU.setPreservesAll(); 130 } 131 }; 132} 133 134char CFGOnlyPrinter::ID = 0; 135INITIALIZE_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/// 144void 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/// 153void Function::viewCFGOnly() const { 154 ViewGraph(this, "cfg" + getName(), true); 155} 156 157FunctionPass *llvm::createCFGPrinterPass () { 158 return new CFGPrinter(); 159} 160 161FunctionPass *llvm::createCFGOnlyPrinterPass () { 162 return new CFGOnlyPrinter(); 163} 164 165