Skip to content

Commit 9ccc740

Browse files
authored
Merge pull request #67257 from tbkka/tbkka-rdar111705059-project-MPE-with-zero-sized-payloads
[RemoteMirror] Correctly project enums with zero-sized payloads
2 parents 6b54ba9 + a897fcb commit 9ccc740

File tree

3 files changed

+186
-16
lines changed

3 files changed

+186
-16
lines changed

stdlib/public/RemoteInspection/TypeLowering.cpp

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -653,13 +653,16 @@ class SinglePayloadEnumTypeInfo: public EnumTypeInfo {
653653
// }
654654
// ```
655655
class TaggedMultiPayloadEnumTypeInfo: public EnumTypeInfo {
656+
unsigned NumEffectivePayloadCases;
656657
public:
657658
TaggedMultiPayloadEnumTypeInfo(unsigned Size, unsigned Alignment,
658659
unsigned Stride, unsigned NumExtraInhabitants,
659660
bool BitwiseTakable,
660-
const std::vector<FieldInfo> &Cases)
661+
const std::vector<FieldInfo> &Cases,
662+
unsigned NumEffectivePayloadCases)
661663
: EnumTypeInfo(Size, Alignment, Stride, NumExtraInhabitants,
662-
BitwiseTakable, EnumKind::MultiPayloadEnum, Cases) {
664+
BitwiseTakable, EnumKind::MultiPayloadEnum, Cases),
665+
NumEffectivePayloadCases(NumEffectivePayloadCases) {
663666
// Definition of "multi-payload enum"
664667
assert(getCases().size() > 1); // At least 2 cases
665668
assert(Cases[0].TR != 0); // At least 2 payloads
@@ -698,7 +701,7 @@ class TaggedMultiPayloadEnumTypeInfo: public EnumTypeInfo {
698701
remote::RemoteAddress address,
699702
int *CaseIndex) const override {
700703
unsigned long PayloadSize = getPayloadSize();
701-
unsigned PayloadCount = getNumPayloadCases();
704+
unsigned PayloadCount = NumEffectivePayloadCases;
702705
unsigned NumCases = getNumCases();
703706
unsigned TagSize = getSize() - PayloadSize;
704707
unsigned tag = 0;
@@ -1030,15 +1033,24 @@ class BitMask {
10301033
// bits in the payload.
10311034
class MultiPayloadEnumTypeInfo: public EnumTypeInfo {
10321035
BitMask spareBitsMask;
1036+
// "Effective" payload cases includes those with
1037+
// generic payload and non-generic cases that are
1038+
// statically known to have non-zero size.
1039+
// It does not include cases with payloads that are
1040+
// non-generic and zero-sized (these are treated as
1041+
// non-payload cases for many purposes).
1042+
unsigned NumEffectivePayloadCases;
10331043
public:
10341044
MultiPayloadEnumTypeInfo(unsigned Size, unsigned Alignment,
10351045
unsigned Stride, unsigned NumExtraInhabitants,
10361046
bool BitwiseTakable,
10371047
const std::vector<FieldInfo> &Cases,
1038-
BitMask spareBitsMask)
1048+
BitMask spareBitsMask,
1049+
unsigned NumEffectivePayloadCases)
10391050
: EnumTypeInfo(Size, Alignment, Stride, NumExtraInhabitants,
10401051
BitwiseTakable, EnumKind::MultiPayloadEnum, Cases),
1041-
spareBitsMask(spareBitsMask) {
1052+
spareBitsMask(spareBitsMask),
1053+
NumEffectivePayloadCases(NumEffectivePayloadCases) {
10421054
assert(Cases[0].TR != 0);
10431055
assert(Cases[1].TR != 0);
10441056
assert(getNumNonEmptyPayloadCases() > 1);
@@ -1125,7 +1137,6 @@ class MultiPayloadEnumTypeInfo: public EnumTypeInfo {
11251137
remote::RemoteAddress address,
11261138
int *CaseIndex) const override {
11271139
unsigned long payloadSize = getPayloadSize();
1128-
unsigned NumPayloadCases = getNumPayloadCases();
11291140

11301141
// Extra Tag (if any) holds upper bits of case value
11311142
auto extraTagSize = getSize() - payloadSize;
@@ -1156,7 +1167,7 @@ class MultiPayloadEnumTypeInfo: public EnumTypeInfo {
11561167
}
11571168

11581169
// If the above identifies a payload case, we're done
1159-
if (static_cast<unsigned>(tagValue) < NumPayloadCases) {
1170+
if (static_cast<unsigned>(tagValue) < NumEffectivePayloadCases) {
11601171
*CaseIndex = tagValue;
11611172
return true;
11621173
}
@@ -1173,9 +1184,9 @@ class MultiPayloadEnumTypeInfo: public EnumTypeInfo {
11731184

11741185
int ComputedCase = 0;
11751186
if (occupiedBitCount >= 32) {
1176-
ComputedCase = payloadValue + NumPayloadCases;
1187+
ComputedCase = payloadValue + NumEffectivePayloadCases;
11771188
} else {
1178-
ComputedCase = (((tagValue - NumPayloadCases) << occupiedBitCount) | payloadValue) + NumPayloadCases;
1189+
ComputedCase = (((tagValue - NumEffectivePayloadCases) << occupiedBitCount) | payloadValue) + NumEffectivePayloadCases;
11791190
}
11801191

11811192
if (static_cast<unsigned>(ComputedCase) < getNumCases()) {
@@ -1193,8 +1204,8 @@ class MultiPayloadEnumTypeInfo: public EnumTypeInfo {
11931204
// * The remainder of the payload bits (for non-payload cases)
11941205
// This computes the bits used for the payload tag.
11951206
BitMask getMultiPayloadTagBitsMask() const {
1196-
auto payloadTagValues = getNumPayloadCases() - 1;
1197-
if (getNumCases() > getNumPayloadCases()) {
1207+
auto payloadTagValues = NumEffectivePayloadCases - 1;
1208+
if (getNumCases() > NumEffectivePayloadCases) {
11981209
payloadTagValues += 1;
11991210
}
12001211
int payloadTagBits = 0;
@@ -2257,7 +2268,7 @@ class EnumTypeInfoBuilder {
22572268
Stride = 1;
22582269
return TC.makeTypeInfo<TaggedMultiPayloadEnumTypeInfo>(
22592270
Size, Alignment, Stride, NumExtraInhabitants,
2260-
BitwiseTakable, Cases);
2271+
BitwiseTakable, Cases, EffectivePayloadCases);
22612272
}
22622273

22632274
// This is a multi-payload enum that:
@@ -2291,7 +2302,7 @@ class EnumTypeInfoBuilder {
22912302
// If there are no spare bits, use the "simple" tag-only implementation.
22922303
return TC.makeTypeInfo<TaggedMultiPayloadEnumTypeInfo>(
22932304
Size, Alignment, Stride, NumExtraInhabitants,
2294-
BitwiseTakable, Cases);
2305+
BitwiseTakable, Cases, EffectivePayloadCases);
22952306
}
22962307

22972308
#if 0 // TODO: This should be !defined(NDEBUG)
@@ -2314,7 +2325,8 @@ class EnumTypeInfoBuilder {
23142325
// Use compiler-provided spare bit information
23152326
return TC.makeTypeInfo<MultiPayloadEnumTypeInfo>(
23162327
Size, Alignment, Stride, NumExtraInhabitants,
2317-
BitwiseTakable, Cases, spareBitsMask);
2328+
BitwiseTakable, Cases, spareBitsMask,
2329+
EffectivePayloadCases);
23182330
}
23192331

23202332
// Either there was no compiler data or it didn't make sense
@@ -2339,13 +2351,14 @@ class EnumTypeInfoBuilder {
23392351
// above only returns an empty mask when the mask is really empty,
23402352
return TC.makeTypeInfo<TaggedMultiPayloadEnumTypeInfo>(
23412353
Size, Alignment, Stride, NumExtraInhabitants,
2342-
BitwiseTakable, Cases);
2354+
BitwiseTakable, Cases, EffectivePayloadCases);
23432355
} else {
23442356
// General case can mix spare bits and extra discriminator
23452357
// It obviously relies on having an accurate spare bit mask.
23462358
return TC.makeTypeInfo<MultiPayloadEnumTypeInfo>(
23472359
Size, Alignment, Stride, NumExtraInhabitants,
2348-
BitwiseTakable, Cases, spareBitsMask);
2360+
BitwiseTakable, Cases, spareBitsMask,
2361+
EffectivePayloadCases);
23492362
}
23502363
}
23512364
};
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -lswiftSwiftReflectionTest %s -o %t/reflect_Enum_values2
3+
// RUN: %target-codesign %t/reflect_Enum_values2
4+
5+
// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_values2 | tee /dev/stderr | %FileCheck %s --check-prefix=CHECK%target-ptrsize --check-prefix=CHECKALL --dump-input=fail %add_num_extra_inhabitants
6+
7+
// REQUIRES: objc_interop
8+
// REQUIRES: executable_test
9+
// UNSUPPORTED: use_os_stdlib
10+
11+
import SwiftReflectionTest
12+
13+
enum EnumB {
14+
case a
15+
case b(Int8)
16+
case c(Int8)
17+
case d(Void)
18+
case e(Void)
19+
case RIGHT(Int8)
20+
case f(Int8)
21+
case g(Void)
22+
case LEFT(Int8, Int64)
23+
}
24+
25+
class PlaceSummaryUnit {
26+
let t: EnumB
27+
init(t: EnumB) { self.t = t }
28+
}
29+
30+
reflect(object: PlaceSummaryUnit(t: .RIGHT(5)))
31+
32+
// CHECKALL: Reflecting an object.
33+
// CHECKALL-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
34+
// CHECKALL-NEXT: Type reference:
35+
// CHECKALL-NEXT: (class reflect_Enum_values2.PlaceSummaryUnit)
36+
37+
// CHECKALL: Type info
38+
39+
// TODO: Check the type layout for 64- and 32-bit targets
40+
41+
reflect(enumValue: PlaceSummaryUnit(t: .RIGHT(5)).t)
42+
43+
// CHECKALL: Reflecting an enum value.
44+
// CHECKALL-NEXT: Type reference:
45+
// CHECKALL-NEXT: (enum reflect_Enum_values2.EnumB)
46+
// CHECKALL-NEXT: Value: .RIGHT(_)
47+
48+
reflect(enumValue: PlaceSummaryUnit(t: .a).t)
49+
50+
// CHECKALL: Reflecting an enum value.
51+
// CHECKALL-NEXT: Type reference:
52+
// CHECKALL-NEXT: (enum reflect_Enum_values2.EnumB)
53+
// CHECKALL-NEXT: Value: .a
54+
55+
reflect(enumValue: PlaceSummaryUnit(t: .LEFT(1,2)).t)
56+
57+
// CHECKALL: Reflecting an enum value.
58+
// CHECKALL-NEXT: Type reference:
59+
// CHECKALL-NEXT: (enum reflect_Enum_values2.EnumB)
60+
// CHECKALL-NEXT: Value: .LEFT(_)
61+
62+
reflect(enumValue: PlaceSummaryUnit(t: .d(())).t)
63+
64+
// CHECKALL: Reflecting an enum value.
65+
// CHECKALL-NEXT: Type reference:
66+
// CHECKALL-NEXT: (enum reflect_Enum_values2.EnumB)
67+
// CHECKALL-NEXT: Value: .d(_)
68+
69+
doneReflecting()
70+
71+
// CHECKALL: Done.
72+
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -lswiftSwiftReflectionTest %s -o %t/reflect_Enum_values3
3+
// RUN: %target-codesign %t/reflect_Enum_values3
4+
5+
// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_values3 | tee /dev/stderr | %FileCheck %s --check-prefix=CHECK%target-ptrsize --check-prefix=CHECKALL --dump-input=fail %add_num_extra_inhabitants
6+
7+
// REQUIRES: objc_interop
8+
// REQUIRES: executable_test
9+
// UNSUPPORTED: use_os_stdlib
10+
11+
import SwiftReflectionTest
12+
13+
enum EnumB<T> {
14+
case a
15+
case b(Int8)
16+
case c(T)
17+
case d(Void)
18+
case e(Void)
19+
case RIGHT(Int8)
20+
case f(Int8)
21+
case g(Void)
22+
case LEFT(Int8, Int64)
23+
}
24+
25+
class PlaceSummaryUnit<T> {
26+
let t: EnumB<T>
27+
init(t: EnumB<T>) { self.t = t }
28+
}
29+
30+
reflect(object: PlaceSummaryUnit<Int8>(t: .RIGHT(5)))
31+
32+
// CHECKALL: Reflecting an object.
33+
// CHECKALL-NEXT: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
34+
// CHECKALL-NEXT: Type reference:
35+
// CHECKALL-NEXT: (bound_generic_class reflect_Enum_values3.PlaceSummaryUnit
36+
// CHECKALL-NEXT: (struct Swift.Int8))
37+
38+
// CHECKALL: Type info
39+
40+
// TODO: Check the type layout for 64- and 32-bit targets
41+
42+
reflect(enumValue: PlaceSummaryUnit<Int8>(t: .RIGHT(5)).t)
43+
44+
// CHECKALL: Reflecting an enum value.
45+
// CHECKALL-NEXT: Type reference:
46+
// CHECKALL-NEXT: (bound_generic_enum reflect_Enum_values3.EnumB
47+
// CHECKALL-NEXT: (struct Swift.Int8))
48+
// CHECKALL-NEXT: Value: .RIGHT(_)
49+
50+
reflect(enumValue: PlaceSummaryUnit<Int8>(t: .a).t)
51+
52+
// CHECKALL: Reflecting an enum value.
53+
// CHECKALL-NEXT: Type reference:
54+
// CHECKALL-NEXT: (bound_generic_enum reflect_Enum_values3.EnumB
55+
// CHECKALL-NEXT: (struct Swift.Int8))
56+
// CHECKALL-NEXT: Value: .a
57+
58+
reflect(enumValue: PlaceSummaryUnit<Int8>(t: .c(7)).t)
59+
60+
// CHECKALL: Reflecting an enum value.
61+
// CHECKALL-NEXT: Type reference:
62+
// CHECKALL-NEXT: (bound_generic_enum reflect_Enum_values3.EnumB
63+
// CHECKALL-NEXT: (struct Swift.Int8))
64+
// CHECKALL-NEXT: Value: .c(_)
65+
66+
reflect(enumValue: PlaceSummaryUnit<Int8>(t: .LEFT(1,2)).t)
67+
68+
// CHECKALL: Reflecting an enum value.
69+
// CHECKALL-NEXT: Type reference:
70+
// CHECKALL-NEXT: (bound_generic_enum reflect_Enum_values3.EnumB
71+
// CHECKALL-NEXT: (struct Swift.Int8))
72+
// CHECKALL-NEXT: Value: .LEFT(_)
73+
74+
reflect(enumValue: PlaceSummaryUnit<Int8>(t: .d(())).t)
75+
76+
// CHECKALL: Reflecting an enum value.
77+
// CHECKALL-NEXT: Type reference:
78+
// CHECKALL-NEXT: (bound_generic_enum reflect_Enum_values3.EnumB
79+
// CHECKALL-NEXT: (struct Swift.Int8))
80+
// CHECKALL-NEXT: Value: .d(_)
81+
82+
doneReflecting()
83+
84+
// CHECKALL: Done.
85+

0 commit comments

Comments
 (0)