summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/IR/PassManager.h118
-rw-r--r--unittests/IR/CMakeLists.txt1
-rw-r--r--unittests/IR/PassManagerTest.cpp88
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);
+}
+
+}