Support for machine function cfg dot dump

Xinliang David Li xinliangli at gmail.com
Wed Jun 12 16:50:13 PDT 2013


The patch is attached.

David

On Wed, Jun 12, 2013 at 4:47 PM, Xinliang David Li <xinliangli at gmail.com> wrote:
> (this patch has been sitting in my computer collecting dust for a
> couple of months now, send it out before I forget about it).
>
>
> Currently only 'opt' driver supports CFG dump. The existing command line is :
>
> opt -<pass_arg> -dot-cfg ....
>
> The pass scheduler will inject the dot-cfg pass after <pass_arg> pass.
>
> However, this is not supported for neither 'clang' nor 'llc' driver.
>
> In fact, there is *no* support for Machine CFG dump at all.
>
> The following patch added the support to dump .dot CFG file for each
> function before/after each pass -- just like IR dump.
>
> The syntax is :
>
>     <driver> -dot-cfg-after=<pass-arg> ...
>     <driver> -dot-cfg-before=<pass-arg> ...
>
> The cfg printer is also enhanced to allow the pass name and order
> string to be included in the name.
>
> For instance,
>
>      opt -dot-cfg-after=gvn t.b ...  # t.b defines 'foo'
>
> It will create file cfg.foo.after.gvn.dot
>
> The new option is now unified across three drivers:
>
>     opt -O2 -dot-cfg-after=gvn t.bc -o to.bc
>     llc  -dot-cfg-before=machine-cp t.bc -o t.o
>     clang -mllvm -dot-cfg-before=...   [1]
>
>
> Brief descriptions of the changes:
>
> 1) The CFGPrinter code is templatized and refactored -- the main
> implementation is moved into CFGPrinterBase<..>
> 2) CFG and CFGOnly dumps are now unified into the same template class
> 3) For Function class, CFGPrinterT used -- which is derived from CFGPrinterBase
> 4) For MachineFunction, MachineCFGPrinterT is derived from CFGPrinterBase
> 5) To avoid creating dependency backwards from core to analysis, the
> cfgprinter is moved to Support, sitting in core.
>
>
> [1]. This currently does not work because Clang driver has a bug that
> it does not register driver scheduled pass names properly.  THis also
> blocks option -print-before|after from working with clang driver.  I
> have another patch for it.
>
>
> LLVM builds fine and regression test is ok.
>
> If the patch looks ok and useful, can someone help check this in?
>
> thanks,
>
> David
-------------- next part --------------
Index: include/llvm/InitializePasses.h
===================================================================
--- include/llvm/InitializePasses.h	(revision 183332)
+++ include/llvm/InitializePasses.h	(working copy)
@@ -88,6 +88,8 @@ void initializeCFGOnlyViewerPass(PassReg
 void initializeCFGPrinterPass(PassRegistry&);
 void initializeCFGSimplifyPassPass(PassRegistry&);
 void initializeCFGViewerPass(PassRegistry&);
+void initializeMachineCFGOnlyPrinterPass(PassRegistry&);
+void initializeMachineCFGPrinterPass(PassRegistry&);
 void initializeCalculateSpillWeightsPass(PassRegistry&);
 void initializeCallGraphAnalysisGroup(PassRegistry&);
 void initializeCodeGenPreparePass(PassRegistry&);
Index: include/llvm/Support/CFGPrinter.h
===================================================================
--- include/llvm/Support/CFGPrinter.h	(revision 177877)
+++ include/llvm/Support/CFGPrinter.h	(working copy)
@@ -15,6 +15,7 @@
 #ifndef LLVM_ANALYSIS_CFGPRINTER_H
 #define LLVM_ANALYSIS_CFGPRINTER_H
 
+#include "llvm/PassSupport.h"
 #include "llvm/Assembly/Writer.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
@@ -103,12 +104,42 @@ struct DOTGraphTraits<const Function*> :
     return "";
   }
 };
-} // End llvm namespace
 
