diff --git a/stdlib/public/RemoteInspection/TypeLowering.cpp b/stdlib/public/RemoteInspection/TypeLowering.cpp index 20ce27e9ea64d..74a4d83205ffe 100644 --- a/stdlib/public/RemoteInspection/TypeLowering.cpp +++ b/stdlib/public/RemoteInspection/TypeLowering.cpp @@ -437,14 +437,24 @@ BitMask RecordTypeInfo::getSpareBits(TypeConverter &TC, bool &hasAddrOnly) const // Mask the rest of the fields as usual... break; } - case RecordKind::ClassExistential: - // Class existential is a bunch of pointers that 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 + DISPATCH_FALLTHROUGH; + } case RecordKind::ExistentialMetatype: { - // A bunch of pointers that expose spare bits + // All the pointers in an Existential Metatype expose spare bits... + auto pointerBytes = TC.targetPointerSize(); auto mpePointerSpareBits = TC.getBuilder().getMultiPayloadEnumPointerMask(); - auto mpePointerSpareBitMask = BitMask(TC.targetPointerSize(), mpePointerSpareBits); - for (int offset = 0; offset < (int)getSize(); offset += TC.targetPointerSize()) { + auto mpePointerSpareBitMask = BitMask(pointerBytes, mpePointerSpareBits); + for (int offset = 0; offset < (int)getSize(); offset += pointerBytes) { mask.andMask(mpePointerSpareBitMask, offset); } return mask; diff --git a/validation-test/Reflection/reflect_Enum_values10.swift b/validation-test/Reflection/reflect_Enum_values10.swift index a41f30eb19153..c9c54addaa68f 100644 --- a/validation-test/Reflection/reflect_Enum_values10.swift +++ b/validation-test/Reflection/reflect_Enum_values10.swift @@ -147,6 +147,30 @@ reflect(enumValue: Q2.e(C())) // 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.