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"
27 class PreservedAnalyses;
29 /// \brief Implementation details of the pass manager interfaces.
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() {}
38 /// \brief The polymorphic API which runs the pass over a given IR entity.
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;
45 /// \brief Polymorphic method to access the name of a pass.
46 virtual StringRef name() = 0;
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,
53 class PassRunAcceptsAnalysisManager {
54 typedef char SmallType;
59 template <typename T, ResultT (T::*)(IRUnitT, AnalysisManagerT *)>
62 template <typename T> static SmallType f(Checker<T, &T::run> *);
63 template <typename T> static BigType f(...);
66 enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) };
69 /// \brief A template wrapper used to implement the polymorphic API.
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>
80 /// \brief Specialization of \c PassModel for passes that accept an analyis
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) {
93 swap(LHS.Pass, RHS.Pass);
95 PassModel &operator=(PassModel RHS) {
100 PreservedAnalysesT run(IRUnitT IR, AnalysisManagerT *AM) override {
101 return Pass.run(IR, AM);
103 StringRef name() override { return PassT::name(); }
107 /// \brief Specialization of \c PassModel for passes that accept an analyis
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) {
120 swap(LHS.Pass, RHS.Pass);
122 PassModel &operator=(PassModel RHS) {
127 PreservedAnalysesT run(IRUnitT IR, AnalysisManagerT *AM) override {
130 StringRef name() override { return PassT::name(); }
134 /// \brief Abstract concept of an analysis result.
136 /// This concept is parameterized over the IR unit that this result pertains
138 template <typename IRUnitT> struct AnalysisResultConcept {
139 virtual ~AnalysisResultConcept() {}
141 /// \brief Method to try and mark a result as invalid.
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.
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.
150 /// \returns true if the result is indeed invalid (the default).
151 virtual bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) = 0;
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;
162 template <typename T, bool (T::*)(IRUnitT, const PreservedAnalyses &)>
165 template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
166 template <typename T> static BigType f(...);
169 enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) };
172 /// \brief Wrapper to model the analysis result concept.
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;
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) {
198 swap(LHS.Result, RHS.Result);
200 AnalysisResultModel &operator=(AnalysisResultModel RHS) {
205 /// \brief The model bases invalidation solely on being in the preserved set.
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());
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) {
231 swap(LHS.Result, RHS.Result);
233 AnalysisResultModel &operator=(AnalysisResultModel RHS) {
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);
246 /// \brief Abstract concept of an analysis pass.
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() {}
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
257 virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>>
258 run(IRUnitT IR, AnalysisManagerT *AM) = 0;
260 /// \brief Polymorphic method to access the name of a pass.
261 virtual StringRef name() = 0;
264 /// \brief Wrapper to model the analysis pass concept.
266 /// Can wrap any type which implements a suitable \c run method. The method
267 /// must accept the IRUnitT as an argument and produce an object which can be
268 /// wrapped in a \c AnalysisResultModel.
269 template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
270 bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
271 IRUnitT, AnalysisManagerT, PassT, typename PassT::Result>::Value>
272 struct AnalysisPassModel;
274 /// \brief Specialization of \c AnalysisPassModel which passes an
275 /// \c AnalysisManager to PassT's run method.
276 template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
277 struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, true>
278 : AnalysisPassConcept<IRUnitT, AnalysisManagerT> {
279 explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
280 // We have to explicitly define all the special member functions because MSVC
281 // refuses to generate them.
282 AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
283 AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
284 friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
286 swap(LHS.Pass, RHS.Pass);
288 AnalysisPassModel &operator=(AnalysisPassModel RHS) {
293 // FIXME: Replace PassT::Result with type traits when we use C++11.
294 typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
297 /// \brief The model delegates to the \c PassT::run method.
299 /// The return is wrapped in an \c AnalysisResultModel.
300 std::unique_ptr<AnalysisResultConcept<IRUnitT>>
301 run(IRUnitT IR, AnalysisManagerT *AM) override {
302 return make_unique<ResultModelT>(Pass.run(IR, AM));
305 /// \brief The model delegates to a static \c PassT::name method.
307 /// The returned string ref must point to constant immutable data!
308 StringRef name() override { return PassT::name(); }
313 /// \brief Specialization of \c AnalysisPassModel which does not pass an
314 /// \c AnalysisManager to PassT's run method.
315 template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
316 struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, false>
317 : AnalysisPassConcept<IRUnitT, AnalysisManagerT> {
318 explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
319 // We have to explicitly define all the special member functions because MSVC
320 // refuses to generate them.
321 AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
322 AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
323 friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
325 swap(LHS.Pass, RHS.Pass);
327 AnalysisPassModel &operator=(AnalysisPassModel RHS) {
332 // FIXME: Replace PassT::Result with type traits when we use C++11.
333 typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
336 /// \brief The model delegates to the \c PassT::run method.
338 /// The return is wrapped in an \c AnalysisResultModel.
339 std::unique_ptr<AnalysisResultConcept<IRUnitT>>
340 run(IRUnitT IR, AnalysisManagerT *) override {
341 return make_unique<ResultModelT>(Pass.run(IR));
344 /// \brief The model delegates to a static \c PassT::name method.
346 /// The returned string ref must point to constant immutable data!
347 StringRef name() override { return PassT::name(); }
352 } // End namespace detail