-namespace llvm {
-  class FunctionPass;
-  FunctionPass *createCFGPrinterPass ();
-  FunctionPass *createCFGOnlyPrinterPass ();
+template <class FC, bool CFGOnly> struct CFGPrinterBase {
+  CFGPrinterBase(const PassInfo *P = 0, const char *O = 0) : PI(P), Order(O) {
+    assert(!PI == !Order);
+  }
+  bool run(FC *F) {
+    std::string Filename = "cfg." + F->template getName().str();
+    if (PI)
+      Filename = Filename + "." + Order + "." + PI->getPassArgument() + ".dot";
+    else
+      Filename += ".dot";
+    errs() << "Writing '" << Filename << "'...";
+
+    std::string ErrorInfo;
+    raw_fd_ostream File(Filename.c_str(), ErrorInfo);
+
+    if (ErrorInfo.empty())
+      WriteGraph(File, (const FC *)F, CFGOnly);
+    else
+      errs() << "  error opening file for writing!";
+
+    errs() << "\n";
+    return false;
+  }
+
+private:
+  const PassInfo *PI;
+  const char *Order;
+};
+
+class FunctionPass;
+FunctionPass *createCFGPrinterPass();
+FunctionPass *createCFGPrinterPass(const PassInfo *, const char *);
+FunctionPass *createCFGOnlyPrinterPass();
+FunctionPass *createMachineCFGPrinterPass(const PassInfo *, const char *);
+FunctionPass *createMachineCFGOnlyPrinterPass();
 } // End llvm namespace
 
 #endif
Index: include/llvm/Analysis/CFGPrinter.h
===================================================================
--- include/llvm/Analysis/CFGPrinter.h	(revision 183332)
+++ include/llvm/Analysis/CFGPrinter.h	(working copy)
@@ -1,114 +0,0 @@
-//===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines external functions that can be called to explicitly
-// instantiate the CFG printer.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_CFGPRINTER_H
-#define LLVM_ANALYSIS_CFGPRINTER_H
-
-#include "llvm/Assembly/Writer.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/Support/CFG.h"
-#include "llvm/Support/GraphWriter.h"
-
-namespace llvm {
-template<>
-struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
-
-  DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
-
-  static std::string getGraphName(const Function *F) {
-    return "CFG for '" + F->getName().str() + "' function";
-  }
-
-  static std::string getSimpleNodeLabel(const BasicBlock *Node,
-                                        const Function *) {
-    if (!Node->getName().empty())
-      return Node->getName().str();
-
-    std::string Str;
-    raw_string_ostream OS(Str);
-
-    WriteAsOperand(OS, Node, false);
-    return OS.str();
-  }
-
-  static std::string getCompleteNodeLabel(const BasicBlock *Node, 
-                                          const Function *) {
-    std::string Str;
-    raw_string_ostream OS(Str);
-
-    if (Node->getName().empty()) {
-      WriteAsOperand(OS, Node, false);
-      OS << ":";
-    }
-
-    OS << *Node;
-    std::string OutStr = OS.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;
-  }
-
-  std::string getNodeLabel(const BasicBlock *Node,
-                           const Function *Graph) {
-    if (isSimple())
-      return getSimpleNodeLabel(Node, Graph);
-    else
-      return getCompleteNodeLabel(Node, Graph);
-  }
-
-  static std::string getEdgeSourceLabel(const BasicBlock *Node,
-                                        succ_const_iterator I) {
-    // Label source of conditional branches with "T" or "F"
-    if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator()))
-      if (BI->isConditional())
-        return (I == succ_begin(Node)) ? "T" : "F";
-    
-    // Label source of switch edges with the associated value.
-    if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) {
-      unsigned SuccNo = I.getSuccessorIndex();
-
-      if (SuccNo == 0) return "def";
-      
-      std::string Str;
-      raw_string_ostream OS(Str);
-      SwitchInst::ConstCaseIt Case =
-          SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); 
-      OS << Case.getCaseValue()->getValue();
-      return OS.str();
-    }    
-    return "";
-  }
-};
-} // End llvm namespace
-
-namespace llvm {
-  class FunctionPass;
-  FunctionPass *createCFGPrinterPass ();
-  FunctionPass *createCFGOnlyPrinterPass ();
-} // End llvm namespace
-
-#endif
Index: include/llvm/Analysis/DOTGraphTraitsPass.h
===================================================================
--- include/llvm/Analysis/DOTGraphTraitsPass.h	(revision 183332)
+++ include/llvm/Analysis/DOTGraphTraitsPass.h	(working copy)
@@ -14,7 +14,7 @@
 #ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
 #define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
 
