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"
22 #include "llvm/ADT/STLExtras.h"
26 template <typename IRUnitT> class AnalysisManager;
27 class PreservedAnalyses;
29 /// \brief Implementation details of the pass manager interfaces.
32 /// \brief Helper template to run a pass *with* an optional analysis manager.
34 /// This accepts the address of the run method as an argument to detect that it
35 /// accepts the analysis manager and pass it through. This isn't (quite)
36 /// a generic optional argument invocation tool, and couldn't be without making
37 /// the calling syntax significantly more verbose.
38 template <typename ResultT, typename IRUnitT, typename PassT>
39 ResultT invokeRunMethod(PassT &Pass,
40 ResultT (PassT::*run)(IRUnitT &,
41 AnalysisManager<IRUnitT> *),
42 IRUnitT &IR, AnalysisManager<IRUnitT> *AM) {
43 return (Pass.*run)(IR, AM);
46 /// \brief Helper template to run a pass *without* an optional analysis manager.
48 /// This accepts the address of the run method as an argument to detect that it
49 /// does not accept an analysis manager and drop it. This isn't (quite)
50 /// a generic optional argument invocation tool, and couldn't be without making
51 /// the calling syntax significantly more verbose.
52 template <typename ResultT, typename IRUnitT, typename PassT>
53 ResultT invokeRunMethod(
55 ResultT (PassT::*run)(IRUnitT &),
56 IRUnitT &IR, AnalysisManager<IRUnitT> * /*AM*/) {
57 return (Pass.*run)(IR);
60 /// \brief Template for the abstract base class used to dispatch
61 /// polymorphically over pass objects.
62 template <typename ResultT, typename IRUnitT> struct PassConceptBase {
63 virtual ~PassConceptBase() {}
65 /// \brief The polymorphic API which runs the pass over a given IR entity.
67 /// Note that actual pass object can omit the analysis manager argument if
68 /// desired. Also that the analysis manager may be null if there is no
69 /// analysis manager in the pass pipeline.
70 virtual ResultT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) = 0;
72 /// \brief Polymorphic method to access the name of a pass.
73 virtual StringRef name() = 0;
76 /// \brief Abstract concept of an transform pass.
78 /// This concept is parameterized over the IR unit that it can run over and
79 /// returns status of preserved analyses.
80 template <typename IRUnitT>
81 using PassConcept = PassConceptBase<PreservedAnalyses, IRUnitT>;
83 /// \brief A template wrapper used to implement the polymorphic API.
85 /// Can be instantiated for any object which provides a \c run method accepting
86 /// an \c IRUnitT. It requires the pass to be a copyable object. When the
87 /// \c run method also accepts an \c AnalysisManager<IRUnitT>*, we pass it
89 template <typename IRUnitT, typename PassT,
90 typename PreservedAnalysesT = PreservedAnalyses>
91 struct PassModel : PassConcept<IRUnitT> {
92 explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
93 // We have to explicitly define all the special member functions because MSVC
94 // refuses to generate them.
95 PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
96 PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
97 friend void swap(PassModel &LHS, PassModel &RHS) {
99 swap(LHS.Pass, RHS.Pass);
101 PassModel &operator=(PassModel RHS) {
106 /// \brief The model delegates to the \c PassT::run method.
107 PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
108 return invokeRunMethod<PreservedAnalysesT>(Pass, &PassT::run, IR, AM);
110 StringRef name() override { return PassT::name(); }
114 /// \brief Abstract concept of an analysis result.
116 /// This concept is parameterized over the IR unit that this result pertains
118 template <typename IRUnitT> struct AnalysisResultConcept {
119 virtual ~AnalysisResultConcept() {}
121 /// \brief Method to try and mark a result as invalid.
123 /// When the outer analysis manager detects a change in some underlying
124 /// unit of the IR, it will call this method on all of the results cached.
126 /// This method also receives a set of preserved analyses which can be used
127 /// to avoid invalidation because the pass which changed the underlying IR
128 /// took care to update or preserve the analysis result in some way.
130 /// \returns true if the result is indeed invalid (the default).
131 virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) = 0;
134 /// \brief SFINAE metafunction for computing whether \c ResultT provides an
135 /// \c invalidate member function.
136 template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
137 typedef char SmallType;
142 template <typename T, bool (T::*)(IRUnitT &, const PreservedAnalyses &)>
145 template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
146 template <typename T> static BigType f(...);
149 enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) };
152 /// \brief Wrapper to model the analysis result concept.
154 /// By default, this will implement the invalidate method with a trivial
155 /// implementation so that the actual analysis result doesn't need to provide
156 /// an invalidation handler. It is only selected when the invalidation handler
157 /// is not part of the ResultT's interface.
158 template <typename IRUnitT, typename PassT, typename ResultT,
159 typename PreservedAnalysesT = PreservedAnalyses,
160 bool HasInvalidateHandler =
161 ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
162 struct AnalysisResultModel;
164 /// \brief Specialization of \c AnalysisResultModel which provides the default
165 /// invalidate functionality.
166 template <typename IRUnitT, typename PassT, typename ResultT,
167 typename PreservedAnalysesT>
168 struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, false>
169 : AnalysisResultConcept<IRUnitT> {
170 explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
171 // We have to explicitly define all the special member functions because MSVC
172 // refuses to generate them.
173 AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
174 AnalysisResultModel(AnalysisResultModel &&Arg)
175 : Result(std::move(Arg.Result)) {}
176 friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
178 swap(LHS.Result, RHS.Result);
180 AnalysisResultModel &operator=(AnalysisResultModel RHS) {
185 /// \brief The model bases invalidation solely on being in the preserved set.
187 // FIXME: We should actually use two different concepts for analysis results
188 // rather than two different models, and avoid the indirect function call for
189 // ones that use the trivial behavior.
190 bool invalidate(IRUnitT &, const PreservedAnalysesT &PA) override {
191 return !PA.preserved(PassT::ID());
197 /// \brief Specialization of \c AnalysisResultModel which delegates invalidate
198 /// handling to \c ResultT.
199 template <typename IRUnitT, typename PassT, typename ResultT,
200 typename PreservedAnalysesT>
201 struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, true>
202 : AnalysisResultConcept<IRUnitT> {
203 explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
204 // We have to explicitly define all the special member functions because MSVC
205 // refuses to generate them.
206 AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
207 AnalysisResultModel(AnalysisResultModel &&Arg)
208 : Result(std::move(Arg.Result)) {}
209 friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
211 swap(LHS.Result, RHS.Result);
213 AnalysisResultModel &operator=(AnalysisResultModel RHS) {
218 /// \brief The model delegates to the \c ResultT method.
219 bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA) override {
220 return Result.invalidate(IR, PA);
226 /// \brief Abstract concept of an analysis pass.
228 /// This concept is parameterized over the IR unit that it can run over and
229 /// produce an analysis result.
230 template <typename IRUnitT>
231 using AnalysisPassConcept =
232 PassConceptBase<std::unique_ptr<AnalysisResultConcept<IRUnitT>>, IRUnitT>;
234 /// \brief Wrapper to model the analysis pass concept.
236 /// Can wrap any type which implements a suitable \c run method. The method
237 /// must accept the IRUnitT as an argument and produce an object which can be
238 /// wrapped in a \c AnalysisResultModel.
239 template <typename IRUnitT, typename PassT>
240 struct AnalysisPassModel : AnalysisPassConcept<IRUnitT> {
241 explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
242 // We have to explicitly define all the special member functions because MSVC
243 // refuses to generate them.
244 AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
245 AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
246 friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
248 swap(LHS.Pass, RHS.Pass);
250 AnalysisPassModel &operator=(AnalysisPassModel RHS) {
255 // FIXME: Replace PassT::Result with type traits when we use C++11.
256 using ResultT = typename PassT::Result;
257 using ResultModelT = AnalysisResultModel<IRUnitT, PassT, ResultT>;
259 /// \brief The model delegates to the \c PassT::run method.
261 /// The return is wrapped in an \c AnalysisResultModel.
262 std::unique_ptr<AnalysisResultConcept<IRUnitT>>
263 run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
264 return make_unique<ResultModelT>(
265 invokeRunMethod<ResultT>(Pass, &PassT::run, IR, AM));
268 /// \brief The model delegates to a static \c PassT::name method.
270 /// The returned string ref must point to constant immutable data!
271 StringRef name() override { return PassT::name(); }
276 } // End namespace detail