LCOV - code coverage report
Current view: top level - include/llvm/IR - PassManagerInternal.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 735 903 81.4 %
Date: 2018-10-20 13:21:21 Functions: 577 930 62.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13