-#include "llvm/Analysis/CFGPrinter.h"
+#include "llvm/Support/CFGPrinter.h"
 #include "llvm/Pass.h"
 
 namespace llvm {
Index: include/llvm/Pass.h
===================================================================
--- include/llvm/Pass.h	(revision 183332)
+++ include/llvm/Pass.h	(working copy)
@@ -129,6 +129,11 @@ public:
   virtual Pass *createPrinterPass(raw_ostream &O,
                                   const std::string &Banner) const = 0;
 
+  /// createCFGPrinterPass - Get a Pass appropriate to print the CFG of functions
+  /// this pass operates. By default it returns Function CFG Printer pass. The
+  /// MachineFunction Pass overrides the definition.
+  virtual Pass *createCFGPrinterPass(const PassInfo *PI, const char *) const;
+
   /// Each pass is responsible for assigning a pass manager to itself.
   /// PMS is the stack of available pass manager.
   virtual void assignPassManager(PMStack &,
Index: include/llvm/CodeGen/MachineFunctionPass.h
===================================================================
--- include/llvm/CodeGen/MachineFunctionPass.h	(revision 183332)
+++ include/llvm/CodeGen/MachineFunctionPass.h	(working copy)
@@ -51,6 +51,8 @@ private:
   virtual Pass *createPrinterPass(raw_ostream &O,
                                   const std::string &Banner) const;
 
+  virtual Pass *createCFGPrinterPass(const PassInfo *, const char *) const;
+
   virtual bool runOnFunction(Function &F);
 };
 
Index: lib/IR/PassManager.cpp
===================================================================
--- lib/IR/PassManager.cpp	(revision 183335)
+++ lib/IR/PassManager.cpp	(working copy)
@@ -17,6 +17,7 @@
 #include "llvm/Assembly/Writer.h"
 #include "llvm/IR/Module.h"
 #include "llvm/PassManager.h"
+#include "llvm/Support/CFGPrinter.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -70,6 +71,16 @@ PrintAfter("print-after",
            llvm::cl::desc("Print IR after specified passes"),
            cl::Hidden);
 
+static PassOptionList
+DotCfgBefore("dot-cfg-before",
+             llvm::cl::desc("Dump CFG DOT file before specified passes"),
+             cl::Hidden);
+
+static PassOptionList
+DotCfgAfter("dot-cfg-after",
+            llvm::cl::desc("Dump CFG DOT file after specified passes"),
+            cl::Hidden);
+
 static cl::opt<bool>
 PrintBeforeAll("print-before-all",
                llvm::cl::desc("Print IR before each pass"),
@@ -106,6 +117,18 @@ static bool ShouldPrintAfterPass(const P
   return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter);
 }
 
+/// This is a utility to check whether a pass should have DOT CFG dumped
+/// before it.
+static bool ShouldPrintCFGBeforePass(const PassInfo *PI) {
+  return ShouldPrintBeforeOrAfterPass(PI, DotCfgBefore);
+}
+
+/// This is a utility to check whether a pass should have DOT CFG dumped
+/// after it.
+static bool ShouldPrintCFGAfterPass(const PassInfo *PI) {
+  return ShouldPrintBeforeOrAfterPass(PI, DotCfgAfter);
+}
+
 } // End of llvm namespace
 
 /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions
@@ -674,6 +697,12 @@ void PMTopLevelManager::schedulePass(Pas
     PP->assignPassManager(activeStack, getTopLevelPassManagerType());
   }
 
+  if (PI && !PI->isAnalysis() && (P->getPassKind() != PT_Loop) &&
+      ShouldPrintCFGBeforePass(PI)) {
+    Pass *PP = P->createCFGPrinterPass(PI, "before");
+    PP->assignPassManager(activeStack, getTopLevelPassManagerType());
+  }
+
   // Add the requested pass to the best available pass manager.
   P->assignPassManager(activeStack, getTopLevelPassManagerType());
 
@@ -682,6 +711,11 @@ void PMTopLevelManager::schedulePass(Pas
       dbgs(), std::string("*** IR Dump After ") + P->getPassName() + " ***");
     PP->assignPassManager(activeStack, getTopLevelPassManagerType());
   }
+
+  if (PI && !PI->isAnalysis() && ShouldPrintCFGAfterPass(PI)) {
+    Pass *PP = P->createCFGPrinterPass(PI, "after");
+    PP->assignPassManager(activeStack, getTopLevelPassManagerType());
+  }
 }
 
 /// Find the pass that implements Analysis AID. Search immutable
Index: lib/IR/Pass.cpp
===================================================================
--- lib/IR/Pass.cpp	(revision 183335)
+++ lib/IR/Pass.cpp	(working copy)
@@ -16,6 +16,7 @@
 #include "llvm/Pass.h"
 #include "llvm/Assembly/PrintModulePass.h"
 #include "llvm/PassRegistry.h"
