CFGPrinter.cpp revision 276479
1193323Sed//===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file defines a '-dot-cfg' analysis pass, which emits the 11193323Sed// cfg.<fnname>.dot file for each function in the program, with a graph of the 12193323Sed// CFG for that function. 13193323Sed// 14193323Sed// The other main feature of this file is that it implements the 15193323Sed// Function::viewCFG method, which is useful for debugging passes which operate 16193323Sed// on the CFG. 17193323Sed// 18193323Sed//===----------------------------------------------------------------------===// 19193323Sed 20198396Srdivacky#include "llvm/Analysis/CFGPrinter.h" 21193323Sed#include "llvm/Pass.h" 22276479Sdim#include "llvm/Support/FileSystem.h" 23193323Sedusing namespace llvm; 24193323Sed 25193323Sednamespace { 26198892Srdivacky struct CFGViewer : public FunctionPass { 27193323Sed static char ID; // Pass identifcation, replacement for typeid 28218893Sdim CFGViewer() : FunctionPass(ID) { 29218893Sdim initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); 30218893Sdim } 31193323Sed 32276479Sdim bool runOnFunction(Function &F) override { 33193323Sed F.viewCFG(); 34193323Sed return false; 35193323Sed } 36193323Sed 37276479Sdim void print(raw_ostream &OS, const Module* = nullptr) const override {} 38193323Sed 39276479Sdim void getAnalysisUsage(AnalysisUsage &AU) const override { 40193323Sed AU.setPreservesAll(); 41193323Sed } 42193323Sed }; 43193323Sed} 44193323Sed 45193323Sedchar CFGViewer::ID = 0; 46218893SdimINITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true) 47193323Sed 48193323Sednamespace { 49198892Srdivacky struct CFGOnlyViewer : public FunctionPass { 50193323Sed static char ID; // Pass identifcation, replacement for typeid 51218893Sdim CFGOnlyViewer() : FunctionPass(ID) { 52218893Sdim initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); 53218893Sdim } 54193323Sed 55276479Sdim bool runOnFunction(Function &F) override { 56198090Srdivacky F.viewCFGOnly(); 57193323Sed return false; 58193323Sed } 59193323Sed 60276479Sdim void print(raw_ostream &OS, const Module* = nullptr) const override {} 61193323Sed 62276479Sdim void getAnalysisUsage(AnalysisUsage &AU) const override { 63193323Sed AU.setPreservesAll(); 64193323Sed } 65193323Sed }; 66193323Sed} 67193323Sed 68193323Sedchar CFGOnlyViewer::ID = 0; 69212904SdimINITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only", 70218893Sdim "View CFG of function (with no function bodies)", false, true) 71193323Sed 72193323Sednamespace { 73198892Srdivacky struct CFGPrinter : public FunctionPass { 74193323Sed static char ID; // Pass identification, replacement for typeid 75218893Sdim CFGPrinter() : FunctionPass(ID) { 76218893Sdim initializeCFGPrinterPass(*PassRegistry::getPassRegistry()); 77218893Sdim } 78193323Sed 79276479Sdim bool runOnFunction(Function &F) override { 80234353Sdim std::string Filename = "cfg." + F.getName().str() + ".dot"; 81198090Srdivacky errs() << "Writing '" << Filename << "'..."; 82198090Srdivacky 83198090Srdivacky std::string ErrorInfo; 84276479Sdim raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text); 85193323Sed 86198090Srdivacky if (ErrorInfo.empty()) 87193323Sed WriteGraph(File, (const Function*)&F); 88193323Sed else 89198090Srdivacky errs() << " error opening file for writing!"; 90198090Srdivacky errs() << "\n"; 91193323Sed return false; 92193323Sed } 93193323Sed 94276479Sdim void print(raw_ostream &OS, const Module* = nullptr) const override {} 95193323Sed 96276479Sdim void getAnalysisUsage(AnalysisUsage &AU) const override { 97193323Sed AU.setPreservesAll(); 98193323Sed } 99193323Sed }; 100193323Sed} 101193323Sed 102193323Sedchar CFGPrinter::ID = 0; 103212904SdimINITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", 104218893Sdim false, true) 105193323Sed 106193323Sednamespace { 107198892Srdivacky struct CFGOnlyPrinter : public FunctionPass { 108193323Sed static char ID; // Pass identification, replacement for typeid 109218893Sdim CFGOnlyPrinter() : FunctionPass(ID) { 110218893Sdim initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry()); 111218893Sdim } 112276479Sdim 113276479Sdim bool runOnFunction(Function &F) override { 114234353Sdim std::string Filename = "cfg." + F.getName().str() + ".dot"; 115198090Srdivacky errs() << "Writing '" << Filename << "'..."; 116195098Sed 117198090Srdivacky std::string ErrorInfo; 118276479Sdim raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text); 119198090Srdivacky 120198090Srdivacky if (ErrorInfo.empty()) 121195098Sed WriteGraph(File, (const Function*)&F, true); 122195098Sed else 123198090Srdivacky errs() << " error opening file for writing!"; 124198090Srdivacky errs() << "\n"; 125193323Sed return false; 126193323Sed } 127276479Sdim void print(raw_ostream &OS, const Module* = nullptr) const override {} 128193323Sed 129276479Sdim void getAnalysisUsage(AnalysisUsage &AU) const override { 130193323Sed AU.setPreservesAll(); 131193323Sed } 132193323Sed }; 133193323Sed} 134193323Sed 135193323Sedchar CFGOnlyPrinter::ID = 0; 136212904SdimINITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only", 137212904Sdim "Print CFG of function to 'dot' file (with no function bodies)", 138218893Sdim false, true) 139193323Sed 140193323Sed/// viewCFG - This function is meant for use from the debugger. You can just 141193323Sed/// say 'call F->viewCFG()' and a ghostview window should pop up from the 142193323Sed/// program, displaying the CFG of the current function. This depends on there 143193323Sed/// being a 'dot' and 'gv' program in your path. 144193323Sed/// 145193323Sedvoid Function::viewCFG() const { 146234353Sdim ViewGraph(this, "cfg" + getName()); 147193323Sed} 148193323Sed 149193323Sed/// viewCFGOnly - This function is meant for use from the debugger. It works 150193323Sed/// just like viewCFG, but it does not include the contents of basic blocks 151276479Sdim/// into the nodes, just the label. If you are only interested in the CFG 152276479Sdim/// this can make the graph smaller. 153193323Sed/// 154193323Sedvoid Function::viewCFGOnly() const { 155234353Sdim ViewGraph(this, "cfg" + getName(), true); 156193323Sed} 157193323Sed 158193323SedFunctionPass *llvm::createCFGPrinterPass () { 159193323Sed return new CFGPrinter(); 160193323Sed} 161193323Sed 162193323SedFunctionPass *llvm::createCFGOnlyPrinterPass () { 163193323Sed return new CFGOnlyPrinter(); 164193323Sed} 165193323Sed 166