PassManagerInternal.h 13 KB

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