Index: include/llvm/IR/PassManagerInternal.h =================================================================== --- include/llvm/IR/PassManagerInternal.h +++ include/llvm/IR/PassManagerInternal.h @@ -29,41 +29,75 @@ /// \brief Implementation details of the pass manager interfaces. namespace detail { +/// \brief Helper template to run a specific class method with optional +/// arguments. +/// +/// This functor can be used as generic utility to invoke specific method on +/// give object of any class from a set of classes fulfilling following +/// prerequisite. +/// 1. All classes in set defines at-least one such method taking all fixed +/// arguments with optional other arguments. +/// 2. In all such methods, if there exist any 2 methods with same fixed +/// argument, they must have at least one optional argument. +/// 3. Return type of such methods defined in the class must be same. +/// 4. All such methods defined in the class can take any number of optional +/// arguments. +/// 5. For successful invocation of '()' operator, given class method should +/// match the arguments passed (fixed/ optional) i.e. if method take an argument +/// as (value/ l-value reference/ r-value reference/ pointer), provided argument +/// should be of type (value/ l-value reference/ r-value reference/ pointer). of +/// same type +/// Example +/// struct Arg1 {}; struct Arg2 {}; struct Arg3 {}; struct Arg4 {}; +/// struct A { void Print(Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4) {} } +/// struct B { void Print(Arg1 a1, Arg2 a2) {} } +/// int main { +/// A a, B b, Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4; +/// Invoke I; +/// I(a, A::Print, a1, a2, a3, a4); // will invoke a.print(a1, a2, a3, a4) +/// I(b, B::Print, a1, a2, a3, a4); // will invoke b.print(a1, a2) +/// } +template struct Invoker { + /// \brief Helper template to run Object::method *with* optional arguments. + template + ReturnT operator()(Object &obj, + ReturnT (Object::*method)(FixedArgs..., OptionalArgs...), + FixedArgs... FAs, OptionalArgs... OAs) { + return (obj.*method)(std::forward(FAs)..., + std::forward(OAs)...); + } + + /// \brief Helper template to run Object::method *without* an optional + /// arguments. + template + ReturnT operator()(Object &obj, ReturnT (Object::*method)(FixedArgs... FFAs), + FixedArgs... FAs, OptionalArgs... /*OAs*/) { + return (obj.*method)(std::forward(FAs)...); + } +}; + /// \brief Template for the abstract base class used to dispatch /// polymorphically over pass objects. -template struct PassConcept { - // Boiler plate necessary for the container of derived classes. - virtual ~PassConcept() {} +template struct PassConceptBase { + virtual ~PassConceptBase() {} /// \brief The polymorphic API which runs the pass over a given IR entity. /// /// Note that actual pass object can omit the analysis manager argument if /// desired. Also that the analysis manager may be null if there is no /// analysis manager in the pass pipeline. - virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager *AM) = 0; + virtual ResultT run(IRUnitT &IR, AnalysisManager *AM) = 0; /// \brief Polymorphic method to access the name of a pass. virtual StringRef name() = 0; }; -/// \brief SFINAE metafunction for computing whether \c PassT has a run method -/// accepting an \c AnalysisManager. -template -class PassRunAcceptsAnalysisManager { - typedef char SmallType; - struct BigType { - char a, b; - }; - - template *)> - struct Checker; - - template static SmallType f(Checker *); - template static BigType f(...); - -public: - enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; -}; +/// \brief Abstract concept of an transform pass. +/// +/// This concept is parameterized over the IR unit that it can run over and +/// returns status of preserved analyses. +template +using PassConcept = PassConceptBase; /// \brief A template wrapper used to implement the polymorphic API. /// @@ -72,16 +106,8 @@ /// \c run method also accepts an \c AnalysisManager*, we pass it /// along. template ::Value> -struct PassModel; - -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template -struct PassModel - : PassConcept { + typename PreservedAnalysesT = PreservedAnalyses> +struct PassModel : PassConceptBase { explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. @@ -96,37 +122,14 @@ return *this; } + /// \brief The model delegates to the \c PassT::run method. PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { - return Pass.run(IR, AM); + return invokeRunMethod(Pass, &PassT::run, IR, AM); } StringRef name() override { return PassT::name(); } - PassT Pass; -}; -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template -struct PassModel - : PassConcept { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { - return Pass.run(IR); - } - StringRef name() override { return PassT::name(); } PassT Pass; + Invoker invokeRunMethod; }; /// \brief Abstract concept of an analysis result. @@ -245,33 +248,17 @@ /// /// This concept is parameterized over the IR unit that it can run over and /// produce an analysis result. -template struct AnalysisPassConcept { - virtual ~AnalysisPassConcept() {} - - /// \brief Method to run this analysis over a unit of IR. - /// \returns A unique_ptr to the analysis result object to be queried by - /// users. - virtual std::unique_ptr> - run(IRUnitT &IR, AnalysisManager *AM) = 0; - - /// \brief Polymorphic method to access the name of a pass. - virtual StringRef name() = 0; -}; +template +using AnalysisPassConcept = + PassConceptBase>, IRUnitT>; /// \brief Wrapper to model the analysis pass concept. /// /// Can wrap any type which implements a suitable \c run method. The method /// must accept the IRUnitT as an argument and produce an object which can be /// wrapped in a \c AnalysisResultModel. -template ::Value> -struct AnalysisPassModel; - -/// \brief Specialization of \c AnalysisPassModel which passes an -/// \c AnalysisManager to PassT's run method. template -struct AnalysisPassModel : AnalysisPassConcept { +struct AnalysisPassModel : AnalysisPassConcept { explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. @@ -287,53 +274,16 @@ } // FIXME: Replace PassT::Result with type traits when we use C++11. - typedef AnalysisResultModel - ResultModelT; + using ResultT = typename PassT::Result; + using ResultModelT = AnalysisResultModel; /// \brief The model delegates to the \c PassT::run method. /// /// The return is wrapped in an \c AnalysisResultModel. std::unique_ptr> run(IRUnitT &IR, AnalysisManager *AM) override { - return make_unique(Pass.run(IR, AM)); - } - - /// \brief The model delegates to a static \c PassT::name method. - /// - /// The returned string ref must point to constant immutable data! - StringRef name() override { return PassT::name(); } - - PassT Pass; -}; - -/// \brief Specialization of \c AnalysisPassModel which does not pass an -/// \c AnalysisManager to PassT's run method. -template -struct AnalysisPassModel : AnalysisPassConcept { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); - return *this; - } - - // FIXME: Replace PassT::Result with type traits when we use C++11. - typedef AnalysisResultModel - ResultModelT; - - /// \brief The model delegates to the \c PassT::run method. - /// - /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr> - run(IRUnitT &IR, AnalysisManager *) override { - return make_unique(Pass.run(IR)); + return make_unique( + invokeRunMethod(Pass, &PassT::run, IR, AM)); } /// \brief The model delegates to a static \c PassT::name method. @@ -342,6 +292,7 @@ StringRef name() override { return PassT::name(); } PassT Pass; + Invoker invokeRunMethod; }; } // End namespace detail