From 8be6039072df15e0ae35d6fb4680b090c920669c Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Wed, 27 May 2015 09:36:33 +0000 Subject: [PATCH] Revert r238305: [PM] Use a simpler technique to drop optional analysis manager arguments... I have no idea why, but compilers seem to hate this and its late, so I'm not going to debug it. :: sigh :: This is why we can't have nice things. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238306 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/PassManagerInternal.h | 169 ++++++++++++++++++-------- 1 file changed, 120 insertions(+), 49 deletions(-) diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h index ebc73743fe1..92de10bcd75 100644 --- a/include/llvm/IR/PassManagerInternal.h +++ b/include/llvm/IR/PassManagerInternal.h @@ -29,56 +29,41 @@ class PreservedAnalyses; /// \brief Implementation details of the pass manager interfaces. namespace detail { -/// \brief Helper template to run a pass *with* an optional analysis manager. -/// -/// This accepts the address of the run method as an argument to detect that it -/// accepts the analysis manager and pass it through. This isn't (quite) -/// a generic optional argument invocation tool, and couldn't be without making -/// the calling syntax significantly more verbose. -template -ResultT invokeRunMethod(PassT &Pass, - ResultT (PassT::*run)(IRUnitT &, - AnalysisManager *), - IRUnitT &IR, AnalysisManager *AM) { - return (Pass.*run)(IR, AM); -} - -/// \brief Helper template to run a pass *without* an optional analysis manager. -/// -/// This accepts the address of the run method as an argument to detect that it -/// does not accept an analysis manager and drop it. This isn't (quite) -/// a generic optional argument invocation tool, and couldn't be without making -/// the calling syntax significantly more verbose. -template -ResultT invokeRunMethod( - PassT &Pass, - ResultT (PassT::*run)(IRUnitT &), - IRUnitT &IR, AnalysisManager * /*AM*/) { - return (Pass.*run)(IR); -} - /// \brief Template for the abstract base class used to dispatch /// polymorphically over pass objects. -template struct PassConceptBase { - virtual ~PassConceptBase() {} +template struct PassConcept { + // Boiler plate necessary for the container of derived classes. + virtual ~PassConcept() {} /// \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 ResultT run(IRUnitT &IR, AnalysisManager *AM) = 0; + virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager *AM) = 0; /// \brief Polymorphic method to access the name of a pass. virtual StringRef name() = 0; }; -/// \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 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 A template wrapper used to implement the polymorphic API. /// @@ -87,8 +72,16 @@ using PassConcept = PassConceptBase; /// \c run method also accepts an \c AnalysisManager*, we pass it /// along. template -struct PassModel : PassConcept { + typename PreservedAnalysesT = PreservedAnalyses, + bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager< + IRUnitT, PassT, PreservedAnalysesT>::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. @@ -103,9 +96,34 @@ struct PassModel : PassConcept { return *this; } - /// \brief The model delegates to the \c PassT::run method. PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { - return invokeRunMethod(Pass, &PassT::run, IR, AM); + 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 { + 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; @@ -227,17 +245,33 @@ struct AnalysisResultModel /// /// This concept is parameterized over the IR unit that it can run over and /// produce an analysis result. -template -using AnalysisPassConcept = - PassConceptBase>, IRUnitT>; +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; +}; /// \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. @@ -253,16 +287,53 @@ struct AnalysisPassModel : AnalysisPassConcept { } // FIXME: Replace PassT::Result with type traits when we use C++11. - using ResultT = typename PassT::Result; - using ResultModelT = AnalysisResultModel; + 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 *AM) override { - return make_unique( - invokeRunMethod(Pass, &PassT::run, IR, AM)); + 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)); } /// \brief The model delegates to a static \c PassT::name method. -- 2.34.1