File indexing completed on 2026-05-10 08:44:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef LLVM_IR_PASSMANAGERINTERNAL_H
0018 #define LLVM_IR_PASSMANAGERINTERNAL_H
0019
0020 #include "llvm/ADT/STLExtras.h"
0021 #include "llvm/ADT/StringRef.h"
0022 #include "llvm/IR/Analysis.h"
0023 #include "llvm/Support/raw_ostream.h"
0024 #include <memory>
0025 #include <type_traits>
0026 #include <utility>
0027
0028 namespace llvm {
0029
0030 template <typename IRUnitT> class AllAnalysesOn;
0031 template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
0032 class PreservedAnalyses;
0033
0034
0035 namespace detail {
0036
0037
0038
0039 template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
0040 struct PassConcept {
0041
0042 virtual ~PassConcept() = default;
0043
0044
0045
0046
0047
0048
0049 virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
0050 ExtraArgTs... ExtraArgs) = 0;
0051
0052 virtual void
0053 printPipeline(raw_ostream &OS,
0054 function_ref<StringRef(StringRef)> MapClassName2PassName) = 0;
0055
0056 virtual StringRef name() const = 0;
0057
0058
0059
0060
0061
0062 virtual bool isRequired() const = 0;
0063 };
0064
0065
0066
0067
0068
0069
0070 template <typename IRUnitT, typename PassT, typename AnalysisManagerT,
0071 typename... ExtraArgTs>
0072 struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
0073 explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
0074
0075
0076 PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
0077 PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
0078
0079 friend void swap(PassModel &LHS, PassModel &RHS) {
0080 using std::swap;
0081 swap(LHS.Pass, RHS.Pass);
0082 }
0083
0084 PassModel &operator=(PassModel RHS) {
0085 swap(*this, RHS);
0086 return *this;
0087 }
0088
0089 PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
0090 ExtraArgTs... ExtraArgs) override {
0091 return Pass.run(IR, AM, ExtraArgs...);
0092 }
0093
0094 void printPipeline(
0095 raw_ostream &OS,
0096 function_ref<StringRef(StringRef)> MapClassName2PassName) override {
0097 Pass.printPipeline(OS, MapClassName2PassName);
0098 }
0099
0100 StringRef name() const override { return PassT::name(); }
0101
0102 template <typename T>
0103 using has_required_t = decltype(std::declval<T &>().isRequired());
0104
0105 template <typename T>
0106 static std::enable_if_t<is_detected<has_required_t, T>::value, bool>
0107 passIsRequiredImpl() {
0108 return T::isRequired();
0109 }
0110 template <typename T>
0111 static std::enable_if_t<!is_detected<has_required_t, T>::value, bool>
0112 passIsRequiredImpl() {
0113 return false;
0114 }
0115
0116 bool isRequired() const override { return passIsRequiredImpl<PassT>(); }
0117
0118 PassT Pass;
0119 };
0120
0121
0122
0123
0124
0125 template <typename IRUnitT, typename InvalidatorT>
0126 struct AnalysisResultConcept {
0127 virtual ~AnalysisResultConcept() = default;
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144 virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
0145 InvalidatorT &Inv) = 0;
0146 };
0147
0148
0149
0150 template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
0151 using EnabledType = char;
0152 struct DisabledType {
0153 char a, b;
0154 };
0155
0156
0157
0158
0159 template <typename T> struct Nonce { using Type = EnabledType; };
0160 template <typename T>
0161 static typename Nonce<decltype(std::declval<T>().invalidate(
0162 std::declval<IRUnitT &>(), std::declval<PreservedAnalyses>()))>::Type
0163 check(rank<2>);
0164
0165
0166
0167
0168
0169 template <typename T, typename U> static DisabledType NonceFunction(T U::*);
0170 struct CheckerBase { int invalidate; };
0171 template <typename T> struct Checker : CheckerBase, std::remove_cv_t<T> {};
0172 template <typename T>
0173 static decltype(NonceFunction(&Checker<T>::invalidate)) check(rank<1>);
0174
0175
0176
0177 template <typename T>
0178 static EnabledType check(rank<0>);
0179
0180 public:
0181 enum { Value = sizeof(check<ResultT>(rank<2>())) == sizeof(EnabledType) };
0182 };
0183
0184
0185
0186
0187
0188
0189
0190 template <typename IRUnitT, typename PassT, typename ResultT,
0191 typename InvalidatorT,
0192 bool HasInvalidateHandler =
0193 ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
0194 struct AnalysisResultModel;
0195
0196
0197
0198 template <typename IRUnitT, typename PassT, typename ResultT,
0199 typename InvalidatorT>
0200 struct AnalysisResultModel<IRUnitT, PassT, ResultT, InvalidatorT, false>
0201 : AnalysisResultConcept<IRUnitT, InvalidatorT> {
0202 explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
0203
0204
0205 AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
0206 AnalysisResultModel(AnalysisResultModel &&Arg)
0207 : Result(std::move(Arg.Result)) {}
0208
0209 friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
0210 using std::swap;
0211 swap(LHS.Result, RHS.Result);
0212 }
0213
0214 AnalysisResultModel &operator=(AnalysisResultModel RHS) {
0215 swap(*this, RHS);
0216 return *this;
0217 }
0218
0219
0220
0221
0222
0223
0224 bool invalidate(IRUnitT &, const PreservedAnalyses &PA,
0225 InvalidatorT &) override {
0226 auto PAC = PA.template getChecker<PassT>();
0227 return !PAC.preserved() &&
0228 !PAC.template preservedSet<AllAnalysesOn<IRUnitT>>();
0229 }
0230
0231 ResultT Result;
0232 };
0233
0234
0235
0236 template <typename IRUnitT, typename PassT, typename ResultT,
0237 typename InvalidatorT>
0238 struct AnalysisResultModel<IRUnitT, PassT, ResultT, InvalidatorT, true>
0239 : AnalysisResultConcept<IRUnitT, InvalidatorT> {
0240 explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
0241
0242
0243 AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
0244 AnalysisResultModel(AnalysisResultModel &&Arg)
0245 : Result(std::move(Arg.Result)) {}
0246
0247 friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
0248 using std::swap;
0249 swap(LHS.Result, RHS.Result);
0250 }
0251
0252 AnalysisResultModel &operator=(AnalysisResultModel RHS) {
0253 swap(*this, RHS);
0254 return *this;
0255 }
0256
0257
0258 bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
0259 InvalidatorT &Inv) override {
0260 return Result.invalidate(IR, PA, Inv);
0261 }
0262
0263 ResultT Result;
0264 };
0265
0266
0267
0268
0269
0270 template <typename IRUnitT, typename InvalidatorT, typename... ExtraArgTs>
0271 struct AnalysisPassConcept {
0272 virtual ~AnalysisPassConcept() = default;
0273
0274
0275
0276
0277 virtual std::unique_ptr<AnalysisResultConcept<IRUnitT, InvalidatorT>>
0278 run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
0279 ExtraArgTs... ExtraArgs) = 0;
0280
0281
0282 virtual StringRef name() const = 0;
0283 };
0284
0285
0286
0287
0288
0289
0290 template <typename IRUnitT, typename PassT, typename InvalidatorT,
0291 typename... ExtraArgTs>
0292 struct AnalysisPassModel
0293 : AnalysisPassConcept<IRUnitT, InvalidatorT, ExtraArgTs...> {
0294 explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
0295
0296
0297 AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
0298 AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
0299
0300 friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
0301 using std::swap;
0302 swap(LHS.Pass, RHS.Pass);
0303 }
0304
0305 AnalysisPassModel &operator=(AnalysisPassModel RHS) {
0306 swap(*this, RHS);
0307 return *this;
0308 }
0309
0310
0311 using ResultModelT =
0312 AnalysisResultModel<IRUnitT, PassT, typename PassT::Result, InvalidatorT>;
0313
0314
0315
0316
0317 std::unique_ptr<AnalysisResultConcept<IRUnitT, InvalidatorT>>
0318 run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
0319 ExtraArgTs... ExtraArgs) override {
0320 return std::make_unique<ResultModelT>(
0321 Pass.run(IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...));
0322 }
0323
0324
0325
0326
0327 StringRef name() const override { return PassT::name(); }
0328
0329 PassT Pass;
0330 };
0331
0332 }
0333
0334 }
0335
0336 #endif