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