diff options
| -rw-r--r-- | llvm/include/llvm/CodeGen/MachineFunction.h | 66 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/MachineFunction.cpp | 78 | 
2 files changed, 143 insertions, 1 deletions
diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h index 2d36777d7a7..3a27fd7cdeb 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -135,6 +135,21 @@ public:    ///    void print(std::ostream &OS) const; +  /// viewCFG - This function is meant for use from the debugger.  You can just +  /// say 'call F->viewCFG()' and a ghostview window should pop up from the +  /// program, displaying the CFG of the current function with the code for each +  /// basic block inside.  This depends on there being a 'dot' and 'gv' program +  /// in your path. +  /// +  void viewCFG() const; +   +  /// viewCFGOnly - This function is meant for use from the debugger.  It works +  /// just like viewCFG, but it does not include the contents of basic blocks +  /// into the nodes, just the label.  If you are only interested in the CFG +  /// this can make the graph smaller. +  /// +  void viewCFGOnly() const; +    /// dump - Print the current MachineFunction to cerr, useful for debugger use.    ///    void dump() const; @@ -206,6 +221,57 @@ public:    }  }; +//===--------------------------------------------------------------------===// +// GraphTraits specializations for function basic block graphs (CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a +// machine function as a graph of machine basic blocks... these are +// the same as the machine basic block iterators, except that the root +// node is implicitly the first node of the function. +// +template <> struct GraphTraits<MachineFunction*> : +  public GraphTraits<MachineBasicBlock*> { +  static NodeType *getEntryNode(MachineFunction *F) { +    return &F->front(); +  } + +  // nodes_iterator/begin/end - Allow iteration over all nodes in the graph +  typedef MachineFunction::iterator nodes_iterator; +  static nodes_iterator nodes_begin(MachineFunction *F) { return F->begin(); } +  static nodes_iterator nodes_end  (MachineFunction *F) { return F->end(); } +}; +template <> struct GraphTraits<const MachineFunction*> : +  public GraphTraits<const MachineBasicBlock*> { +  static NodeType *getEntryNode(const MachineFunction *F) { +    return &F->front(); +  } + +  // nodes_iterator/begin/end - Allow iteration over all nodes in the graph +  typedef MachineFunction::const_iterator nodes_iterator; +  static nodes_iterator nodes_begin(const MachineFunction *F) { return F->begin(); } +  static nodes_iterator nodes_end  (const MachineFunction *F) { return F->end(); } +}; + + +// Provide specializations of GraphTraits to be able to treat a function as a  +// graph of basic blocks... and to walk it in inverse order.  Inverse order for +// a function is considered to be when traversing the predecessor edges of a BB +// instead of the successor edges. +// +template <> struct GraphTraits<Inverse<MachineFunction*> > : +  public GraphTraits<Inverse<MachineBasicBlock*> > { +  static NodeType *getEntryNode(Inverse<MachineFunction*> G) { +    return &G.Graph->front(); +  } +}; +template <> struct GraphTraits<Inverse<const MachineFunction*> > : +  public GraphTraits<Inverse<const MachineBasicBlock*> > { +  static NodeType *getEntryNode(Inverse<const MachineFunction *> G) { +    return &G.Graph->front(); +  } +}; +  } // End llvm namespace  #endif diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp index 520f1da9609..63785a301b9 100644 --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -26,7 +26,10 @@  #include "llvm/iOther.h"  #include "llvm/Type.h"  #include "Support/LeakDetector.h" +#include "Support/GraphWriter.h" +#include <fstream>  #include <iostream> +#include <sstream>  using namespace llvm; @@ -140,6 +143,80 @@ void MachineFunction::print(std::ostream &OS) const {    OS << "\n# End machine code for " << Fn->getName () << "().\n\n";  } +/// CFGOnly flag - This is used to control whether or not the CFG graph printer +/// prints out the contents of basic blocks or not.  This is acceptable because +/// this code is only really used for debugging purposes. +/// +static bool CFGOnly = false; + +namespace llvm { +template<> +struct DOTGraphTraits<const MachineFunction*> : public DefaultDOTGraphTraits { +  static std::string getGraphName(const MachineFunction *F) { +    return "CFG for '" + F->getFunction()->getName() + "' function"; +  } + +  static std::string getNodeLabel(const MachineBasicBlock *Node, +                                  const MachineFunction *Graph) { +    if (CFGOnly && Node->getBasicBlock() && +        !Node->getBasicBlock()->getName().empty()) +      return Node->getBasicBlock()->getName() + ":"; + +    std::ostringstream Out; +    if (CFGOnly) { +      Out << Node->getNumber() << ':'; +      return Out.str(); +    } + +    Node->print(Out); + +    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'); +      } +    return OutStr; +  } +}; +} + +void MachineFunction::viewCFG() const +{ +  std::string Filename = "/tmp/cfg." + getFunction()->getName() + ".dot"; +  std::cerr << "Writing '" << Filename << "'... "; +  std::ofstream F(Filename.c_str()); +   +  if (!F) { +    std::cerr << "  error opening file for writing!\n"; +    return; +  } + +  WriteGraph(F, this); +  F.close(); +  std::cerr << "\n"; + +  std::cerr << "Running 'dot' program... " << std::flush; +  if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename +              + " > /tmp/cfg.tempgraph.ps").c_str())) { +    std::cerr << "Error running dot: 'dot' not in path?\n"; +  } else { +    std::cerr << "\n"; +    system("gv /tmp/cfg.tempgraph.ps"); +  } +  system(("rm " + Filename + " /tmp/cfg.tempgraph.ps").c_str()); +} + +void MachineFunction::viewCFGOnly() const +{ +  CFGOnly = true; +  viewCFG(); +  CFGOnly = false; +} +  // The next two methods are used to construct and to retrieve  // the MachineCodeForFunction object for the given function.  // construct() -- Allocates and initializes for a given function and target @@ -405,4 +482,3 @@ MachineFunctionInfo::pushTempValue(unsigned size)  void MachineFunctionInfo::popAllTempValues() {    resetTmpAreaSize();            // clear tmp area to reuse  } -  | 

