1 //===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // 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.
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
19 //===----------------------------------------------------------------------===//
21 #include "llvm/Analysis/CFGPrinter.h"
22 #include "llvm/Pass.h"
23 #include "llvm/Support/FileSystem.h"
26 static 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."));
31 static cl::opt
<std::string
> CFGDotFilenamePrefix(
32 "cfg-dot-filename-prefix", cl::Hidden
,
33 cl::desc("The prefix used for the CFG dot file names."));
36 struct CFGViewerLegacyPass
: public FunctionPass
{
37 static char ID
; // Pass identifcation, replacement for typeid
38 CFGViewerLegacyPass() : FunctionPass(ID
) {
39 initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
42 bool runOnFunction(Function
&F
) override
{
47 void print(raw_ostream
&OS
, const Module
* = nullptr) const override
{}
49 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
55 char CFGViewerLegacyPass::ID
= 0;
56 INITIALIZE_PASS(CFGViewerLegacyPass
, "view-cfg", "View CFG of function", false, true)
58 PreservedAnalyses
CFGViewerPass::run(Function
&F
,
59 FunctionAnalysisManager
&AM
) {
61 return PreservedAnalyses::all();
66 struct CFGOnlyViewerLegacyPass
: public FunctionPass
{
67 static char ID
; // Pass identifcation, replacement for typeid
68 CFGOnlyViewerLegacyPass() : FunctionPass(ID
) {
69 initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
72 bool runOnFunction(Function
&F
) override
{
77 void print(raw_ostream
&OS
, const Module
* = nullptr) const override
{}
79 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
85 char CFGOnlyViewerLegacyPass::ID
= 0;
86 INITIALIZE_PASS(CFGOnlyViewerLegacyPass
, "view-cfg-only",
87 "View CFG of function (with no function bodies)", false, true)
89 PreservedAnalyses
CFGOnlyViewerPass::run(Function
&F
,
90 FunctionAnalysisManager
&AM
) {
92 return PreservedAnalyses::all();
95 static void writeCFGToDotFile(Function
&F
, bool CFGOnly
= false) {
96 if (!CFGFuncName
.empty() && !F
.getName().contains(CFGFuncName
))
98 std::string Filename
=
99 (CFGDotFilenamePrefix
+ "." + F
.getName() + ".dot").str();
100 errs() << "Writing '" << Filename
<< "'...";
103 raw_fd_ostream
File(Filename
, EC
, sys::fs::F_Text
);
106 WriteGraph(File
, (const Function
*)&F
, CFGOnly
);
108 errs() << " error opening file for writing!";
113 struct CFGPrinterLegacyPass
: public FunctionPass
{
114 static char ID
; // Pass identification, replacement for typeid
115 CFGPrinterLegacyPass() : FunctionPass(ID
) {
116 initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
119 bool runOnFunction(Function
&F
) override
{
120 writeCFGToDotFile(F
);
124 void print(raw_ostream
&OS
, const Module
* = nullptr) const override
{}
126 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
127 AU
.setPreservesAll();
132 char CFGPrinterLegacyPass::ID
= 0;
133 INITIALIZE_PASS(CFGPrinterLegacyPass
, "dot-cfg", "Print CFG of function to 'dot' file",
136 PreservedAnalyses
CFGPrinterPass::run(Function
&F
,
137 FunctionAnalysisManager
&AM
) {
138 writeCFGToDotFile(F
);
139 return PreservedAnalyses::all();
143 struct CFGOnlyPrinterLegacyPass
: public FunctionPass
{
144 static char ID
; // Pass identification, replacement for typeid
145 CFGOnlyPrinterLegacyPass() : FunctionPass(ID
) {
146 initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
149 bool runOnFunction(Function
&F
) override
{
150 writeCFGToDotFile(F
, /*CFGOnly=*/true);
153 void print(raw_ostream
&OS
, const Module
* = nullptr) const override
{}
155 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
156 AU
.setPreservesAll();
161 char CFGOnlyPrinterLegacyPass::ID
= 0;
162 INITIALIZE_PASS(CFGOnlyPrinterLegacyPass
, "dot-cfg-only",
163 "Print CFG of function to 'dot' file (with no function bodies)",
166 PreservedAnalyses
CFGOnlyPrinterPass::run(Function
&F
,
167 FunctionAnalysisManager
&AM
) {
168 writeCFGToDotFile(F
, /*CFGOnly=*/true);
169 return PreservedAnalyses::all();
172 /// 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.
177 void Function::viewCFG() const {
178 if (!CFGFuncName
.empty() && !getName().contains(CFGFuncName
))
180 ViewGraph(this, "cfg" + getName());
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
185 /// into the nodes, just the label. If you are only interested in the CFG
186 /// this can make the graph smaller.
188 void Function::viewCFGOnly() const {
189 if (!CFGFuncName
.empty() && !getName().contains(CFGFuncName
))
191 ViewGraph(this, "cfg" + getName(), true);
194 FunctionPass
*llvm::createCFGPrinterLegacyPassPass () {
195 return new CFGPrinterLegacyPass();
198 FunctionPass
*llvm::createCFGOnlyPrinterLegacyPassPass () {
199 return new CFGOnlyPrinterLegacyPass();