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