Skip to content

Commit 5bd2c4b

Browse files
authored
Merge pull request #77027 from tbkka/tbkka-remotemirror-classexistential
Fix multi-payload enums with Class Existential payloads on 32-bit targets
2 parents ce83bf7 + cfc7b2e commit 5bd2c4b

File tree

2 files changed

+130
-12
lines changed

2 files changed

+130
-12
lines changed

stdlib/public/RemoteInspection/TypeLowering.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -437,14 +437,26 @@ BitMask RecordTypeInfo::getSpareBits(TypeConverter &TC, bool &hasAddrOnly) const
437437
// Mask the rest of the fields as usual...
438438
break;
439439
}
440-
case RecordKind::ClassExistential:
441-
// Class existential is a data pointer that does expose spare bits
442-
// ... so we can fall through ...
440+
case RecordKind::ClassExistential: {
441+
// First pointer in a Class Existential is the class pointer
442+
// itself, which can be tagged or have other mysteries on 64-bit, so
443+
// it exposes no spare bits from the first word there...
444+
auto pointerBytes = TC.targetPointerSize();
445+
if (pointerBytes == 8) {
446+
auto zeroPointerSizedMask = BitMask::zeroMask(pointerBytes);
447+
mask.andMask(zeroPointerSizedMask, 0);
448+
}
449+
// Otherwise, it's the same as an Existential Metatype
450+
SWIFT_FALLTHROUGH;
451+
}
443452
case RecordKind::ExistentialMetatype: {
444-
// Initial metadata pointer has spare bits
453+
// All the pointers in an Existential Metatype expose spare bits...
454+
auto pointerBytes = TC.targetPointerSize();
445455
auto mpePointerSpareBits = TC.getBuilder().getMultiPayloadEnumPointerMask();
446-
mask.andMask(mpePointerSpareBits, 0);
447-
mask.keepOnlyLeastSignificantBytes(TC.targetPointerSize());
456+
auto mpePointerSpareBitMask = BitMask(pointerBytes, mpePointerSpareBits);
457+
for (int offset = 0; offset < (int)getSize(); offset += pointerBytes) {
458+
mask.andMask(mpePointerSpareBitMask, offset);
459+
}
448460
return mask;
449461
}
450462
case RecordKind::ErrorExistential:

validation-test/Reflection/reflect_Enum_values10.swift

Lines changed: 112 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
// UNSUPPORTED: use_os_stdlib
1111
// UNSUPPORTED: asan
1212

13-
// This is broken on ARM64_32, disable it temporarily until we can fix it. rdar://137351613
14-
// UNSUPPORTED: CPU=arm64_32
15-
1613
import SwiftReflectionTest
1714

