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