LCOV - code coverage report
Current view: top level - lib/Analysis - CFGPrinter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 31 70 44.3 %
Date: 2018-10-20 13:21:21 Functions: 16 29 55.2 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : // `<prefix>.<fnname>.dot` file for each function in the program, with a graph
      12             : // of the CFG for that function. The default value for `<prefix>` is `cfg` but
      13             : // can be customized as needed.
      14             : //
      15             : // The other main feature of this file is that it implements the
      16             : // Function::viewCFG method, which is useful for debugging passes which operate
      17             : // on the CFG.
      18             : //
      19             : //===----------------------------------------------------------------------===//
      20             : 
      21             : #include "llvm/Analysis/CFGPrinter.h"
      22             : #include "llvm/Pass.h"
      23             : #include "llvm/Support/FileSystem.h"
      24             : using namespace llvm;
      25             : 
      26             : static cl::opt<std::string> CFGFuncName(
      27             :     "cfg-func-name", cl::Hidden,
      28             :     cl::desc("The name of a function (or its substring)"
      29             :              " whose CFG is viewed/printed."));
      30             : 
      31             : static cl::opt<std::string> CFGDotFilenamePrefix(
      32             :     "cfg-dot-filename-prefix", cl::Hidden,
      33             :     cl::desc("The prefix used for the CFG dot file names."));
      34             : 
      35             : namespace {
      36             :   struct CFGViewerLegacyPass : public FunctionPass {
      37             :     static char ID; // Pass identifcation, replacement for typeid
      38           0 :     CFGViewerLegacyPass() : FunctionPass(ID) {
      39           0 :       initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
      40             :     }
      41             : 
      42           0 :     bool runOnFunction(Function &F) override {
      43           0 :       F.viewCFG();
      44           0 :       return false;
      45             :     }
      46             : 
      47           0 :     void print(raw_ostream &OS, const Module* = nullptr) const override {}
      48             : 
      49           0 :     void getAnalysisUsage(AnalysisUsage &AU) const override {
      50             :       AU.setPreservesAll();
      51           0 :     }
      52             :   };
      53             : }
      54             : 
      55             : char CFGViewerLegacyPass::ID = 0;
      56       21512 : INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true)
      57             : 
      58           0 : PreservedAnalyses CFGViewerPass::run(Function &F,
      59             :                                      FunctionAnalysisManager &AM) {
      60           0 :   F.viewCFG();
      61           0 :   return PreservedAnalyses::all();
      62             : }
      63             : 
      64             : 
      65             : namespace {
      66             :   struct CFGOnlyViewerLegacyPass : public FunctionPass {
      67             :     static char ID; // Pass identifcation, replacement for typeid
      68           0 :     CFGOnlyViewerLegacyPass() : FunctionPass(ID) {
      69           0 :       initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
      70             :     }
      71             : 
      72           0 :     bool runOnFunction(Function &F) override {
      73           0 :       F.viewCFGOnly();
      74           0 :       return false;
      75             :     }
      76             : 
      77           0 :     void print(raw_ostream &OS, const Module* = nullptr) const override {}
      78             : 
      79           0 :     void getAnalysisUsage(AnalysisUsage &AU) const override {
      80             :       AU.setPreservesAll();
      81           0 :     }
      82             :   };
      83             : }
      84             : 
      85             : char CFGOnlyViewerLegacyPass::ID = 0;
      86       21512 : INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
      87             :                 "View CFG of function (with no function bodies)", false, true)
      88             : 
      89           0 : PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
      90             :                                          FunctionAnalysisManager &AM) {
      91           0 :   F.viewCFGOnly();
      92           0 :   return PreservedAnalyses::all();
      93             : }
      94             : 
      95           3 : static void writeCFGToDotFile(Function &F, bool CFGOnly = false) {
      96           3 :   if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
      97           0 :      return;
      98             :   std::string Filename =
      99           6 :       (CFGDotFilenamePrefix + "." + F.getName() + ".dot").str();
     100           6 :   errs() << "Writing '" << Filename << "'...";
     101             : 
     102             :   std::error_code EC;
     103           6 :   raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
     104             : 
     105           3 :   if (!EC)
     106           3 :     WriteGraph(File, (const Function*)&F, CFGOnly);
     107             :   else
     108           0 :     errs() << "  error opening file for writing!";
     109           3 :   errs() << "\n";
     110             : }
     111             : 
     112             : namespace {
     113             :   struct CFGPrinterLegacyPass : public FunctionPass {
     114             :     static char ID; // Pass identification, replacement for typeid
     115           1 :     CFGPrinterLegacyPass() : FunctionPass(ID) {
     116           1 :       initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
     117             :     }
     118             : 
     119           1 :     bool runOnFunction(Function &F) override {
     120           1 :       writeCFGToDotFile(F);
     121           1 :       return false;
     122             :     }
     123             : 
     124           1 :     void print(raw_ostream &OS, const Module* = nullptr) const override {}
     125             : 
     126           1 :     void getAnalysisUsage(AnalysisUsage &AU) const override {
     127             :       AU.setPreservesAll();
     128           1 :     }
     129             :   };
     130             : }
     131             : 
     132             : char CFGPrinterLegacyPass::ID = 0;
     133       21513 : INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file",
     134             :                 false, true)
     135             : 
     136           0 : PreservedAnalyses CFGPrinterPass::run(Function &F,
     137             :                                       FunctionAnalysisManager &AM) {
     138           0 :   writeCFGToDotFile(F);
     139           0 :   return PreservedAnalyses::all();
     140             : }
     141             : 
     142             : namespace {
     143             :   struct CFGOnlyPrinterLegacyPass : public FunctionPass {
     144             :     static char ID; // Pass identification, replacement for typeid
     145           1 :     CFGOnlyPrinterLegacyPass() : FunctionPass(ID) {
     146           1 :       initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
     147             :     }
     148             : 
     149           1 :     bool runOnFunction(Function &F) override {
     150           1 :       writeCFGToDotFile(F, /*CFGOnly=*/true);
     151           1 :       return false;
     152             :     }
     153           1 :     void print(raw_ostream &OS, const Module* = nullptr) const override {}
     154             : 
     155           1 :     void getAnalysisUsage(AnalysisUsage &AU) const override {
     156             :       AU.setPreservesAll();
     157           1 :     }
     158             :   };
     159             : }
     160             : 
     161             : char CFGOnlyPrinterLegacyPass::ID = 0;
     162       21513 : INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
     163             :    "Print CFG of function to 'dot' file (with no function bodies)",
     164             :    false, true)
     165             : 
     166           1 : PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
     167             :                                           FunctionAnalysisManager &AM) {
     168           1 :   writeCFGToDotFile(F, /*CFGOnly=*/true);
     169           1 :   return PreservedAnalyses::all();
     170             : }
     171             : 
     172             : /// viewCFG - This function is meant for use from the debugger.  You can just
     173             : /// say 'call F->viewCFG()' and a ghostview window should pop up from the
     174             : /// program, displaying the CFG of the current function.  This depends on there
     175             : /// being a 'dot' and 'gv' program in your path.
     176             : ///
     177           0 : void Function::viewCFG() const {
     178           0 :   if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
     179           0 :      return;
     180           0 :   ViewGraph(this, "cfg" + getName());
     181             : }
     182             : 
     183             : /// viewCFGOnly - This function is meant for use from the debugger.  It works
     184             : /// just like viewCFG, but it does not include the contents of basic blocks
     185             : /// into the nodes, just the label.  If you are only interested in the CFG
     186             : /// this can make the graph smaller.
     187             : ///
     188           0 : void Function::viewCFGOnly() const {
     189           0 :   if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
     190           0 :      return;
     191           0 :   ViewGraph(this, "cfg" + getName(), true);
     192             : }
     193             : 
     194           0 : FunctionPass *llvm::createCFGPrinterLegacyPassPass () {
     195           0 :   return new CFGPrinterLegacyPass();
     196             : }
     197             : 
     198           0 : FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () {
     199           0 :   return new CFGOnlyPrinterLegacyPass();
     200             : }
     201             : 

Generated by: LCOV version 1.13