CFGPrinter.cpp revision 8cbc94afb71fd2da72d8f1284f7f53e39019fdec
1002362c837ecf2e68008789a42c9634bb951491fChris Lattner//===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
22b37d7cf28b1382420b5e4007042feeb66d21ac8Misha Brukman//
3002362c837ecf2e68008789a42c9634bb951491fChris Lattner//                     The LLVM Compiler Infrastructure
4002362c837ecf2e68008789a42c9634bb951491fChris Lattner//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
72b37d7cf28b1382420b5e4007042feeb66d21ac8Misha Brukman//
8002362c837ecf2e68008789a42c9634bb951491fChris Lattner//===----------------------------------------------------------------------===//
9002362c837ecf2e68008789a42c9634bb951491fChris Lattner//
103ee8fc964952a65bcb3668b85938c46f90631e42Duncan Sands// This file defines a '-dot-cfg' analysis pass, which emits the
11002362c837ecf2e68008789a42c9634bb951491fChris Lattner// cfg.<fnname>.dot file for each function in the program, with a graph of the
12002362c837ecf2e68008789a42c9634bb951491fChris Lattner// CFG for that function.
13002362c837ecf2e68008789a42c9634bb951491fChris Lattner//
14002362c837ecf2e68008789a42c9634bb951491fChris Lattner// The other main feature of this file is that it implements the
15002362c837ecf2e68008789a42c9634bb951491fChris Lattner// Function::viewCFG method, which is useful for debugging passes which operate
16002362c837ecf2e68008789a42c9634bb951491fChris Lattner// on the CFG.
17002362c837ecf2e68008789a42c9634bb951491fChris Lattner//
18002362c837ecf2e68008789a42c9634bb951491fChris Lattner//===----------------------------------------------------------------------===//
19002362c837ecf2e68008789a42c9634bb951491fChris Lattner
20002362c837ecf2e68008789a42c9634bb951491fChris Lattner#include "llvm/Function.h"
2147b14a4a6a455c7be169cfd312fcbe796f0ad426Misha Brukman#include "llvm/Instructions.h"
22bf94a1e22a20faf34c3f30b5503a2d2bbb8106baMisha Brukman#include "llvm/Pass.h"
23c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke#include "llvm/Analysis/CFGPrinter.h"
24bf94a1e22a20faf34c3f30b5503a2d2bbb8106baMisha Brukman#include "llvm/Assembly/Writer.h"
25002362c837ecf2e68008789a42c9634bb951491fChris Lattner#include "llvm/Support/CFG.h"
26d7d83db5f22d05e5b14b6b1d838668222113c83aReid Spencer#include "llvm/Support/Compiler.h"
27551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/GraphWriter.h"
28b06f677c5399d13392f0d9561b76c10f97dbf85aChris Lattner#include "llvm/Config/config.h"
296f81b510217bd87f265cca054c5d9885250d8525Bill Wendling#include <iosfwd>
30002362c837ecf2e68008789a42c9634bb951491fChris Lattner#include <sstream>
31002362c837ecf2e68008789a42c9634bb951491fChris Lattner#include <fstream>
321ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattnerusing namespace llvm;
33d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
341ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattnernamespace llvm {
35002362c837ecf2e68008789a42c9634bb951491fChris Lattnertemplate<>
36002362c837ecf2e68008789a42c9634bb951491fChris Lattnerstruct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
37002362c837ecf2e68008789a42c9634bb951491fChris Lattner  static std::string getGraphName(const Function *F) {
38002362c837ecf2e68008789a42c9634bb951491fChris Lattner    return "CFG for '" + F->getName() + "' function";
39002362c837ecf2e68008789a42c9634bb951491fChris Lattner  }
40002362c837ecf2e68008789a42c9634bb951491fChris Lattner
41002362c837ecf2e68008789a42c9634bb951491fChris Lattner  static std::string getNodeLabel(const BasicBlock *Node,
428cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson                                  const Function *Graph,
438cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson                                  bool ShortNames) {
448cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson    if (ShortNames && !Node->getName().empty())
45d073ea00535614323aafd36e3e71582311089700Chris Lattner      return Node->getName() + ":";
46002362c837ecf2e68008789a42c9634bb951491fChris Lattner
47002362c837ecf2e68008789a42c9634bb951491fChris Lattner    std::ostringstream Out;
488cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson    if (ShortNames) {
493749c9cae41d2e682f67a41b07e0c50b46dbb000Chris Lattner      WriteAsOperand(Out, Node, false);
50a75b3ef9a8b1c88a362eed65f7527d0dc1e54b54Chris Lattner      return Out.str();
51a75b3ef9a8b1c88a362eed65f7527d0dc1e54b54Chris Lattner    }
52a75b3ef9a8b1c88a362eed65f7527d0dc1e54b54Chris Lattner
53d073ea00535614323aafd36e3e71582311089700Chris Lattner    if (Node->getName().empty()) {
543749c9cae41d2e682f67a41b07e0c50b46dbb000Chris Lattner      WriteAsOperand(Out, Node, false);
55d073ea00535614323aafd36e3e71582311089700Chris Lattner      Out << ":";
56d073ea00535614323aafd36e3e71582311089700Chris Lattner    }
57d073ea00535614323aafd36e3e71582311089700Chris Lattner
58002362c837ecf2e68008789a42c9634bb951491fChris Lattner    Out << *Node;
59002362c837ecf2e68008789a42c9634bb951491fChris Lattner    std::string OutStr = Out.str();
60002362c837ecf2e68008789a42c9634bb951491fChris Lattner    if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
61002362c837ecf2e68008789a42c9634bb951491fChris Lattner
62002362c837ecf2e68008789a42c9634bb951491fChris Lattner    // Process string output to make it nicer...
63002362c837ecf2e68008789a42c9634bb951491fChris Lattner    for (unsigned i = 0; i != OutStr.length(); ++i)
64002362c837ecf2e68008789a42c9634bb951491fChris Lattner      if (OutStr[i] == '\n') {                            // Left justify
65002362c837ecf2e68008789a42c9634bb951491fChris Lattner        OutStr[i] = '\\';
66002362c837ecf2e68008789a42c9634bb951491fChris Lattner        OutStr.insert(OutStr.begin()+i+1, 'l');
67002362c837ecf2e68008789a42c9634bb951491fChris Lattner      } else if (OutStr[i] == ';') {                      // Delete comments!
68002362c837ecf2e68008789a42c9634bb951491fChris Lattner        unsigned Idx = OutStr.find('\n', i+1);            // Find end of line
69002362c837ecf2e68008789a42c9634bb951491fChris Lattner        OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx);
70002362c837ecf2e68008789a42c9634bb951491fChris Lattner        --i;
71002362c837ecf2e68008789a42c9634bb951491fChris Lattner      }
72002362c837ecf2e68008789a42c9634bb951491fChris Lattner
73002362c837ecf2e68008789a42c9634bb951491fChris Lattner    return OutStr;
74002362c837ecf2e68008789a42c9634bb951491fChris Lattner  }
75002362c837ecf2e68008789a42c9634bb951491fChris Lattner
76002362c837ecf2e68008789a42c9634bb951491fChris Lattner  static std::string getEdgeSourceLabel(const BasicBlock *Node,
77002362c837ecf2e68008789a42c9634bb951491fChris Lattner                                        succ_const_iterator I) {
78002362c837ecf2e68008789a42c9634bb951491fChris Lattner    // Label source of conditional branches with "T" or "F"
79002362c837ecf2e68008789a42c9634bb951491fChris Lattner    if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator()))
80002362c837ecf2e68008789a42c9634bb951491fChris Lattner      if (BI->isConditional())
81002362c837ecf2e68008789a42c9634bb951491fChris Lattner        return (I == succ_begin(Node)) ? "T" : "F";
82002362c837ecf2e68008789a42c9634bb951491fChris Lattner    return "";
83002362c837ecf2e68008789a42c9634bb951491fChris Lattner  }
84002362c837ecf2e68008789a42c9634bb951491fChris Lattner};
851ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner}
86002362c837ecf2e68008789a42c9634bb951491fChris Lattner
87002362c837ecf2e68008789a42c9634bb951491fChris Lattnernamespace {
88a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman  struct VISIBILITY_HIDDEN CFGViewer : public FunctionPass {
89a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    static char ID; // Pass identifcation, replacement for typeid
90ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman    CFGViewer() : FunctionPass(&ID) {}
911cee94f04111cfd7114979d6dfddce2669c9380dDevang Patel
92a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    virtual bool runOnFunction(Function &F) {
93a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman      F.viewCFG();
94a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman      return false;
95a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    }
96a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
97a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    void print(std::ostream &OS, const Module* = 0) const {}
98a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
99a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
100a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman      AU.setPreservesAll();
101a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    }
102a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman  };
103844731a7f1909f55935e3514c9e713a62d67662eDan Gohman}
104a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
105844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanchar CFGViewer::ID = 0;
106844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanstatic RegisterPass<CFGViewer>
107844731a7f1909f55935e3514c9e713a62d67662eDan GohmanV0("view-cfg", "View CFG of function", false, true);
108a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
109844731a7f1909f55935e3514c9e713a62d67662eDan Gohmannamespace {
110a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman  struct VISIBILITY_HIDDEN CFGOnlyViewer : public FunctionPass {
111a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    static char ID; // Pass identifcation, replacement for typeid
112ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman    CFGOnlyViewer() : FunctionPass(&ID) {}
1131cee94f04111cfd7114979d6dfddce2669c9380dDevang Patel
114a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    virtual bool runOnFunction(Function &F) {
115a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman      F.viewCFG();
116a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman      return false;
117a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    }
118a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
119a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    void print(std::ostream &OS, const Module* = 0) const {}
120a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
121a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
122a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman      AU.setPreservesAll();
123a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    }
124a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman  };
125844731a7f1909f55935e3514c9e713a62d67662eDan Gohman}
126a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
127844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanchar CFGOnlyViewer::ID = 0;
128844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanstatic RegisterPass<CFGOnlyViewer>
129844731a7f1909f55935e3514c9e713a62d67662eDan GohmanV1("view-cfg-only",
130844731a7f1909f55935e3514c9e713a62d67662eDan Gohman   "View CFG of function (with no function bodies)", false, true);
131a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
132844731a7f1909f55935e3514c9e713a62d67662eDan Gohmannamespace {
133d7d83db5f22d05e5b14b6b1d838668222113c83aReid Spencer  struct VISIBILITY_HIDDEN CFGPrinter : public FunctionPass {
134ecd94c804a563f2a86572dcf1d2e81f397e19daaNick Lewycky    static char ID; // Pass identification, replacement for typeid
135ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman    CFGPrinter() : FunctionPass(&ID) {}
136ae73dc1448d25b02cabc7c64c86c64371453dda8Dan Gohman    explicit CFGPrinter(void *pid) : FunctionPass(pid) {}
1371cee94f04111cfd7114979d6dfddce2669c9380dDevang Patel
138002362c837ecf2e68008789a42c9634bb951491fChris Lattner    virtual bool runOnFunction(Function &F) {
139002362c837ecf2e68008789a42c9634bb951491fChris Lattner      std::string Filename = "cfg." + F.getName() + ".dot";
140e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling      cerr << "Writing '" << Filename << "'...";
141002362c837ecf2e68008789a42c9634bb951491fChris Lattner      std::ofstream File(Filename.c_str());
1422b37d7cf28b1382420b5e4007042feeb66d21ac8Misha Brukman
143002362c837ecf2e68008789a42c9634bb951491fChris Lattner      if (File.good())
144002362c837ecf2e68008789a42c9634bb951491fChris Lattner        WriteGraph(File, (const Function*)&F);
145002362c837ecf2e68008789a42c9634bb951491fChris Lattner      else
146e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling        cerr << "  error opening file for writing!";
147e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling      cerr << "\n";
148002362c837ecf2e68008789a42c9634bb951491fChris Lattner      return false;
149002362c837ecf2e68008789a42c9634bb951491fChris Lattner    }
150002362c837ecf2e68008789a42c9634bb951491fChris Lattner
151ce9653ce449f1409815547e1bf60abcd1332d2c9Reid Spencer    void print(std::ostream &OS, const Module* = 0) const {}
1522b37d7cf28b1382420b5e4007042feeb66d21ac8Misha Brukman
153002362c837ecf2e68008789a42c9634bb951491fChris Lattner    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
154002362c837ecf2e68008789a42c9634bb951491fChris Lattner      AU.setPreservesAll();
155002362c837ecf2e68008789a42c9634bb951491fChris Lattner    }
156002362c837ecf2e68008789a42c9634bb951491fChris Lattner  };
157844731a7f1909f55935e3514c9e713a62d67662eDan Gohman}
158002362c837ecf2e68008789a42c9634bb951491fChris Lattner
159844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanchar CFGPrinter::ID = 0;
160844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanstatic RegisterPass<CFGPrinter>
1613ee8fc964952a65bcb3668b85938c46f90631e42Duncan SandsP1("dot-cfg", "Print CFG of function to 'dot' file", false, true);
1621ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner
163844731a7f1909f55935e3514c9e713a62d67662eDan Gohmannamespace {
1648cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson  struct VISIBILITY_HIDDEN CFGOnlyPrinter : public FunctionPass {
165ecd94c804a563f2a86572dcf1d2e81f397e19daaNick Lewycky    static char ID; // Pass identification, replacement for typeid
1668cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson    CFGOnlyPrinter() : FunctionPass(&ID) {}
1678cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson    explicit CFGOnlyPrinter(void *pid) : FunctionPass(pid) {}
1681ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner    virtual bool runOnFunction(Function &F) {
1698cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson      std::string Filename = "cfg." + F.getName() + ".dot";
1708cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson      cerr << "Writing '" << Filename << "'...";
1718cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson      std::ofstream File(Filename.c_str());
1728cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson
1738cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson      if (File.good())
1748cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson        WriteGraph(File, (const Function*)&F, true);
1758cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson      else
1768cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson        cerr << "  error opening file for writing!";
1778cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson      cerr << "\n";
1781ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner      return false;
1791ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner    }
180ce9653ce449f1409815547e1bf60abcd1332d2c9Reid Spencer    void print(std::ostream &OS, const Module* = 0) const {}
1812b37d7cf28b1382420b5e4007042feeb66d21ac8Misha Brukman
1821ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
1831ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner      AU.setPreservesAll();
1841ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner    }
1851ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner  };
1861ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner}
187002362c837ecf2e68008789a42c9634bb951491fChris Lattner
188844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanchar CFGOnlyPrinter::ID = 0;
189844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanstatic RegisterPass<CFGOnlyPrinter>
1903ee8fc964952a65bcb3668b85938c46f90631e42Duncan SandsP2("dot-cfg-only",
191844731a7f1909f55935e3514c9e713a62d67662eDan Gohman   "Print CFG of function to 'dot' file (with no function bodies)", false, true);
192844731a7f1909f55935e3514c9e713a62d67662eDan Gohman
193002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// viewCFG - This function is meant for use from the debugger.  You can just
194002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// say 'call F->viewCFG()' and a ghostview window should pop up from the
195002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// program, displaying the CFG of the current function.  This depends on there
196002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// being a 'dot' and 'gv' program in your path.
197002362c837ecf2e68008789a42c9634bb951491fChris Lattner///
198002362c837ecf2e68008789a42c9634bb951491fChris Lattnervoid Function::viewCFG() const {
1999d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer  ViewGraph(this, "cfg" + getName());
200002362c837ecf2e68008789a42c9634bb951491fChris Lattner}
201002362c837ecf2e68008789a42c9634bb951491fChris Lattner
202002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// viewCFGOnly - This function is meant for use from the debugger.  It works
203002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// just like viewCFG, but it does not include the contents of basic blocks
204002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// into the nodes, just the label.  If you are only interested in the CFG t
205002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// his can make the graph smaller.
206002362c837ecf2e68008789a42c9634bb951491fChris Lattner///
207002362c837ecf2e68008789a42c9634bb951491fChris Lattnervoid Function::viewCFGOnly() const {
2088cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson  ViewGraph(this, "cfg" + getName(), true);
209002362c837ecf2e68008789a42c9634bb951491fChris Lattner}
210c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke
211c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian GaekeFunctionPass *llvm::createCFGPrinterPass () {
212c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke  return new CFGPrinter();
213c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke}
214c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke
215c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian GaekeFunctionPass *llvm::createCFGOnlyPrinterPass () {
216c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke  return new CFGOnlyPrinter();
217c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke}
218c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke
219