]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Analysis/CFGPrinter.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / 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 // `<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     CFGViewerLegacyPass() : FunctionPass(ID) {
39       initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
40     }
41
42     bool runOnFunction(Function &F) override {
43       F.viewCFG();
44       return false;
45     }
46
47     void print(raw_ostream &OS, const Module* = nullptr) const override {}
48
49     void getAnalysisUsage(AnalysisUsage &AU) const override {
50       AU.setPreservesAll();
51     }
52   };
53 }
54
55 char CFGViewerLegacyPass::ID = 0;
56 INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true)
57
58 PreservedAnalyses CFGViewerPass::run(Function &F,
59                                      FunctionAnalysisManager &AM) {
60   F.viewCFG();
61   return PreservedAnalyses::all();
62 }
63
64
65 namespace {
66   struct CFGOnlyViewerLegacyPass : public FunctionPass {
67     static char ID; // Pass identifcation, replacement for typeid
68     CFGOnlyViewerLegacyPass() : FunctionPass(ID) {
69       initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
70     }
71
72     bool runOnFunction(Function &F) override {
73       F.viewCFGOnly();
74       return false;
75     }
76
77     void print(raw_ostream &OS, const Module* = nullptr) const override {}
78
79     void getAnalysisUsage(AnalysisUsage &AU) const override {
80       AU.setPreservesAll();
81     }
82   };
83 }
84
85 char CFGOnlyViewerLegacyPass::ID = 0;
86 INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
87                 "View CFG of function (with no function bodies)", false, true)
88
89 PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
90                                          FunctionAnalysisManager &AM) {
91   F.viewCFGOnly();
92   return PreservedAnalyses::all();
93 }
94
95 static void writeCFGToDotFile(Function &F, bool CFGOnly = false) {
96   if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
97      return;
98   std::string Filename =
99       (CFGDotFilenamePrefix + "." + F.getName() + ".dot").str();
100   errs() << "Writing '" << Filename << "'...";
101
102   std::error_code EC;
103   raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
104
105   if (!EC)
106     WriteGraph(File, (const Function*)&F, CFGOnly);
107   else
108     errs() << "  error opening file for writing!";
109   errs() << "\n";
110 }
111
112 namespace {
113   struct CFGPrinterLegacyPass : public FunctionPass {
114     static char ID; // Pass identification, replacement for typeid
115     CFGPrinterLegacyPass() : FunctionPass(ID) {
116       initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
117     }
118
119     bool runOnFunction(Function &F) override {
120       writeCFGToDotFile(F);
121       return false;
122     }
123
124     void print(raw_ostream &OS, const Module* = nullptr) const override {}
125
126     void getAnalysisUsage(AnalysisUsage &AU) const override {
127       AU.setPreservesAll();
128     }
129   };
130 }
131
132 char CFGPrinterLegacyPass::ID = 0;
133 INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file",
134                 false, true)
135
136 PreservedAnalyses CFGPrinterPass::run(Function &F,
137                                       FunctionAnalysisManager &AM) {
138   writeCFGToDotFile(F);
139   return PreservedAnalyses::all();
140 }
141
142 namespace {
143   struct CFGOnlyPrinterLegacyPass : public FunctionPass {
144     static char ID; // Pass identification, replacement for typeid
145     CFGOnlyPrinterLegacyPass() : FunctionPass(ID) {
146       initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
147     }
148
149     bool runOnFunction(Function &F) override {
150       writeCFGToDotFile(F, /*CFGOnly=*/true);
151       return false;
152     }
153     void print(raw_ostream &OS, const Module* = nullptr) const override {}
154
155     void getAnalysisUsage(AnalysisUsage &AU) const override {
156       AU.setPreservesAll();
157     }
158   };
159 }
160
161 char CFGOnlyPrinterLegacyPass::ID = 0;
162 INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
163    "Print CFG of function to 'dot' file (with no function bodies)",
164    false, true)
165
166 PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
167                                           FunctionAnalysisManager &AM) {
168   writeCFGToDotFile(F, /*CFGOnly=*/true);
169   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 void Function::viewCFG() const {
178   if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
179      return;
180   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 void Function::viewCFGOnly() const {
189   if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
190      return;
191   ViewGraph(this, "cfg" + getName(), true);
192 }
193
194 FunctionPass *llvm::createCFGPrinterLegacyPassPass () {
195   return new CFGPrinterLegacyPass();
196 }
197
198 FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () {
199   return new CFGOnlyPrinterLegacyPass();
200 }
201