]> git.proxmox.com Git - rustc.git/blob - src/llvm/include/llvm/IR/PassManagerInternal.h
Imported Upstream version 1.0.0+dfsg1
[rustc.git] / src / llvm / 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