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