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