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