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