@@ -257,7 +257,7 @@ struct PolymorphicBuiltinSpecializedOverloadInfo {
257
257
// / return SILValue().
258
258
SILValue getStaticOverloadForSpecializedPolymorphicBuiltin (BuiltinInst *bi);
259
259
260
- // / An ADT for writing generic code against conversion instructions.
260
+ // / A wrapper type for writing generic code against conversion instructions.
261
261
struct ConversionOperation {
262
262
SingleValueInstruction *inst = nullptr ;
263
263
@@ -331,6 +331,101 @@ struct ConversionOperation {
331
331
SILValue getConverted () { return inst->getOperand (0 ); }
332
332
};
333
333
334
+ // / A wrapper type for writing generic code against SelectEnumAddrInst and
335
+ // / SelectEnumInst.
336
+ // /
337
+ // / We use this instead of SelectEnumInstBase in order to avoid the need for
338
+ // / templating SelectEnumInstBase.
339
+ class SelectEnumOperation {
340
+ PointerUnion<SelectEnumAddrInst *, SelectEnumInst *> value;
341
+
342
+ public:
343
+ SelectEnumOperation (SelectEnumAddrInst *seai) : value(seai) {}
344
+ SelectEnumOperation (SelectEnumInst *seai) : value(seai) {}
345
+ SelectEnumOperation (SILInstruction *i) : value(nullptr ) {
346
+ if (auto *seai = dyn_cast<SelectEnumAddrInst>(i)) {
347
+ value = seai;
348
+ return ;
349
+ }
350
+
351
+ if (auto *sei = dyn_cast<SelectEnumInst>(i)) {
352
+ value = sei;
353
+ return ;
354
+ }
355
+ }
356
+
357
+ SelectEnumOperation (const SILInstruction *i)
358
+ : SelectEnumOperation(const_cast <SILInstruction *>(i)) {}
359
+
360
+ operator SingleValueInstruction *() const {
361
+ if (auto *seai = value.dyn_cast <SelectEnumAddrInst *>())
362
+ return seai;
363
+ return value.get <SelectEnumInst *>();
364
+ }
365
+
366
+ SingleValueInstruction *operator *() const {
367
+ if (auto *seai = value.dyn_cast <SelectEnumAddrInst *>())
368
+ return seai;
369
+ return value.get <SelectEnumInst *>();
370
+ }
371
+
372
+ SingleValueInstruction *operator ->() const {
373
+ if (auto *seai = value.dyn_cast <SelectEnumAddrInst *>())
374
+ return seai;
375
+ return value.get <SelectEnumInst *>();
376
+ }
377
+
378
+ operator bool () const { return bool (value); }
379
+
380
+ SILValue getOperand () {
381
+ if (auto *sei = value.dyn_cast <SelectEnumInst *>())
382
+ return sei->getOperand ();
383
+ return value.get <SelectEnumAddrInst *>()->getOperand ();
384
+ }
385
+
386
+ SILValue getEnumOperand () { return getOperand (); }
387
+
388
+ const Operand &getEnumOperandRef () {
389
+ if (auto *sei = value.dyn_cast <SelectEnumInst *>())
390
+ return sei->getEnumOperandRef ();
391
+ return value.get <SelectEnumAddrInst *>()->getEnumOperandRef ();
392
+ }
393
+
394
+ unsigned getNumCases () const {
395
+ if (auto *sei = value.dyn_cast <SelectEnumInst *>())
396
+ return sei->getNumCases ();
397
+ return value.get <SelectEnumAddrInst *>()->getNumCases ();
398
+ }
399
+
400
+ std::pair<EnumElementDecl *, SILValue> getCase (unsigned i) const {
401
+ if (auto *sei = value.dyn_cast <SelectEnumInst *>())
402
+ return sei->getCase (i);
403
+ return value.get <SelectEnumAddrInst *>()->getCase (i);
404
+ }
405
+ // / Return the value that will be used as the result for the specified enum
406
+ // / case.
407
+ SILValue getCaseResult (EnumElementDecl *D) {
408
+ if (auto *sei = value.dyn_cast <SelectEnumInst *>())
409
+ return sei->getCaseResult (D);
410
+ return value.get <SelectEnumAddrInst *>()->getCaseResult (D);
411
+ }
412
+
413
+ // / If the default refers to exactly one case decl, return it.
414
+ NullablePtr<EnumElementDecl> getUniqueCaseForDefault ();
415
+
416
+ bool hasDefault () const {
417
+ if (auto *sei = value.dyn_cast <SelectEnumInst *>())
418
+ return sei->hasDefault ();
419
+ return value.get <SelectEnumAddrInst *>()->hasDefault ();
420
+ }
421
+
422
+ SILValue getDefaultResult () const {
423
+ if (auto *sei = value.dyn_cast <SelectEnumInst *>())
424
+ return sei->getDefaultResult ();
425
+ return value.get <SelectEnumAddrInst *>()->getDefaultResult ();
426
+ }
427
+ };
428
+
334
429
} // end namespace swift
335
430
336
431
#endif
0 commit comments