blob: 5b170dfa7903b4e950cbc18d995604a7d6b9cc7e [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//
Duncan Sands9c40c282008-09-23 12:47:39 +000010// This file defines a '-dot-cfg' analysis pass, which emits the
Chris Lattnera93d11b2003-10-22 16:03:49 +000011// 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
Brian Gaeke104341f2004-04-26 16:27:08 +000020#include "llvm/Analysis/CFGPrinter.h"
Chris Lattnerda424262009-10-18 04:09:11 +000021#include "llvm/Pass.h"
Benjamin Kramerd59664f2014-04-29 23:26:49 +000022#include "llvm/Support/FileSystem.h"
Chris Lattner62aff842003-12-11 21:48:18 +000023using namespace llvm;
Brian Gaeke960707c2003-11-11 22:41:34 +000024
Xinliang David Li45a607e2018-07-25 17:22:12 +000025static 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
Chris Lattnera93d11b2003-10-22 16:03:49 +000030namespace {
Sean Fertilecd0d7632018-06-29 17:48:58 +000031 struct CFGViewerLegacyPass : public FunctionPass {
Dan Gohman90d97ac2007-05-14 14:25:08 +000032 static char ID; // Pass identifcation, replacement for typeid
Sean Fertilecd0d7632018-06-29 17:48:58 +000033 CFGViewerLegacyPass() : FunctionPass(ID) {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000034 initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +000035 }
Devang Patel864970e2008-03-18 00:39:19 +000036
Sean Fertilecd0d7632018-06-29 17:48:58 +000037 bool runOnFunction(Function &F) override {
38 F.viewCFG();
Dan Gohman90d97ac2007-05-14 14:25:08 +000039 return false;
40 }
41
Sean Fertilecd0d7632018-06-29 17:48:58 +000042 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Dan Gohman90d97ac2007-05-14 14:25:08 +000043
Craig Toppere9ba7592014-03-05 07:30:04 +000044 void getAnalysisUsage(AnalysisUsage &AU) const override {
Dan Gohman90d97ac2007-05-14 14:25:08 +000045 AU.setPreservesAll();
46 }
47 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +000048}
Dan Gohman90d97ac2007-05-14 14:25:08 +000049
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000050char CFGViewerLegacyPass::ID = 0;
51INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true)
52
Sean Fertilecd0d7632018-06-29 17:48:58 +000053PreservedAnalyses CFGViewerPass::run(Function &F,
54 FunctionAnalysisManager &AM) {
55 F.viewCFG();
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000056 return PreservedAnalyses::all();
57}
58
Dan Gohman90d97ac2007-05-14 14:25:08 +000059
Dan Gohmand78c4002008-05-13 00:00:25 +000060namespace {
Sean Fertilecd0d7632018-06-29 17:48:58 +000061 struct CFGOnlyViewerLegacyPass : public FunctionPass {
Dan Gohman90d97ac2007-05-14 14:25:08 +000062 static char ID; // Pass identifcation, replacement for typeid
Sean Fertilecd0d7632018-06-29 17:48:58 +000063 CFGOnlyViewerLegacyPass() : FunctionPass(ID) {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000064 initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +000065 }
Devang Patel864970e2008-03-18 00:39:19 +000066
Sean Fertilecd0d7632018-06-29 17:48:58 +000067 bool runOnFunction(Function &F) override {
68 F.viewCFGOnly();
Dan Gohman90d97ac2007-05-14 14:25:08 +000069 return false;
70 }
71
Sean Fertilecd0d7632018-06-29 17:48:58 +000072 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Dan Gohman90d97ac2007-05-14 14:25:08 +000073
Craig Toppere9ba7592014-03-05 07:30:04 +000074 void getAnalysisUsage(AnalysisUsage &AU) const override {
Dan Gohman90d97ac2007-05-14 14:25:08 +000075 AU.setPreservesAll();
76 }
77 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +000078}
Dan Gohman90d97ac2007-05-14 14:25:08 +000079
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000080char CFGOnlyViewerLegacyPass::ID = 0;
81INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
Owen Andersondf7a4f22010-10-07 22:25:06 +000082 "View CFG of function (with no function bodies)", false, true)
Dan Gohman90d97ac2007-05-14 14:25:08 +000083
Sean Fertilecd0d7632018-06-29 17:48:58 +000084PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
85 FunctionAnalysisManager &AM) {
86 F.viewCFGOnly();
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000087 return PreservedAnalyses::all();
88}
89
Sean Fertilecd0d7632018-06-29 17:48:58 +000090static void writeCFGToDotFile(Function &F, bool CFGOnly = false) {
Xinliang David Li45a607e2018-07-25 17:22:12 +000091 if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName))
92 return;
Sean Fertilecd0d7632018-06-29 17:48:58 +000093 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
Dan Gohmand78c4002008-05-13 00:00:25 +0000106namespace {
Sean Fertilecd0d7632018-06-29 17:48:58 +0000107 struct CFGPrinterLegacyPass : public FunctionPass {
Nick Lewyckye7da2d62007-05-06 13:37:16 +0000108 static char ID; // Pass identification, replacement for typeid
Sean Fertilecd0d7632018-06-29 17:48:58 +0000109 CFGPrinterLegacyPass() : FunctionPass(ID) {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000110 initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000111 }
Devang Patel864970e2008-03-18 00:39:19 +0000112
Sean Fertilecd0d7632018-06-29 17:48:58 +0000113 bool runOnFunction(Function &F) override {
114 writeCFGToDotFile(F);
Chris Lattnera93d11b2003-10-22 16:03:49 +0000115 return false;
116 }
117
Sean Fertilecd0d7632018-06-29 17:48:58 +0000118 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Misha Brukman01808ca2005-04-21 21:13:18 +0000119
Craig Toppere9ba7592014-03-05 07:30:04 +0000120 void getAnalysisUsage(AnalysisUsage &AU) const override {
Chris Lattnera93d11b2003-10-22 16:03:49 +0000121 AU.setPreservesAll();
122 }
123 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000124}
Chris Lattnera93d11b2003-10-22 16:03:49 +0000125
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000126char CFGPrinterLegacyPass::ID = 0;
Fangrui Songf78650a2018-07-30 19:41:25 +0000127INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000128 false, true)
Chris Lattner62aff842003-12-11 21:48:18 +0000129
Sean Fertilecd0d7632018-06-29 17:48:58 +0000130PreservedAnalyses CFGPrinterPass::run(Function &F,
131 FunctionAnalysisManager &AM) {
132 writeCFGToDotFile(F);
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000133 return PreservedAnalyses::all();
134}
135
Dan Gohmand78c4002008-05-13 00:00:25 +0000136namespace {
Sean Fertilecd0d7632018-06-29 17:48:58 +0000137 struct CFGOnlyPrinterLegacyPass : public FunctionPass {
Nick Lewyckye7da2d62007-05-06 13:37:16 +0000138 static char ID; // Pass identification, replacement for typeid
Sean Fertilecd0d7632018-06-29 17:48:58 +0000139 CFGOnlyPrinterLegacyPass() : FunctionPass(ID) {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000140 initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000141 }
Craig Toppere9ba7592014-03-05 07:30:04 +0000142
Sean Fertilecd0d7632018-06-29 17:48:58 +0000143 bool runOnFunction(Function &F) override {
144 writeCFGToDotFile(F, /*CFGOnly=*/true);
Chris Lattner62aff842003-12-11 21:48:18 +0000145 return false;
146 }
Sean Fertilecd0d7632018-06-29 17:48:58 +0000147 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Misha Brukman01808ca2005-04-21 21:13:18 +0000148
Craig Toppere9ba7592014-03-05 07:30:04 +0000149 void getAnalysisUsage(AnalysisUsage &AU) const override {
Chris Lattner62aff842003-12-11 21:48:18 +0000150 AU.setPreservesAll();
151 }
152 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000153}
Chris Lattnera93d11b2003-10-22 16:03:49 +0000154
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000155char CFGOnlyPrinterLegacyPass::ID = 0;
156INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
Owen Andersond31d82d2010-08-23 17:52:01 +0000157 "Print CFG of function to 'dot' file (with no function bodies)",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000158 false, true)
Dan Gohmand78c4002008-05-13 00:00:25 +0000159
Sean Fertilecd0d7632018-06-29 17:48:58 +0000160PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
161 FunctionAnalysisManager &AM) {
162 writeCFGToDotFile(F, /*CFGOnly=*/true);
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000163 return PreservedAnalyses::all();
164}
165
Chris Lattnera93d11b2003-10-22 16:03:49 +0000166/// 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///
171void Function::viewCFG() const {
Xinliang David Li45a607e2018-07-25 17:22:12 +0000172 if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
173 return;
Sean Fertilecd0d7632018-06-29 17:48:58 +0000174 ViewGraph(this, "cfg" + getName());
Chris Lattnera93d11b2003-10-22 16:03:49 +0000175}
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
Eric Christopher650c8f22014-05-20 17:11:11 +0000179/// into the nodes, just the label. If you are only interested in the CFG
180/// this can make the graph smaller.
Chris Lattnera93d11b2003-10-22 16:03:49 +0000181///
182void Function::viewCFGOnly() const {
Xinliang David Li45a607e2018-07-25 17:22:12 +0000183 if (!CFGFuncName.empty() && !getName().contains(CFGFuncName))
184 return;
Sean Fertilecd0d7632018-06-29 17:48:58 +0000185 ViewGraph(this, "cfg" + getName(), true);
Chris Lattnera93d11b2003-10-22 16:03:49 +0000186}
Brian Gaeke104341f2004-04-26 16:27:08 +0000187
Sean Fertilecd0d7632018-06-29 17:48:58 +0000188FunctionPass *llvm::createCFGPrinterLegacyPassPass () {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000189 return new CFGPrinterLegacyPass();
Brian Gaeke104341f2004-04-26 16:27:08 +0000190}
191
Sean Fertilecd0d7632018-06-29 17:48:58 +0000192FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000193 return new CFGOnlyPrinterLegacyPass();
Brian Gaeke104341f2004-04-26 16:27:08 +0000194}
Sean Fertilecd0d7632018-06-29 17:48:58 +0000195