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 :
|