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" 23using namespace llvm; 24 25namespace { 26 struct CFGViewer : public FunctionPass { 27 static char ID; // Pass identifcation, replacement for typeid 28 CFGViewer() : FunctionPass(ID) { 29 initializeCFGOnlyViewerPass(*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 45char CFGViewer::ID = 0; 46INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true) 47 48namespace { 49 struct CFGOnlyViewer : public FunctionPass { 50 static char ID; // Pass identifcation, replacement for typeid 51 CFGOnlyViewer() : FunctionPass(ID) { 52 initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); 53 } 54 55 bool runOnFunction(Function &F) override { 56 F.viewCFGOnly(); 57 return false; 58 } 59 60 void print(raw_ostream &OS, const Module* = nullptr) const override {} 61 62 void getAnalysisUsage(AnalysisUsage &AU) const override { 63 AU.setPreservesAll(); 64 } 65 }; 66} 67 68char CFGOnlyViewer::ID = 0; 69INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only", 70 "View CFG of function (with no function bodies)", false, true) 71 72namespace { 73 struct CFGPrinter : public FunctionPass { 74 static char ID; // Pass identification, replacement for typeid 75 CFGPrinter() : FunctionPass(ID) { 76 initializeCFGPrinterPass(*PassRegistry::getPassRegistry()); 77 } 78 79 bool runOnFunction(Function &F) override { 80 std::string Filename = "cfg." + F.getName().str() + ".dot"; 81 errs() << "Writing '" << Filename << "'..."; 82 83 std::string ErrorInfo; 84 raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text); 85 86 if (ErrorInfo.empty()) 87 WriteGraph(File, (const Function*)&F); 88 else 89 errs() << " error opening file for writing!"; 90 errs() << "\n"; 91 return false; 92 } 93 94 void print(raw_ostream &OS, const Module* = nullptr) const override {} 95 96 void getAnalysisUsage(AnalysisUsage &AU) const override { 97 AU.setPreservesAll(); 98 } 99 }; 100} 101 102char CFGPrinter::ID = 0; 103INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", 104 false, true) 105 106namespace { 107 struct CFGOnlyPrinter : public FunctionPass { 108 static char ID; // Pass identification, replacement for typeid 109 CFGOnlyPrinter() : FunctionPass(ID) { 110 initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry()); 111 } 112 113 bool runOnFunction(Function &F) override { 114 std::string Filename = "cfg." + F.getName().str() + ".dot"; 115 errs() << "Writing '" << Filename << "'..."; 116 117 std::string ErrorInfo; 118 raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text); 119 120 if (ErrorInfo.empty()) 121 WriteGraph(File, (const Function*)&F, true); 122 else 123 errs() << " error opening file for writing!"; 124 errs() << "\n"; 125 return false; 126 } 127 void print(raw_ostream &OS, const Module* = nullptr) const override {} 128 129 void getAnalysisUsage(AnalysisUsage &AU) const override { 130 AU.setPreservesAll(); 131 } 132 }; 133} 134 135char CFGOnlyPrinter::ID = 0; 136INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only", 137 "Print CFG of function to 'dot' file (with no function bodies)", 138 false, true) 139 140/// viewCFG - This function is meant for use from the debugger. You can just 141/// say 'call F->viewCFG()' and a ghostview window should pop up from the 142/// program, displaying the CFG of the current function. This depends on there 143/// being a 'dot' and 'gv' program in your path. 144/// 145void Function::viewCFG() const { 146 ViewGraph(this, "cfg" + getName()); 147} 148 149/// viewCFGOnly - This function is meant for use from the debugger. It works 150/// just like viewCFG, but it does not include the contents of basic blocks 151/// into the nodes, just the label. If you are only interested in the CFG 152/// this can make the graph smaller. 153/// 154void Function::viewCFGOnly() const { 155 ViewGraph(this, "cfg" + getName(), true); 156} 157 158FunctionPass *llvm::createCFGPrinterPass () { 159 return new CFGPrinter(); 160} 161 162FunctionPass *llvm::createCFGOnlyPrinterPass () { 163 return new CFGOnlyPrinter(); 164} 165 166