@@ -68,6 +68,8 @@ template<typename Class>
68
68
struct class_match {
69
69
template <typename ITy>
70
70
bool match (ITy *V) { return isa<Class>(V); }
71
+
72
+ bool match (SILValue v) { return isa<Class>(&*v); }
71
73
};
72
74
73
75
template <typename Class>
@@ -83,6 +85,8 @@ struct bind_ty {
83
85
}
84
86
return false ;
85
87
}
88
+
89
+ bool match (SILValue v) { return match (&*v); }
86
90
};
87
91
88
92
// ===----------------------------------------------------------------------===//
@@ -104,6 +108,8 @@ struct match_combine_or {
104
108
return true ;
105
109
return false ;
106
110
}
111
+
112
+ bool match (SILValue v) { return match (&*v); }
107
113
};
108
114
109
115
template <typename LTy, typename RTy>
@@ -113,6 +119,8 @@ struct match_combine_and {
113
119
114
120
match_combine_and (const LTy &Left, const RTy &Right) : L(Left), R(Right) { }
115
121
122
+ bool match (SILValue v) { return match (&*v); }
123
+
116
124
template <typename ITy>
117
125
bool match (ITy *V) {
118
126
if (L.match (V))
@@ -257,10 +265,10 @@ static inline bool isSameAPIntValue(const APInt &I1, const APInt &I2,
257
265
}
258
266
259
267
// Builtin Integer Matcher
260
- struct integerliteral_ty {
268
+ struct specificintegerliteral_ty {
261
269
APInt Value;
262
270
bool isSigned;
263
- integerliteral_ty (APInt V, bool S) : Value(V), isSigned(S) { }
271
+ specificintegerliteral_ty (APInt V, bool S) : Value(V), isSigned(S) {}
264
272
265
273
template <typename ITy>
266
274
bool match (ITy *V) {
@@ -274,7 +282,8 @@ struct integerliteral_ty {
274
282
}
275
283
};
276
284
277
- static inline integerliteral_ty m_IntegerLiteralInst (APInt V, bool isSigned) {
285
+ static inline specificintegerliteral_ty
286
+ m_SpecificIntegerLiteral (APInt V, bool isSigned) {
278
287
return {V, isSigned};
279
288
}
280
289
@@ -293,187 +302,103 @@ using m_Zero = match_integer<0>;
293
302
using m_One = match_integer<1 >;
294
303
295
304
// ===----------------------------------------------------------------------===//
296
- // Unary Instructions
305
+ // Instruction Operand Matchers
297
306
// ===----------------------------------------------------------------------===//
298
307
299
- template <typename OpMatchTy, SILInstructionKind Kind>
300
- struct UnaryOp_match {
301
- OpMatchTy OpMatch;
308
+ namespace detail {
302
309
303
- UnaryOp_match (const OpMatchTy &Op) : OpMatch(Op) { }
310
+ struct GetOperandsFunctor {
311
+ template <size_t ... Idx>
312
+ std::array<SILValue, sizeof ...(Idx)>
313
+ operator ()(SILInstruction *i, llvm::index_sequence<Idx...> seq) const {
314
+ return {i->getOperand (Idx)...};
315
+ }
316
+ };
304
317
305
- bool match (SILNode *node) {
306
- if (node->getKind () != SILNodeKind (Kind))
307
- return false ;
318
+ template <typename ... MatcherTys> struct MatcherFunctor {
319
+ std::tuple<MatcherTys...> matchers;
308
320
309
- return match (cast<SILInstruction>(node));
310
- }
321
+ MatcherFunctor (const MatcherTys &... matchers) : matchers(matchers...) {}
311
322
312
- bool match (SILInstruction *I ) {
313
- if (I-> getKind () != Kind)
314
- return false ;
323
+ template < typename MatcherTy> bool individual (MatcherTy matcher, SILValue v ) {
324
+ return matcher. match (v);
325
+ }
315
326
316
- if (I->getNumOperands () != 1 )
317
- return false ;
327
+ template <size_t ... Idx>
328
+ std::array<bool , sizeof ...(MatcherTys)>
329
+ matchHelper (const std::array<SILValue, sizeof ...(MatcherTys)> &operands,
330
+ llvm::index_sequence<Idx...> seq) {
331
+ return {individual (std::get<Idx>(matchers), std::get<Idx>(operands))...};
332
+ }
318
333
319
- return OpMatch.match (I->getOperand (0 ));
334
+ bool match (SILInstruction *i) {
335
+ std::array<SILValue, sizeof ...(MatcherTys)> operands =
336
+ GetOperandsFunctor{}(i, llvm::index_sequence_for<MatcherTys...>{});
337
+ auto tmpResult =
338
+ matchHelper (operands, llvm::index_sequence_for<MatcherTys...>{});
339
+ for (unsigned i : indices (tmpResult)) {
340
+ if (!tmpResult[i])
341
+ return false ;
342
+ }
343
+ return true ;
320
344
}
321
345
};
322
346
323
- // XMacro for generating a matcher for unary op instructions that can apply
324
- // further matchers to the operands of the unary operation.
325
- #define UNARY_OP_MATCH_WITH_ARG_MATCHER (Class ) \
326
- template <typename Ty> \
327
- UnaryOp_match<Ty, SILInstructionKind::Class> \
328
- m_##Class(const Ty &T) { \
329
- return T; \
330
- }
331
- UNARY_OP_MATCH_WITH_ARG_MATCHER (AllocRefDynamicInst)
332
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ConvertFunctionInst)
333
- UNARY_OP_MATCH_WITH_ARG_MATCHER (UpcastInst)
334
- UNARY_OP_MATCH_WITH_ARG_MATCHER (PointerToAddressInst)
335
- UNARY_OP_MATCH_WITH_ARG_MATCHER (AddressToPointerInst)
336
- UNARY_OP_MATCH_WITH_ARG_MATCHER (UncheckedRefCastInst)
337
- UNARY_OP_MATCH_WITH_ARG_MATCHER (UncheckedAddrCastInst)
338
- UNARY_OP_MATCH_WITH_ARG_MATCHER (UncheckedTrivialBitCastInst)
339
- UNARY_OP_MATCH_WITH_ARG_MATCHER (UncheckedBitwiseCastInst)
340
- UNARY_OP_MATCH_WITH_ARG_MATCHER (RawPointerToRefInst)
341
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ThinToThickFunctionInst)
342
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ThickToObjCMetatypeInst)
343
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ObjCToThickMetatypeInst)
344
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ObjCMetatypeToObjectInst)
345
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ObjCExistentialMetatypeToObjectInst)
346
- UNARY_OP_MATCH_WITH_ARG_MATCHER (RetainValueInst)
347
- UNARY_OP_MATCH_WITH_ARG_MATCHER (RetainValueAddrInst)
348
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ReleaseValueInst)
349
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ReleaseValueAddrInst)
350
- UNARY_OP_MATCH_WITH_ARG_MATCHER (AutoreleaseValueInst)
351
- UNARY_OP_MATCH_WITH_ARG_MATCHER (UncheckedEnumDataInst)
352
- UNARY_OP_MATCH_WITH_ARG_MATCHER (InitEnumDataAddrInst)
353
- UNARY_OP_MATCH_WITH_ARG_MATCHER (InjectEnumAddrInst)
354
- UNARY_OP_MATCH_WITH_ARG_MATCHER (UncheckedTakeEnumDataAddrInst)
355
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ValueMetatypeInst)
356
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ExistentialMetatypeInst)
357
- UNARY_OP_MATCH_WITH_ARG_MATCHER (TupleExtractInst)
358
- UNARY_OP_MATCH_WITH_ARG_MATCHER (TupleElementAddrInst)
359
- UNARY_OP_MATCH_WITH_ARG_MATCHER (StructExtractInst)
360
- UNARY_OP_MATCH_WITH_ARG_MATCHER (StructElementAddrInst)
361
- UNARY_OP_MATCH_WITH_ARG_MATCHER (LoadInst)
362
- UNARY_OP_MATCH_WITH_ARG_MATCHER (RefElementAddrInst)
363
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ClassMethodInst)
364
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ObjCMethodInst)
365
- UNARY_OP_MATCH_WITH_ARG_MATCHER (SuperMethodInst)
366
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ObjCSuperMethodInst)
367
- UNARY_OP_MATCH_WITH_ARG_MATCHER (OpenExistentialAddrInst)
368
- UNARY_OP_MATCH_WITH_ARG_MATCHER (OpenExistentialRefInst)
369
- UNARY_OP_MATCH_WITH_ARG_MATCHER (OpenExistentialValueInst)
370
- UNARY_OP_MATCH_WITH_ARG_MATCHER (InitExistentialAddrInst)
371
- UNARY_OP_MATCH_WITH_ARG_MATCHER (InitExistentialValueInst)
372
- UNARY_OP_MATCH_WITH_ARG_MATCHER (InitExistentialRefInst)
373
- UNARY_OP_MATCH_WITH_ARG_MATCHER (DeinitExistentialAddrInst)
374
- UNARY_OP_MATCH_WITH_ARG_MATCHER (DeinitExistentialValueInst)
375
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ProjectBlockStorageInst)
376
- UNARY_OP_MATCH_WITH_ARG_MATCHER (StrongRetainInst)
377
- UNARY_OP_MATCH_WITH_ARG_MATCHER (StrongReleaseInst)
378
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ClassifyBridgeObjectInst)
379
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ValueToBridgeObjectInst)
380
- UNARY_OP_MATCH_WITH_ARG_MATCHER (FixLifetimeInst)
381
- UNARY_OP_MATCH_WITH_ARG_MATCHER (CopyBlockInst)
382
- UNARY_OP_MATCH_WITH_ARG_MATCHER (DeallocStackInst)
383
- UNARY_OP_MATCH_WITH_ARG_MATCHER (DeallocRefInst)
384
- UNARY_OP_MATCH_WITH_ARG_MATCHER (DeallocPartialRefInst)
385
- UNARY_OP_MATCH_WITH_ARG_MATCHER (DeallocBoxInst)
386
- UNARY_OP_MATCH_WITH_ARG_MATCHER (DestroyAddrInst)
387
- UNARY_OP_MATCH_WITH_ARG_MATCHER (CondFailInst)
388
- UNARY_OP_MATCH_WITH_ARG_MATCHER (ReturnInst)
389
- #define LOADABLE_REF_STORAGE_HELPER (Name ) \
390
- UNARY_OP_MATCH_WITH_ARG_MATCHER (RefTo##Name##Inst) \
391
- UNARY_OP_MATCH_WITH_ARG_MATCHER (Name##ToRefInst)
392
- #define NEVER_LOADABLE_CHECKED_REF_STORAGE (Name, ...) \
393
- UNARY_OP_MATCH_WITH_ARG_MATCHER (Load##Name##Inst)
394
- #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE (Name, ...) \
395
- LOADABLE_REF_STORAGE_HELPER (Name) \
396
- UNARY_OP_MATCH_WITH_ARG_MATCHER (Name##RetainInst) \
397
- UNARY_OP_MATCH_WITH_ARG_MATCHER (Name##ReleaseInst) \
398
- UNARY_OP_MATCH_WITH_ARG_MATCHER (StrongRetain##Name##Inst)
399
- #define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE (Name, ...) \
400
- NEVER_LOADABLE_CHECKED_REF_STORAGE (Name, " ..." ) \
401
- ALWAYS_LOADABLE_CHECKED_REF_STORAGE (Name, " ..." )
402
- #define UNCHECKED_REF_STORAGE (Name, ...) \
403
- LOADABLE_REF_STORAGE_HELPER (Name)
404
- #include " swift/AST/ReferenceStorage.def"
405
- #undef LOADABLE_REF_STORAGE_HELPER
406
-
407
- #undef UNARY_OP_MATCH_WITH_ARG_MATCHER
347
+ } // namespace detail
408
348
409
- // ===----------------------------------------------------------------------===//
410
- // Binary Instructions
411
- // ===----------------------------------------------------------------------===//
349
+ // NOTE: These matchers only can accept compound, non-fundamental
350
+ // types. This prevents by mistake passing in int, float, etc to these
351
+ // matchers.
352
+ template <SILInstructionKind Kind, typename ... MatcherTys>
353
+ struct InstructionOperand_match {
354
+ // This just makes sure that we catch common mistakes passing
355
+ // fundamental types (i.e. int, float, etc) to this API.
356
+ static_assert (
357
+ are_all_compound<MatcherTys...>::value,
358
+ " Expected all matcher tys to be non-fundamental compound types?!" );
359
+ detail::MatcherFunctor<MatcherTys...> matcherFunctor;
412
360
413
- template <typename LHSTy, typename RHSTy, SILInstructionKind Kind>
414
- struct BinaryOp_match {
415
- LHSTy L;
416
- RHSTy R;
361
+ static constexpr unsigned NumMatchers = sizeof ...(MatcherTys);
417
362
418
- BinaryOp_match (const LHSTy &LHS, const RHSTy &RHS) : L(LHS), R(RHS) {}
363
+ // Only allow for these to be constructed from non-fundamental types.
364
+ InstructionOperand_match (const MatcherTys &... matchers)
365
+ : matcherFunctor(matchers...) {}
419
366
420
367
bool match (SILNode *node) {
421
368
if (node->getKind () != SILNodeKind (Kind))
422
369
return false ;
423
-
424
370
return match (cast<SILInstruction>(node));
425
371
}
426
372
427
- bool match (SILInstruction *I ) {
428
- if (I ->getKind () != Kind)
373
+ bool match (SILInstruction *i ) {
374
+ if (i ->getKind () != Kind || !(i-> getNumOperands () <= NumMatchers) )
429
375
return false ;
430
376
431
- if (I->getNumOperands () != 2 )
432
- return false ;
433
-
434
- return L.match ((ValueBase *)I->getOperand (0 )) &&
435
- R.match ((ValueBase *)I->getOperand (1 ));
377
+ return matcherFunctor.match (i);
436
378
}
437
379
};
438
380
439
- template <typename LTy, typename RTy>
440
- BinaryOp_match<LTy, RTy, SILInstructionKind::IndexRawPointerInst>
441
- m_IndexRawPointerInst (const LTy &Left, const RTy &Right) {
442
- return {Left, Right};
443
- }
381
+ #define FULL_INST (ID, NAME, PARENT, MEMBEHAVIOR, MAYRELEASE ) \
382
+ template <typename ... MatcherTys> \
383
+ InstructionOperand_match<SILInstructionKind::ID, MatcherTys...> m_##ID( \
384
+ const MatcherTys &... matchers) { \
385
+ return {matchers...}; \
386
+ }
387
+ #include " swift/SIL/SILNodes.def"
444
388
445
389
// ===----------------------------------------------------------------------===//
446
390
// Address/Struct Projections
447
391
// ===----------------------------------------------------------------------===//
448
392
449
- template <typename LTy>
450
- struct tupleextract_ty {
451
- LTy L;
452
- unsigned index;
453
- tupleextract_ty (const LTy &Left, unsigned i) : L(Left), index(i) { }
454
-
455
- template <typename ITy>
456
- bool match (ITy *V) {
457
- auto *TEI = dyn_cast<TupleExtractInst>(V);
458
- if (!TEI)
459
- return false ;
460
-
461
- return TEI->getFieldNo () == index && L.match ((ValueBase *)TEI->getOperand ());
462
- }
463
- };
464
-
465
- template <typename LTy>
466
- tupleextract_ty<LTy> m_TupleExtractInst (const LTy &Left, unsigned Index) {
467
- return tupleextract_ty<LTy>(Left, Index);
468
- }
469
-
470
393
// / Match either a tuple_extract that the index field from a tuple or the
471
394
// / indexth destructure_tuple result.
472
395
template <typename LTy> struct tupleextractoperation_ty {
473
396
LTy L;
474
397
unsigned index;
475
398
tupleextractoperation_ty (const LTy &Left, unsigned i) : L(Left), index(i) {}
476
399
400
+ bool match (SILValue v) { return match (v->getDefiningInstruction ()); }
401
+
477
402
template <typename ITy> bool match (ITy *V) {
478
403
if (auto *TEI = dyn_cast<TupleExtractInst>(V)) {
479
404
return TEI->getFieldNo () == index &&
0 commit comments