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 #include "llvm/Support/FileSystem.h" 00023 using namespace llvm; 00024 00025 namespace { 00026 struct CFGViewer : public FunctionPass { 00027 static char ID; // Pass identifcation, replacement for typeid 00028 CFGViewer() : FunctionPass(ID) { 00029 initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); 00030 } 00031 00032 bool runOnFunction(Function &F) override { 00033 F.viewCFG(); 00034 return false; 00035 } 00036 00037 void print(raw_ostream &OS, const Module* = nullptr) const override {} 00038 00039 void getAnalysisUsage(AnalysisUsage &AU) const override { 00040 AU.setPreservesAll(); 00041 } 00042 }; 00043 } 00044 00045 char CFGViewer::ID = 0; 00046 INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true) 00047 00048 namespace { 00049 struct CFGOnlyViewer : public FunctionPass { 00050 static char ID; // Pass identifcation, replacement for typeid 00051 CFGOnlyViewer() : FunctionPass(ID) { 00052 initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); 00053 } 00054 00055 bool runOnFunction(Function &F) override { 00056 F.viewCFGOnly(); 00057 return false; 00058 } 00059 00060 void print(raw_ostream &OS, const Module* = nullptr) const override {} 00061 00062 void getAnalysisUsage(AnalysisUsage &AU) const override { 00063 AU.setPreservesAll(); 00064 } 00065 }; 00066 } 00067 00068 char CFGOnlyViewer::ID = 0; 00069 INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only", 00070 "View CFG of function (with no function bodies)", false, true) 00071 00072 namespace { 00073 struct CFGPrinter : public FunctionPass { 00074 static char ID; // Pass identification, replacement for typeid 00075 CFGPrinter() : FunctionPass(ID) { 00076 initializeCFGPrinterPass(*PassRegistry::getPassRegistry()); 00077 } 00078 00079 bool runOnFunction(Function &F) override { 00080 std::string Filename = "cfg." + F.getName().str() + ".dot"; 00081 errs() << "Writing '" << Filename << "'..."; 00082 00083 std::error_code EC; 00084 raw_fd_ostream File(Filename, EC, sys::fs::F_Text); 00085 00086 if (!EC) 00087 WriteGraph(File, (const Function*)&F); 00088 else 00089 errs() << " error opening file for writing!"; 00090 errs() << "\n"; 00091 return false; 00092 } 00093 00094 void print(raw_ostream &OS, const Module* = nullptr) const override {} 00095 00096 void getAnalysisUsage(AnalysisUsage &AU) const override { 00097 AU.setPreservesAll(); 00098 } 00099 }; 00100 } 00101 00102 char CFGPrinter::ID = 0; 00103 INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", 00104 false, true) 00105 00106 namespace { 00107 struct CFGOnlyPrinter : public FunctionPass { 00108 static char ID; // Pass identification, replacement for typeid 00109 CFGOnlyPrinter() : FunctionPass(ID) { 00110 initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry()); 00111 } 00112 00113 bool runOnFunction(Function &F) override { 00114 std::string Filename = "cfg." + F.getName().str() + ".dot"; 00115 errs() << "Writing '" << Filename << "'..."; 00116 00117 std::error_code EC; 00118 raw_fd_ostream File(Filename, EC, sys::fs::F_Text); 00119 00120 if (!EC) 00121 WriteGraph(File, (const Function*)&F, true); 00122 else 00123 errs() << " error opening file for writing!"; 00124 errs() << "\n"; 00125 return false; 00126 } 00127 void print(raw_ostream &OS, const Module* = nullptr) const override {} 00128 00129 void getAnalysisUsage(AnalysisUsage &AU) const override { 00130 AU.setPreservesAll(); 00131 } 00132 }; 00133 } 00134 00135 char CFGOnlyPrinter::ID = 0; 00136 INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only", 00137 "Print CFG of function to 'dot' file (with no function bodies)", 00138 false, true) 00139 00140 /// viewCFG - This function is meant for use from the debugger. You can just 00141 /// say 'call F->viewCFG()' and a ghostview window should pop up from the 00142 /// program, displaying the CFG of the current function. This depends on there 00143 /// being a 'dot' and 'gv' program in your path. 00144 /// 00145 void Function::viewCFG() const { 00146 ViewGraph(this, "cfg" + getName()); 00147 } 00148 00149 /// viewCFGOnly - This function is meant for use from the debugger. It works 00150 /// just like viewCFG, but it does not include the contents of basic blocks 00151 /// into the nodes, just the label. If you are only interested in the CFG 00152 /// this can make the graph smaller. 00153 /// 00154 void Function::viewCFGOnly() const { 00155 ViewGraph(this, "cfg" + getName(), true); 00156 } 00157 00158 FunctionPass *llvm::createCFGPrinterPass () { 00159 return new CFGPrinter(); 00160 } 00161 00162 FunctionPass *llvm::createCFGOnlyPrinterPass () { 00163 return new CFGOnlyPrinter(); 00164 } 00165