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
20c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke#include "llvm/Analysis/CFGPrinter.h"
2188067b9133103de3bfadd4f5166f4fb082ba2496Chris Lattner#include "llvm/Pass.h"
22dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/Support/FileSystem.h"
231ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattnerusing namespace llvm;
24d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
25002362c837ecf2e68008789a42c9634bb951491fChris Lattnernamespace {
266726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky  struct CFGViewer : public FunctionPass {
27a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    static char ID; // Pass identifcation, replacement for typeid
28081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    CFGViewer() : FunctionPass(ID) {
29081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson      initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry());
30081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    }
311cee94f04111cfd7114979d6dfddce2669c9380dDevang Patel
3236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool runOnFunction(Function &F) override {
33a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman      F.viewCFG();
34a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman      return false;
35a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    }
36a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
37dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    void print(raw_ostream &OS, const Module* = nullptr) const override {}
38a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
3936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void getAnalysisUsage(AnalysisUsage &AU) const override {
40a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman      AU.setPreservesAll();
41a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    }
42a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman  };
43844731a7f1909f55935e3514c9e713a62d67662eDan Gohman}
44a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
45844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanchar CFGViewer::ID = 0;
46ce665bd2e2b581ab0858d1afe359192bac96b868Owen AndersonINITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true)
47a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
48844731a7f1909f55935e3514c9e713a62d67662eDan Gohmannamespace {
496726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky  struct CFGOnlyViewer : public FunctionPass {
50a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    static char ID; // Pass identifcation, replacement for typeid
51081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    CFGOnlyViewer() : FunctionPass(ID) {
52081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson      initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry());
53081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    }
541cee94f04111cfd7114979d6dfddce2669c9380dDevang Patel
5536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool runOnFunction(Function &F) override {
56ad3893678172e7b22a6d4ef3e6387b8d773aa1c7Duncan Sands      F.viewCFGOnly();
57a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman      return false;
58a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    }
59a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
60dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    void print(raw_ostream &OS, const Module* = nullptr) const override {}
61a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
6236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void getAnalysisUsage(AnalysisUsage &AU) const override {
63a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman      AU.setPreservesAll();
64a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman    }
65a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman  };
66844731a7f1909f55935e3514c9e713a62d67662eDan Gohman}
67a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
68844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanchar CFGOnlyViewer::ID = 0;
69d8cc7be0262092882d848a1c7d8a4cb6752cce6fOwen AndersonINITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only",
70ce665bd2e2b581ab0858d1afe359192bac96b868Owen Anderson                "View CFG of function (with no function bodies)", false, true)
71a196b993e0b79142c6388c75b71f1fc54c767dd1Dan Gohman
72844731a7f1909f55935e3514c9e713a62d67662eDan Gohmannamespace {
736726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky  struct CFGPrinter : public FunctionPass {
74ecd94c804a563f2a86572dcf1d2e81f397e19daaNick Lewycky    static char ID; // Pass identification, replacement for typeid
75081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    CFGPrinter() : FunctionPass(ID) {
76081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson      initializeCFGPrinterPass(*PassRegistry::getPassRegistry());
77081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    }
781cee94f04111cfd7114979d6dfddce2669c9380dDevang Patel
7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool runOnFunction(Function &F) override {
800c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      std::string Filename = ("cfg." + F.getName() + ".dot").str();
81103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      errs() << "Writing '" << Filename << "'...";
822b37d7cf28b1382420b5e4007042feeb66d21ac8Misha Brukman
8337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      std::error_code EC;
8437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
8537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
8637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      if (!EC)
87002362c837ecf2e68008789a42c9634bb951491fChris Lattner        WriteGraph(File, (const Function*)&F);
88002362c837ecf2e68008789a42c9634bb951491fChris Lattner      else
89103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner        errs() << "  error opening file for writing!";
90103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      errs() << "\n";
91002362c837ecf2e68008789a42c9634bb951491fChris Lattner      return false;
92002362c837ecf2e68008789a42c9634bb951491fChris Lattner    }
93002362c837ecf2e68008789a42c9634bb951491fChris Lattner
94dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    void print(raw_ostream &OS, const Module* = nullptr) const override {}
952b37d7cf28b1382420b5e4007042feeb66d21ac8Misha Brukman
9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void getAnalysisUsage(AnalysisUsage &AU) const override {
97002362c837ecf2e68008789a42c9634bb951491fChris Lattner      AU.setPreservesAll();
98002362c837ecf2e68008789a42c9634bb951491fChris Lattner    }
99002362c837ecf2e68008789a42c9634bb951491fChris Lattner  };
100844731a7f1909f55935e3514c9e713a62d67662eDan Gohman}
101002362c837ecf2e68008789a42c9634bb951491fChris Lattner
102844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanchar CFGPrinter::ID = 0;
10302dd53e1c5b941ca5f60fca1b95ebcaf9ccd1dfcOwen AndersonINITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file",
104ce665bd2e2b581ab0858d1afe359192bac96b868Owen Anderson                false, true)
1051ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner
106844731a7f1909f55935e3514c9e713a62d67662eDan Gohmannamespace {
1076726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky  struct CFGOnlyPrinter : public FunctionPass {
108ecd94c804a563f2a86572dcf1d2e81f397e19daaNick Lewycky    static char ID; // Pass identification, replacement for typeid
109081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    CFGOnlyPrinter() : FunctionPass(ID) {
110081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson      initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry());
111081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    }
11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool runOnFunction(Function &F) override {
1140c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar      std::string Filename = ("cfg." + F.getName() + ".dot").str();
115103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      errs() << "Writing '" << Filename << "'...";
1168cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson
11737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      std::error_code EC;
11837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
11937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
12037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      if (!EC)
1218cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson        WriteGraph(File, (const Function*)&F, true);
1228cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson      else
123103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner        errs() << "  error opening file for writing!";
124103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner      errs() << "\n";
1251ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner      return false;
1261ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner    }
127dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    void print(raw_ostream &OS, const Module* = nullptr) const override {}
1282b37d7cf28b1382420b5e4007042feeb66d21ac8Misha Brukman
12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void getAnalysisUsage(AnalysisUsage &AU) const override {
1301ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner      AU.setPreservesAll();
1311ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner    }
1321ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner  };
1331ca2a583cb234cc8b26710e0f2ff68da2b6d24cdChris Lattner}
134002362c837ecf2e68008789a42c9634bb951491fChris Lattner
135844731a7f1909f55935e3514c9e713a62d67662eDan Gohmanchar CFGOnlyPrinter::ID = 0;
13602dd53e1c5b941ca5f60fca1b95ebcaf9ccd1dfcOwen AndersonINITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only",
13702dd53e1c5b941ca5f60fca1b95ebcaf9ccd1dfcOwen Anderson   "Print CFG of function to 'dot' file (with no function bodies)",
138ce665bd2e2b581ab0858d1afe359192bac96b868Owen Anderson   false, true)
139844731a7f1909f55935e3514c9e713a62d67662eDan Gohman
140002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// viewCFG - This function is meant for use from the debugger.  You can just
141002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// say 'call F->viewCFG()' and a ghostview window should pop up from the
142002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// program, displaying the CFG of the current function.  This depends on there
143002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// being a 'dot' and 'gv' program in your path.
144002362c837ecf2e68008789a42c9634bb951491fChris Lattner///
145002362c837ecf2e68008789a42c9634bb951491fChris Lattnervoid Function::viewCFG() const {
14625ad1cc32af8d526eb72893a513a486bc28c5106Benjamin Kramer  ViewGraph(this, "cfg" + getName());
147002362c837ecf2e68008789a42c9634bb951491fChris Lattner}
148002362c837ecf2e68008789a42c9634bb951491fChris Lattner
149002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// viewCFGOnly - This function is meant for use from the debugger.  It works
150002362c837ecf2e68008789a42c9634bb951491fChris Lattner/// just like viewCFG, but it does not include the contents of basic blocks
151dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// into the nodes, just the label.  If you are only interested in the CFG
152dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines/// this can make the graph smaller.
153002362c837ecf2e68008789a42c9634bb951491fChris Lattner///
154002362c837ecf2e68008789a42c9634bb951491fChris Lattnervoid Function::viewCFGOnly() const {
15525ad1cc32af8d526eb72893a513a486bc28c5106Benjamin Kramer  ViewGraph(this, "cfg" + getName(), true);
156002362c837ecf2e68008789a42c9634bb951491fChris Lattner}
157c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke
158c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian GaekeFunctionPass *llvm::createCFGPrinterPass () {
159c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke  return new CFGPrinter();
160c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke}
161c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke
162c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian GaekeFunctionPass *llvm::createCFGOnlyPrinterPass () {
163c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke  return new CFGOnlyPrinter();
164c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke}
165c6e2d8a2ffc04084dcf4a96e56aca155856aed92Brian Gaeke
166