LLVM  3.7.0
PassManagerInternal.h
Go to the documentation of this file.
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 
24 namespace llvm {
25 
26 template <typename IRUnitT> class AnalysisManager;
27 class PreservedAnalyses;
28 
29 /// \brief Implementation details of the pass manager interfaces.
30 namespace detail {
31 
32 /// \brief Template for the abstract base class used to dispatch
33 /// polymorphically over pass objects.
34 template <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>.
51 template <typename IRUnitT, typename PassT, typename ResultT>
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 
64 public:
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.
74 template <typename IRUnitT, typename PassT,
75  typename PreservedAnalysesT = PreservedAnalyses,
76  bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
77  IRUnitT, PassT, PreservedAnalysesT>::Value>
78 struct PassModel;
79 
80 /// \brief Specialization of \c PassModel for passes that accept an analyis
81 /// manager.
82 template <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
83 struct 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  }
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.
108 template <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
109 struct 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  }
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.
136 template <typename IRUnitT> struct 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.
154 template <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 
166 public:
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.
176 template <typename IRUnitT, typename PassT, typename ResultT,
177  typename PreservedAnalysesT = PreservedAnalyses,
178  bool HasInvalidateHandler =
181 
182 /// \brief Specialization of \c AnalysisResultModel which provides the default
183 /// invalidate functionality.
184 template <typename IRUnitT, typename PassT, typename ResultT,
185  typename PreservedAnalysesT>
186 struct 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) {}
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  }
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.
217 template <typename IRUnitT, typename PassT, typename ResultT,
218  typename PreservedAnalysesT>
219 struct 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) {}
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  }
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.
248 template <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.
266 template <typename IRUnitT, typename PassT,
267  bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
268  IRUnitT, PassT, typename PassT::Result>::Value>
270 
271 /// \brief Specialization of \c AnalysisPassModel which passes an
272 /// \c AnalysisManager to PassT's run method.
273 template <typename IRUnitT, typename PassT>
274 struct 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.
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  }
285  swap(*this, RHS);
286  return *this;
287  }
288 
289  // FIXME: Replace PassT::Result with type traits when we use C++11.
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.
311 template <typename IRUnitT, typename PassT>
312 struct 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.
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  }
323  swap(*this, RHS);
324  return *this;
325  }
326 
327  // FIXME: Replace PassT::Result with type traits when we use C++11.
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
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:82
Wrapper to model the analysis pass concept.
friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS)
virtual StringRef name()=0
Polymorphic method to access the name of a pass.
AnalysisResultModel< IRUnitT, PassT, typename PassT::Result > ResultModelT
Template for the abstract base class used to dispatch polymorphically over pass objects.
SFINAE metafunction for computing whether ResultT provides an invalidate member function.
AnalysisPassModel & operator=(AnalysisPassModel RHS)
Abstract concept of an analysis pass.
friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS)
SFINAE metafunction for computing whether PassT has a run method accepting an AnalysisManager<IRUnitT...
virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager< IRUnitT > *AM)=0
The polymorphic API which runs the pass over a given IR entity.
#define false
Definition: ConvertUTF.c:65
bool invalidate(IRUnitT &, const PreservedAnalysesT &PA) override
The model bases invalidation solely on being in the preserved set.
std::unique_ptr< AnalysisResultConcept< IRUnitT > > run(IRUnitT &IR, AnalysisManager< IRUnitT > *) override
The model delegates to the PassT::run method.
#define true
Definition: ConvertUTF.c:66
friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS)
An abstract set of preserved analyses following a transformation pass run.
Definition: PassManager.h:69
Wrapper to model the analysis result concept.
AnalysisPassModel & operator=(AnalysisPassModel RHS)
bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA) override
The model delegates to the ResultT method.
PreservedAnalysesT run(IRUnitT &IR, AnalysisManager< IRUnitT > *AM) override
The polymorphic API which runs the pass over a given IR entity.
A template wrapper used to implement the polymorphic API.
std::unique_ptr< AnalysisResultConcept< IRUnitT > > run(IRUnitT &IR, AnalysisManager< IRUnitT > *AM) override
The model delegates to the PassT::run method.
Abstract concept of an analysis result.
StringRef name() override
The model delegates to a static PassT::name method.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:576
StringRef name() override
The model delegates to a static PassT::name method.
AnalysisResultModel< IRUnitT, PassT, typename PassT::Result > ResultModelT
StringRef name() override
Polymorphic method to access the name of a pass.
LLVM Value Representation.
Definition: Value.h:69
static const char * name
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
A generic analysis pass manager with lazy running and caching of results.
friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS)
PreservedAnalysesT run(IRUnitT &IR, AnalysisManager< IRUnitT > *AM) override
The polymorphic API which runs the pass over a given IR entity.
Statically lint checks LLVM IR
Definition: Lint.cpp:169
StringRef name() override
Polymorphic method to access the name of a pass.