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