• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines a '-dot-cfg' analysis pass, which emits the
11 // 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 
20 #include "llvm/Analysis/CFGPrinter.h"
21 #include "llvm/Pass.h"
22 #include "llvm/Support/FileSystem.h"
23 using namespace llvm;
24 
25 namespace {
26   struct CFGViewer : public FunctionPass {
27     static char ID; // Pass identifcation, replacement for typeid
CFGViewer__anon0fe2cb9e0111::CFGViewer28     CFGViewer() : FunctionPass(ID) {
29       initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry());
30     }
31 
runOnFunction__anon0fe2cb9e0111::CFGViewer32     bool runOnFunction(Function &F) override {
33       F.viewCFG();
34       return false;
35     }
36 
print__anon0fe2cb9e0111::CFGViewer37     void print(raw_ostream &OS, const Module* = nullptr) const override {}
38 
getAnalysisUsage__anon0fe2cb9e0111::CFGViewer39     void getAnalysisUsage(AnalysisUsage &AU) const override {
40       AU.setPreservesAll();
41     }
42   };
43 }
44 
45 char CFGViewer::ID = 0;
46 INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true)
47 
48 namespace {
49   struct CFGOnlyViewer : public FunctionPass {
50     static char ID; // Pass identifcation, replacement for typeid
CFGOnlyViewer__anon0fe2cb9e0211::CFGOnlyViewer51     CFGOnlyViewer() : FunctionPass(ID) {
52       initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry());
53     }
54 
runOnFunction__anon0fe2cb9e0211::CFGOnlyViewer55     bool runOnFunction(Function &F) override {
56       F.viewCFGOnly();
57       return false;
58     }
59 
print__anon0fe2cb9e0211::CFGOnlyViewer60     void print(raw_ostream &OS, const Module* = nullptr) const override {}
61 
getAnalysisUsage__anon0fe2cb9e0211::CFGOnlyViewer62     void getAnalysisUsage(AnalysisUsage &AU) const override {
63       AU.setPreservesAll();
64     }
65   };
66 }
67 
68 char CFGOnlyViewer::ID = 0;
69 INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only",
70                 "View CFG of function (with no function bodies)", false, true)
71 
72 namespace {
73   struct CFGPrinter : public FunctionPass {
74     static char ID; // Pass identification, replacement for typeid
CFGPrinter__anon0fe2cb9e0311::CFGPrinter75     CFGPrinter() : FunctionPass(ID) {
76       initializeCFGPrinterPass(*PassRegistry::getPassRegistry());
77     }
78 
runOnFunction__anon0fe2cb9e0311::CFGPrinter79     bool runOnFunction(Function &F) override {
80       std::string Filename = ("cfg." + F.getName() + ".dot").str();
81       errs() << "Writing '" << Filename << "'...";
82 
83       std::error_code EC;
84       raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
85 
86       if (!EC)
87         WriteGraph(File, (const Function*)&F);
88       else
89         errs() << "  error opening file for writing!";
90       errs() << "\n";
91       return false;
92     }
93 
print__anon0fe2cb9e0311::CFGPrinter94     void print(raw_ostream &OS, const Module* = nullptr) const override {}
95 
getAnalysisUsage__anon0fe2cb9e0311::CFGPrinter96     void getAnalysisUsage(AnalysisUsage &AU) const override {
97       AU.setPreservesAll();
98     }
99   };
100 }
101 
102 char CFGPrinter::ID = 0;
103 INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file",
104                 false, true)
105 
106 namespace {
107   struct CFGOnlyPrinter : public FunctionPass {
108     static char ID; // Pass identification, replacement for typeid
CFGOnlyPrinter__anon0fe2cb9e0411::CFGOnlyPrinter109     CFGOnlyPrinter() : FunctionPass(ID) {
110       initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry());
111     }
112 
runOnFunction__anon0fe2cb9e0411::CFGOnlyPrinter113     bool runOnFunction(Function &F) override {
114       std::string Filename = ("cfg." + F.getName() + ".dot").str();
115       errs() << "Writing '" << Filename << "'...";
116 
117       std::error_code EC;
118       raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
119 
120       if (!EC)
121         WriteGraph(File, (const Function*)&F, true);
122       else
123         errs() << "  error opening file for writing!";
124       errs() << "\n";
125       return false;
126     }
print__anon0fe2cb9e0411::CFGOnlyPrinter127     void print(raw_ostream &OS, const Module* = nullptr) const override {}
128 
getAnalysisUsage__anon0fe2cb9e0411::CFGOnlyPrinter129     void getAnalysisUsage(AnalysisUsage &AU) const override {
130       AU.setPreservesAll();
131     }
132   };
133 }
134 
135 char CFGOnlyPrinter::ID = 0;
136 INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only",
137    "Print CFG of function to 'dot' file (with no function bodies)",
138    false, true)
139 
140 /// 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 ///
viewCFG() const145 void Function::viewCFG() const {
146   ViewGraph(this, "cfg" + getName());
147 }
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
151 /// into the nodes, just the label.  If you are only interested in the CFG
152 /// this can make the graph smaller.
153 ///
viewCFGOnly() const154 void Function::viewCFGOnly() const {
155   ViewGraph(this, "cfg" + getName(), true);
156 }
157 
createCFGPrinterPass()158 FunctionPass *llvm::createCFGPrinterPass () {
159   return new CFGPrinter();
160 }
161 
createCFGOnlyPrinterPass()162 FunctionPass *llvm::createCFGOnlyPrinterPass () {
163   return new CFGOnlyPrinter();
164 }
165 
166