+#include "llvm/Support/CFGPrinter.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/PassNameParser.h"
 #include "llvm/Support/raw_ostream.h"
@@ -63,6 +64,10 @@ const char *Pass::getPassName() const {
   return "Unnamed pass: implement Pass::getPassName()";
 }
 
+Pass * Pass::createCFGPrinterPass(const PassInfo *PI, const char *O) const {
+  return llvm::createCFGPrinterPass(PI, O);
+}
+
 void Pass::preparePassManager(PMStack &) {
   // By default, don't do anything.
 }
Index: lib/Support/CFGPrinter.cpp
===================================================================
--- lib/Support/CFGPrinter.cpp	(revision 177877)
+++ lib/Support/CFGPrinter.cpp	(working copy)
@@ -17,8 +17,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Analysis/CFGPrinter.h"
+#include "llvm/Support/CFGPrinter.h"
 #include "llvm/Pass.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
 using namespace llvm;
 
 namespace {
@@ -69,69 +71,42 @@ INITIALIZE_PASS(CFGOnlyViewer, "view-cfg
                 "View CFG of function (with no function bodies)", false, true)
 
 namespace {
-  struct CFGPrinter : public FunctionPass {
-    static char ID; // Pass identification, replacement for typeid
-    CFGPrinter() : FunctionPass(ID) {
+template <bool CFGOnly>
+struct CFGPrinterT : public FunctionPass,
+                     public CFGPrinterBase<Function, CFGOnly> {
+
+  static char ID; // Pass identification, replacement for typeid
+  typedef CFGPrinterBase<Function, CFGOnly> BaseT;
+
+  CFGPrinterT(const PassInfo *P = 0, const char *O = 0)
+      : FunctionPass(ID), BaseT(P, O) {
+    if (CFGOnly)
+      initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry());
+    else
       initializeCFGPrinterPass(*PassRegistry::getPassRegistry());
-    }
+  }
 
-    virtual bool runOnFunction(Function &F) {
-      std::string Filename = "cfg." + F.getName().str() + ".dot";
-      errs() << "Writing '" << Filename << "'...";
-      
-      std::string ErrorInfo;
-      raw_fd_ostream File(Filename.c_str(), ErrorInfo);
-
-      if (ErrorInfo.empty())
-        WriteGraph(File, (const Function*)&F);
-      else
-        errs() << "  error opening file for writing!";
-      errs() << "\n";
-      return false;
-    }
+  virtual bool runOnFunction(Function &F) { return BaseT::run(&F); }
 
-    void print(raw_ostream &OS, const Module* = 0) const {}
+  void print(raw_ostream &OS, const Module * = 0) const {}
 
-    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
-      AU.setPreservesAll();
-    }
-  };
-}
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+    AU.setPreservesAll();
+  }
+};
 
-char CFGPrinter::ID = 0;
-INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", 
-                false, true)
 
-namespace {
-  struct CFGOnlyPrinter : public FunctionPass {
-    static char ID; // Pass identification, replacement for typeid
-    CFGOnlyPrinter() : FunctionPass(ID) {
-      initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry());
-    }
-    
-    virtual bool runOnFunction(Function &F) {
-      std::string Filename = "cfg." + F.getName().str() + ".dot";
-      errs() << "Writing '" << Filename << "'...";
+template<bool CFGOnly> char CFGPrinterT<CFGOnly> ::ID = 0;
+template struct CFGPrinterT<true>;
+template struct CFGPrinterT<false>;
+typedef CFGPrinterT<true> CFGOnlyPrinter;
+typedef CFGPrinterT<false> CFGPrinter;
 
-      std::string ErrorInfo;
-      raw_fd_ostream File(Filename.c_str(), ErrorInfo);
-      
-      if (ErrorInfo.empty())
-        WriteGraph(File, (const Function*)&F, true);
-      else
-        errs() << "  error opening file for writing!";
-      errs() << "\n";
-      return false;
-    }
-    void print(raw_ostream &OS, const Module* = 0) const {}
-
-    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
-      AU.setPreservesAll();
-    }
-  };
 }
 
-char CFGOnlyPrinter::ID = 0;
+INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file",
+                false, true)
+
 INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only",
    "Print CFG of function to 'dot' file (with no function bodies)",
    false, true)
@@ -158,7 +133,10 @@ FunctionPass *llvm::createCFGPrinterPass
   return new CFGPrinter();
 }
 
