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 24 namespace llvm { 25 26 template <typename IRUnitT> class AnalysisManager; 27 class PreservedAnalyses; 28 29 /// \brief Implementation details of the pass manager interfaces. 30 namespace detail { 31 32 /// \brief Template for the abstract base class used to dispatch 33 /// polymorphically over pass objects. 34 template <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>. 51 template <typename IRUnitT, typename PassT, typename ResultT> 52 class 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 64 public: 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. 74 template <typename IRUnitT, typename PassT, 75 typename PreservedAnalysesT = PreservedAnalyses, 76 bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager< 77 IRUnitT, PassT, PreservedAnalysesT>::Value> 78 struct PassModel; 79 80 /// \brief Specialization of \c PassModel for passes that accept an analyis 81 /// manager. 82 template <typename IRUnitT, typename PassT, typename PreservedAnalysesT> 83 struct 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. 108 template <typename IRUnitT, typename PassT, typename PreservedAnalysesT> 109 struct 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. 136 template <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. 154 template <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 166 public: 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. 176 template <typename IRUnitT, typename PassT, typename ResultT, 177 typename PreservedAnalysesT = PreservedAnalyses, 178 bool HasInvalidateHandler = 179 ResultHasInvalidateMethod<IRUnitT, ResultT>::Value> 180 struct AnalysisResultModel; 181 182 /// \brief Specialization of \c AnalysisResultModel which provides the default 183 /// invalidate functionality. 184 template <typename IRUnitT, typename PassT, typename ResultT, 185 typename PreservedAnalysesT> 186 struct 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. 217 template <typename IRUnitT, typename PassT, typename ResultT, 218 typename PreservedAnalysesT> 219 struct 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. 248 template <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. 266 template <typename IRUnitT, typename PassT, 267 bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager< 268 IRUnitT, PassT, typename PassT::Result>::Value> 269 struct AnalysisPassModel; 270 271 /// \brief Specialization of \c AnalysisPassModel which passes an 272 /// \c AnalysisManager to PassT's run method. 273 template <typename IRUnitT, typename PassT> 274 struct 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. 311 template <typename IRUnitT, typename PassT> 312 struct 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