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