+FunctionPass *llvm::createCFGPrinterPass (const PassInfo *PI, const char *O) {
+    return new CFGPrinter(PI, O);
+}
+
 FunctionPass *llvm::createCFGOnlyPrinterPass () {
   return new CFGOnlyPrinter();
 }
-
Index: lib/Analysis/CFGPrinter.cpp
===================================================================
--- lib/Analysis/CFGPrinter.cpp	(revision 183332)
+++ lib/Analysis/CFGPrinter.cpp	(working copy)
@@ -1,164 +0,0 @@
-//===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a '-dot-cfg' analysis pass, which emits the
-// cfg.<fnname>.dot file for each function in the program, with a graph of the
-// CFG for that function.
-//
-// The other main feature of this file is that it implements the
-// Function::viewCFG method, which is useful for debugging passes which operate
-// on the CFG.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Analysis/CFGPrinter.h"
-#include "llvm/Pass.h"
-using namespace llvm;
-
-namespace {
-  struct CFGViewer : public FunctionPass {
-    static char ID; // Pass identifcation, replacement for typeid
-    CFGViewer() : FunctionPass(ID) {
-      initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry());
-    }
-
-    virtual bool runOnFunction(Function &F) {
-      F.viewCFG();
-      return false;
-    }
-
-    void print(raw_ostream &OS, const Module* = 0) const {}
-
-    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
-      AU.setPreservesAll();
-    }
-  };
-}
-
-char CFGViewer::ID = 0;
-INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true)
-
-namespace {
-  struct CFGOnlyViewer : public FunctionPass {
-    static char ID; // Pass identifcation, replacement for typeid
-    CFGOnlyViewer() : FunctionPass(ID) {
-      initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry());
-    }
-
-    virtual bool runOnFunction(Function &F) {
-      F.viewCFGOnly();
-      return false;
-    }
-
-    void print(raw_ostream &OS, const Module* = 0) const {}
-
-    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
-      AU.setPreservesAll();
-    }
-  };
-}
-
-char CFGOnlyViewer::ID = 0;
-INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only",
-                "View CFG of function (with no function bodies)", false, true)
-
-namespace {
-  struct CFGPrinter : public FunctionPass {
-    static char ID; // Pass identification, replacement for typeid
-    CFGPrinter() : FunctionPass(ID) {
-      initializeCFGPrinterPass(*PassRegistry::getPassRegistry());
-    }
-
-    virtual bool runOnFunction(Function &F) {
-      std::string Filename = "cfg." + F.getName().str() + ".dot";
-      errs() << "Writing '" << Filename << "'...";
-      
-      std::string ErrorInfo;
-      raw_fd_ostream File(Filename.c_str(), ErrorInfo);
-
-      if (ErrorInfo.empty())
-        WriteGraph(File, (const Function*)&F);
-      else
-        errs() << "  error opening file for writing!";
-      errs() << "\n";
-      return false;
-    }
-
-    void print(raw_ostream &OS, const Module* = 0) const {}
-
-    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
-      AU.setPreservesAll();
-    }
-  };
-}
-
-char CFGPrinter::ID = 0;
-INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", 
-                false, true)
-
-namespace {
-  struct CFGOnlyPrinter : public FunctionPass {
-    static char ID; // Pass identification, replacement for typeid
-    CFGOnlyPrinter() : FunctionPass(ID) {
-      initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry());
-    }
-    
-    virtual bool runOnFunction(Function &F) {
-      std::string Filename = "cfg." + F.getName().str() + ".dot";
-      errs() << "Writing '" << Filename << "'...";
-
-      std::string ErrorInfo;
-      raw_fd_ostream File(Filename.c_str(), ErrorInfo);
-      
-      if (ErrorInfo.empty())
-        WriteGraph(File, (const Function*)&F, true);
-      else
-        errs() << "  error opening file for writing!";
-      errs() << "\n";
-      return false;
-    }
-    void print(raw_ostream &OS, const Module* = 0) const {}
-
-    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
-      AU.setPreservesAll();
-    }
-  };
-}
-
-char CFGOnlyPrinter::ID = 0;
-INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only",
-   "Print CFG of function to 'dot' file (with no function bodies)",
-   false, true)
-
-/// 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.  This depends on there
-/// being a 'dot' and 'gv' program in your path.
-///
-void Function::viewCFG() const {
-  ViewGraph(this, "cfg" + getName());
-}
-
-/// 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 t
-/// his can make the graph smaller.
-///
-void Function::viewCFGOnly() const {
-  ViewGraph(this, "cfg" + getName(), true);
-}
-
-FunctionPass *llvm::createCFGPrinterPass () {
-  return new CFGPrinter();
-}
-
-FunctionPass *llvm::createCFGOnlyPrinterPass () {
-  return new CFGOnlyPrinter();
-}
-
Index: lib/CodeGen/MachineFunctionPass.cpp
===================================================================
--- lib/CodeGen/MachineFunctionPass.cpp	(revision 183335)
+++ lib/CodeGen/MachineFunctionPass.cpp	(working copy)
@@ -16,6 +16,7 @@
 #include "llvm/CodeGen/MachineFunctionAnalysis.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/Passes.h"
