CFGPrinter.cpp revision 193323
1193323Sed//===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file defines a '-dot-cfg' analysis pass, which emits the
11193323Sed// cfg.<fnname>.dot file for each function in the program, with a graph of the
12193323Sed// CFG for that function.
13193323Sed//
14193323Sed// The other main feature of this file is that it implements the
15193323Sed// Function::viewCFG method, which is useful for debugging passes which operate
16193323Sed// on the CFG.
17193323Sed//
18193323Sed//===----------------------------------------------------------------------===//
19193323Sed
20193323Sed#include "llvm/Function.h"
21193323Sed#include "llvm/Instructions.h"
22193323Sed#include "llvm/Pass.h"
23193323Sed#include "llvm/Analysis/CFGPrinter.h"
24193323Sed#include "llvm/Assembly/Writer.h"
25193323Sed#include "llvm/Support/CFG.h"
26193323Sed#include "llvm/Support/Compiler.h"
27193323Sed#include "llvm/Support/GraphWriter.h"
28193323Sed#include "llvm/Config/config.h"
29193323Sed#include <iosfwd>
30193323Sed#include <sstream>
31193323Sed#include <fstream>
32193323Sedusing namespace llvm;
33193323Sed
34193323Sed/// CFGOnly flag - This is used to control whether or not the CFG graph printer
35193323Sed/// prints out the contents of basic blocks or not.  This is acceptable because
36193323Sed/// this code is only really used for debugging purposes.
37193323Sed///
38193323Sedstatic bool CFGOnly = false;
39193323Sed
40193323Sednamespace llvm {
41193323Sedtemplate<>
42193323Sedstruct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
43193323Sed  static std::string getGraphName(const Function *F) {
44193323Sed    return "CFG for '" + F->getName() + "' function";
45193323Sed  }
46193323Sed
47193323Sed  static std::string getNodeLabel(const BasicBlock *Node,
48193323Sed                                  const Function *Graph) {
49193323Sed    if (CFGOnly && !Node->getName().empty())
50193323Sed      return Node->getName() + ":";
51193323Sed
52193323Sed    std::ostringstream Out;
53193323Sed    if (CFGOnly) {
54193323Sed      WriteAsOperand(Out, Node, false);
55193323Sed      return Out.str();
56193323Sed    }
57193323Sed
58193323Sed    if (Node->getName().empty()) {
59193323Sed      WriteAsOperand(Out, Node, false);
60193323Sed      Out << ":";
61193323Sed    }
62193323Sed
63193323Sed    Out << *Node;
64193323Sed    std::string OutStr = Out.str();
65193323Sed    if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
66193323Sed
67193323Sed    // Process string output to make it nicer...
68193323Sed    for (unsigned i = 0; i != OutStr.length(); ++i)
69193323Sed      if (OutStr[i] == '\n') {                            // Left justify
70193323Sed        OutStr[i] = '\\';
71193323Sed        OutStr.insert(OutStr.begin()+i+1, 'l');
72193323Sed      } else if (OutStr[i] == ';') {                      // Delete comments!
73193323Sed        unsigned Idx = OutStr.find('\n', i+1);            // Find end of line
74193323Sed        OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx);
75193323Sed        --i;
76193323Sed      }
77193323Sed
78193323Sed    return OutStr;
79193323Sed  }
80193323Sed
81193323Sed  static std::string getEdgeSourceLabel(const BasicBlock *Node,
82193323Sed                                        succ_const_iterator I) {
83193323Sed    // Label source of conditional branches with "T" or "F"
84193323Sed    if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator()))
85193323Sed      if (BI->isConditional())
86193323Sed        return (I == succ_begin(Node)) ? "T" : "F";
87193323Sed    return "";
88193323Sed  }
89193323Sed};
90193323Sed}
91193323Sed
92193323Sednamespace {
93193323Sed  struct VISIBILITY_HIDDEN CFGViewer : public FunctionPass {
94193323Sed    static char ID; // Pass identifcation, replacement for typeid
95193323Sed    CFGViewer() : FunctionPass(&ID) {}
96193323Sed
97193323Sed    virtual bool runOnFunction(Function &F) {
98193323Sed      F.viewCFG();
99193323Sed      return false;
100193323Sed    }
101193323Sed
102193323Sed    void print(std::ostream &OS, const Module* = 0) const {}
103193323Sed
104193323Sed    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
105193323Sed      AU.setPreservesAll();
106193323Sed    }
107193323Sed  };
108193323Sed}
109193323Sed
110193323Sedchar CFGViewer::ID = 0;
111193323Sedstatic RegisterPass<CFGViewer>
112193323SedV0("view-cfg", "View CFG of function", false, true);
113193323Sed
114193323Sednamespace {
115193323Sed  struct VISIBILITY_HIDDEN CFGOnlyViewer : public FunctionPass {
116193323Sed    static char ID; // Pass identifcation, replacement for typeid
117193323Sed    CFGOnlyViewer() : FunctionPass(&ID) {}
118193323Sed
119193323Sed    virtual bool runOnFunction(Function &F) {
120193323Sed      CFGOnly = true;
121193323Sed      F.viewCFG();
122193323Sed      CFGOnly = false;
123193323Sed      return false;
124193323Sed    }
125193323Sed
126193323Sed    void print(std::ostream &OS, const Module* = 0) const {}
127193323Sed
128193323Sed    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
129193323Sed      AU.setPreservesAll();
130193323Sed    }
131193323Sed  };
132193323Sed}
133193323Sed
134193323Sedchar CFGOnlyViewer::ID = 0;
135193323Sedstatic RegisterPass<CFGOnlyViewer>
136193323SedV1("view-cfg-only",
137193323Sed   "View CFG of function (with no function bodies)", false, true);
138193323Sed
139193323Sednamespace {
140193323Sed  struct VISIBILITY_HIDDEN CFGPrinter : public FunctionPass {
141193323Sed    static char ID; // Pass identification, replacement for typeid
142193323Sed    CFGPrinter() : FunctionPass(&ID) {}
143193323Sed    explicit CFGPrinter(void *pid) : FunctionPass(pid) {}
144193323Sed
145193323Sed    virtual bool runOnFunction(Function &F) {
146193323Sed      std::string Filename = "cfg." + F.getName() + ".dot";
147193323Sed      cerr << "Writing '" << Filename << "'...";
148193323Sed      std::ofstream File(Filename.c_str());
149193323Sed
150193323Sed      if (File.good())
151193323Sed        WriteGraph(File, (const Function*)&F);
152193323Sed      else
153193323Sed        cerr << "  error opening file for writing!";
154193323Sed      cerr << "\n";
155193323Sed      return false;
156193323Sed    }
157193323Sed
158193323Sed    void print(std::ostream &OS, const Module* = 0) const {}
159193323Sed
160193323Sed    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
161193323Sed      AU.setPreservesAll();
162193323Sed    }
163193323Sed  };
164193323Sed}
165193323Sed
166193323Sedchar CFGPrinter::ID = 0;
167193323Sedstatic RegisterPass<CFGPrinter>
168193323SedP1("dot-cfg", "Print CFG of function to 'dot' file", false, true);
169193323Sed
170193323Sednamespace {
171193323Sed  struct VISIBILITY_HIDDEN CFGOnlyPrinter : public CFGPrinter {
172193323Sed    static char ID; // Pass identification, replacement for typeid
173193323Sed    CFGOnlyPrinter() : CFGPrinter(&ID) {}
174193323Sed    virtual bool runOnFunction(Function &F) {
175193323Sed      bool OldCFGOnly = CFGOnly;
176193323Sed      CFGOnly = true;
177193323Sed      CFGPrinter::runOnFunction(F);
178193323Sed      CFGOnly = OldCFGOnly;
179193323Sed      return false;
180193323Sed    }
181193323Sed    void print(std::ostream &OS, const Module* = 0) const {}
182193323Sed
183193323Sed    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
184193323Sed      AU.setPreservesAll();
185193323Sed    }
186193323Sed  };
187193323Sed}
188193323Sed
189193323Sedchar CFGOnlyPrinter::ID = 0;
190193323Sedstatic RegisterPass<CFGOnlyPrinter>
191193323SedP2("dot-cfg-only",
192193323Sed   "Print CFG of function to 'dot' file (with no function bodies)", false, true);
193193323Sed
194193323Sed/// viewCFG - This function is meant for use from the debugger.  You can just
195193323Sed/// say 'call F->viewCFG()' and a ghostview window should pop up from the
196193323Sed/// program, displaying the CFG of the current function.  This depends on there
197193323Sed/// being a 'dot' and 'gv' program in your path.
198193323Sed///
199193323Sedvoid Function::viewCFG() const {
200193323Sed  ViewGraph(this, "cfg" + getName());
201193323Sed}
202193323Sed
203193323Sed/// viewCFGOnly - This function is meant for use from the debugger.  It works
204193323Sed/// just like viewCFG, but it does not include the contents of basic blocks
205193323Sed/// into the nodes, just the label.  If you are only interested in the CFG t
206193323Sed/// his can make the graph smaller.
207193323Sed///
208193323Sedvoid Function::viewCFGOnly() const {
209193323Sed  CFGOnly = true;
210193323Sed  viewCFG();
211193323Sed  CFGOnly = false;
212193323Sed}
213193323Sed
214193323SedFunctionPass *llvm::createCFGPrinterPass () {
215193323Sed  return new CFGPrinter();
216193323Sed}
217193323Sed
218193323SedFunctionPass *llvm::createCFGOnlyPrinterPass () {
219193323Sed  return new CFGOnlyPrinter();
220193323Sed}
221193323Sed
222