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