@@ -1457,6 +1457,8 @@ EnumTypeLayoutEntry::CopyDestroyStrategy
1457
1457
EnumTypeLayoutEntry::copyDestroyKind (IRGenFunction &IGF) const {
1458
1458
if (isPOD ()) {
1459
1459
return POD;
1460
+ } else if (isSingleton ()) {
1461
+ return ForwardToPayload;
1460
1462
} else if (cases.size () == 1 && numEmptyCases <= 1 &&
1461
1463
cases[0 ]->isSingleRetainablePointer ()) {
1462
1464
return NullableRefcounted;
@@ -1476,7 +1478,9 @@ llvm::Value *EnumTypeLayoutEntry::size(IRGenFunction &IGF) const {
1476
1478
auto &ctx = IGM.getLLVMContext ();
1477
1479
1478
1480
auto emptyCaseCount = IGM.getInt32 (numEmptyCases);
1479
- if (cases.size () == 1 ) {
1481
+ if (cases.size () == 1 && numEmptyCases == 0 ) {
1482
+ return cases[0 ]->size (IGF);
1483
+ } else if (cases.size () == 1 ) {
1480
1484
// Single payload enum.
1481
1485
// // If there are enough extra inhabitants for all of the cases, then the
1482
1486
// // size of the enum is the same as its payload.
@@ -1570,7 +1574,10 @@ llvm::Optional<Size> EnumTypeLayoutEntry::fixedSize(IRGenModule &IGM) const {
1570
1574
if (_fixedSize)
1571
1575
return *_fixedSize;
1572
1576
assert (!cases.empty ());
1573
- if (cases.size () == 1 ) {
1577
+
1578
+ if (cases.size () == 1 && numEmptyCases == 0 ) {
1579
+ return cases[0 ]->fixedSize (IGM);
1580
+ } else if (cases.size () == 1 ) {
1574
1581
// Single payload enum.
1575
1582
//
1576
1583
// If there are enough extra inhabitants for all of the cases, then the
@@ -1632,7 +1639,9 @@ EnumTypeLayoutEntry::fixedXICount(IRGenModule &IGM) const {
1632
1639
return *_fixedXICount;
1633
1640
assert (!cases.empty ());
1634
1641
1635
- if (cases.size () == 1 ) {
1642
+ if (cases.size () == 1 && numEmptyCases == 0 ) {
1643
+ return cases[0 ]->fixedXICount (IGM);
1644
+ } else if (cases.size () == 1 ) {
1636
1645
// Single payload enum.
1637
1646
// unsigned unusedExtraInhabitants =
1638
1647
// payloadNumExtraInhabitants >= emptyCases ?
@@ -1677,7 +1686,9 @@ llvm::Value *EnumTypeLayoutEntry::extraInhabitantCount(IRGenFunction &IGF) const
1677
1686
auto &IGM = IGF.IGM ;
1678
1687
auto &Builder = IGF.Builder ;
1679
1688
1680
- if (cases.size () == 1 ) {
1689
+ if (cases.size () == 1 && numEmptyCases == 0 ) {
1690
+ return cases[0 ]->extraInhabitantCount (IGF);
1691
+ } else if (cases.size () == 1 ) {
1681
1692
// Single payload enum.
1682
1693
// unsigned unusedExtraInhabitants =
1683
1694
// payloadNumExtraInhabitants >= emptyCases ?
@@ -2211,7 +2222,9 @@ llvm::Value *EnumTypeLayoutEntry::getEnumTagSinglePayloadForSinglePayloadEnum(
2211
2222
llvm::Value *EnumTypeLayoutEntry::getEnumTagSinglePayload (
2212
2223
IRGenFunction &IGF, llvm::Value *emptyCases, Address addr) const {
2213
2224
assert (!cases.empty ());
2214
- if (cases.size () == 1 ) {
2225
+ if (cases.size () == 1 && numEmptyCases == 0 ) {
2226
+ return cases[0 ]->getEnumTagSinglePayload (IGF, emptyCases, addr);
2227
+ } else if (cases.size () == 1 ) {
2215
2228
return getEnumTagSinglePayloadForSinglePayloadEnum (IGF, addr, emptyCases);
2216
2229
}
2217
2230
return getEnumTagSinglePayloadForMultiPayloadEnum (IGF, addr, emptyCases);
@@ -2290,7 +2303,9 @@ void EnumTypeLayoutEntry::storeEnumTagSinglePayload(IRGenFunction &IGF,
2290
2303
llvm::Value *emptyCases,
2291
2304
Address addr) const {
2292
2305
assert (!cases.empty ());
2293
- if (cases.size () == 1 ) {
2306
+ if (cases.size () == 1 && numEmptyCases == 0 ) {
2307
+ return cases[0 ]->storeEnumTagSinglePayload (IGF, tag, emptyCases, addr);
2308
+ } else if (cases.size () == 1 ) {
2294
2309
storeEnumTagSinglePayloadForSinglePayloadEnum (IGF, tag, emptyCases, addr);
2295
2310
return ;
2296
2311
}
@@ -2302,6 +2317,10 @@ bool EnumTypeLayoutEntry::isMultiPayloadEnum() const {
2302
2317
return cases.size () > 1 ;
2303
2318
}
2304
2319
2320
+ bool EnumTypeLayoutEntry::isSingleton () const {
2321
+ return cases.size () + numEmptyCases == 1 ;
2322
+ }
2323
+
2305
2324
llvm::Value *
2306
2325
EnumTypeLayoutEntry::getEnumTagMultipayload (IRGenFunction &IGF,
2307
2326
Address enumAddr) const {
@@ -2376,7 +2395,10 @@ llvm::Value *EnumTypeLayoutEntry::getEnumTag(IRGenFunction &IGF,
2376
2395
Address enumAddr) const {
2377
2396
assert (!cases.empty ());
2378
2397
2379
- if (cases.size () == 1 ) {
2398
+ if (isSingleton ()) {
2399
+ // Singleton tag is always `0`
2400
+ return IGF.IGM .getInt32 (0 );
2401
+ } else if (cases.size () == 1 ) {
2380
2402
// Single payload enum.
2381
2403
auto &IGM = IGF.IGM ;
2382
2404
auto payload = cases[0 ];
@@ -2480,7 +2502,10 @@ void EnumTypeLayoutEntry::storeEnumTagMultipayload(IRGenFunction &IGF,
2480
2502
void EnumTypeLayoutEntry::destructiveInjectEnumTag (IRGenFunction &IGF,
2481
2503
llvm::Value *tag,
2482
2504
Address enumAddr) const {
2483
- if (cases.size () == 1 ) {
2505
+ if (isSingleton ()) {
2506
+ // No tag, nothing to do
2507
+ return ;
2508
+ } else if (cases.size () == 1 ) {
2484
2509
auto payload = cases[0 ];
2485
2510
auto emptyCases = IGF.IGM .getInt32 (numEmptyCases);
2486
2511
payload->storeEnumTagSinglePayload (IGF, tag, emptyCases, enumAddr);
0 commit comments