diff options
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 a782e5a82e..6093750124 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 6774cecdcf..6ca35ac026 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 f0f6e7a9ef..2d69dce07f 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 |