blob: 6d01e9d5d447b3a0f81bbe53d8bffa3f4ac2720a [file] [log] [blame]
Chris Lattner002362c2003-10-22 16:03:49 +00001//===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
Misha Brukman2b37d7c2005-04-21 21:13:18 +00002//
Chris Lattner002362c2003-10-22 16:03:49 +00003// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Misha Brukman2b37d7c2005-04-21 21:13:18 +00007//
Chris Lattner002362c2003-10-22 16:03:49 +00008//===----------------------------------------------------------------------===//
9//
Chandler Carruthc179d7b2018-10-09 04:30:23 +000010// 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.
Chris Lattner002362c2003-10-22 16:03:49 +000014//
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
Brian Gaekec6e2d8a2004-04-26 16:27:08 +000021#include "llvm/Analysis/CFGPrinter.h"
Chris Lattner88067b92009-10-18 04:09:11 +000022#include "llvm/Pass.h"
Benjamin Kramer7259f142014-04-29 23:26:49 +000023#include "llvm/Support/FileSystem.h"
Chris Lattner1ca2a582003-12-11 21:48:18 +000024using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000025
Xinliang David Li8544cc82018-07-25 17:22:12 +000026static 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
Chandler Carruthc179d7b2018-10-09 04:30:23 +000031static 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
Chris Lattner002362c2003-10-22 16:03:49 +000035namespace {
Sean Fertile551913f2018-06-29 17:48:58 +000036 struct CFGViewerLegacyPass : public FunctionPass {
Dan Gohmana196b992007-05-14 14:25:08 +000037 static char ID; // Pass identifcation, replacement for typeid
Sean Fertile551913f2018-06-29 17:48:58 +000038 CFGViewerLegacyPass() : FunctionPass(ID) {
Sriraman Tallamf31e6632016-09-15 18:35:27 +000039 initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson081c34b2010-10-19 17:21:58 +000040 }
Devang Patel1cee94f2008-03-18 00:39:19 +000041
Sean Fertile551913f2018-06-29 17:48:58 +000042 bool runOnFunction(Function &F) override {
43 F.viewCFG();
Dan Gohmana196b992007-05-14 14:25:08 +000044 return false;
45 }
46
Sean Fertile551913f2018-06-29 17:48:58 +000047 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Dan Gohmana196b992007-05-14 14:25:08 +000048
Craig Topperc37e6c02014-03-05 07:30:04 +000049 void getAnalysisUsage(AnalysisUsage &AU) const override {
Dan Gohmana196b992007-05-14 14:25:08 +000050 AU.setPreservesAll();
51 }
52 };
Alexander Kornienkocd52a7a2015-06-23 09:49:53 +000053}
Dan Gohmana196b992007-05-14 14:25:08 +000054
Sriraman Tallamf31e6632016-09-15 18:35:27 +000055char CFGViewerLegacyPass::ID = 0;
56INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true)
57
Sean Fertile551913f2018-06-29 17:48:58 +000058PreservedAnalyses CFGViewerPass::run(Function &F,
59 FunctionAnalysisManager &AM) {
60 F.viewCFG();
Sriraman Tallamf31e6632016-09-15 18:35:27 +000061 return PreservedAnalyses::all();
62}
63
Dan Gohmana196b992007-05-14 14:25:08 +000064
Dan Gohman844731a2008-05-13 00:00:25 +000065namespace {
Sean Fertile551913f2018-06-29 17:48:58 +000066 struct CFGOnlyViewerLegacyPass : public FunctionPass {
Dan Gohmana196b992007-05-14 14:25:08 +000067 static char ID; // Pass identifcation, replacement for typeid
Sean Fertile551913f2018-06-29 17:48:58 +000068 CFGOnlyViewerLegacyPass() : FunctionPass(ID) {
Sriraman Tallamf31e6632016-09-15 18:35:27 +000069 initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson081c34b2010-10-19 17:21:58 +000070 }
Devang Patel1cee94f2008-03-18 00:39:19 +000071
Sean Fertile551913f2018-06-29 17:48:58 +000072 bool runOnFunction(Function &F) override {
73 F.viewCFGOnly();
Dan Gohmana196b992007-05-14 14:25:08 +000074 return false;
75 }
76
Sean Fertile551913f2018-06-29 17:48:58 +000077 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Dan Gohmana196b992007-05-14 14:25:08 +000078
Craig Topperc37e6c02014-03-05 07:30:04 +000079 void getAnalysisUsage(AnalysisUsage &AU) const override {
Dan Gohmana196b992007-05-14 14:25:08 +000080 AU.setPreservesAll();
81 }
82 };
Alexander Kornienkocd52a7a2015-06-23 09:49:53 +000083}
Dan Gohmana196b992007-05-14 14:25:08 +000084
Sriraman Tallamf31e6632016-09-15 18:35:27 +000085char CFGOnlyViewerLegacyPass::ID = 0;
86INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
Owen Andersonce665bd2010-10-07 22:25:06 +000087 "View CFG of function (with no function bodies)", false, true)
Dan Gohmana196b992007-05-14 14:25:08 +000088
Sean Fertile551913f2018-06-29 17:48:58 +000089PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
90 FunctionAnalysisManager &AM) {
91 F.viewCFGOnly();
Sriraman Tallamf31e6632016-09-15 18:35:27 +000092 return PreservedAnalyses::all();
93}
94
Sean Fertile551913f2018-06-29 17:48:58 +000095static void writeCFGToDotFile(Function &F, bool CFGOnly = false) {
Xinliang David Li8544cc82018-07-25 17:22:12 +000096 if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
97 return;
Chandler Carruthc179d7b2018-10-09 04:30:23 +000098 std::string Filename =
99 (CFGDotFilenamePrefix + "." + F.getName() + ".dot").str();
Sean Fertile551913f2018-06-29 17:48:58 +0000100 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
Dan Gohman844731a2008-05-13 00:00:25 +0000112namespace {
Sean Fertile551913f2018-06-29 17:48:58 +0000113 struct CFGPrinterLegacyPass : public FunctionPass {
Nick Lewyckyecd94c82007-05-06 13:37:16 +0000114 static char ID; // Pass identification, replacement for typeid
Sean Fertile551913f2018-06-29 17:48:58 +0000115 CFGPrinterLegacyPass() : FunctionPass(ID) {
Sriraman Tallamf31e6632016-09-15 18:35:27 +0000116 initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson081c34b2010-10-19 17:21:58 +0000117 }
Devang Patel1cee94f2008-03-18 00:39:19 +0000118
Sean Fertile551913f2018-06-29 17:48:58 +0000119 bool runOnFunction(Function &F) override {
120 writeCFGToDotFile(F);
Chris Lattner002362c2003-10-22 16:03:49 +0000121 return false;
122 }
123
Sean Fertile551913f2018-06-29 17:48:58 +0000124 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Misha Brukman2b37d7c2005-04-21 21:13:18 +0000125
Craig Topperc37e6c02014-03-05 07:30:04 +0000126 void getAnalysisUsage(AnalysisUsage &AU) const override {
Chris Lattner002362c2003-10-22 16:03:49 +0000127 AU.setPreservesAll();
128 }
129 };
Alexander Kornienkocd52a7a2015-06-23 09:49:53 +0000130}
Chris Lattner002362c2003-10-22 16:03:49 +0000131
Sriraman Tallamf31e6632016-09-15 18:35:27 +0000132char CFGPrinterLegacyPass::ID = 0;
Fangrui Songaf7b1832018-07-30 19:41:25 +0000133INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file",
Owen Andersonce665bd2010-10-07 22:25:06 +0000134 false, true)
Chris Lattner1ca2a582003-12-11 21:48:18 +0000135
Sean Fertile551913f2018-06-29 17:48:58 +0000136PreservedAnalyses CFGPrinterPass::run(Function &F,
137 FunctionAnalysisManager &AM) {
138 writeCFGToDotFile(F);
Sriraman Tallamf31e6632016-09-15 18:35:27 +0000139 return PreservedAnalyses::all();
140}
141
Dan Gohman844731a2008-05-13 00:00:25 +0000142namespace {
Sean Fertile551913f2018-06-29 17:48:58 +0000143 struct CFGOnlyPrinterLegacyPass : public FunctionPass {
Nick Lewyckyecd94c82007-05-06 13:37:16 +0000144 static char ID; // Pass identification, replacement for typeid
Sean Fertile551913f2018-06-29 17:48:58 +0000145 CFGOnlyPrinterLegacyPass() : FunctionPass(ID) {
Sriraman Tallamf31e6632016-09-15 18:35:27 +0000146 initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson081c34b2010-10-19 17:21:58 +0000147 }
Craig Topperc37e6c02014-03-05 07:30:04 +0000148
Sean Fertile551913f2018-06-29 17:48:58 +0000149 bool runOnFunction(Function &F) override {
150 writeCFGToDotFile(F, /*CFGOnly=*/true);
Chris Lattner1ca2a582003-12-11 21:48:18 +0000151 return false;
152 }
Sean Fertile551913f2018-06-29 17:48:58 +0000153 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Misha Brukman2b37d7c2005-04-21 21:13:18 +0000154
Craig Topperc37e6c02014-03-05 07:30:04 +0000155 void getAnalysisUsage(AnalysisUsage &AU) const override {
Chris Lattner1ca2a582003-12-11 21:48:18 +0000156 AU.setPreservesAll();
157 }
158 };
Alexander Kornienkocd52a7a2015-06-23 09:49:53 +0000159}
Chris Lattner002362c2003-10-22 16:03:49 +0000160
Sriraman Tallamf31e6632016-09-15 18:35:27 +0000161char CFGOnlyPrinterLegacyPass::ID = 0;
162INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
Owen Anderson02dd53e2010-08-23 17:52:01 +0000163 "Print CFG of function to 'dot' file (with no function bodies)",
Owen Andersonce665bd2010-10-07 22:25:06 +0000164 false, true)
Dan Gohman844731a2008-05-13 00:00:25 +0000165
Sean Fertile551913f2018-06-29 17:48:58 +0000166PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
167 FunctionAnalysisManager &AM) {
168 writeCFGToDotFile(F, /*CFGOnly=*/true);
Sriraman Tallamf31e6632016-09-15 18:35:27 +0000169 return PreservedAnalyses::all();
170}
171
Chris Lattner002362c2003-10-22 16:03:49 +0000172/// 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///
177void Function::viewCFG() const {
Xinliang David Li8544cc82018-07-25 17:22:12 +0000178 if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
179 return;
Sean Fertile551913f2018-06-29 17:48:58 +0000180 ViewGraph(this, "cfg" + getName());
Chris Lattner002362c2003-10-22 16:03:49 +0000181}
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
Eric Christopher68c7a1c2014-05-20 17:11:11 +0000185/// into the nodes, just the label. If you are only interested in the CFG
186/// this can make the graph smaller.
Chris Lattner002362c2003-10-22 16:03:49 +0000187///
188void Function::viewCFGOnly() const {
Xinliang David Li8544cc82018-07-25 17:22:12 +0000189 if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
190 return;
Sean Fertile551913f2018-06-29 17:48:58 +0000191 ViewGraph(this, "cfg" + getName(), true);
Chris Lattner002362c2003-10-22 16:03:49 +0000192}
Brian Gaekec6e2d8a2004-04-26 16:27:08 +0000193
Sean Fertile551913f2018-06-29 17:48:58 +0000194FunctionPass *llvm::createCFGPrinterLegacyPassPass () {
Sriraman Tallamf31e6632016-09-15 18:35:27 +0000195 return new CFGPrinterLegacyPass();
Brian Gaekec6e2d8a2004-04-26 16:27:08 +0000196}
197
Sean Fertile551913f2018-06-29 17:48:58 +0000198FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () {
Sriraman Tallamf31e6632016-09-15 18:35:27 +0000199 return new CFGOnlyPrinterLegacyPass();
Brian Gaekec6e2d8a2004-04-26 16:27:08 +0000200}
Sean Fertile551913f2018-06-29 17:48:58 +0000201