Index: include/llvm/IR/PassManagerInternal.h =================================================================== --- include/llvm/IR/PassManagerInternal.h +++ include/llvm/IR/PassManagerInternal.h @@ -29,41 +29,46 @@ /// \brief Implementation details of the pass manager interfaces. namespace detail { +/// \brief Template function to invoke given function with correct argument. +/// +/// Call to \c invokeWithOptionalArgs will be resolved to this function if +/// C::f() accepts two arguments of type A1 and A2, respectively. +template +R invokeWithOptionalArgs(C &c, R (C::*f)(A1, A2), A1 &&a1, A2 &a2) { + return (c.*f)(a1, a2); +} + +/// \brief Template function to invoke given function with correct argument. +/// +/// Call to \c invokeWithOptionalArgs will be resolved to this function if +/// C::f() accepts only one argument of type A1. +template +R invokeWithOptionalArgs(C &c, R (C::*f)(A1), A1 &&a1, A2 &a2) { + return (c.*f)(a1); +} + /// \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,42 +77,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 { - 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, 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 { + typename PreservedAnalysesT = PreservedAnalyses> +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. @@ -122,8 +93,10 @@ return *this; } + /// \brief The model delegates to the \c PassT::run method. PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { - return Pass.run(IR); + return invokeWithOptionalArgs(Pass, &PassT::run, IR, + AM); } StringRef name() override { return PassT::name(); } PassT Pass; @@ -245,33 +218,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 +244,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( + invokeWithOptionalArgs(Pass, &PassT::run, IR, AM)); } /// \brief The model delegates to a static \c PassT::name method.