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" 22 #include "llvm/Support/FileSystem.h" 23 using namespace llvm; 24 25 static cl::opt<std::string> CFGFuncName( 26 "cfg-func-name", cl::Hidden, 27 cl::desc("The name of a function (or its substring)" 28 " whose CFG is viewed/printed.")); 29 30 namespace { 31 struct CFGViewerLegacyPass : public FunctionPass { 32 static char ID; // Pass identifcation, replacement for typeid 33 CFGViewerLegacyPass() : FunctionPass(ID) { 34 initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry()); 35 } 36 37 bool runOnFunction(Function &F) override { 38 F.viewCFG(); 39 return false; 40 } 41 42 void print(raw_ostream &OS, const Module* = nullptr) const override {} 43 44 void getAnalysisUsage(AnalysisUsage &AU) const override { 45 AU.setPreservesAll(); 46 } 47 }; 48 } 49 50 char CFGViewerLegacyPass::ID = 0; 51 INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true) 52 53 PreservedAnalyses CFGViewerPass::run(Function &F, 54 FunctionAnalysisManager &AM) { 55 F.viewCFG(); 56 return PreservedAnalyses::all(); 57 } 58 59 60 namespace { 61 struct CFGOnlyViewerLegacyPass : public FunctionPass { 62 static char ID; // Pass identifcation, replacement for typeid 63 CFGOnlyViewerLegacyPass() : FunctionPass(ID) { 64 initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry()); 65 } 66 67 bool runOnFunction(Function &F) override { 68 F.viewCFGOnly(); 69 return false; 70 } 71 72 void print(raw_ostream &OS, const Module* = nullptr) const override {} 73 74 void getAnalysisUsage(AnalysisUsage &AU) const override { 75 AU.setPreservesAll(); 76 } 77 }; 78 } 79 80 char CFGOnlyViewerLegacyPass::ID = 0; 81 INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only", 82 "View CFG of function (with no function bodies)", false, true) 83 84 PreservedAnalyses CFGOnlyViewerPass::run(Function &F, 85 FunctionAnalysisManager &AM) { 86 F.viewCFGOnly(); 87 return PreservedAnalyses::all(); 88 } 89 90 static void writeCFGToDotFile(Function &F, bool CFGOnly = false) { 91 if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName)) 92 return; 93 std::string Filename = ("cfg." + F.getName() + ".dot").str(); 94 errs() << "Writing '" << Filename << "'..."; 95 96 std::error_code EC; 97 raw_fd_ostream File(Filename, EC, sys::fs::F_Text); 98 99 if (!EC) 100 WriteGraph(File, (const Function*)&F, CFGOnly); 101 else 102 errs() << " error opening file for writing!"; 103 errs() << "\n"; 104 } 105 106 namespace { 107 struct CFGPrinterLegacyPass : public FunctionPass { 108 static char ID; // Pass identification, replacement for typeid 109 CFGPrinterLegacyPass() : FunctionPass(ID) { 110 initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry()); 111 } 112 113 bool runOnFunction(Function &F) override { 114 writeCFGToDotFile(F); 115 return false; 116 } 117 118 void print(raw_ostream &OS, const Module* = nullptr) const override {} 119 120 void getAnalysisUsage(AnalysisUsage &AU) const override { 121 AU.setPreservesAll(); 122 } 123 }; 124 } 125 126 char CFGPrinterLegacyPass::ID = 0; 127 INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file", 128 false, true) 129 130 PreservedAnalyses CFGPrinterPass::run(Function &F, 131 FunctionAnalysisManager &AM) { 132 writeCFGToDotFile(F); 133 return PreservedAnalyses::all(); 134 } 135 136 namespace { 137 struct CFGOnlyPrinterLegacyPass : public FunctionPass { 138 static char ID; // Pass identification, replacement for typeid 139 CFGOnlyPrinterLegacyPass() : FunctionPass(ID) { 140 initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry()); 141 } 142 143 bool runOnFunction(Function &F) override { 144 writeCFGToDotFile(F, /*CFGOnly=*/true); 145 return false; 146 } 147 void print(raw_ostream &OS, const Module* = nullptr) const override {} 148 149 void getAnalysisUsage(AnalysisUsage &AU) const override { 150 AU.setPreservesAll(); 151 } 152 }; 153 } 154 155 char CFGOnlyPrinterLegacyPass::ID = 0; 156 INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only", 157 "Print CFG of function to 'dot' file (with no function bodies)", 158 false, true) 159 160 PreservedAnalyses CFGOnlyPrinterPass::run(Function &F, 161 FunctionAnalysisManager &AM) { 162 writeCFGToDotFile(F, /*CFGOnly=*/true); 163 return PreservedAnalyses::all(); 164 } 165 166 /// viewCFG - This function is meant for use from the debugger. You can just 167 /// say 'call F->viewCFG()' and a ghostview window should pop up from the 168 /// program, displaying the CFG of the current function. This depends on there 169 /// being a 'dot' and 'gv' program in your path. 170 /// 171 void Function::viewCFG() const { 172 if (!CFGFuncName.empty() && !getName().contains(CFGFuncName)) 173 return; 174 ViewGraph(this, "cfg" + getName()); 175 } 176 177 /// viewCFGOnly - This function is meant for use from the debugger. It works 178 /// just like viewCFG, but it does not include the contents of basic blocks 179 /// into the nodes, just the label. If you are only interested in the CFG 180 /// this can make the graph smaller. 181 /// 182 void Function::viewCFGOnly() const { 183 if (!CFGFuncName.empty() && !getName().contains(CFGFuncName)) 184 return; 185 ViewGraph(this, "cfg" + getName(), true); 186 } 187 188 FunctionPass *llvm::createCFGPrinterLegacyPassPass () { 189 return new CFGPrinterLegacyPass(); 190 } 191 192 FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () { 193 return new CFGOnlyPrinterLegacyPass(); 194 } 195 196