1815
protocol P : AnyObject {
@@ -24,7 +21,8 @@ class C : P {
2421
init() { a = 0; b = 0; }
2522
}
2623

27-
// MemoryLayout<B>.size == 8
24+
// On 64-bit: MemoryLayout<B>.size == 8
25+
// On 32-bit: MemoryLayout<B>.size == 4
2826
enum B {
2927
case a(C)
3028
case b(C)
@@ -44,8 +42,8 @@ reflect(enumValue: B.b(C()))
4442
// CHECKALL-NEXT: (enum reflect_Enum_values10.B)
4543
// CHECKALL-NEXT: Value: .b(_)
4644

47-
// MemoryLayout<Q>.size == 16
48-
// MemoryLayout<P>.size == 16
45+
// On 64-bit: MemoryLayout<Q>.size == MemoryLayout<P>.size == 16
46+
// On 32-bit: MemoryLayout<Q>.size == MemoryLayout<P>.size == 8
4947
enum Q {
5048
case a(P)
5149
case b(P)
@@ -65,6 +63,114 @@ reflect(enumValue: Q.b(C()))
6563
// CHECKALL-NEXT: (enum reflect_Enum_values10.Q)
6664
// CHECKALL-NEXT: Value: .b(_)
6765

66+
enum B1 {
67+
case a(C)
68+
case b
69+
}
70+
71+
reflect(enumValue: B1.a(C()))
72+
73+
// CHECKALL: Reflecting an enum value.
74+
// CHECKALL-NEXT: Type reference:
75+
// CHECKALL-NEXT: (enum reflect_Enum_values10.B1)
76+
// CHECKALL-NEXT: Value: .a(_)
77+
78+
reflect(enumValue: B1.b)
79+
80+
// CHECKALL: Reflecting an enum value.
81+
// CHECKALL-NEXT: Type reference:
82+
// CHECKALL-NEXT: (enum reflect_Enum_values10.B1)
83+
// CHECKALL-NEXT: Value: .b
84+
85+
enum Q1 {
86+
case a(P)
87+
case b
88+
}
89+
90+
reflect(enumValue: Q1.a(C()))
91+
92+
// CHECKALL: Reflecting an enum value.
93+
// CHECKALL-NEXT: Type reference:
94+
// CHECKALL-NEXT: (enum reflect_Enum_values10.Q1)
95+
// CHECKALL-NEXT: Value: .a(_)
96+
97+
reflect(enumValue: Q1.b)
98+
99+
// CHECKALL: Reflecting an enum value.
100+
// CHECKALL-NEXT: Type reference:
101+
// CHECKALL-NEXT: (enum reflect_Enum_values10.Q1)
102+
// CHECKALL-NEXT: Value: .b
103+
104+
enum B2 {
105+
case a(C)
106+
case b(C)
107+
case c(C)
108+
case d(C)
109+
case e(C)
110+
}
111+
112+
reflect(enumValue: B2.a(C()))
113+
114+
// CHECKALL: Reflecting an enum value.
115+
// CHECKALL-NEXT: Type reference:
116+
// CHECKALL-NEXT: (enum reflect_Enum_values10.B2)
117+
// CHECKALL-NEXT: Value: .a(_)
118+
119+
reflect(enumValue: B2.e(C()))
120+
121+
// CHECKALL: Reflecting an enum value.
122+
// CHECKALL-NEXT: Type reference:
123+
// CHECKALL-NEXT: (enum reflect_Enum_values10.B2)
124+
// CHECKALL-NEXT: Value: .e(_)
125+
126+
// On 64-bit: MemoryLayout<Q>.size == MemoryLayout<P>.size == 16
127+
// On 32-bit: MemoryLayout<Q>.size == MemoryLayout<P>.size == 8
128+
enum Q2 {
129+
case a(P)
130+
case b(P)
131+
case c(P)
132+
case d(P)
133+
case e(P)
134+
}
135+
136+
reflect(enumValue: Q2.a(C()))
137+
138+
// CHECKALL: Reflecting an enum value.
139+
// CHECKALL-NEXT: Type reference:
140+
// CHECKALL-NEXT: (enum reflect_Enum_values10.Q2)
141+
// CHECKALL-NEXT: Value: .a(_)
142+
143+
reflect(enumValue: Q2.e(C()))
144+
145+
// CHECKALL: Reflecting an enum value.
146+
// CHECKALL-NEXT: Type reference:
147+
// CHECKALL-NEXT: (enum reflect_Enum_values10.Q2)
148+
// CHECKALL-NEXT: Value: .e(_)
149+
150+
reflect(enumValue: Optional<Q2>.some(.a(C())))
151+
152+
// CHECKALL: Reflecting an enum value.
153+
// CHECKALL-NEXT: Type reference:
154+
// CHECKALL-NEXT: (bound_generic_enum Swift.Optional
155+
// CHECKALL-NEXT: (enum reflect_Enum_values10.Q2))
156+
// CHECKALL-NEXT: Value: .some(.a(_))
157+
158+
reflect(enumValue: Optional<Q2>.some(.e(C())))
159+
160+
// CHECKALL: Reflecting an enum value.
161+
// CHECKALL-NEXT: Type reference:
162+
// CHECKALL-NEXT: (bound_generic_enum Swift.Optional
163+
// CHECKALL-NEXT: (enum reflect_Enum_values10.Q2))
164+
// CHECKALL-NEXT: Value: .some(.e(_))
165+
166+
reflect(enumValue: Optional<Q2>.none)
167+
168+
// CHECKALL: Reflecting an enum value.
169+
// CHECKALL-NEXT: Type reference:
170+
// CHECKALL-NEXT: (bound_generic_enum Swift.Optional
171+
// CHECKALL-NEXT: (enum reflect_Enum_values10.Q2))
172+
// CHECKALL-NEXT: Value: .none
173+
68174
doneReflecting()
69175

70176
// CHECKALL: Done.

0 commit comments

Comments
 (0)