blob: a85af6c9c93f0946f7049cf7365bc4b0b1de5b38 [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
Chris Lattnera93d11b2003-10-22 16:03:49 +000025namespace {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000026 struct CFGViewerLegacyPass : public FunctionPass {
Dan Gohman90d97ac2007-05-14 14:25:08 +000027 static char ID; // Pass identifcation, replacement for typeid
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000028 CFGViewerLegacyPass() : FunctionPass(ID) {
29 initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +000030 }
Devang Patel864970e2008-03-18 00:39:19 +000031
Craig Toppere9ba7592014-03-05 07:30:04 +000032 bool runOnFunction(Function &F) override {
Dan Gohman90d97ac2007-05-14 14:25:08 +000033 F.viewCFG();
34 return false;
35 }
36
Craig Topper9f008862014-04-15 04:59:12 +000037 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Dan Gohman90d97ac2007-05-14 14:25:08 +000038
Craig Toppere9ba7592014-03-05 07:30:04 +000039 void getAnalysisUsage(AnalysisUsage &AU) const override {
Dan Gohman90d97ac2007-05-14 14:25:08 +000040 AU.setPreservesAll();
41 }
42 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +000043}
Dan Gohman90d97ac2007-05-14 14:25:08 +000044
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000045char CFGViewerLegacyPass::ID = 0;
46INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true)
47
48PreservedAnalyses CFGViewerPass::run(Function &F,
49 FunctionAnalysisManager &AM) {
50 F.viewCFG();
51 return PreservedAnalyses::all();
52}
53
Dan Gohman90d97ac2007-05-14 14:25:08 +000054
Dan Gohmand78c4002008-05-13 00:00:25 +000055namespace {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000056 struct CFGOnlyViewerLegacyPass : public FunctionPass {
Dan Gohman90d97ac2007-05-14 14:25:08 +000057 static char ID; // Pass identifcation, replacement for typeid
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000058 CFGOnlyViewerLegacyPass() : FunctionPass(ID) {
59 initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +000060 }
Devang Patel864970e2008-03-18 00:39:19 +000061
Craig Toppere9ba7592014-03-05 07:30:04 +000062 bool runOnFunction(Function &F) override {
Duncan Sands1636b7e2009-09-19 11:25:44 +000063 F.viewCFGOnly();
Dan Gohman90d97ac2007-05-14 14:25:08 +000064 return false;
65 }
66
Craig Topper9f008862014-04-15 04:59:12 +000067 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Dan Gohman90d97ac2007-05-14 14:25:08 +000068
Craig Toppere9ba7592014-03-05 07:30:04 +000069 void getAnalysisUsage(AnalysisUsage &AU) const override {
Dan Gohman90d97ac2007-05-14 14:25:08 +000070 AU.setPreservesAll();
71 }
72 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +000073}
Dan Gohman90d97ac2007-05-14 14:25:08 +000074
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000075char CFGOnlyViewerLegacyPass::ID = 0;
76INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
Owen Andersondf7a4f22010-10-07 22:25:06 +000077 "View CFG of function (with no function bodies)", false, true)
Dan Gohman90d97ac2007-05-14 14:25:08 +000078
Sriraman Tallam06a67ba2016-09-15 18:35:27 +000079PreservedAnalyses CFGOnlyViewerPass::run(Function &F,
80 FunctionAnalysisManager &AM) {
81 F.viewCFGOnly();
82 return PreservedAnalyses::all();
83}
84
85static void writeCFGToDotFile(Function &F) {
86 std::string Filename = ("cfg." + F.getName() + ".dot").str();
87 errs() << "Writing '" << Filename << "'...";
88
89 std::error_code EC;
90 raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
91
92 if (!EC)
93 WriteGraph(File, (const Function*)&F);
94 else
95 errs() << " error opening file for writing!";
96 errs() << "\n";
97}
98
Dan Gohmand78c4002008-05-13 00:00:25 +000099namespace {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000100 struct CFGPrinterLegacyPass : public FunctionPass {
Nick Lewyckye7da2d62007-05-06 13:37:16 +0000101 static char ID; // Pass identification, replacement for typeid
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000102 CFGPrinterLegacyPass() : FunctionPass(ID) {
103 initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000104 }
Devang Patel864970e2008-03-18 00:39:19 +0000105
Craig Toppere9ba7592014-03-05 07:30:04 +0000106 bool runOnFunction(Function &F) override {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000107 writeCFGToDotFile(F);
Chris Lattnera93d11b2003-10-22 16:03:49 +0000108 return false;
109 }
110
Craig Topper9f008862014-04-15 04:59:12 +0000111 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Misha Brukman01808ca2005-04-21 21:13:18 +0000112
Craig Toppere9ba7592014-03-05 07:30:04 +0000113 void getAnalysisUsage(AnalysisUsage &AU) const override {
Chris Lattnera93d11b2003-10-22 16:03:49 +0000114 AU.setPreservesAll();
115 }
116 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000117}
Chris Lattnera93d11b2003-10-22 16:03:49 +0000118
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000119char CFGPrinterLegacyPass::ID = 0;
120INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000121 false, true)
Chris Lattner62aff842003-12-11 21:48:18 +0000122
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000123PreservedAnalyses CFGPrinterPass::run(Function &F,
124 FunctionAnalysisManager &AM) {
125 writeCFGToDotFile(F);
126 return PreservedAnalyses::all();
127}
128
Dan Gohmand78c4002008-05-13 00:00:25 +0000129namespace {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000130 struct CFGOnlyPrinterLegacyPass : public FunctionPass {
Nick Lewyckye7da2d62007-05-06 13:37:16 +0000131 static char ID; // Pass identification, replacement for typeid
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000132 CFGOnlyPrinterLegacyPass() : FunctionPass(ID) {
133 initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000134 }
Craig Toppere9ba7592014-03-05 07:30:04 +0000135
136 bool runOnFunction(Function &F) override {
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000137 writeCFGToDotFile(F);
Chris Lattner62aff842003-12-11 21:48:18 +0000138 return false;
139 }
Craig Topper9f008862014-04-15 04:59:12 +0000140 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Misha Brukman01808ca2005-04-21 21:13:18 +0000141
Craig Toppere9ba7592014-03-05 07:30:04 +0000142 void getAnalysisUsage(AnalysisUsage &AU) const override {
Chris Lattner62aff842003-12-11 21:48:18 +0000143 AU.setPreservesAll();
144 }
145 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000146}
Chris Lattnera93d11b2003-10-22 16:03:49 +0000147
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000148char CFGOnlyPrinterLegacyPass::ID = 0;
149INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
Owen Andersond31d82d2010-08-23 17:52:01 +0000150 "Print CFG of function to 'dot' file (with no function bodies)",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000151 false, true)
Dan Gohmand78c4002008-05-13 00:00:25 +0000152
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000153PreservedAnalyses CFGOnlyPrinterPass::run(Function &F,
154 FunctionAnalysisManager &AM) {
155 writeCFGToDotFile(F);
156 return PreservedAnalyses::all();
157}
158
Chris Lattnera93d11b2003-10-22 16:03:49 +0000159/// viewCFG - This function is meant for use from the debugger. You can just
160/// say 'call F->viewCFG()' and a ghostview window should pop up from the
161/// program, displaying the CFG of the current function. This depends on there
162/// being a 'dot' and 'gv' program in your path.
163///
164void Function::viewCFG() const {
Benjamin Kramer4c93d152011-11-15 16:26:38 +0000165 ViewGraph(this, "cfg" + getName());
Chris Lattnera93d11b2003-10-22 16:03:49 +0000166}
167
168/// viewCFGOnly - This function is meant for use from the debugger. It works
169/// just like viewCFG, but it does not include the contents of basic blocks
Eric Christopher650c8f22014-05-20 17:11:11 +0000170/// into the nodes, just the label. If you are only interested in the CFG
171/// this can make the graph smaller.
Chris Lattnera93d11b2003-10-22 16:03:49 +0000172///
173void Function::viewCFGOnly() const {
Benjamin Kramer4c93d152011-11-15 16:26:38 +0000174 ViewGraph(this, "cfg" + getName(), true);
Chris Lattnera93d11b2003-10-22 16:03:49 +0000175}
Brian Gaeke104341f2004-04-26 16:27:08 +0000176
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000177FunctionPass *llvm::createCFGPrinterLegacyPassPass () {
178 return new CFGPrinterLegacyPass();
Brian Gaeke104341f2004-04-26 16:27:08 +0000179}
180
Sriraman Tallam06a67ba2016-09-15 18:35:27 +0000181FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () {
182 return new CFGOnlyPrinterLegacyPass();
Brian Gaeke104341f2004-04-26 16:27:08 +0000183}
184