diff --git a/stdlib/public/RemoteInspection/TypeLowering.cpp b/stdlib/public/RemoteInspection/TypeLowering.cpp index eb10a809c77e6..541c039f6141f 100644 --- a/stdlib/public/RemoteInspection/TypeLowering.cpp +++ b/stdlib/public/RemoteInspection/TypeLowering.cpp @@ -437,14 +437,26 @@ BitMask RecordTypeInfo::getSpareBits(TypeConverter &TC, bool &hasAddrOnly) const // Mask the rest of the fields as usual... break; } - case RecordKind::ClassExistential: - // Class existential is a data pointer that does expose spare bits - // ... so we can fall through ... + case RecordKind::ClassExistential: { + // First pointer in a Class Existential is the class pointer + // itself, which can be tagged or have other mysteries on 64-bit, so + // it exposes no spare bits from the first word there... + auto pointerBytes = TC.targetPointerSize(); + if (pointerBytes == 8) { + auto zeroPointerSizedMask = BitMask::zeroMask(pointerBytes); + mask.andMask(zeroPointerSizedMask, 0); + } + // Otherwise, it's the same as an Existential Metatype + SWIFT_FALLTHROUGH; + } case RecordKind::ExistentialMetatype: { - // Initial metadata pointer has spare bits + // All the pointers in an Existential Metatype expose spare bits... + auto pointerBytes = TC.targetPointerSize(); auto mpePointerSpareBits = TC.getBuilder().getMultiPayloadEnumPointerMask(); - mask.andMask(mpePointerSpareBits, 0); - mask.keepOnlyLeastSignificantBytes(TC.targetPointerSize()); + auto mpePointerSpareBitMask = BitMask(pointerBytes, mpePointerSpareBits); + for (int offset = 0; offset < (int)getSize(); offset += pointerBytes) { + mask.andMask(mpePointerSpareBitMask, offset); + } return mask; } case RecordKind::ErrorExistential: diff --git a/validation-test/Reflection/reflect_Enum_values10.swift b/validation-test/Reflection/reflect_Enum_values10.swift index 728c79b67a05d..c9c54addaa68f 100644 --- a/validation-test/Reflection/reflect_Enum_values10.swift +++ b/validation-test/Reflection/reflect_Enum_values10.swift @@ -10,9 +10,6 @@ // UNSUPPORTED: use_os_stdlib // UNSUPPORTED: asan -// This is broken on ARM64_32, disable it temporarily until we can fix it. rdar://137351613 -// UNSUPPORTED: CPU=arm64_32 - import SwiftReflectionTest protocol P : AnyObject { @@ -24,7 +21,8 @@ class C : P { init() { a = 0; b = 0; } } -// MemoryLayout.size == 8 +// On 64-bit: MemoryLayout.size == 8 +// On 32-bit: MemoryLayout.size == 4 enum B { case a(C) case b(C) @@ -44,8 +42,8 @@ reflect(enumValue: B.b(C())) // CHECKALL-NEXT: (enum reflect_Enum_values10.B) // CHECKALL-NEXT: Value: .b(_) -// MemoryLayout.size == 16 -// MemoryLayout

.size == 16 +// On 64-bit: MemoryLayout.size == MemoryLayout

.size == 16 +// On 32-bit: MemoryLayout.size == MemoryLayout

.size == 8 enum Q { case a(P) case b(P) @@ -65,6 +63,114 @@ reflect(enumValue: Q.b(C())) // CHECKALL-NEXT: (enum reflect_Enum_values10.Q) // CHECKALL-NEXT: Value: .b(_) +enum B1 { +case a(C) +case b +} + +reflect(enumValue: B1.a(C())) + +// CHECKALL: Reflecting an enum value. +// CHECKALL-NEXT: Type reference: +// CHECKALL-NEXT: (enum reflect_Enum_values10.B1) +// CHECKALL-NEXT: Value: .a(_) + +reflect(enumValue: B1.b) + +// CHECKALL: Reflecting an enum value. +// CHECKALL-NEXT: Type reference: +// CHECKALL-NEXT: (enum reflect_Enum_values10.B1) +// CHECKALL-NEXT: Value: .b + +enum Q1 { +case a(P) +case b +} + +reflect(enumValue: Q1.a(C())) + +// CHECKALL: Reflecting an enum value. +// CHECKALL-NEXT: Type reference: +// CHECKALL-NEXT: (enum reflect_Enum_values10.Q1) +// CHECKALL-NEXT: Value: .a(_) + +reflect(enumValue: Q1.b) + +// CHECKALL: Reflecting an enum value. +// CHECKALL-NEXT: Type reference: +// CHECKALL-NEXT: (enum reflect_Enum_values10.Q1) +// CHECKALL-NEXT: Value: .b + +enum B2 { +case a(C) +case b(C) +case c(C) +case d(C) +case e(C) +} + +reflect(enumValue: B2.a(C())) + +// CHECKALL: Reflecting an enum value. +// CHECKALL-NEXT: Type reference: +// CHECKALL-NEXT: (enum reflect_Enum_values10.B2) +// CHECKALL-NEXT: Value: .a(_) + +reflect(enumValue: B2.e(C())) + +// CHECKALL: Reflecting an enum value. +// CHECKALL-NEXT: Type reference: +// CHECKALL-NEXT: (enum reflect_Enum_values10.B2) +// CHECKALL-NEXT: Value: .e(_) + +// On 64-bit: MemoryLayout.size == MemoryLayout

.size == 16 +// On 32-bit: MemoryLayout.size == MemoryLayout

.size == 8 +enum Q2 { +case a(P) +case b(P) +case c(P) +case d(P) +case e(P) +} + +reflect(enumValue: Q2.a(C())) + +// CHECKALL: Reflecting an enum value. +// CHECKALL-NEXT: Type reference: +// CHECKALL-NEXT: (enum reflect_Enum_values10.Q2) +// CHECKALL-NEXT: Value: .a(_) + +reflect(enumValue: Q2.e(C())) + +// CHECKALL: Reflecting an enum value. +// CHECKALL-NEXT: Type reference: +// CHECKALL-NEXT: (enum reflect_Enum_values10.Q2) +// CHECKALL-NEXT: Value: .e(_) + +reflect(enumValue: Optional.some(.a(C()))) + +// CHECKALL: Reflecting an enum value. +// CHECKALL-NEXT: Type reference: +// CHECKALL-NEXT: (bound_generic_enum Swift.Optional +// CHECKALL-NEXT: (enum reflect_Enum_values10.Q2)) +// CHECKALL-NEXT: Value: .some(.a(_)) + +reflect(enumValue: Optional.some(.e(C()))) + +// CHECKALL: Reflecting an enum value. +// CHECKALL-NEXT: Type reference: +// CHECKALL-NEXT: (bound_generic_enum Swift.Optional +// CHECKALL-NEXT: (enum reflect_Enum_values10.Q2)) +// CHECKALL-NEXT: Value: .some(.e(_)) + +reflect(enumValue: Optional.none) + +// CHECKALL: Reflecting an enum value. +// CHECKALL-NEXT: Type reference: +// CHECKALL-NEXT: (bound_generic_enum Swift.Optional +// CHECKALL-NEXT: (enum reflect_Enum_values10.Q2)) +// CHECKALL-NEXT: Value: .none + doneReflecting() // CHECKALL: Done.