diff --git a/stdlib/public/runtime/BytecodeLayouts.cpp b/stdlib/public/runtime/BytecodeLayouts.cpp index aba790330961a..9ec13c9efb43f 100644 --- a/stdlib/public/runtime/BytecodeLayouts.cpp +++ b/stdlib/public/runtime/BytecodeLayouts.cpp @@ -659,25 +659,45 @@ extern "C" unsigned swift_singletonEnum_getEnumTag(swift::OpaqueValue *address, return 0; } -extern "C" -unsigned swift_enumSimple_getEnumTag(swift::OpaqueValue *address, - const Metadata *metadata) { - auto addr = reinterpret_cast(address); - LayoutStringReader reader{metadata->getLayoutString(), - layoutStringHeaderSize + sizeof(uint64_t)}; +template +static inline T handleSinglePayloadEnumSimpleTag( + LayoutStringReader &reader, uint8_t *addr, + std::function(size_t, size_t, uint8_t)> + extraTagBytesHandler, + std::function + xiHandler) { auto byteCountsAndOffset = reader.readBytes(); auto extraTagBytesPattern = (uint8_t)(byteCountsAndOffset >> 62); auto xiTagBytesPattern = ((uint8_t)(byteCountsAndOffset >> 59)) & 0x7; auto xiTagBytesOffset = byteCountsAndOffset & std::numeric_limits::max(); + auto numExtraTagBytes = 1 << (extraTagBytesPattern - 1); + auto payloadSize = reader.readBytes(); + auto zeroTagValue = reader.readBytes(); + auto payloadNumExtraInhabitants = reader.readBytes(); if (extraTagBytesPattern) { - auto extraTagBytes = 1 << (extraTagBytesPattern - 1); - auto payloadSize = reader.readBytes(); - auto tagBytes = readTagBytes(addr + payloadSize, extraTagBytes); + if (auto result = extraTagBytesHandler(payloadNumExtraInhabitants, + payloadSize, numExtraTagBytes)) { + return *result; + } + } + + return xiHandler(payloadNumExtraInhabitants, zeroTagValue, xiTagBytesPattern, + xiTagBytesOffset, payloadSize, numExtraTagBytes); +} + +extern "C" unsigned swift_enumSimple_getEnumTag(swift::OpaqueValue *address, + const Metadata *metadata) { + auto addr = reinterpret_cast(address); + LayoutStringReader reader{metadata->getLayoutString(), + layoutStringHeaderSize + sizeof(uint64_t)}; + + auto extraTagBytesHandler = + [addr](size_t payloadNumExtraInhabitants, size_t payloadSize, + uint8_t numExtraTagBytes) -> std::optional { + auto tagBytes = readTagBytes(addr + payloadSize, numExtraTagBytes); if (tagBytes) { - reader.skip(sizeof(uint64_t)); - auto payloadNumExtraInhabitants = reader.readBytes(); unsigned caseIndexFromExtraTagBits = payloadSize >= 4 ? 0 : (tagBytes - 1U) << (payloadSize * 8U); unsigned caseIndexFromValue = loadEnumElement(addr, payloadSize); @@ -686,24 +706,27 @@ unsigned swift_enumSimple_getEnumTag(swift::OpaqueValue *address, payloadNumExtraInhabitants; return noPayloadIndex + 1; } - } else { - reader.skip(sizeof(size_t)); - } - if (xiTagBytesPattern) { - auto zeroTagValue = reader.readBytes(); - auto xiTagValues = reader.readBytes(); + return std::nullopt; + }; + auto xihandler = [addr](size_t payloadNumExtraInhabitants, + uint64_t zeroTagValue, uint8_t xiTagBytesPattern, + unsigned xiTagBytesOffset, size_t payloadSize, + uint8_t numExtraTagBytes) -> unsigned { auto xiTagBytes = 1 << (xiTagBytesPattern - 1); uint64_t tagBytes = readTagBytes(addr + xiTagBytesOffset, xiTagBytes) - zeroTagValue; - if (tagBytes < xiTagValues) { + if (tagBytes < payloadNumExtraInhabitants) { return tagBytes + 1; } - } - return 0; + return 0; + }; + + return handleSinglePayloadEnumSimpleTag( + reader, addr, extraTagBytesHandler, xihandler); } extern "C"