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 #include "llvm/Support/FileSystem.h"
     23 using namespace llvm;
     24 
     25 namespace {
     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 
     45 char CFGViewer::ID = 0;
     46 INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true)
     47 
     48 namespace {
     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 
     68 char CFGOnlyViewer::ID = 0;
     69 INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only",
     70                 "View CFG of function (with no function bodies)", false, true)
     71 
     72 namespace {
     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() + ".dot").str();
     81       errs() << "Writing '" << Filename << "'...";
     82 
     83       std::error_code EC;
     84       raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
     85 
     86       if (!EC)
     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 
    102 char CFGPrinter::ID = 0;
    103 INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file",
    104                 false, true)
    105 
    106 namespace {
    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() + ".dot").str();
    115       errs() << "Writing '" << Filename << "'...";
    116 
    117       std::error_code EC;
    118       raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
    119 
    120       if (!EC)
    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 
    135 char CFGOnlyPrinter::ID = 0;
    136 INITIALIZE_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 ///
    145 void 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 ///
    154 void Function::viewCFGOnly() const {
    155   ViewGraph(this, "cfg" + getName(), true);
    156 }
    157 
    158 FunctionPass *llvm::createCFGPrinterPass () {
    159   return new CFGPrinter();
    160 }
    161 
    162 FunctionPass *llvm::createCFGOnlyPrinterPass () {
    163   return new CFGOnlyPrinter();
    164 }
    165 
    166