CFGPrinter.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
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"
22using namespace llvm;
23
24namespace {
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    bool runOnFunction(Function &F) override {
32      F.viewCFG();
33      return false;
34    }
35
36    void print(raw_ostream &OS, const Module* = 0) const override {}
37
38    void getAnalysisUsage(AnalysisUsage &AU) const override {
39      AU.setPreservesAll();
40    }
41  };
42}
43
44char CFGViewer::ID = 0;
45INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true)
46
47namespace {
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    bool runOnFunction(Function &F) override {
55      F.viewCFGOnly();
56      return false;
57    }
58
59    void print(raw_ostream &OS, const Module* = 0) const override {}
60
61    void getAnalysisUsage(AnalysisUsage &AU) const override {
62      AU.setPreservesAll();
63    }
64  };
65}
66
67char CFGOnlyViewer::ID = 0;
68INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only",
69                "View CFG of function (with no function bodies)", false, true)
70
71namespace {
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    bool runOnFunction(Function &F) override {
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, sys::fs::F_Text);
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 override {}
94
95    void getAnalysisUsage(AnalysisUsage &AU) const override {
96      AU.setPreservesAll();
97    }
98  };
99}
100
101char CFGPrinter::ID = 0;
102INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file",
103                false, true)
104
105namespace {
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    bool runOnFunction(Function &F) override {
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, sys::fs::F_Text);
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 override {}
127
128    void getAnalysisUsage(AnalysisUsage &AU) const override {
129      AU.setPreservesAll();
130    }
131  };
132}
133
134char CFGOnlyPrinter::ID = 0;
135INITIALIZE_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///
144void 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///
153void Function::viewCFGOnly() const {
154  ViewGraph(this, "cfg" + getName(), true);
155}
156
157FunctionPass *llvm::createCFGPrinterPass () {
158  return new CFGPrinter();
159}
160
161FunctionPass *llvm::createCFGOnlyPrinterPass () {
162  return new CFGOnlyPrinter();
163}
164
165