LLVM API Documentation

CFGPrinter.cpp
Go to the documentation of this file.
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::string ErrorInfo;
00084       raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text);
00085 
00086       if (ErrorInfo.empty())
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::string ErrorInfo;
00118       raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text);
00119       
00120       if (ErrorInfo.empty())
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