297f5f4e07f41588a11711b415398df56da8f902
[oota-llvm.git] / include / llvm / IR / PassManagerInternal.h
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.
35   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