1 //===- PassManager internal APIs and implementation details -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
16 //===----------------------------------------------------------------------===//
18 #ifndef LLVM_IR_PASSMANAGERINTERNAL_H
19 #define LLVM_IR_PASSMANAGERINTERNAL_H
21 #include "llvm/ADT/StringRef.h"
25 template <typename IRUnitT> class AnalysisManager;
26 class PreservedAnalyses;
28 /// \brief Implementation details of the pass manager interfaces.
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() {}
37 /// \brief The polymorphic API which runs the pass over a given IR entity.
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;
44 /// \brief Polymorphic method to access the name of a pass.
45 virtual StringRef name() = 0;
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;
57 template <typename T, ResultT (T::*)(IRUnitT &, AnalysisManager<IRUnitT> *)>
60 template <typename T> static SmallType f(Checker<T, &T::run> *);
61 template <typename T> static BigType f(...);
64 enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) };
67 /// \brief A template wrapper used to implement the polymorphic API.
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
73 template <typename IRUnitT, typename PassT,
74 typename PreservedAnalysesT = PreservedAnalyses,
75 bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
76 IRUnitT, PassT, PreservedAnalysesT>::Value>
79 /// \brief Specialization of \c PassModel for passes that accept an analyis
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) {
91 swap(LHS.Pass, RHS.Pass);
93 PassModel &operator=(PassModel RHS) {
98 PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
99 return Pass.run(IR, AM);
101 StringRef name() override { return PassT::name(); }
105 /// \brief Specialization of \c PassModel for passes that accept an analyis
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) {
117 swap(LHS.Pass, RHS.Pass);
119 PassModel &operator=(PassModel RHS) {
124 PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
127 StringRef name() override { return PassT::name(); }
131 /// \brief Abstract concept of an analysis result.
133 /// This concept is parameterized over the IR unit that this result pertains
135 template <typename IRUnitT> struct AnalysisResultConcept {
136 virtual ~AnalysisResultConcept() {}
138 /// \brief Method to try and mark a result as invalid.
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.
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.
147 /// \returns true if the result is indeed invalid (the default).
148 virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) = 0;
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;
159 template <typename T, bool (T::*)(IRUnitT &, const PreservedAnalyses &)>
162 template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
163 template <typename T> static BigType f(...);
166 enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) };
169 /// \brief Wrapper to model the analysis result concept.
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;
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) {
195 swap(LHS.Result, RHS.Result);
197 AnalysisResultModel &operator=(AnalysisResultModel RHS) {
202 /// \brief The model bases invalidation solely on being in the preserved set.
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());
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) {
228 swap(LHS.Result, RHS.Result);
230 AnalysisResultModel &operator=(AnalysisResultModel RHS) {
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);
243 /// \brief Abstract concept of an analysis pass.
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() {}
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
253 virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>>
254 run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) = 0;
256 /// \brief Polymorphic method to access the name of a pass.
257 virtual StringRef name() = 0;
260 /// \brief Wrapper to model the analysis pass concept.
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;
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) {
281 swap(LHS.Pass, RHS.Pass);
283 AnalysisPassModel &operator=(AnalysisPassModel RHS) {
288 // FIXME: Replace PassT::Result with type traits when we use C++11.
289 typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
292 /// \brief The model delegates to the \c PassT::run method.
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));
300 /// \brief The model delegates to a static \c PassT::name method.
302 /// The returned string ref must point to constant immutable data!
303 StringRef name() override { return PassT::name(); }
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) {
319 swap(LHS.Pass, RHS.Pass);
321 AnalysisPassModel &operator=(AnalysisPassModel RHS) {
326 // FIXME: Replace PassT::Result with type traits when we use C++11.
327 typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
330 /// \brief The model delegates to the \c PassT::run method.
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));
338 /// \brief The model delegates to a static \c PassT::name method.
340 /// The returned string ref must point to constant immutable data!
341 StringRef name() override { return PassT::name(); }
346 } // End namespace detail