blob: c86f1f55954b7764a8bdf2a7da23c2053ae69256 [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 {
Nick Lewycky02d5f772009-10-25 06:33:48 +000026 struct CFGViewer : public FunctionPass {
Dan Gohman90d97ac2007-05-14 14:25:08 +000027 static char ID; // Pass identifcation, replacement for typeid
Owen Anderson6c18d1a2010-10-19 17:21:58 +000028 CFGViewer() : FunctionPass(ID) {
29 initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry());
30 }
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
Dan Gohmand78c4002008-05-13 00:00:25 +000045char CFGViewer::ID = 0;
Owen Andersondf7a4f22010-10-07 22:25:06 +000046INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true)
Dan Gohman90d97ac2007-05-14 14:25:08 +000047
Dan Gohmand78c4002008-05-13 00:00:25 +000048namespace {
Nick Lewycky02d5f772009-10-25 06:33:48 +000049 struct CFGOnlyViewer : public FunctionPass {
Dan Gohman90d97ac2007-05-14 14:25:08 +000050 static char ID; // Pass identifcation, replacement for typeid
Owen Anderson6c18d1a2010-10-19 17:21:58 +000051 CFGOnlyViewer() : FunctionPass(ID) {
52 initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry());
53 }
Devang Patel864970e2008-03-18 00:39:19 +000054
Craig Toppere9ba7592014-03-05 07:30:04 +000055 bool runOnFunction(Function &F) override {
Duncan Sands1636b7e2009-09-19 11:25:44 +000056 F.viewCFGOnly();
Dan Gohman90d97ac2007-05-14 14:25:08 +000057 return false;
58 }
59
Craig Topper9f008862014-04-15 04:59:12 +000060 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Dan Gohman90d97ac2007-05-14 14:25:08 +000061
Craig Toppere9ba7592014-03-05 07:30:04 +000062 void getAnalysisUsage(AnalysisUsage &AU) const override {
Dan Gohman90d97ac2007-05-14 14:25:08 +000063 AU.setPreservesAll();
64 }
65 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +000066}
Dan Gohman90d97ac2007-05-14 14:25:08 +000067
Dan Gohmand78c4002008-05-13 00:00:25 +000068char CFGOnlyViewer::ID = 0;
Owen Andersonac4a1ed2010-07-21 23:07:00 +000069INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only",
Owen Andersondf7a4f22010-10-07 22:25:06 +000070 "View CFG of function (with no function bodies)", false, true)
Dan Gohman90d97ac2007-05-14 14:25:08 +000071
Dan Gohmand78c4002008-05-13 00:00:25 +000072namespace {
Nick Lewycky02d5f772009-10-25 06:33:48 +000073 struct CFGPrinter : public FunctionPass {
Nick Lewyckye7da2d62007-05-06 13:37:16 +000074 static char ID; // Pass identification, replacement for typeid
Owen Anderson6c18d1a2010-10-19 17:21:58 +000075 CFGPrinter() : FunctionPass(ID) {
76 initializeCFGPrinterPass(*PassRegistry::getPassRegistry());
77 }
Devang Patel864970e2008-03-18 00:39:19 +000078
Craig Toppere9ba7592014-03-05 07:30:04 +000079 bool runOnFunction(Function &F) override {
Yaron Keren75e0c4b2015-03-27 17:51:30 +000080 std::string Filename = ("cfg." + F.getName() + ".dot").str();
Chris Lattner4883d902009-08-23 07:19:13 +000081 errs() << "Writing '" << Filename << "'...";
Misha Brukman01808ca2005-04-21 21:13:18 +000082
Rafael Espindola3fd1e992014-08-25 18:16:47 +000083 std::error_code EC;
84 raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
85
86 if (!EC)
Chris Lattnera93d11b2003-10-22 16:03:49 +000087 WriteGraph(File, (const Function*)&F);
88 else
Chris Lattner4883d902009-08-23 07:19:13 +000089 errs() << " error opening file for writing!";
90 errs() << "\n";
Chris Lattnera93d11b2003-10-22 16:03:49 +000091 return false;
92 }
93
Craig Topper9f008862014-04-15 04:59:12 +000094 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Misha Brukman01808ca2005-04-21 21:13:18 +000095
Craig Toppere9ba7592014-03-05 07:30:04 +000096 void getAnalysisUsage(AnalysisUsage &AU) const override {
Chris Lattnera93d11b2003-10-22 16:03:49 +000097 AU.setPreservesAll();
98 }
99 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000100}
Chris Lattnera93d11b2003-10-22 16:03:49 +0000101
Dan Gohmand78c4002008-05-13 00:00:25 +0000102char CFGPrinter::ID = 0;
Owen Andersond31d82d2010-08-23 17:52:01 +0000103INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000104 false, true)
Chris Lattner62aff842003-12-11 21:48:18 +0000105
Dan Gohmand78c4002008-05-13 00:00:25 +0000106namespace {
Nick Lewycky02d5f772009-10-25 06:33:48 +0000107 struct CFGOnlyPrinter : public FunctionPass {
Nick Lewyckye7da2d62007-05-06 13:37:16 +0000108 static char ID; // Pass identification, replacement for typeid
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000109 CFGOnlyPrinter() : FunctionPass(ID) {
110 initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry());
111 }
Craig Toppere9ba7592014-03-05 07:30:04 +0000112
113 bool runOnFunction(Function &F) override {
Yaron Keren75e0c4b2015-03-27 17:51:30 +0000114 std::string Filename = ("cfg." + F.getName() + ".dot").str();
Chris Lattner4883d902009-08-23 07:19:13 +0000115 errs() << "Writing '" << Filename << "'...";
Owen Andersonb70adf22009-06-24 17:37:09 +0000116
Rafael Espindola3fd1e992014-08-25 18:16:47 +0000117 std::error_code EC;
118 raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
119
120 if (!EC)
Owen Andersonb70adf22009-06-24 17:37:09 +0000121 WriteGraph(File, (const Function*)&F, true);
122 else
Chris Lattner4883d902009-08-23 07:19:13 +0000123 errs() << " error opening file for writing!";
124 errs() << "\n";
Chris Lattner62aff842003-12-11 21:48:18 +0000125 return false;
126 }
Craig Topper9f008862014-04-15 04:59:12 +0000127 void print(raw_ostream &OS, const Module* = nullptr) const override {}
Misha Brukman01808ca2005-04-21 21:13:18 +0000128
Craig Toppere9ba7592014-03-05 07:30:04 +0000129 void getAnalysisUsage(AnalysisUsage &AU) const override {
Chris Lattner62aff842003-12-11 21:48:18 +0000130 AU.setPreservesAll();
131 }
132 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000133}
Chris Lattnera93d11b2003-10-22 16:03:49 +0000134
Dan Gohmand78c4002008-05-13 00:00:25 +0000135char CFGOnlyPrinter::ID = 0;
Owen Andersond31d82d2010-08-23 17:52:01 +0000136INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only",
137 "Print CFG of function to 'dot' file (with no function bodies)",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000138 false, true)
Dan Gohmand78c4002008-05-13 00:00:25 +0000139
Chris Lattnera93d11b2003-10-22 16:03:49 +0000140/// viewCFG - This function is meant for use from the debugger. You can just
141/// say 'call F->viewCFG()' and a ghostview window should pop up from the
142/// program, displaying the CFG of the current function. This depends on there
143/// being a 'dot' and 'gv' program in your path.
144///
145void Function::viewCFG() const {
Benjamin Kramer4c93d152011-11-15 16:26:38 +0000146 ViewGraph(this, "cfg" + getName());
Chris Lattnera93d11b2003-10-22 16:03:49 +0000147}
148
149/// viewCFGOnly - This function is meant for use from the debugger. It works
150/// just like viewCFG, but it does not include the contents of basic blocks
Eric Christopher650c8f22014-05-20 17:11:11 +0000151/// into the nodes, just the label. If you are only interested in the CFG
152/// this can make the graph smaller.
Chris Lattnera93d11b2003-10-22 16:03:49 +0000153///
154void Function::viewCFGOnly() const {
Benjamin Kramer4c93d152011-11-15 16:26:38 +0000155 ViewGraph(this, "cfg" + getName(), true);
Chris Lattnera93d11b2003-10-22 16:03:49 +0000156}
Brian Gaeke104341f2004-04-26 16:27:08 +0000157
158FunctionPass *llvm::createCFGPrinterPass () {
159 return new CFGPrinter();
160}
161
162FunctionPass *llvm::createCFGOnlyPrinterPass () {
163 return new CFGOnlyPrinter();
164}
165