Skip to content

Commit c10991a

Browse files
authored
Merge pull request #71428 from augusto2112/nfc-sbm
[NFC] Move MultiPayloadEnum spare bits mask calculation into a function
2 parents 9b06293 + 9c6dfd4 commit c10991a

File tree

3 files changed

+58
-28
lines changed

3 files changed

+58
-28
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5836,6 +5836,32 @@ namespace {
58365836
tagBits.append(APInt(extraTagSize, (1U << ExtraTagBitCount) - 1U));
58375837
return tagBits.build();
58385838
}
5839+
5840+
std::optional<SpareBitsMaskInfo> calculateSpareBitsMask() const override {
5841+
SpareBitVector spareBits;
5842+
for (auto enumCase : getElementsWithPayload()) {
5843+
cast<FixedTypeInfo>(enumCase.ti)
5844+
->applyFixedSpareBitsMask(IGM, spareBits);
5845+
}
5846+
// Trim leading/trailing zero bytes, then pad to a multiple of 32 bits
5847+
llvm::APInt bits = spareBits.asAPInt();
5848+
uint32_t byteOffset = bits.countTrailingZeros() / 8;
5849+
bits.lshrInPlace(byteOffset * 8); // Trim zero bytes from bottom end
5850+
5851+
auto bitsInMask = bits.getActiveBits(); // Ignore high-order zero bits
5852+
uint32_t bytesInMask = (bitsInMask + 7) / 8;
5853+
auto wordsInMask = (bytesInMask + 3) / 4;
5854+
bits = bits.zextOrTrunc(wordsInMask * 32);
5855+
5856+
// Never write an MPE descriptor bigger than 16k
5857+
// The runtime will fall back on its own internal
5858+
// spare bits calculation for this (very rare) case.
5859+
if (bytesInMask > 16384) {
5860+
return {};
5861+
}
5862+
5863+
return {{bits, byteOffset, bytesInMask}};
5864+
}
58395865
};
58405866

58415867
class ResilientEnumImplStrategy final

lib/IRGen/GenEnum.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,20 @@ class EnumImplStrategy {
518518
return false;
519519
}
520520

521+
struct SpareBitsMaskInfo {
522+
const llvm::APInt bits;
523+
const uint32_t byteOffset;
524+
const uint32_t bytesInMask;
525+
526+
uint64_t wordsInMask() const { return (bytesInMask + 3) / 4; }
527+
};
528+
529+
/// Calculates the spare bits mask for the enum. Returns none if the type
530+
/// should not emit the spare bits.
531+
virtual std::optional<SpareBitsMaskInfo> calculateSpareBitsMask() const {
532+
return {};
533+
};
534+
521535
private:
522536
EnumImplStrategy(const EnumImplStrategy &) = delete;
523537
EnumImplStrategy &operator=(const EnumImplStrategy &) = delete;

lib/IRGen/GenReflection.cpp

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,54 +1125,44 @@ class MultiPayloadEnumDescriptorBuilder : public ReflectionMetadataBuilder {
11251125
void layout() override {
11261126
auto &strategy = getEnumImplStrategy(IGM, typeInContext);
11271127
bool isMPE = strategy.getElementsWithPayload().size() > 1;
1128-
assert(isMPE && "Cannot emit Multi-Payload Enum data for an enum that doesn't have multiple payloads");
1128+
assert(isMPE && "Cannot emit Multi-Payload Enum data for an enum that "
1129+
"doesn't have multiple payloads");
11291130

11301131
const TypeInfo &TI = strategy.getTypeInfo();
11311132
auto fixedTI = dyn_cast<FixedTypeInfo>(&TI);
1132-
assert(fixedTI != nullptr
1133-
&& "MPE reflection records can only be emitted for fixed-layout enums");
1133+
assert(fixedTI != nullptr &&
1134+
"MPE reflection records can only be emitted for fixed-layout enums");
11341135

1135-
// Get the spare bits mask for the enum payloads.
1136-
SpareBitVector spareBits;
1137-
for (auto enumCase : strategy.getElementsWithPayload()) {
1138-
cast<FixedTypeInfo>(enumCase.ti)->applyFixedSpareBitsMask(IGM, spareBits);
1139-
}
1140-
1141-
// Trim leading/trailing zero bytes, then pad to a multiple of 32 bits
1142-
llvm::APInt bits = spareBits.asAPInt();
1143-
uint32_t byteOffset = bits.countTrailingZeros() / 8;
1144-
bits.lshrInPlace(byteOffset * 8); // Trim zero bytes from bottom end
1145-
1146-
auto bitsInMask = bits.getActiveBits(); // Ignore high-order zero bits
1147-
auto usesPayloadSpareBits = bitsInMask > 0;
1148-
uint32_t bytesInMask = (bitsInMask + 7) / 8;
1149-
auto wordsInMask = (bytesInMask + 3) / 4;
1150-
bits = bits.zextOrTrunc(wordsInMask * 32);
1136+
auto spareBitsMaskInfo = strategy.calculateSpareBitsMask();
11511137

11521138
// Never write an MPE descriptor bigger than 16k
11531139
// The runtime will fall back on its own internal
11541140
// spare bits calculation for this (very rare) case.
1155-
if (bytesInMask > 16384) {
1141+
if (!spareBitsMaskInfo)
11561142
return;
1157-
}
1143+
1144+
auto bits = spareBitsMaskInfo->bits;
11581145

11591146
addTypeRef(type, CanGenericSignature());
11601147

1148+
bool usesPayloadSpareBits = spareBitsMaskInfo->bytesInMask > 0;
1149+
11611150
// MPE record contents are a multiple of 32-bits
11621151
uint32_t contentsSizeInWords = 1; /* Size + flags is mandatory */
1163-
if (wordsInMask > 0) {
1164-
contentsSizeInWords +=
1165-
1 /* SpareBits byte count */
1166-
+ wordsInMask;
1152+
if (usesPayloadSpareBits) {
1153+
contentsSizeInWords += 1 /* SpareBits byte count */
1154+
+ spareBitsMaskInfo->wordsInMask();
11671155
}
1156+
11681157
uint32_t flags = usesPayloadSpareBits ? 1 : 0;
11691158

11701159
B.addInt32((contentsSizeInWords << 16) | flags);
11711160

1172-
if (bytesInMask > 0) {
1173-
B.addInt32((byteOffset << 16) | bytesInMask);
1161+
if (usesPayloadSpareBits) {
1162+
B.addInt32((spareBitsMaskInfo->byteOffset << 16) |
1163+
spareBitsMaskInfo->bytesInMask);
11741164
// TODO: Endianness??
1175-
for (unsigned i = 0; i < wordsInMask; ++i) {
1165+
for (unsigned i = 0; i < spareBitsMaskInfo->wordsInMask(); ++i) {
11761166
uint32_t nextWord = bits.extractBitsAsZExtValue(32, 0);
11771167
B.addInt32(nextWord);
11781168
bits.lshrInPlace(32);

0 commit comments

Comments
 (0)