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