diff options
-rw-r--r-- | include/llvm/IR/PassManager.h | 118 | ||||
-rw-r--r-- | unittests/IR/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unittests/IR/PassManagerTest.cpp | 88 |
3 files changed, 207 insertions, 0 deletions
diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h new file mode 100644 index 0000000..aeadd41 --- /dev/null +++ b/include/llvm/IR/PassManager.h @@ -0,0 +1,118 @@ +//===- PassManager.h - LegacyContainer for Passes --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header defines various interfaces for pass management in LLVM. There +/// is no "pass" interface in LLVM per se. Instead, an instance of any class +/// which supports a method to 'run' it over a unit of IR can be used as +/// a pass. A pass manager is generally a tool to collect a sequence of passes +/// which run over a particular IR construct, and run each of them in sequence +/// over each such construct in the containing IR construct. As there is no +/// containing IR construct for a Module, a manager for passes over modules +/// forms the base case which runs its managed passes in sequence over the +/// single module provided. +/// +/// The core IR library provides managers for running passes over +/// modules and functions. +/// +/// * FunctionPassManager can run over a Module, runs each pass over +/// a Function. +/// * ModulePassManager must be directly run, runs each pass over the Module. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/polymorphic_ptr.h" +#include "llvm/IR/Module.h" +#include <vector> + +namespace llvm { + +class Module; +class Function; + +/// \brief Implementation details of the pass manager interfaces. +namespace detail { + +/// \brief Template for the abstract base class used to dispatch +/// polymorphically over pass objects. +template <typename T> struct PassConcept { + // Boiler plate necessary for the container of derived classes. + virtual ~PassConcept() {} + virtual PassConcept *clone() = 0; + + /// \brief The polymorphic API which runs the pass over a given IR entity. + virtual bool run(T Arg) = 0; +}; + +/// \brief A template wrapper used to implement the polymorphic API. +/// +/// Can be instantiated for any object which provides a \c run method +/// accepting a \c T. It requires the pass to be a copyable +/// object. +template <typename T, typename PassT> struct PassModel : PassConcept<T> { + PassModel(PassT Pass) : Pass(llvm_move(Pass)) {} + virtual PassModel *clone() { return new PassModel(Pass); } + virtual bool run(T Arg) { return Pass.run(Arg); } + PassT Pass; +}; + +} + +class ModulePassManager { +public: + ModulePassManager(Module *M) : M(M) {} + + template <typename ModulePassT> void addPass(ModulePassT Pass) { + Passes.push_back(new ModulePassModel<ModulePassT>(llvm_move(Pass))); + } + + void run() { + for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) + Passes[Idx]->run(M); + } + +private: + // Pull in the concept type and model template specialized for modules. + typedef detail::PassConcept<Module *> ModulePassConcept; + template <typename PassT> + struct ModulePassModel : detail::PassModel<Module *, PassT> { + ModulePassModel(PassT Pass) : detail::PassModel<Module *, PassT>(Pass) {} + }; + + Module *M; + std::vector<polymorphic_ptr<ModulePassConcept> > Passes; +}; + +class FunctionPassManager { +public: + template <typename FunctionPassT> void addPass(FunctionPassT Pass) { + Passes.push_back(new FunctionPassModel<FunctionPassT>(llvm_move(Pass))); + } + + bool run(Module *M) { + bool Changed = false; + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) + Changed |= Passes[Idx]->run(I); + return Changed; + } + +private: + // Pull in the concept type and model template specialized for functions. + typedef detail::PassConcept<Function *> FunctionPassConcept; + template <typename PassT> + struct FunctionPassModel : detail::PassModel<Function *, PassT> { + FunctionPassModel(PassT Pass) + : detail::PassModel<Function *, PassT>(Pass) {} + }; + + std::vector<polymorphic_ptr<FunctionPassConcept> > Passes; +}; + +} diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index 1ab8e38..fd0831f 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -13,6 +13,7 @@ set(IRSources LegacyPassManagerTest.cpp MDBuilderTest.cpp MetadataTest.cpp + PassManagerTest.cpp PatternMatch.cpp TypeBuilderTest.cpp TypesTest.cpp diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp new file mode 100644 index 0000000..f2e04d9 --- /dev/null +++ b/unittests/IR/PassManagerTest.cpp @@ -0,0 +1,88 @@ +//===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Assembly/Parser.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +struct TestModulePass { + TestModulePass(int &RunCount) : RunCount(RunCount) {} + + bool run(Module *M) { + ++RunCount; + return true; + } + + int &RunCount; +}; + +struct TestFunctionPass { + TestFunctionPass(int &RunCount) : RunCount(RunCount) {} + + bool run(Function *F) { + ++RunCount; + return true; + } + + int &RunCount; +}; + +Module *parseIR(const char *IR) { + LLVMContext &C = getGlobalContext(); + SMDiagnostic Err; + return ParseAssemblyString(IR, 0, Err, C); +} + +class PassManagerTest : public ::testing::Test { +protected: + OwningPtr<Module> M; + +public: + PassManagerTest() + : M(parseIR("define void @f() {\n" + "entry:\n" + " call void @g()\n" + " call void @h()\n" + " ret void\n" + "}\n" + "define void @g() {\n" + " ret void\n" + "}\n" + "define void @h() {\n" + " ret void\n" + "}\n")) {} +}; + +TEST_F(PassManagerTest, Basic) { + ModulePassManager MPM(M.get()); + FunctionPassManager FPM; + + // Count the runs over a module. + int ModulePassRunCount = 0; + MPM.addPass(TestModulePass(ModulePassRunCount)); + + // Count the runs over a Function. + int FunctionPassRunCount = 0; + FPM.addPass(TestFunctionPass(FunctionPassRunCount)); + MPM.addPass(FPM); + + MPM.run(); + EXPECT_EQ(1, ModulePassRunCount); + EXPECT_EQ(3, FunctionPassRunCount); +} + +} |