LLVM API Documentation
00001 //===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines a '-dot-cfg' analysis pass, which emits the 00011 // cfg.<fnname>.dot file for each function in the program, with a graph of the 00012 // CFG for that function. 00013 // 00014 // The other main feature of this file is that it implements the 00015 // Function::viewCFG method, which is useful for debugging passes which operate 00016 // on the CFG. 00017 // 00018 //===----------------------------------------------------------------------===// 00019 00020 #include "llvm/Analysis/CFGPrinter.h" 00021 #include "llvm/Pass.h" 00022 using namespace llvm; 00023 00024 namespace { 00025 struct CFGViewer : public FunctionPass { 00026 static char ID; // Pass identifcation, replacement for typeid 00027 CFGViewer() : FunctionPass(ID) { 00028 initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); 00029 } 00030 00031 virtual bool runOnFunction(Function &F) { 00032 F.viewCFG(); 00033 return false; 00034 } 00035 00036 void print(raw_ostream &OS, const Module* = 0) const {} 00037 00038 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00039 AU.setPreservesAll(); 00040 } 00041 }; 00042 } 00043 00044 char CFGViewer::ID = 0; 00045 INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true) 00046 00047 namespace { 00048 struct CFGOnlyViewer : public FunctionPass { 00049 static char ID; // Pass identifcation, replacement for typeid 00050 CFGOnlyViewer() : FunctionPass(ID) { 00051 initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); 00052 } 00053 00054 virtual bool runOnFunction(Function &F) { 00055 F.viewCFGOnly(); 00056 return false; 00057 } 00058 00059 void print(raw_ostream &OS, const Module* = 0) const {} 00060 00061 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00062 AU.setPreservesAll(); 00063 } 00064 }; 00065 } 00066 00067 char CFGOnlyViewer::ID = 0; 00068 INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only", 00069 "View CFG of function (with no function bodies)", false, true) 00070 00071 namespace { 00072 struct CFGPrinter : public FunctionPass { 00073 static char ID; // Pass identification, replacement for typeid 00074 CFGPrinter() : FunctionPass(ID) { 00075 initializeCFGPrinterPass(*PassRegistry::getPassRegistry()); 00076 } 00077 00078 virtual bool runOnFunction(Function &F) { 00079 std::string Filename = "cfg." + F.getName().str() + ".dot"; 00080 errs() << "Writing '" << Filename << "'..."; 00081 00082 std::string ErrorInfo; 00083 raw_fd_ostream File(Filename.c_str(), ErrorInfo); 00084 00085 if (ErrorInfo.empty()) 00086 WriteGraph(File, (const Function*)&F); 00087 else 00088 errs() << " error opening file for writing!"; 00089 errs() << "\n"; 00090 return false; 00091 } 00092 00093 void print(raw_ostream &OS, const Module* = 0) const {} 00094 00095 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00096 AU.setPreservesAll(); 00097 } 00098 }; 00099 } 00100 00101 char CFGPrinter::ID = 0; 00102 INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", 00103 false, true) 00104 00105 namespace { 00106 struct CFGOnlyPrinter : public FunctionPass { 00107 static char ID; // Pass identification, replacement for typeid 00108 CFGOnlyPrinter() : FunctionPass(ID) { 00109 initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry()); 00110 } 00111 00112 virtual bool runOnFunction(Function &F) { 00113 std::string Filename = "cfg." + F.getName().str() + ".dot"; 00114 errs() << "Writing '" << Filename << "'..."; 00115 00116 std::string ErrorInfo; 00117 raw_fd_ostream File(Filename.c_str(), ErrorInfo); 00118 00119 if (ErrorInfo.empty()) 00120 WriteGraph(File, (const Function*)&F, true); 00121 else 00122 errs() << " error opening file for writing!"; 00123 errs() << "\n"; 00124 return false; 00125 } 00126 void print(raw_ostream &OS, const Module* = 0) const {} 00127 00128 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00129 AU.setPreservesAll(); 00130 } 00131 }; 00132 } 00133 00134 char CFGOnlyPrinter::ID = 0; 00135 INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only", 00136 "Print CFG of function to 'dot' file (with no function bodies)", 00137 false, true) 00138 00139 /// viewCFG - This function is meant for use from the debugger. You can just 00140 /// say 'call F->viewCFG()' and a ghostview window should pop up from the 00141 /// program, displaying the CFG of the current function. This depends on there 00142 /// being a 'dot' and 'gv' program in your path. 00143 /// 00144 void Function::viewCFG() const { 00145 ViewGraph(this, "cfg" + getName()); 00146 } 00147 00148 /// viewCFGOnly - This function is meant for use from the debugger. It works 00149 /// just like viewCFG, but it does not include the contents of basic blocks 00150 /// into the nodes, just the label. If you are only interested in the CFG t 00151 /// his can make the graph smaller. 00152 /// 00153 void Function::viewCFGOnly() const { 00154 ViewGraph(this, "cfg" + getName(), true); 00155 } 00156 00157 FunctionPass *llvm::createCFGPrinterPass () { 00158 return new CFGPrinter(); 00159 } 00160 00161 FunctionPass *llvm::createCFGOnlyPrinterPass () { 00162 return new CFGOnlyPrinter(); 00163 } 00164