From: Chris Lattner Date: Mon, 7 Oct 2002 18:38:01 +0000 (+0000) Subject: - Implement a new -print-cfg option for analyze, that causes it to print the X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ac859db3e4dcfe0626dd7ed4b7a3c54a34986381;p=oota-llvm.git - Implement a new -print-cfg option for analyze, that causes it to print the CFG of each function in the module to 'dot' files. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4062 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/tools/analyze/GraphPrinters.cpp b/tools/analyze/GraphPrinters.cpp new file mode 100644 index 00000000000..35bff565a1f --- /dev/null +++ b/tools/analyze/GraphPrinters.cpp @@ -0,0 +1,88 @@ +//===- GraphPrinters.cpp - DOT printers for various graph types -----------===// +// +// This file defines several printers for various different types of graphs used +// by the LLVM infrastructure. It uses the generic graph interface to convert +// the graph into a .dot graph. These graphs can then be processed with the +// "dot" tool to convert them to postscript or some other suitable format. +// +//===----------------------------------------------------------------------===// + +#include "Support/GraphWriter.h" +#include "llvm/Pass.h" +#include "llvm/iTerminators.h" +#include "llvm/Support/CFG.h" +#include +#include + +template<> +struct DOTGraphTraits : public DefaultDOTGraphTraits { + static std::string getGraphName(Function *F) { + return "CFG for '" + F->getName() + "' function"; + } + + static std::string getNodeLabel(BasicBlock *Node, Function *Graph) { + std::ostringstream Out; + Out << Node; + std::string OutStr = Out.str(); + if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); + + // Process string output to make it nicer... + for (unsigned i = 0; i != OutStr.length(); ++i) + if (OutStr[i] == '\n') { // Left justify + OutStr[i] = '\\'; + OutStr.insert(OutStr.begin()+i+1, 'l'); + } else if (OutStr[i] == ';') { // Delete comments! + unsigned Idx = OutStr.find('\n', i+1); // Find end of line + OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); + --i; + } + + return OutStr; + } + + static std::string getNodeAttributes(BasicBlock *N) { + return "fontname=Courier"; + } + + static std::string getEdgeSourceLabel(BasicBlock *Node, succ_iterator I) { + // Label source of conditional branches with "T" or "F" + if (BranchInst *BI = dyn_cast(Node->getTerminator())) + if (BI->isConditional()) + return (I == succ_begin(Node)) ? "T" : "F"; + return ""; + } +}; + +template +static void WriteGraphToFile(std::ostream &O, const std::string &GraphName, + const GraphType >) { + std::string Filename = GraphName + ".dot"; + O << "Writing '" << Filename << "'..."; + std::ofstream F(Filename.c_str()); + + if (F.good()) + WriteGraph(F, GT); + else + O << " error opening file for writing!"; + O << "\n"; +} + + +namespace { + struct CFGPrinter : public FunctionPass { + Function *F; + virtual bool runOnFunction(Function &Func) { + WriteGraphToFile(std::cerr, "cfg."+Func.getName(), &Func); + return false; + } + + void print(std::ostream &OS) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; + + RegisterAnalysis P1("print-cfg", + "Print CFG of function to 'dot' file"); +}; diff --git a/tools/opt/GraphPrinters.cpp b/tools/opt/GraphPrinters.cpp new file mode 100644 index 00000000000..35bff565a1f --- /dev/null +++ b/tools/opt/GraphPrinters.cpp @@ -0,0 +1,88 @@ +//===- GraphPrinters.cpp - DOT printers for various graph types -----------===// +// +// This file defines several printers for various different types of graphs used +// by the LLVM infrastructure. It uses the generic graph interface to convert +// the graph into a .dot graph. These graphs can then be processed with the +// "dot" tool to convert them to postscript or some other suitable format. +// +//===----------------------------------------------------------------------===// + +#include "Support/GraphWriter.h" +#include "llvm/Pass.h" +#include "llvm/iTerminators.h" +#include "llvm/Support/CFG.h" +#include +#include + +template<> +struct DOTGraphTraits : public DefaultDOTGraphTraits { + static std::string getGraphName(Function *F) { + return "CFG for '" + F->getName() + "' function"; + } + + static std::string getNodeLabel(BasicBlock *Node, Function *Graph) { + std::ostringstream Out; + Out << Node; + std::string OutStr = Out.str(); + if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); + + // Process string output to make it nicer... + for (unsigned i = 0; i != OutStr.length(); ++i) + if (OutStr[i] == '\n') { // Left justify + OutStr[i] = '\\'; + OutStr.insert(OutStr.begin()+i+1, 'l'); + } else if (OutStr[i] == ';') { // Delete comments! + unsigned Idx = OutStr.find('\n', i+1); // Find end of line + OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); + --i; + } + + return OutStr; + } + + static std::string getNodeAttributes(BasicBlock *N) { + return "fontname=Courier"; + } + + static std::string getEdgeSourceLabel(BasicBlock *Node, succ_iterator I) { + // Label source of conditional branches with "T" or "F" + if (BranchInst *BI = dyn_cast(Node->getTerminator())) + if (BI->isConditional()) + return (I == succ_begin(Node)) ? "T" : "F"; + return ""; + } +}; + +template +static void WriteGraphToFile(std::ostream &O, const std::string &GraphName, + const GraphType >) { + std::string Filename = GraphName + ".dot"; + O << "Writing '" << Filename << "'..."; + std::ofstream F(Filename.c_str()); + + if (F.good()) + WriteGraph(F, GT); + else + O << " error opening file for writing!"; + O << "\n"; +} + + +namespace { + struct CFGPrinter : public FunctionPass { + Function *F; + virtual bool runOnFunction(Function &Func) { + WriteGraphToFile(std::cerr, "cfg."+Func.getName(), &Func); + return false; + } + + void print(std::ostream &OS) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; + + RegisterAnalysis P1("print-cfg", + "Print CFG of function to 'dot' file"); +};