LCOV - code coverage report
Current view: top level - include/llvm/IR - PassManagerInternal.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 20 20 100.0 %
Date: 2017-09-14 15:23:50 Functions: 846 1617 52.3 %
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             : /// \brief Implementation details of the pass manager interfaces.
      33             : namespace detail {
      34             : 
      35             : /// \brief 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             :   /// \brief 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             :   /// \brief Polymorphic method to access the name of a pass.
      51             :   virtual StringRef name() = 0;
      52             : };
      53             : 
      54             : /// \brief 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       11128 : struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
      62       11660 :   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       15034 :   PreservedAnalysesT run(IRUnitT &IR, AnalysisManagerT &AM,
      79             :                          ExtraArgTs... ExtraArgs) override {
      80       15374 :     return Pass.run(IR, AM, ExtraArgs...);
      81             :   }
      82             : 
      83        4889 :   StringRef name() override { return PassT::name(); }
      84             : 
      85             :   PassT Pass;
      86             : };
      87             : 
      88             : /// \brief Abstract concept of an analysis result.
      89             : ///
      90             : /// This concept is parameterized over the IR unit that this result pertains
      91             : /// to.
      92             : template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT>
      93             : struct AnalysisResultConcept {
      94             :   virtual ~AnalysisResultConcept() = default;
      95             : 
      96             :   /// \brief Method to try and mark a result as invalid.
      97             :   ///
      98             :   /// 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             :   ///
     101             :   /// \p PA is a set of preserved analyses which can be used to avoid
     102             :   /// invalidation because the pass which changed the underlying IR took care
     103             :   /// to update or preserve the analysis result in some way.
     104             :   ///
     105             :   /// \p Inv is typically a \c AnalysisManager::Invalidator object that can be
     106             :   /// used by a particular analysis result to discover if other analyses
     107             :   /// results are also invalidated in the event that this result depends on
     108             :   /// them. See the documentation in the \c AnalysisManager for more details.
     109             :   ///
     110             :   /// \returns true if the result is indeed invalid (the default).
     111             :   virtual bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
     112             :                           InvalidatorT &Inv) = 0;
     113             : };
     114             : 
     115             : /// \brief SFINAE metafunction for computing whether \c ResultT provides an
     116             : /// \c invalidate member function.
     117             : template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
     118             :   using EnabledType = char;
     119             :   struct DisabledType {
     120             :     char a, b;
     121             :   };
     122             : 
     123             :   // Purely to help out MSVC which fails to disable the below specialization,
     124             :   // explicitly enable using the result type's invalidate routine if we can
     125             :   // successfully call that routine.
     126             :   template <typename T> struct Nonce { using Type = EnabledType; };
     127             :   template <typename T>
     128             :   static typename Nonce<decltype(std::declval<T>().invalidate(
     129             :       std::declval<IRUnitT &>(), std::declval<PreservedAnalyses>()))>::Type
     130             :       check(rank<2>);
     131             : 
     132             :   // 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             :   // 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             :   template <typename T, typename U> static DisabledType NonceFunction(T U::*);
     137             :   struct CheckerBase { int invalidate; };
     138             :   template <typename T> struct Checker : CheckerBase, T {};
     139             :   template <typename T>
     140             :   static decltype(NonceFunction(&Checker<T>::invalidate)) check(rank<1>);
     141             : 
     142             :   // Now we have the fallback that will only be reached when there is an
     143             :   // invalidate member, and enables the trait.
     144             :   template <typename T>
     145             :   static EnabledType check(rank<0>);
     146             : 
     147             : public:
     148             :   enum { Value = sizeof(check<ResultT>(rank<2>())) == sizeof(EnabledType) };
     149             : };
     150             : 
     151             : /// \brief Wrapper to model the analysis result concept.
     152             : ///
     153             : /// By default, this will implement the invalidate method with a trivial
     154             : /// 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             : /// is not part of the ResultT's interface.
     157             : template <typename IRUnitT, typename PassT, typename ResultT,
     158             :           typename PreservedAnalysesT, typename InvalidatorT,
     159             :           bool HasInvalidateHandler =
     160             :               ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
     161             : struct AnalysisResultModel;
     162             : 
     163             : /// \brief Specialization of \c AnalysisResultModel which provides the default
     164             : /// invalidate functionality.
     165             : template <typename IRUnitT, typename PassT, typename ResultT,
     166             :           typename PreservedAnalysesT, typename InvalidatorT>
     167        3084 : struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
     168             :                            InvalidatorT, false>
     169             :     : AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT> {
     170        3098 :   explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
     171             :   // We have to explicitly define all the special member functions because MSVC
     172             :   // refuses to generate them.
     173             :   AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
     174             :   AnalysisResultModel(AnalysisResultModel &&Arg)
     175             :       : Result(std::move(Arg.Result)) {}
     176             : 
     177             :   friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
     178             :     using std::swap;
     179             :     swap(LHS.Result, RHS.Result);
     180             :   }
     181             : 
     182             :   AnalysisResultModel &operator=(AnalysisResultModel RHS) {
     183             :     swap(*this, RHS);
     184             :     return *this;
     185             :   }
     186             : 
     187             :   /// \brief The model bases invalidation solely on being in the preserved set.
     188             :   //
     189             :   // FIXME: We should actually use two different concepts for analysis results
     190             :   // rather than two different models, and avoid the indirect function call for
     191             :   // ones that use the trivial behavior.
     192        1488 :   bool invalidate(IRUnitT &, const PreservedAnalysesT &PA,
     193             :                   InvalidatorT &) override {
     194        1488 :     auto PAC = PA.template getChecker<PassT>();
     195        2762 :     return !PAC.preserved() &&
     196        2762 :            !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
     197             :   }
     198             : 
     199             :   ResultT Result;
     200             : };
     201             : 
     202             : /// \brief Specialization of \c AnalysisResultModel which delegates invalidate
     203             : /// handling to \c ResultT.
     204             : template <typename IRUnitT, typename PassT, typename ResultT,
     205             :           typename PreservedAnalysesT, typename InvalidatorT>
     206       22878 : struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT,
     207             :                            InvalidatorT, true>
     208             :     : AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT> {
     209       26667 :   explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
     210             :   // We have to explicitly define all the special member functions because MSVC
     211             :   // refuses to generate them.
     212             :   AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
     213             :   AnalysisResultModel(AnalysisResultModel &&Arg)
     214             :       : Result(std::move(Arg.Result)) {}
     215             : 
     216             :   friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
     217             :     using std::swap;
     218             :     swap(LHS.Result, RHS.Result);
     219             :   }
     220             : 
     221             :   AnalysisResultModel &operator=(AnalysisResultModel RHS) {
     222             :     swap(*this, RHS);
     223             :     return *this;
     224             :   }
     225             : 
     226             :   /// \brief The model delegates to the \c ResultT method.
     227       13816 :   bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA,
     228             :                   InvalidatorT &Inv) override {
     229       13838 :     return Result.invalidate(IR, PA, Inv);
     230             :   }
     231             : 
     232             :   ResultT Result;
     233             : };
     234             : 
     235             : /// \brief Abstract concept of an analysis pass.
     236             : ///
     237             : /// This concept is parameterized over the IR unit that it can run over and
     238             : /// produce an analysis result.
     239             : template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT,
     240             :           typename... ExtraArgTs>
     241             : struct AnalysisPassConcept {
     242             :   virtual ~AnalysisPassConcept() = default;
     243             : 
     244             :   /// \brief Method to run this analysis over a unit of IR.
     245             :   /// \returns A unique_ptr to the analysis result object to be queried by
     246             :   /// users.
     247             :   virtual std::unique_ptr<
     248             :       AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
     249             :   run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
     250             :       ExtraArgTs... ExtraArgs) = 0;
     251             : 
     252             :   /// \brief Polymorphic method to access the name of a pass.
     253             :   virtual StringRef name() = 0;
     254             : };
     255             : 
     256             : /// \brief Wrapper to model the analysis pass concept.
     257             : ///
     258             : /// Can wrap any type which implements a suitable \c run method. The method
     259             : /// must accept an \c IRUnitT& and an \c AnalysisManager<IRUnitT>& as arguments
     260             : /// and produce an object which can be wrapped in a \c AnalysisResultModel.
     261             : template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
     262             :           typename InvalidatorT, typename... ExtraArgTs>
     263       43435 : struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT,
     264             :                                                InvalidatorT, ExtraArgTs...> {
     265       45600 :   explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
     266             :   // We have to explicitly define all the special member functions because MSVC
     267             :   // refuses to generate them.
     268             :   AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
     269             :   AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
     270             : 
     271             :   friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
     272             :     using std::swap;
     273             :     swap(LHS.Pass, RHS.Pass);
     274             :   }
     275             : 
     276             :   AnalysisPassModel &operator=(AnalysisPassModel RHS) {
     277             :     swap(*this, RHS);
     278             :     return *this;
     279             :   }
     280             : 
     281             :   // FIXME: Replace PassT::Result with type traits when we use C++11.
     282             :   using ResultModelT =
     283             :       AnalysisResultModel<IRUnitT, PassT, typename PassT::Result,
     284             :                           PreservedAnalysesT, InvalidatorT>;
     285             : 
     286             :   /// \brief The model delegates to the \c PassT::run method.
     287             :   ///
     288             :   /// The return is wrapped in an \c AnalysisResultModel.
     289             :   std::unique_ptr<
     290             :       AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
     291       19975 :   run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
     292             :       ExtraArgTs... ExtraArgs) override {
     293       74948 :     return llvm::make_unique<ResultModelT>(Pass.run(IR, AM, ExtraArgs...));
     294             :   }
     295             : 
     296             :   /// \brief The model delegates to a static \c PassT::name method.
     297             :   ///
     298             :   /// The returned string ref must point to constant immutable data!
     299        3128 :   StringRef name() override { return PassT::name(); }
     300             : 
     301             :   PassT Pass;
     302             : };
     303             : 
     304             : } // end namespace detail
     305             : 
     306             : } // end namespace llvm
     307             : 
     308             : #endif // LLVM_IR_PASSMANAGERINTERNAL_H

Generated by: LCOV version 1.13