<div dir="ltr">You may want to link to Sean Parent's GoingNative talk in PassManager.h for an introduction to this pattern, since it might be unfamiliar to many people ("which class do I inherit from for my pass?"). (the idea is freaking brilliant; it's like the lightweight Golang interfaces, but for C++ (dynamic dispatch and heap allocation only when you want). With Concepts Lite it's going to be like heaven!).<div>
<br></div><div>In particular, the third part of <<a href="http://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning">http://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning</a>>, or <<a href="http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil">http://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil</a>>, or <<a href="https://github.com/sean-parent/sean-parent.github.com/wiki/Papers-and-Presentations">https://github.com/sean-parent/sean-parent.github.com/wiki/Papers-and-Presentations</a>>.<br>
<div><br></div><div>-- Sean Silva</div></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Nov 9, 2013 at 8:09 AM, Chandler Carruth <span dir="ltr"><<a href="mailto:chandlerc@gmail.com" target="_blank">chandlerc@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: chandlerc<br>
Date: Sat Nov  9 07:09:08 2013<br>
New Revision: 194325<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=194325&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=194325&view=rev</a><br>
Log:<br>
[PM] Start sketching out the new module and function pass manager.<br>
<br>
This is still just a skeleton. I'm trying to pull together the<br>
experimentation I've done into committable chunks, and this is the first<br>
coherent one. Others will follow in hopefully short order that move this<br>
more toward a useful initial implementation. I still expect the design<br>
to continue evolving in small ways as I work through the different<br>
requirements and features needed here though.<br>
<br>
Keep in mind, all of this is off by default.<br>
<br>
Currently, this mostly exercises the use of a polymorphic smart pointer<br>
and templates to hide the polymorphism for the pass manager from the<br>
pass implementation. The next step will be more significant, adding the<br>
first framework of analysis support.<br>
<br>
Added:<br>
    llvm/trunk/include/llvm/IR/PassManager.h<br>
    llvm/trunk/unittests/IR/PassManagerTest.cpp<br>
Modified:<br>
    llvm/trunk/unittests/IR/CMakeLists.txt<br>