+#include "llvm/Support/CFGPrinter.h"
 using namespace llvm;
 
 Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O,
@@ -23,6 +24,12 @@ Pass *MachineFunctionPass::createPrinter
   return createMachineFunctionPrinterPass(O, Banner);
 }
 
+Pass *MachineFunctionPass::createCFGPrinterPass(const PassInfo *PI,
+                                                const char *O) const {
+
+  return createMachineCFGPrinterPass(PI, O);
+}
+
 bool MachineFunctionPass::runOnFunction(Function &F) {
   // Do not codegen any 'available_externally' functions at all, they have
   // definitions outside the translation unit.
Index: lib/CodeGen/MachineFunctionPrinterPass.cpp
===================================================================
--- lib/CodeGen/MachineFunctionPrinterPass.cpp	(revision 183335)
+++ lib/CodeGen/MachineFunctionPrinterPass.cpp	(working copy)
@@ -15,6 +15,7 @@
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/SlotIndexes.h"
+#include "llvm/Support/CFGPrinter.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -49,12 +50,54 @@ struct MachineFunctionPrinterPass : publ
 };
 
 char MachineFunctionPrinterPass::ID = 0;
+
+template <bool CFGOnly>
+struct MachineCFGPrinterT : public MachineFunctionPass,
+                            public CFGPrinterBase<MachineFunction, CFGOnly> {
+
+  static char ID; // Pass identification, replacement for typeid
+  typedef CFGPrinterBase<MachineFunction, CFGOnly> BaseT;
+
+  MachineCFGPrinterT(const PassInfo *P = 0, const char *O = 0)
+      : MachineFunctionPass(ID), BaseT(P, O) {
+    if (CFGOnly)
+      initializeMachineCFGOnlyPrinterPass(*PassRegistry::getPassRegistry());
+    else
+      initializeMachineCFGPrinterPass(*PassRegistry::getPassRegistry());
+  }
+
+  virtual bool runOnMachineFunction(MachineFunction &F) {
+    return BaseT::run(&F);
+  }
+
+  void print(raw_ostream &OS, const Module * = 0) const {}
+
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+    AU.setPreservesAll();
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
+};
+
+template <bool CFGOnly> char MachineCFGPrinterT<CFGOnly>::ID = 0;
+template struct MachineCFGPrinterT<true>;
+template struct MachineCFGPrinterT<false>;
+typedef MachineCFGPrinterT<true> MachineCFGOnlyPrinter;
+typedef MachineCFGPrinterT<false> MachineCFGPrinter;
+
 }
 
 char &llvm::MachineFunctionPrinterPassID = MachineFunctionPrinterPass::ID;
 INITIALIZE_PASS(MachineFunctionPrinterPass, "print-machineinstrs",
                 "Machine Function Printer", false, false)
 
+INITIALIZE_PASS(MachineCFGPrinter, "machine-dot-cfg",
+                "Print CFG of machine function to 'dot' file", false, true)
+INITIALIZE_PASS(
+    MachineCFGOnlyPrinter, "machine-dot-cfg-only",
+    "Print CFG of machine function to 'dot' file (with no function bodies)",
+    false, true)
+
+
 namespace llvm {
 /// Returns a newly-created MachineFunction Printer pass. The
 /// default banner is empty.
@@ -64,4 +107,12 @@ MachineFunctionPass *createMachineFuncti
   return new MachineFunctionPrinterPass(OS, Banner);
 }
 
+FunctionPass *createMachineCFGPrinterPass (const PassInfo *PI, const char *O) {
+  return new MachineCFGPrinter(PI, O);
+}
+
+FunctionPass *createMachineCFGOnlyPrinterPass () {
+  return new MachineCFGOnlyPrinter();
+}
+
 }


More information about the llvm-commits mailing list