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#include "llvm/ADT/STLExtras.h"
23
24namespace llvm {
25
26template <typename IRUnitT> class AnalysisManager;
27class PreservedAnalyses;
28
29/// \brief Implementation details of the pass manager interfaces.
30namespace detail {
31
32/// \brief Template for the abstract base class used to dispatch
33/// polymorphically over pass objects.
34template <typename IRUnitT> struct PassConcept {
35  // Boiler plate necessary for the container of derived classes.
36  virtual ~PassConcept() {}
37
38  /// \brief The polymorphic API which runs the pass over a given IR entity.
39  ///
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, AnalysisManager<IRUnitT> *AM) = 0;
44
45  /// \brief Polymorphic method to access the name of a pass.
46  virtual StringRef name() = 0;
47};
48
49/// \brief SFINAE metafunction for computing whether \c PassT has a run method
50/// accepting an \c AnalysisManager<IRUnitT>.
51template <typename IRUnitT, typename PassT, typename ResultT>
52class PassRunAcceptsAnalysisManager {
53  typedef char SmallType;
54  struct BigType {
55    char a, b;
56  };
57
58  template <typename T, ResultT (T::*)(IRUnitT &, AnalysisManager<IRUnitT> *)>
59  struct Checker;
60
61  template <typename T> static SmallType f(Checker<T, &T::run> *);
62  template <typename T> static BigType f(...);
63
64public:
65  enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) };
66};
67
68/// \brief A template wrapper used to implement the polymorphic API.
69///
70/// Can be instantiated for any object which provides a \c run method accepting
71/// an \c IRUnitT. It requires the pass to be a copyable object. When the
72/// \c run method also accepts an \c AnalysisManager<IRUnitT>*, we pass it
73/// along.
74template <typename IRUnitT, typename PassT,
75          typename PreservedAnalysesT = PreservedAnalyses,
76          bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
77              IRUnitT, PassT, PreservedAnalysesT>::Value>
78struct PassModel;
79
80/// \brief Specialization of \c PassModel for passes that accept an analyis
81/// manager.
82template <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
83struct PassModel<IRUnitT, PassT, PreservedAnalysesT, true>
84    : PassConcept<IRUnitT> {
85  explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
86  // We have to explicitly define all the special member functions because MSVC
87  // refuses to generate them.
88  PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
89  PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
90  friend void swap(PassModel &LHS, PassModel &RHS) {
91    using std::swap;
92    swap(LHS.Pass, RHS.Pass);
93  }
94  PassModel &operator=(PassModel RHS) {
95    swap(*this, RHS);
96    return *this;
97  }
98
99  PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
100    return Pass.run(IR, AM);
101  }
102  StringRef name() override { return PassT::name(); }
103  PassT Pass;
104};
105
106/// \brief Specialization of \c PassModel for passes that accept an analyis
107/// manager.
108template <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
109struct PassModel<IRUnitT, PassT, PreservedAnalysesT, false>
110    : PassConcept<IRUnitT> {
111  explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
112  // We have to explicitly define all the special member functions because MSVC
113  // refuses to generate them.
114  PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
115  PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
116  friend void swap(PassModel &LHS, PassModel &RHS) {
117    using std::swap;
118    swap(LHS.Pass, RHS.Pass);
119  }
120  PassModel &operator=(PassModel RHS) {
121    swap(*this, RHS);
122    return *this;
123  }
124
125  PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
126    return Pass.run(IR);
127  }
128  StringRef name() override { return PassT::name(); }
129  PassT Pass;
130};
131
132/// \brief Abstract concept of an analysis result.
133///
134/// This concept is parameterized over the IR unit that this result pertains
135/// to.
136template <typename IRUnitT> struct AnalysisResultConcept {
137  virtual ~AnalysisResultConcept() {}
138
139  /// \brief Method to try and mark a result as invalid.
140  ///
141  /// When the outer analysis manager detects a change in some underlying
142  /// unit of the IR, it will call this method on all of the results cached.
143  ///
144  /// This method also receives a set of preserved analyses which can be used
145  /// to avoid invalidation because the pass which changed the underlying IR
146  /// took care to update or preserve the analysis result in some way.
147  ///
148  /// \returns true if the result is indeed invalid (the default).
149  virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) = 0;
150};
151
152/// \brief SFINAE metafunction for computing whether \c ResultT provides an
153/// \c invalidate member function.
154template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
155  typedef char SmallType;
156  struct BigType {
157    char a, b;
158  };
159
160  template <typename T, bool (T::*)(IRUnitT &, const PreservedAnalyses &)>
161  struct Checker;
162
163  template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
164  template <typename T> static BigType f(...);
165
166public:
167  enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) };
168};
169
170/// \brief Wrapper to model the analysis result concept.
171///
172/// By default, this will implement the invalidate method with a trivial
173/// implementation so that the actual analysis result doesn't need to provide
174/// an invalidation handler. It is only selected when the invalidation handler
175/// is not part of the ResultT's interface.
176template <typename IRUnitT, typename PassT, typename ResultT,
177          typename PreservedAnalysesT = PreservedAnalyses,
178          bool HasInvalidateHandler =
179              ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
180struct AnalysisResultModel;
181
182/// \brief Specialization of \c AnalysisResultModel which provides the default
183/// invalidate functionality.
184template <typename IRUnitT, typename PassT, typename ResultT,
185          typename PreservedAnalysesT>
186struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, false>
187    : AnalysisResultConcept<IRUnitT> {
188  explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
189  // We have to explicitly define all the special member functions because MSVC
190  // refuses to generate them.
191  AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
192  AnalysisResultModel(AnalysisResultModel &&Arg)
193      : Result(std::move(Arg.Result)) {}
194  friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
195    using std::swap;
196    swap(LHS.Result, RHS.Result);
197  }
198  AnalysisResultModel &operator=(AnalysisResultModel RHS) {
199    swap(*this, RHS);
200    return *this;
201  }
202
203  /// \brief The model bases invalidation solely on being in the preserved set.
204  //
205  // FIXME: We should actually use two different concepts for analysis results
206  // rather than two different models, and avoid the indirect function call for
207  // ones that use the trivial behavior.
208  bool invalidate(IRUnitT &, const PreservedAnalysesT &PA) override {
209    return !PA.preserved(PassT::ID());
210  }
211
212  ResultT Result;
213};
214
215/// \brief Specialization of \c AnalysisResultModel which delegates invalidate
216/// handling to \c ResultT.
217template <typename IRUnitT, typename PassT, typename ResultT,
218          typename PreservedAnalysesT>
219struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, true>
220    : AnalysisResultConcept<IRUnitT> {
221  explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
222  // We have to explicitly define all the special member functions because MSVC
223  // refuses to generate them.
224  AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
225  AnalysisResultModel(AnalysisResultModel &&Arg)
226      : Result(std::move(Arg.Result)) {}
227  friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
228    using std::swap;
229    swap(LHS.Result, RHS.Result);
230  }
231  AnalysisResultModel &operator=(AnalysisResultModel RHS) {
232    swap(*this, RHS);
233    return *this;
234  }
235
236  /// \brief The model delegates to the \c ResultT method.
237  bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA) override {
238    return Result.invalidate(IR, PA);
239  }
240
241  ResultT Result;
242};
243
244/// \brief Abstract concept of an analysis pass.
245///
246/// This concept is parameterized over the IR unit that it can run over and
247/// produce an analysis result.
248template <typename IRUnitT> struct AnalysisPassConcept {
249  virtual ~AnalysisPassConcept() {}
250
251  /// \brief Method to run this analysis over a unit of IR.
252  /// \returns A unique_ptr to the analysis result object to be queried by
253  /// users.
254  virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>>
255  run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) = 0;
256
257  /// \brief Polymorphic method to access the name of a pass.
258  virtual StringRef name() = 0;
259};
260
261/// \brief Wrapper to model the analysis pass concept.
262///
263/// Can wrap any type which implements a suitable \c run method. The method
264/// must accept the IRUnitT as an argument and produce an object which can be
265/// wrapped in a \c AnalysisResultModel.
266template <typename IRUnitT, typename PassT,
267          bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
268              IRUnitT, PassT, typename PassT::Result>::Value>
269struct AnalysisPassModel;
270
271/// \brief Specialization of \c AnalysisPassModel which passes an
272/// \c AnalysisManager to PassT's run method.
273template <typename IRUnitT, typename PassT>
274struct AnalysisPassModel<IRUnitT, PassT, true> : AnalysisPassConcept<IRUnitT> {
275  explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
276  // We have to explicitly define all the special member functions because MSVC
277  // refuses to generate them.
278  AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
279  AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
280  friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
281    using std::swap;
282    swap(LHS.Pass, RHS.Pass);
283  }
284  AnalysisPassModel &operator=(AnalysisPassModel RHS) {
285    swap(*this, RHS);
286    return *this;
287  }
288
289  // FIXME: Replace PassT::Result with type traits when we use C++11.
290  typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
291      ResultModelT;
292
293  /// \brief The model delegates to the \c PassT::run method.
294  ///
295  /// The return is wrapped in an \c AnalysisResultModel.
296  std::unique_ptr<AnalysisResultConcept<IRUnitT>>
297  run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
298    return make_unique<ResultModelT>(Pass.run(IR, AM));
299  }
300
301  /// \brief The model delegates to a static \c PassT::name method.
302  ///
303  /// The returned string ref must point to constant immutable data!
304  StringRef name() override { return PassT::name(); }
305
306  PassT Pass;
307};
308
309/// \brief Specialization of \c AnalysisPassModel which does not pass an
310/// \c AnalysisManager to PassT's run method.
311template <typename IRUnitT, typename PassT>
312struct AnalysisPassModel<IRUnitT, PassT, false> : AnalysisPassConcept<IRUnitT> {
313  explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
314  // We have to explicitly define all the special member functions because MSVC
315  // refuses to generate them.
316  AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
317  AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
318  friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
319    using std::swap;
320    swap(LHS.Pass, RHS.Pass);
321  }
322  AnalysisPassModel &operator=(AnalysisPassModel RHS) {
323    swap(*this, RHS);
324    return *this;
325  }
326
327  // FIXME: Replace PassT::Result with type traits when we use C++11.
328  typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
329      ResultModelT;
330
331  /// \brief The model delegates to the \c PassT::run method.
332  ///
333  /// The return is wrapped in an \c AnalysisResultModel.
334  std::unique_ptr<AnalysisResultConcept<IRUnitT>>
335  run(IRUnitT &IR, AnalysisManager<IRUnitT> *) override {
336    return make_unique<ResultModelT>(Pass.run(IR));
337  }
338
339  /// \brief The model delegates to a static \c PassT::name method.
340  ///
341  /// The returned string ref must point to constant immutable data!
342  StringRef name() override { return PassT::name(); }
343
344  PassT Pass;
345};
346
347} // End namespace detail
348}
349
350#endif
351