Skip to content

Commit 2ad9bec

Browse files
committed
Back out the experimental spare bits calculation and everything that depended on it
The experimental spare bits calculation helped to validate the structure of this code and the handling of various multi-payload enum details, but it cannot be done here in a way that will always agree with the compiler. So I've backed that out: The result can still handle certain multi-payload enums (those with dynamic layouts that can never utilize spare bits) but the remainder will require some additional work for the compiler to expose the real spare bit data for use in the runtime.
1 parent cfed291 commit 2ad9bec

File tree

4 files changed

+31
-647
lines changed

4 files changed

+31
-647
lines changed

stdlib/public/Reflection/TypeLowering.cpp

+23-78
Original file line numberDiff line numberDiff line change
@@ -963,63 +963,6 @@ class MultiPayloadEnumTypeInfo: public EnumTypeInfo {
963963
}
964964
};
965965

966-
// XXX FIXME XXX Make sure the following calculation returns `false` (failure)
967-
// when it is unable to accurately obtain the spare bit mask.
968-
969-
// Recursively populate the spare bit mask for this single type
970-
static bool populateSpareBitsMask(const TypeInfo *TI, BitMask &mask);
971-
972-
// Recursively populate the spare bit mask for this collection of
973-
// record fields or enum cases.
974-
static bool populateSpareBitsMask(const std::vector<FieldInfo> &Fields, BitMask &mask) {
975-
for (auto Field : Fields) {
976-
if (Field.TR != 0) {
977-
BitMask submask(Field.TI.getSize());
978-
if (!populateSpareBitsMask(&Field.TI, submask)) {
979-
return false;
980-
}
981-
mask.andMask(submask, Field.Offset);
982-
}
983-
}
984-
return true;
985-
}
986-
987-
// General recursive type walk to combine spare bit info from nested structures.
988-
static bool populateSpareBitsMask(const TypeInfo *TI, BitMask &mask) {
989-
switch (TI->getKind()) {
990-
case TypeInfoKind::Reference: {
991-
// Or else somehow get access to target architecture information?
992-
if (TI->getSize() == 8) {
993-
// x86_64 masking (ARM64 is different)
994-
mask.andMask((uint64_t)0xFF00000000000007ULL, 0);
995-
} else {
996-
// Common to all 32-bit platforms
997-
mask.andMask((uint32_t)0x00000003U, 0);
998-
}
999-
break;
1000-
}
1001-
case TypeInfoKind::Enum: {
1002-
auto EnumTI = reinterpret_cast<const EnumTypeInfo *>(TI);
1003-
if (!populateSpareBitsMask(EnumTI->getCases(), mask)) {
1004-
return false;
1005-
}
1006-
break;
1007-
}
1008-
case TypeInfoKind::Record: {
1009-
auto RecordTI = dyn_cast<RecordTypeInfo>(TI);
1010-
if (!populateSpareBitsMask(RecordTI->getFields(), mask)) {
1011-
return false;
1012-
}
1013-
break;
1014-
}
1015-
default: {
1016-
mask.makeZero();
1017-
break;
1018-
}
1019-
}
1020-
return true;
1021-
}
1022-
1023966
/// Utility class for building values that contain witness tables.
1024967
class ExistentialTypeInfoBuilder {
1025968
TypeConverter &TC;
@@ -1900,30 +1843,32 @@ class EnumTypeInfoBuilder {
19001843
if (Stride == 0)
19011844
Stride = 1;
19021845

1846+
/*
1847+
// TODO: Obtain spare bit mask data from the field descriptor
1848+
// TODO: Have the compiler emit spare bit mask data in the FD
19031849
auto PayloadSize = EnumTypeInfo::getPayloadSizeForCases(Cases);
19041850
BitMask spareBitsMask(PayloadSize);
1905-
auto validSpareBitsMask = populateSpareBitsMask(Cases, spareBitsMask);
1906-
1907-
if (!validSpareBitsMask) {
1908-
// If we couldn't correctly determine the spare bits mask,
1909-
// return a TI that will always fail when asked for XIs or value.
1910-
return TC.makeTypeInfo<UnsupportedEnumTypeInfo>(
1911-
Size, Alignment, Stride, NumExtraInhabitants,
1912-
BitwiseTakable, EnumKind::MultiPayloadEnum, Cases);
1913-
} else if (spareBitsMask.isZero()) {
1914-
// Simple case that does not use spare bits
1915-
// This is correct as long as our local spare bits calculation
1916-
// above only returns an empty mask when the mask is really empty,
1917-
return TC.makeTypeInfo<SimpleMultiPayloadEnumTypeInfo>(
1918-
Size, Alignment, Stride, NumExtraInhabitants,
1919-
BitwiseTakable, Cases);
1920-
} else {
1921-
// General case can mix spare bits and extra discriminator
1922-
// It obviously relies on having an accurate spare bit mask.
1923-
return TC.makeTypeInfo<MultiPayloadEnumTypeInfo>(
1924-
Size, Alignment, Stride, NumExtraInhabitants,
1925-
BitwiseTakable, Cases, spareBitsMask);
1851+
if (readSpareBitsMask(XYZ, spareBitsMask)) {
1852+
if (spareBitsMask.isZero()) {
1853+
// If there are no spare bits, use the "simple" tag-only implementation.
1854+
return TC.makeTypeInfo<SimpleMultiPayloadEnumTypeInfo>(
1855+
Size, Alignment, Stride, NumExtraInhabitants,
1856+
BitwiseTakable, Cases);
1857+
} else {
1858+
// General case using a mix of spare bits and extra tag
1859+
return TC.makeTypeInfo<MultiPayloadEnumTypeInfo>(
1860+
Size, Alignment, Stride, NumExtraInhabitants,
1861+
BitwiseTakable, Cases, spareBitsMask);
1862+
}
19261863
}
1864+
*/
1865+
1866+
// Without spare bit mask info, we have to leave this particular
1867+
// enum as "Unsupported", meaning we will not be able to project
1868+
// cases or evaluate XIs.
1869+
return TC.makeTypeInfo<UnsupportedEnumTypeInfo>(
1870+
Size, Alignment, Stride, NumExtraInhabitants,
1871+
BitwiseTakable, EnumKind::MultiPayloadEnum, Cases);
19271872
} else {
19281873
// Dynamic multi-payload enums cannot use spare bits, so they
19291874
// always use a separate tag value:

0 commit comments

Comments
 (0)