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