<br>
Added: llvm/trunk/include/llvm/IR/PassManager.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=194325&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=194325&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/include/llvm/IR/PassManager.h (added)<br>
+++ llvm/trunk/include/llvm/IR/PassManager.h Sat Nov  9 07:09:08 2013<br>
@@ -0,0 +1,118 @@<br>
+//===- PassManager.h - LegacyContainer for Passes --------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+/// \file<br>
+///<br>
+/// This header defines various interfaces for pass management in LLVM. There<br>
+/// is no "pass" interface in LLVM per se. Instead, an instance of any class<br>
+/// which supports a method to 'run' it over a unit of IR can be used as<br>
+/// a pass. A pass manager is generally a tool to collect a sequence of passes<br>
+/// which run over a particular IR construct, and run each of them in sequence<br>
+/// over each such construct in the containing IR construct. As there is no<br>
+/// containing IR construct for a Module, a manager for passes over modules<br>
+/// forms the base case which runs its managed passes in sequence over the<br>
+/// single module provided.<br>
+///<br>
+/// The core IR library provides managers for running passes over<br>
+/// modules and functions.<br>
+///<br>
+/// * FunctionPassManager can run over a Module, runs each pass over<br>
+///   a Function.<br>
+/// * ModulePassManager must be directly run, runs each pass over the Module.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/ADT/polymorphic_ptr.h"<br>
+#include "llvm/IR/Module.h"<br>
+#include <vector><br>
+<br>
+namespace llvm {<br>
+<br>
+class Module;<br>
+class Function;<br>
+<br>
+/// \brief Implementation details of the pass manager interfaces.<br>
+namespace detail {<br>
+<br>
+/// \brief Template for the abstract base class used to dispatch<br>
+/// polymorphically over pass objects.<br>
+template <typename T> struct PassConcept {<br>
+  // Boiler plate necessary for the container of derived classes.<br>
+  virtual ~PassConcept() {}<br>
+  virtual PassConcept *clone() = 0;<br>
+<br>
+  /// \brief The polymorphic API which runs the pass over a given IR entity.<br>
+  virtual bool run(T Arg) = 0;<br>
+};<br>
+<br>
+/// \brief A template wrapper used to implement the polymorphic API.<br>
+///<br>
+/// Can be instantiated for any object which provides a \c run method<br>
+/// accepting a \c T. It requires the pass to be a copyable<br>
+/// object.<br>
+template <typename T, typename PassT> struct PassModel : PassConcept<T> {<br>
+  PassModel(PassT Pass) : Pass(llvm_move(Pass)) {}<br>
+  virtual PassModel *clone() { return new PassModel(Pass); }<br>
+  virtual bool run(T Arg) { return Pass.run(Arg); }<br>
+  PassT Pass;<br>
+};<br>
+<br>
+}<br>
+<br>
+class ModulePassManager {<br>
+public:<br>
+  ModulePassManager(Module *M) : M(M) {}<br>
+<br>
+  template <typename ModulePassT> void addPass(ModulePassT Pass) {<br>
+    Passes.push_back(new ModulePassModel<ModulePassT>(llvm_move(Pass)));<br>
+  }<br>
+<br>
+  void run() {<br>
+    for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx)<br>
+      Passes[Idx]->run(M);<br>
+  }<br>
+<br>
+private:<br>
+  // Pull in the concept type and model template specialized for modules.<br>
+  typedef detail::PassConcept<Module *> ModulePassConcept;<br>
+  template <typename PassT><br>
+  struct ModulePassModel : detail::PassModel<Module *, PassT> {<br>
+    ModulePassModel(PassT Pass) : detail::PassModel<Module *, PassT>(Pass) {}<br>
+  };<br>
+<br>
+  Module *M;<br>
+  std::vector<polymorphic_ptr<ModulePassConcept> > Passes;<br>
+};<br>
+<br>
+class FunctionPassManager {<br>
+public:<br>
+  template <typename FunctionPassT> void addPass(FunctionPassT Pass) {<br>
+    Passes.push_back(new FunctionPassModel<FunctionPassT>(llvm_move(Pass)));<br>
+  }<br>
+<br>
+  bool run(Module *M) {<br>
+    bool Changed = false;<br>
+    for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)<br>
+      for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx)<br>
+        Changed |= Passes[Idx]->run(I);<br>
+    return Changed;<br>
+  }<br>
+<br>
+private:<br>
+  // Pull in the concept type and model template specialized for functions.<br>
+  typedef detail::PassConcept<Function *> FunctionPassConcept;<br>
+  template <typename PassT><br>
+  struct FunctionPassModel : detail::PassModel<Function *, PassT> {<br>
+    FunctionPassModel(PassT Pass)<br>
+        : detail::PassModel<Function *, PassT>(Pass) {}<br>
+  };<br>
+<br>
+  std::vector<polymorphic_ptr<FunctionPassConcept> > Passes;<br>
+};<br>
+<br>
+}<br>
<br>
Modified: llvm/trunk/unittests/IR/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/CMakeLists.txt?rev=194325&r1=194324&r2=194325&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/CMakeLists.txt?rev=194325&r1=194324&r2=194325&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/unittests/IR/CMakeLists.txt (original)<br>
+++ llvm/trunk/unittests/IR/CMakeLists.txt Sat Nov  9 07:09:08 2013<br>
@@ -13,6 +13,7 @@ set(IRSources<br>
   LegacyPassManagerTest.cpp<br>
   MDBuilderTest.cpp<br>
   MetadataTest.cpp<br>
+  PassManagerTest.cpp<br>
   PatternMatch.cpp<br>
   TypeBuilderTest.cpp<br>
   TypesTest.cpp<br>
<br>
Added: llvm/trunk/unittests/IR/PassManagerTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/PassManagerTest.cpp?rev=194325&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/PassManagerTest.cpp?rev=194325&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/unittests/IR/PassManagerTest.cpp (added)<br>
+++ llvm/trunk/unittests/IR/PassManagerTest.cpp Sat Nov  9 07:09:08 2013<br>
@@ -0,0 +1,88 @@<br>
+//===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/Assembly/Parser.h"<br>
+#include "llvm/IR/Function.h"<br>
+#include "llvm/IR/LLVMContext.h"<br>
+#include "llvm/IR/Module.h"<br>
+#include "llvm/IR/PassManager.h"<br>
+#include "llvm/Support/SourceMgr.h"<br>
+#include "gtest/gtest.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+namespace {<br>
+<br>
+struct TestModulePass {<br>
+  TestModulePass(int &RunCount) : RunCount(RunCount) {}<br>
+<br>
+  bool run(Module *M) {<br>
+    ++RunCount;<br>
+    return true;<br>
+  }<br>
+<br>
+  int &RunCount;<br>
+};<br>
+<br>
+struct TestFunctionPass {<br>
+  TestFunctionPass(int &RunCount) : RunCount(RunCount) {}<br>
+<br>
+  bool run(Function *F) {<br>
+    ++RunCount;<br>
+    return true;<br>
+  }<br>
+<br>
+  int &RunCount;<br>
+};<br>
+<br>
+Module *parseIR(const char *IR) {<br>
+  LLVMContext &C = getGlobalContext();<br>
+  SMDiagnostic Err;<br>
+  return ParseAssemblyString(IR, 0, Err, C);<br>
+}<br>
+<br>
+class PassManagerTest : public ::testing::Test {<br>
+protected:<br>
+  OwningPtr<Module> M;<br>
+<br>
+public:<br>
+  PassManagerTest()<br>
+      : M(parseIR("define void @f() {\n"<br>
+                  "entry:\n"<br>
+                  "  call void @g()\n"<br>
+                  "  call void @h()\n"<br>
+                  "  ret void\n"<br>
+                  "}\n"<br>
+                  "define void @g() {\n"<br>
+                  "  ret void\n"<br>
+                  "}\n"<br>
+                  "define void @h() {\n"<br>
+                  "  ret void\n"<br>
+                  "}\n")) {}<br>
+};<br>
+<br>
+TEST_F(PassManagerTest, Basic) {<br>
+  ModulePassManager MPM(M.get());<br>
+  FunctionPassManager FPM;<br>
+<br>
+  // Count the runs over a module.<br>
+  int ModulePassRunCount = 0;<br>
+  MPM.addPass(TestModulePass(ModulePassRunCount));<br>
+<br>
+  // Count the runs over a Function.<br>
+  int FunctionPassRunCount = 0;<br>
+  FPM.addPass(TestFunctionPass(FunctionPassRunCount));<br>
+  MPM.addPass(FPM);<br>
+<br>
+  MPM.run();<br>
+  EXPECT_EQ(1, ModulePassRunCount);<br>
+  EXPECT_EQ(3, FunctionPassRunCount);<br>
+}<br>
+<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>