LLVM API Documentation

CFGPrinter.cpp

Go to the documentation of this file.
00001 //===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines a '-dot-cfg' analysis pass, which emits the
00011 // cfg.<fnname>.dot file for each function in the program, with a graph of the
00012 // CFG for that function.
00013 //
00014 // The other main feature of this file is that it implements the
00015 // Function::viewCFG method, which is useful for debugging passes which operate
00016 // on the CFG.
00017 //
00018 //===----------------------------------------------------------------------===//
00019 
00020 #include "llvm/Function.h"
00021 #include "llvm/Instructions.h"
00022 #include "llvm/Pass.h"
00023 #include "llvm/Analysis/CFGPrinter.h"
00024 #include "llvm/Assembly/Writer.h"
00025 #include "llvm/Support/CFG.h"
00026 #include "llvm/Support/Compiler.h"
00027 #include "llvm/Support/GraphWriter.h"
00028 #include "llvm/Config/config.h"
00029 #include <iosfwd>
00030 #include <sstream>
00031 #include <fstream>
00032 using namespace llvm;
00033 
00034 /// CFGOnly flag - This is used to control whether or not the CFG graph printer
00035 /// prints out the contents of basic blocks or not.  This is acceptable because
00036 /// this code is only really used for debugging purposes.
00037 ///
00038 static bool CFGOnly = false;
00039 
00040 namespace llvm {
00041 template<>
00042 struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
00043   static std::string getGraphName(const Function *F) {
00044     return "CFG for '" + F->getName() + "' function";
00045   }
00046 
00047   static std::string getNodeLabel(const BasicBlock *Node,
00048                                   const Function *Graph) {
00049     if (CFGOnly && !Node->getName().empty())
00050       return Node->getName() + ":";
00051 
00052     std::ostringstream Out;
00053     if (CFGOnly) {
00054       WriteAsOperand(Out, Node, false);
00055       return Out.str();
00056     }
00057 
00058     if (Node->getName().empty()) {
00059       WriteAsOperand(Out, Node, false);
00060       Out << ":";
00061     }
00062 
00063     Out << *Node;
00064     std::string OutStr = Out.str();
00065     if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
00066 
00067     // Process string output to make it nicer...
00068     for (unsigned i = 0; i != OutStr.length(); ++i)
00069       if (OutStr[i] == '\n') {                            // Left justify
00070         OutStr[i] = '\\';
00071         OutStr.insert(OutStr.begin()+i+1, 'l');
00072       } else if (OutStr[i] == ';') {                      // Delete comments!
00073         unsigned Idx = OutStr.find('\n', i+1);            // Find end of line
00074         OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx);
00075         --i;
00076       }
00077 
00078     return OutStr;
00079   }
00080 
00081   static std::string getEdgeSourceLabel(const BasicBlock *Node,
00082                                         succ_const_iterator I) {
00083     // Label source of conditional branches with "T" or "F"
00084     if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator()))
00085       if (BI->isConditional())
00086         return (I == succ_begin(Node)) ? "T" : "F";
00087     return "";
00088   }
00089 };
00090 }
00091 
00092 namespace {
00093   struct VISIBILITY_HIDDEN CFGViewer : public FunctionPass {
00094     static char ID; // Pass identifcation, replacement for typeid
00095     CFGViewer() : FunctionPass(&ID) {}
00096 
00097     virtual bool runOnFunction(Function &F) {
00098       F.viewCFG();
00099       return false;
00100     }
00101 
00102     void print(std::ostream &OS, const Module* = 0) const {}
00103 
00104     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
00105       AU.setPreservesAll();
00106     }
00107   };
00108 }
00109 
00110 char CFGViewer::ID = 0;
00111 static RegisterPass<CFGViewer>
00112 V0("view-cfg", "View CFG of function", false, true);
00113 
00114 namespace {
00115   struct VISIBILITY_HIDDEN CFGOnlyViewer : public FunctionPass {
00116     static char ID; // Pass identifcation, replacement for typeid
00117     CFGOnlyViewer() : FunctionPass(&ID) {}
00118 
00119     virtual bool runOnFunction(Function &F) {
00120       CFGOnly = true;
00121       F.viewCFG();
00122       CFGOnly = false;
00123       return false;
00124     }
00125 
00126     void print(std::ostream &OS, const Module* = 0) const {}
00127 
00128     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
00129       AU.setPreservesAll();
00130     }
00131   };
00132 }
00133 
00134 char CFGOnlyViewer::ID = 0;
00135 static RegisterPass<CFGOnlyViewer>
00136 V1("view-cfg-only",
00137    "View CFG of function (with no function bodies)", false, true);
00138 
00139 namespace {
00140   struct VISIBILITY_HIDDEN CFGPrinter : public FunctionPass {
00141     static char ID; // Pass identification, replacement for typeid
00142     CFGPrinter() : FunctionPass(&ID) {}
00143     explicit CFGPrinter(void *pid) : FunctionPass(pid) {}
00144 
00145     virtual bool runOnFunction(Function &F) {
00146       std::string Filename = "cfg." + F.getName() + ".dot";
00147       cerr << "Writing '" << Filename << "'...";
00148       std::ofstream File(Filename.c_str());
00149 
00150       if (File.good())
00151         WriteGraph(File, (const Function*)&F);
00152       else
00153         cerr << "  error opening file for writing!";
00154       cerr << "\n";
00155       return false;
00156     }
00157 
00158     void print(std::ostream &OS, const Module* = 0) const {}
00159 
00160     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
00161       AU.setPreservesAll();
00162     }
00163   };
00164 }
00165 
00166 char CFGPrinter::ID = 0;
00167 static RegisterPass<CFGPrinter>
00168 P1("dot-cfg", "Print CFG of function to 'dot' file", false, true);
00169 
00170 namespace {
00171   struct VISIBILITY_HIDDEN CFGOnlyPrinter : public CFGPrinter {
00172     static char ID; // Pass identification, replacement for typeid
00173     CFGOnlyPrinter() : CFGPrinter(&ID) {}
00174     virtual bool runOnFunction(Function &F) {
00175       bool OldCFGOnly = CFGOnly;
00176       CFGOnly = true;
00177       CFGPrinter::runOnFunction(F);
00178       CFGOnly = OldCFGOnly;
00179       return false;
00180     }
00181     void print(std::ostream &OS, const Module* = 0) const {}
00182 
00183     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
00184       AU.setPreservesAll();
00185     }
00186   };
00187 }
00188 
00189 char CFGOnlyPrinter::ID = 0;
00190 static RegisterPass<CFGOnlyPrinter>
00191 P2("dot-cfg-only",
00192    "Print CFG of function to 'dot' file (with no function bodies)", false, true);
00193 
00194 /// viewCFG - This function is meant for use from the debugger.  You can just
00195 /// say 'call F->viewCFG()' and a ghostview window should pop up from the
00196 /// program, displaying the CFG of the current function.  This depends on there
00197 /// being a 'dot' and 'gv' program in your path.
00198 ///
00199 void Function::viewCFG() const {
00200   ViewGraph(this, "cfg" + getName());
00201 }
00202 
00203 /// viewCFGOnly - This function is meant for use from the debugger.  It works
00204 /// just like viewCFG, but it does not include the contents of basic blocks
00205 /// into the nodes, just the label.  If you are only interested in the CFG t
00206 /// his can make the graph smaller.
00207 ///
00208 void Function::viewCFGOnly() const {
00209   CFGOnly = true;
00210   viewCFG();
00211   CFGOnly = false;
00212 }
00213 
00214 FunctionPass *llvm::createCFGPrinterPass () {
00215   return new CFGPrinter();
00216 }
00217 
00218 FunctionPass *llvm::createCFGOnlyPrinterPass () {
00219   return new CFGOnlyPrinter();
00220 }
00221