Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- PassManager internal APIs and implementation details -----*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. /// \file
  9. ///
  10. /// This header provides internal APIs and implementation details used by the
  11. /// pass management interfaces exposed in PassManager.h. To understand more
  12. /// context of why these particular interfaces are needed, see that header
  13. /// file. None of these APIs should be used elsewhere.
  14. ///
  15. //===----------------------------------------------------------------------===//
  16.  
  17. #ifndef LLVM_IR_PASSMANAGERINTERNAL_H
  18. #define LLVM_IR_PASSMANAGERINTERNAL_H
  19.  
  20. #include "llvm/ADT/STLExtras.h"
  21. #include "llvm/ADT/StringRef.h"
  22. #include "llvm/Support/raw_ostream.h"
  23. #include <memory>
  24. #include <utility>
  25.  
  26. namespace llvm {
  27.  
  28. template <typename IRUnitT> class AllAnalysesOn;
  29. template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
  30. class PreservedAnalyses;
  31.  
  32. // Implementation details of the pass manager interfaces.
  33. namespace detail {
  34.  
  35. /// Template for the abstract base class used to dispatch
  36. /// polymorphically over pass objects.
  37. template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
  38. struct PassConcept {
  39.   // Boiler plate necessary for the container of derived classes.
  40.   virtual ~PassConcept() = default;
  41.  
  42.   /// The polymorphic API which runs the pass over a given IR entity.
  43.   ///
  44.   /// Note that actual pass object can omit the analysis manager argument if
  45.   /// desired. Also that the analysis manager may be null if there is no
  46.   /// analysis manager in the pass pipeline.
  47.   virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
  48.                                 ExtraArgTs... ExtraArgs) = 0;
  49.  
  50.   virtual void
  51.   printPipeline(raw_ostream &OS,
  52.                 function_ref<StringRef(StringRef)> MapClassName2PassName) = 0;
  53.   /// Polymorphic method to access the name of a pass.
  54.   virtual StringRef name() const = 0;
  55.  
  56.   /// Polymorphic method to to let a pass optionally exempted from skipping by
  57.   /// PassInstrumentation.
  58.   /// To opt-in, pass should implement `static bool isRequired()`. It's no-op
  59.   /// to have `isRequired` always return false since that is the default.
  60.   virtual bool isRequired() const = 0;
  61. };
  62.  
  63. /// A template wrapper used to implement the polymorphic API.
  64. ///
  65. /// Can be instantiated for any object which provides a \c run method accepting
  66. /// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&. It requires the pass to
  67. /// be a copyable object.
  68. template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
  69.           typename AnalysisManagerT, typename... ExtraArgTs>
  70. struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
  71.   explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
  72.   // We have to explicitly define all the special member functions because MSVC
  73.   // refuses to generate them.
  74.   PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
  75.   PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
  76.  
  77.   friend void swap(PassModel &LHS, PassModel &RHS) {
  78.     using std::swap;
  79.     swap(LHS.Pass, RHS.Pass);
  80.   }
  81.  
  82.   PassModel &operator=(PassModel RHS) {
  83.     swap(*this, RHS);
  84.     return *this;
  85.   }
  86.  
  87.   PreservedAnalysesT run(IRUnitT &IR, AnalysisManagerT &AM,
  88.                          ExtraArgTs... ExtraArgs) override {
  89.     return Pass.run(IR, AM, ExtraArgs...);
  90.   }
  91.  
  92.   void printPipeline(
  93.       raw_ostream &OS,
  94.       function_ref<StringRef(StringRef)> MapClassName2PassName) override {
  95.     Pass.printPipeline(OS, MapClassName2PassName);
  96.   }
  97.  
  98.   StringRef name() const override { return PassT::name(); }
  99.  
  100.   template <typename T>
  101.   using has_required_t = decltype(std::declval<T &>().isRequired());
  102.  
  103.   template <typename T>
  104.   static std::enable_if_t<is_detected<has_required_t, T>::value, bool>
  105.   passIsRequiredImpl() {
  106.     return T::isRequired();
  107.   }
  108.   template <typename T>
  109.   static std::enable_if_t<!is_detected<has_required_t, T>::value, bool>
  110.   passIsRequiredImpl() {
  111.     return false;
  112.   }
  113.  
  114.   bool isRequired() const override { return passIsRequiredImpl<PassT>(); }
  115.  
  116.   PassT Pass;
  117. };
  118.  
  119. /// Abstract concept of an analysis result.
  120. ///
  121. /// This concept is parameterized over the IR unit that this result pertains
  122. /// to.
  123. template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT>
  124. struct AnalysisResultConcept {
  125.   virtual ~AnalysisResultConcept() = default;
  126.  
  127.   /// Method to try and mark a result as invalid.
  128.   ///
  129.   /// When the outer analysis manager detects a change in some underlying
  130.   /// unit of the IR, it will call this method on all of the results cached.
  131.   ///
  132.   /// \p PA is a set of preserved analyses which can be used to avoid
  133.   /// invalidation because the pass which changed the underlying IR took care
  134.   /// to update or preserve the analysis result in some way.
  135.   ///
  136.   /// \p Inv is typically a \c AnalysisManager::Invalidator object that can be
  137.   /// used by a particular analysis result to discover if other analyses
  138.   /// results are also invalidated in the event that this result depends on
  139.   /// them. See the documentation in the \c AnalysisManager for more details.
  140.   ///
  141.   /// \returns true if the result is indeed invalid (the default).
  142.   virtual bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
  143.                           InvalidatorT &Inv) = 0;
  144. };
  145.  
  146. /// SFINAE metafunction for computing whether \c ResultT provides an
  147. /// \c invalidate member function.
  148. template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
  149.   using EnabledType = char;
  150.   struct DisabledType {
  151.     char a, b;
  152.   };
  153.  
  154.   // Purely to help out MSVC which fails to disable the below specialization,
  155.   // explicitly enable using the result type's invalidate routine if we can
  156.   // successfully call that routine.
  157.   template <typename T> struct Nonce { using Type = EnabledType; };
  158.   template <typename T>
  159.   static typename Nonce<decltype(std::declval<T>().invalidate(
  160.       std::declval<IRUnitT &>(), std::declval<PreservedAnalyses>()))>::Type
  161.       check(rank<2>);
  162.  
  163.   // First we define an overload that can only be taken if there is no
  164.   // invalidate member. We do this by taking the address of an invalidate
  165.   // member in an adjacent base class of a derived class. This would be
  166.   // ambiguous if there were an invalidate member in the result type.
  167.   template <typename T, typename U> static DisabledType NonceFunction(T U::*);
  168.   struct CheckerBase { int invalidate; };
  169.   template <typename T> struct Checker : CheckerBase, T {};
  170.   template <typename T>
  171.   static decltype(NonceFunction(&Checker<T>::invalidate)) check(rank<1>);
  172.  
  173.   // Now we have the fallback that will only be reached when there is an
  174.   // invalidate member, and enables the trait.
  175.   template <typename T>
  176.   static EnabledType check(rank<0>);
  177.  
  178. public:
  179.   enum { Value = sizeof(check<ResultT>(rank<2>())) == sizeof(EnabledType) };
  180. };
  181.  
  182. /// Wrapper to model the analysis result concept.
  183. ///
  184. /// By default, this will implement the invalidate method with a trivial
  185. /// implementation so that the actual analysis result doesn't need to provide
  186. /// an invalidation handler. It is only selected when the invalidation handler
  187. /// is not part of the ResultT's interface.
  188. template <typename IRUnitT, typename PassT, typename ResultT,
  189.           typename PreservedAnalysesT, typename InvalidatorT,
  190.           bool HasInvalidateHandler =
  191.               ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
  192. struct AnalysisResultModel;
  193.  
  194. /// Specialization of \c AnalysisResultModel which provides the default
  195. /// invalidate functionality.
  196. template <typename IRUnitT, typename PassT, typename ResultT,
  197.           typename PreservedAnalysesT, typename InvalidatorT>
  198. struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
  199.                            InvalidatorT, false>
  200.     : AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT> {
  201.   explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
  202.   // We have to explicitly define all the special member functions because MSVC
  203.   // refuses to generate them.
  204.   AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
  205.   AnalysisResultModel(AnalysisResultModel &&Arg)
  206.       : Result(std::move(Arg.Result)) {}
  207.  
  208.   friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
  209.     using std::swap;
  210.     swap(LHS.Result, RHS.Result);
  211.   }
  212.  
  213.   AnalysisResultModel &operator=(AnalysisResultModel RHS) {
  214.     swap(*this, RHS);
  215.     return *this;
  216.   }
  217.  
  218.   /// The model bases invalidation solely on being in the preserved set.
  219.   //
  220.   // FIXME: We should actually use two different concepts for analysis results
  221.   // rather than two different models, and avoid the indirect function call for
  222.   // ones that use the trivial behavior.
  223.   bool invalidate(IRUnitT &, const PreservedAnalysesT &PA,
  224.                   InvalidatorT &) override {
  225.     auto PAC = PA.template getChecker<PassT>();
  226.     return !PAC.preserved() &&
  227.            !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
  228.   }
  229.  
  230.   ResultT Result;
  231. };
  232.  
  233. /// Specialization of \c AnalysisResultModel which delegates invalidate
  234. /// handling to \c ResultT.
  235. template <typename IRUnitT, typename PassT, typename ResultT,
  236.           typename PreservedAnalysesT, typename InvalidatorT>
  237. struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
  238.                            InvalidatorT, true>
  239.     : AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT> {
  240.   explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
  241.   // We have to explicitly define all the special member functions because MSVC
  242.   // refuses to generate them.
  243.   AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
  244.   AnalysisResultModel(AnalysisResultModel &&Arg)
  245.       : Result(std::move(Arg.Result)) {}
  246.  
  247.   friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
  248.     using std::swap;
  249.     swap(LHS.Result, RHS.Result);
  250.   }
  251.  
  252.   AnalysisResultModel &operator=(AnalysisResultModel RHS) {
  253.     swap(*this, RHS);
  254.     return *this;
  255.   }
  256.  
  257.   /// The model delegates to the \c ResultT method.
  258.   bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
  259.                   InvalidatorT &Inv) override {
  260.     return Result.invalidate(IR, PA, Inv);
  261.   }
  262.  
  263.   ResultT Result;
  264. };
  265.  
  266. /// Abstract concept of an analysis pass.
  267. ///
  268. /// This concept is parameterized over the IR unit that it can run over and
  269. /// produce an analysis result.
  270. template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT,
  271.           typename... ExtraArgTs>
  272. struct AnalysisPassConcept {
  273.   virtual ~AnalysisPassConcept() = default;
  274.  
  275.   /// Method to run this analysis over a unit of IR.
  276.   /// \returns A unique_ptr to the analysis result object to be queried by
  277.   /// users.
  278.   virtual std::unique_ptr<
  279.       AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
  280.   run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
  281.       ExtraArgTs... ExtraArgs) = 0;
  282.  
  283.   /// Polymorphic method to access the name of a pass.
  284.   virtual StringRef name() const = 0;
  285. };
  286.  
  287. /// Wrapper to model the analysis pass concept.
  288. ///
  289. /// Can wrap any type which implements a suitable \c run method. The method
  290. /// must accept an \c IRUnitT& and an \c AnalysisManager<IRUnitT>& as arguments
  291. /// and produce an object which can be wrapped in a \c AnalysisResultModel.
  292. template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
  293.           typename InvalidatorT, typename... ExtraArgTs>
  294. struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT,
  295.                                                InvalidatorT, ExtraArgTs...> {
  296.   explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
  297.   // We have to explicitly define all the special member functions because MSVC
  298.   // refuses to generate them.
  299.   AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
  300.   AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
  301.  
  302.   friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
  303.     using std::swap;
  304.     swap(LHS.Pass, RHS.Pass);
  305.   }
  306.  
  307.   AnalysisPassModel &operator=(AnalysisPassModel RHS) {
  308.     swap(*this, RHS);
  309.     return *this;
  310.   }
  311.  
  312.   // FIXME: Replace PassT::Result with type traits when we use C++11.
  313.   using ResultModelT =
  314.       AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
  315.                           PreservedAnalysesT, InvalidatorT>;
  316.  
  317.   /// The model delegates to the \c PassT::run method.
  318.   ///
  319.   /// The return is wrapped in an \c AnalysisResultModel.
  320.   std::unique_ptr<
  321.       AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
  322.   run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
  323.       ExtraArgTs... ExtraArgs) override {
  324.     return std::make_unique<ResultModelT>(
  325.         Pass.run(IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...));
  326.   }
  327.  
  328.   /// The model delegates to a static \c PassT::name method.
  329.   ///
  330.   /// The returned string ref must point to constant immutable data!
  331.   StringRef name() const override { return PassT::name(); }
  332.  
  333.   PassT Pass;
  334. };
  335.  
  336. } // end namespace detail
  337.  
  338. } // end namespace llvm
  339.  
  340. #endif // LLVM_IR_PASSMANAGERINTERNAL_H
  341.