Modernize raw_fd_ostream's constructor a bit.
[oota-llvm.git] / lib / Analysis / CFGPrinter.cpp
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().str() + ".dot";
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().str() + ".dot";
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