1*9880d681SAndroid Build Coastguard Worker //===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file defines a '-dot-cfg' analysis pass, which emits the
11*9880d681SAndroid Build Coastguard Worker // cfg.<fnname>.dot file for each function in the program, with a graph of the
12*9880d681SAndroid Build Coastguard Worker // CFG for that function.
13*9880d681SAndroid Build Coastguard Worker //
14*9880d681SAndroid Build Coastguard Worker // The other main feature of this file is that it implements the
15*9880d681SAndroid Build Coastguard Worker // Function::viewCFG method, which is useful for debugging passes which operate
16*9880d681SAndroid Build Coastguard Worker // on the CFG.
17*9880d681SAndroid Build Coastguard Worker //
18*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
19*9880d681SAndroid Build Coastguard Worker
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/CFGPrinter.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileSystem.h"
23*9880d681SAndroid Build Coastguard Worker using namespace llvm;
24*9880d681SAndroid Build Coastguard Worker
25*9880d681SAndroid Build Coastguard Worker namespace {
26*9880d681SAndroid Build Coastguard Worker struct CFGViewer : public FunctionPass {
27*9880d681SAndroid Build Coastguard Worker static char ID; // Pass identifcation, replacement for typeid
CFGViewer__anon9228af6f0111::CFGViewer28*9880d681SAndroid Build Coastguard Worker CFGViewer() : FunctionPass(ID) {
29*9880d681SAndroid Build Coastguard Worker initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry());
30*9880d681SAndroid Build Coastguard Worker }
31*9880d681SAndroid Build Coastguard Worker
runOnFunction__anon9228af6f0111::CFGViewer32*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &F) override {
33*9880d681SAndroid Build Coastguard Worker F.viewCFG();
34*9880d681SAndroid Build Coastguard Worker return false;
35*9880d681SAndroid Build Coastguard Worker }
36*9880d681SAndroid Build Coastguard Worker
print__anon9228af6f0111::CFGViewer37*9880d681SAndroid Build Coastguard Worker void print(raw_ostream &OS, const Module* = nullptr) const override {}
38*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage__anon9228af6f0111::CFGViewer39*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
40*9880d681SAndroid Build Coastguard Worker AU.setPreservesAll();
41*9880d681SAndroid Build Coastguard Worker }
42*9880d681SAndroid Build Coastguard Worker };
43*9880d681SAndroid Build Coastguard Worker }
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker char CFGViewer::ID = 0;
46*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true)
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker namespace {
49*9880d681SAndroid Build Coastguard Worker struct CFGOnlyViewer : public FunctionPass {
50*9880d681SAndroid Build Coastguard Worker static char ID; // Pass identifcation, replacement for typeid
CFGOnlyViewer__anon9228af6f0211::CFGOnlyViewer51*9880d681SAndroid Build Coastguard Worker CFGOnlyViewer() : FunctionPass(ID) {
52*9880d681SAndroid Build Coastguard Worker initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry());
53*9880d681SAndroid Build Coastguard Worker }
54*9880d681SAndroid Build Coastguard Worker
runOnFunction__anon9228af6f0211::CFGOnlyViewer55*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &F) override {
56*9880d681SAndroid Build Coastguard Worker F.viewCFGOnly();
57*9880d681SAndroid Build Coastguard Worker return false;
58*9880d681SAndroid Build Coastguard Worker }
59*9880d681SAndroid Build Coastguard Worker
print__anon9228af6f0211::CFGOnlyViewer60*9880d681SAndroid Build Coastguard Worker void print(raw_ostream &OS, const Module* = nullptr) const override {}
61*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage__anon9228af6f0211::CFGOnlyViewer62*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
63*9880d681SAndroid Build Coastguard Worker AU.setPreservesAll();
64*9880d681SAndroid Build Coastguard Worker }
65*9880d681SAndroid Build Coastguard Worker };
66*9880d681SAndroid Build Coastguard Worker }
67*9880d681SAndroid Build Coastguard Worker
68*9880d681SAndroid Build Coastguard Worker char CFGOnlyViewer::ID = 0;
69*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only",
70*9880d681SAndroid Build Coastguard Worker "View CFG of function (with no function bodies)", false, true)
71*9880d681SAndroid Build Coastguard Worker
72*9880d681SAndroid Build Coastguard Worker namespace {
73*9880d681SAndroid Build Coastguard Worker struct CFGPrinter : public FunctionPass {
74*9880d681SAndroid Build Coastguard Worker static char ID; // Pass identification, replacement for typeid
CFGPrinter__anon9228af6f0311::CFGPrinter75*9880d681SAndroid Build Coastguard Worker CFGPrinter() : FunctionPass(ID) {
76*9880d681SAndroid Build Coastguard Worker initializeCFGPrinterPass(*PassRegistry::getPassRegistry());
77*9880d681SAndroid Build Coastguard Worker }
78*9880d681SAndroid Build Coastguard Worker
runOnFunction__anon9228af6f0311::CFGPrinter79*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &F) override {
80*9880d681SAndroid Build Coastguard Worker std::string Filename = ("cfg." + F.getName() + ".dot").str();
81*9880d681SAndroid Build Coastguard Worker errs() << "Writing '" << Filename << "'...";
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker std::error_code EC;
84*9880d681SAndroid Build Coastguard Worker raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker if (!EC)
87*9880d681SAndroid Build Coastguard Worker WriteGraph(File, (const Function*)&F);
88*9880d681SAndroid Build Coastguard Worker else
89*9880d681SAndroid Build Coastguard Worker errs() << " error opening file for writing!";
90*9880d681SAndroid Build Coastguard Worker errs() << "\n";
91*9880d681SAndroid Build Coastguard Worker return false;
92*9880d681SAndroid Build Coastguard Worker }
93*9880d681SAndroid Build Coastguard Worker
print__anon9228af6f0311::CFGPrinter94*9880d681SAndroid Build Coastguard Worker void print(raw_ostream &OS, const Module* = nullptr) const override {}
95*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage__anon9228af6f0311::CFGPrinter96*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
97*9880d681SAndroid Build Coastguard Worker AU.setPreservesAll();
98*9880d681SAndroid Build Coastguard Worker }
99*9880d681SAndroid Build Coastguard Worker };
100*9880d681SAndroid Build Coastguard Worker }
101*9880d681SAndroid Build Coastguard Worker
102*9880d681SAndroid Build Coastguard Worker char CFGPrinter::ID = 0;
103*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file",
104*9880d681SAndroid Build Coastguard Worker false, true)
105*9880d681SAndroid Build Coastguard Worker
106*9880d681SAndroid Build Coastguard Worker namespace {
107*9880d681SAndroid Build Coastguard Worker struct CFGOnlyPrinter : public FunctionPass {
108*9880d681SAndroid Build Coastguard Worker static char ID; // Pass identification, replacement for typeid
CFGOnlyPrinter__anon9228af6f0411::CFGOnlyPrinter109*9880d681SAndroid Build Coastguard Worker CFGOnlyPrinter() : FunctionPass(ID) {
110*9880d681SAndroid Build Coastguard Worker initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry());
111*9880d681SAndroid Build Coastguard Worker }
112*9880d681SAndroid Build Coastguard Worker
runOnFunction__anon9228af6f0411::CFGOnlyPrinter113*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &F) override {
114*9880d681SAndroid Build Coastguard Worker std::string Filename = ("cfg." + F.getName() + ".dot").str();
115*9880d681SAndroid Build Coastguard Worker errs() << "Writing '" << Filename << "'...";
116*9880d681SAndroid Build Coastguard Worker
117*9880d681SAndroid Build Coastguard Worker std::error_code EC;
118*9880d681SAndroid Build Coastguard Worker raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker if (!EC)
121*9880d681SAndroid Build Coastguard Worker WriteGraph(File, (const Function*)&F, true);
122*9880d681SAndroid Build Coastguard Worker else
123*9880d681SAndroid Build Coastguard Worker errs() << " error opening file for writing!";
124*9880d681SAndroid Build Coastguard Worker errs() << "\n";
125*9880d681SAndroid Build Coastguard Worker return false;
126*9880d681SAndroid Build Coastguard Worker }
print__anon9228af6f0411::CFGOnlyPrinter127*9880d681SAndroid Build Coastguard Worker void print(raw_ostream &OS, const Module* = nullptr) const override {}
128*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage__anon9228af6f0411::CFGOnlyPrinter129*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
130*9880d681SAndroid Build Coastguard Worker AU.setPreservesAll();
131*9880d681SAndroid Build Coastguard Worker }
132*9880d681SAndroid Build Coastguard Worker };
133*9880d681SAndroid Build Coastguard Worker }
134*9880d681SAndroid Build Coastguard Worker
135*9880d681SAndroid Build Coastguard Worker char CFGOnlyPrinter::ID = 0;
136*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only",
137*9880d681SAndroid Build Coastguard Worker "Print CFG of function to 'dot' file (with no function bodies)",
138*9880d681SAndroid Build Coastguard Worker false, true)
139*9880d681SAndroid Build Coastguard Worker
140*9880d681SAndroid Build Coastguard Worker /// viewCFG - This function is meant for use from the debugger. You can just
141*9880d681SAndroid Build Coastguard Worker /// say 'call F->viewCFG()' and a ghostview window should pop up from the
142*9880d681SAndroid Build Coastguard Worker /// program, displaying the CFG of the current function. This depends on there
143*9880d681SAndroid Build Coastguard Worker /// being a 'dot' and 'gv' program in your path.
144*9880d681SAndroid Build Coastguard Worker ///
viewCFG() const145*9880d681SAndroid Build Coastguard Worker void Function::viewCFG() const {
146*9880d681SAndroid Build Coastguard Worker ViewGraph(this, "cfg" + getName());
147*9880d681SAndroid Build Coastguard Worker }
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker /// viewCFGOnly - This function is meant for use from the debugger. It works
150*9880d681SAndroid Build Coastguard Worker /// just like viewCFG, but it does not include the contents of basic blocks
151*9880d681SAndroid Build Coastguard Worker /// into the nodes, just the label. If you are only interested in the CFG
152*9880d681SAndroid Build Coastguard Worker /// this can make the graph smaller.
153*9880d681SAndroid Build Coastguard Worker ///
viewCFGOnly() const154*9880d681SAndroid Build Coastguard Worker void Function::viewCFGOnly() const {
155*9880d681SAndroid Build Coastguard Worker ViewGraph(this, "cfg" + getName(), true);
156*9880d681SAndroid Build Coastguard Worker }
157*9880d681SAndroid Build Coastguard Worker
createCFGPrinterPass()158*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createCFGPrinterPass () {
159*9880d681SAndroid Build Coastguard Worker return new CFGPrinter();
160*9880d681SAndroid Build Coastguard Worker }
161*9880d681SAndroid Build Coastguard Worker
createCFGOnlyPrinterPass()162*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createCFGOnlyPrinterPass () {
163*9880d681SAndroid Build Coastguard Worker return new CFGOnlyPrinter();
164*9880d681SAndroid Build Coastguard Worker }
165*9880d681SAndroid Build Coastguard Worker
166