diff options
| author | David Greene <greened@obbligato.org> | 2010-04-01 22:43:57 +0000 | 
|---|---|---|
| committer | David Greene <greened@obbligato.org> | 2010-04-01 22:43:57 +0000 | 
| commit | 8ef3acba00c9c42d450fa52c7d3faebce1e507dd (patch) | |
| tree | eb24eedb1c0e990efe72699d85bdd7ddd7f28e73 /lib/VMCore | |
| parent | 3ea97550e361bc6ae23e9415abc7b0a34c540f53 (diff) | |
| download | external_llvm-8ef3acba00c9c42d450fa52c7d3faebce1e507dd.zip external_llvm-8ef3acba00c9c42d450fa52c7d3faebce1e507dd.tar.gz external_llvm-8ef3acba00c9c42d450fa52c7d3faebce1e507dd.tar.bz2 | |
Add some switches helpful for debugging:
-print-before=<Pass Name>
Dump IR before running pass <Pass Name>.
-print-before-all
Dump IR before running each pass.
-print-after-all
Dump IR after running each pass.
These are helpful when tracking down a miscompilation.  It is easy to
get IR dumps and do diffs on them, etc.
To make this work well, add a new getPrinterPass API to Pass so that
each kind of pass (ModulePass, FunctionPass, etc.) can create a Pass
suitable for dumping out the kind of object the Pass works on.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100143 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
| -rw-r--r-- | lib/VMCore/Pass.cpp | 18 | ||||
| -rw-r--r-- | lib/VMCore/PassManager.cpp | 83 | ||||
| -rw-r--r-- | lib/VMCore/PrintModulePass.cpp | 12 | 
3 files changed, 108 insertions, 5 deletions
| diff --git a/lib/VMCore/Pass.cpp b/lib/VMCore/Pass.cpp index a782e5a..6093750 100644 --- a/lib/VMCore/Pass.cpp +++ b/lib/VMCore/Pass.cpp @@ -18,6 +18,7 @@  #include "llvm/Module.h"  #include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/StringMap.h" +#include "llvm/Assembly/PrintModulePass.h"  #include "llvm/Support/Debug.h"  #include "llvm/Support/ManagedStatic.h"  #include "llvm/Support/PassNameParser.h" @@ -42,6 +43,11 @@ Pass::~Pass() {  // Force out-of-line virtual method.  ModulePass::~ModulePass() { } +Pass *ModulePass::createPrinterPass(raw_ostream &O, +                                    const std::string &Banner) const { +  return createPrintModulePass(&O, false, Banner); +} +  PassManagerType ModulePass::getPotentialPassManagerType() const {    return PMT_ModulePassManager;  } @@ -113,6 +119,11 @@ void ImmutablePass::initializePass() {  // FunctionPass Implementation  // +Pass *FunctionPass::createPrinterPass(raw_ostream &O, +                                      const std::string &Banner) const { +  return createPrintFunctionPass(Banner, &O); +} +  // run - On a module, we run this pass by initializing, runOnFunction'ing once  // for every function in the module, then by finalizing.  // @@ -155,6 +166,13 @@ PassManagerType FunctionPass::getPotentialPassManagerType() const {  // BasicBlockPass Implementation  // +Pass *BasicBlockPass::createPrinterPass(raw_ostream &O, +                                        const std::string &Banner) const { +   +  llvm_unreachable("BasicBlockPass printing unsupported."); +  return 0; +} +  // To run this pass on a function, we simply call runOnBasicBlock once for each  // function.  // diff --git a/lib/VMCore/PassManager.cpp b/lib/VMCore/PassManager.cpp index 6774cec..6ca35ac0 100644 --- a/lib/VMCore/PassManager.cpp +++ b/lib/VMCore/PassManager.cpp @@ -13,6 +13,7 @@  #include "llvm/PassManagers.h" +#include "llvm/Assembly/PrintModulePass.h"  #include "llvm/Assembly/Writer.h"  #include "llvm/Support/CommandLine.h"  #include "llvm/Support/Debug.h" @@ -20,6 +21,7 @@  #include "llvm/Module.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PassNameParser.h"  #include "llvm/Support/raw_ostream.h"  #include "llvm/System/Mutex.h"  #include "llvm/System/Threading.h" @@ -55,6 +57,57 @@ PassDebugging("debug-pass", cl::Hidden,    clEnumVal(Executions, "print pass name before it is executed"),    clEnumVal(Details   , "print pass details when it is executed"),                               clEnumValEnd)); + +typedef llvm::cl::list<const llvm::PassInfo *, bool, PassNameParser> +PassOptionList; + +// Print IR out before/after specified passes. +static PassOptionList +PrintBefore("print-before", +            llvm::cl::desc("Print IR before specified passes")); + +static PassOptionList +PrintAfter("print-after", +           llvm::cl::desc("Print IR after specified passes")); + +static cl::opt<bool> +PrintBeforeAll("print-before-all", +               llvm::cl::desc("Print IR before each pass"), +               cl::init(false)); +static cl::opt<bool> +PrintAfterAll("print-after-all", +              llvm::cl::desc("Print IR after each pass"), +              cl::init(false)); + +/// This is a helper to determine whether to print IR before or +/// after a pass. + +static bool ShouldPrintBeforeOrAfterPass(Pass *P, +                                         PassOptionList &PassesToPrint) { +  for (unsigned i = 0, ie = PassesToPrint.size(); i < ie; ++i) { +    const llvm::PassInfo *PassInf = PassesToPrint[i]; +    if (PassInf && P->getPassInfo()) +      if (PassInf->getPassArgument() == +          P->getPassInfo()->getPassArgument()) { +        return true; +      } +  } +  return false; +} +   + +/// This is a utility to check whether a pass should have IR dumped +/// before it. +static bool ShouldPrintBeforePass(Pass *P) { +  return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(P, PrintBefore); +} + +/// This is a utility to check whether a pass should have IR dumped +/// after it. +static bool ShouldPrintAfterPass(Pass *P) { +  return PrintAfterAll || ShouldPrintBeforeOrAfterPass(P, PrintAfter); +} +  } // End of llvm namespace  /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions @@ -182,6 +235,11 @@ public:      schedulePass(P);    } +  /// createPrinterPass - Get a function printer pass.  +  Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const { +    return createPrintFunctionPass(Banner, &O); +  } +    // Prepare for running an on the fly pass, freeing memory if needed    // from a previous run.    void releaseMemoryOnTheFly(); @@ -252,6 +310,11 @@ public:      }    } +  /// createPrinterPass - Get a module printer pass.  +  Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const { +    return createPrintModulePass(&O, false, Banner); +  } +    /// run - Execute all of the passes scheduled for execution.  Keep track of    /// whether any of the passes modifies the module, and if so, return true.    bool runOnModule(Module &M); @@ -331,6 +394,11 @@ public:      schedulePass(P);    } +  /// createPrinterPass - Get a module printer pass.  +  Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const { +    return createPrintModulePass(&O, false, Banner); +  } +    /// run - Execute all of the passes scheduled for execution.  Keep track of    /// whether any of the passes modifies the module, and if so, return true.    bool run(Module &M); @@ -1208,7 +1276,14 @@ FunctionPassManager::~FunctionPassManager() {  /// there is no need to delete the pass. (TODO delete passes.)  /// This implies that all passes MUST be allocated with 'new'.  void FunctionPassManager::add(Pass *P) {  +  if (ShouldPrintBeforePass(P)) +    add(P->createPrinterPass(dbgs(), std::string("*** IR Dump Before ") +                             + P->getPassName() + " ***"));    FPM->add(P); + +  if (ShouldPrintAfterPass(P)) +    add(P->createPrinterPass(dbgs(), std::string("*** IR Dump After ") +                             + P->getPassName() + " ***"));  }  /// run - Execute all of the passes scheduled for execution.  Keep @@ -1519,7 +1594,15 @@ PassManager::~PassManager() {  /// will be destroyed as well, so there is no need to delete the pass.  This  /// implies that all passes MUST be allocated with 'new'.  void PassManager::add(Pass *P) { +  if (ShouldPrintBeforePass(P)) +    add(P->createPrinterPass(dbgs(), std::string("*** IR Dump Before ") +                             + P->getPassName() + " ***")); +    PM->add(P); + +  if (ShouldPrintAfterPass(P)) +    add(P->createPrinterPass(dbgs(), std::string("*** IR Dump After ") +                             + P->getPassName() + " ***"));  }  /// run - Execute all of the passes scheduled for execution.  Keep track of diff --git a/lib/VMCore/PrintModulePass.cpp b/lib/VMCore/PrintModulePass.cpp index f0f6e7a..2d69dce 100644 --- a/lib/VMCore/PrintModulePass.cpp +++ b/lib/VMCore/PrintModulePass.cpp @@ -23,21 +23,22 @@ using namespace llvm;  namespace {    class PrintModulePass : public ModulePass { +    std::string Banner;      raw_ostream *Out;       // raw_ostream to print on      bool DeleteStream;      // Delete the ostream in our dtor?    public:      static char ID;      PrintModulePass() : ModulePass(&ID), Out(&dbgs()),         DeleteStream(false) {} -    PrintModulePass(raw_ostream *o, bool DS) -      : ModulePass(&ID), Out(o), DeleteStream(DS) {} +    PrintModulePass(const std::string &B, raw_ostream *o, bool DS) +        : ModulePass(&ID), Banner(B), Out(o), DeleteStream(DS) {}      ~PrintModulePass() {        if (DeleteStream) delete Out;      }      bool runOnModule(Module &M) { -      (*Out) << M; +      (*Out) << Banner << M;        return false;      } @@ -85,8 +86,9 @@ Y("print-function","Print function to stderr");  /// createPrintModulePass - Create and return a pass that writes the  /// module to the specified raw_ostream.  ModulePass *llvm::createPrintModulePass(llvm::raw_ostream *OS,  -                                        bool DeleteStream) { -  return new PrintModulePass(OS, DeleteStream); +                                        bool DeleteStream, +                                        const std::string &Banner) { +  return new PrintModulePass(Banner, OS, DeleteStream);  }  /// createPrintFunctionPass - Create and return a pass that prints | 
