Skip to content

Commit 8114ecc

Browse files
committed
[Runtime] Add destructiveInjectEnumTag support for generic multi payload enums with layout strings
1 parent 622f7a2 commit 8114ecc

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2366,6 +2366,17 @@ FUNCTION(MultiPayloadEnumGenericGetEnumTag,
23662366
ATTRS(NoUnwind, WillReturn),
23672367
EFFECT(NoEffect))
23682368

2369+
// void swift_multiPayloadEnumGeneric_destructiveInjectEnumTag(swift::OpaqueValue *address,
2370+
// unsigned tag,
2371+
// const Metadata *metadata)
2372+
FUNCTION(MultiPayloadEnumGenericDestructiveInjectEnumTag,
2373+
swift_multiPayloadEnumGeneric_destructiveInjectEnumTag,
2374+
C_CC, AlwaysAvailable,
2375+
RETURNS(VoidTy),
2376+
ARGS(Int8PtrTy, Int32Ty, TypeMetadataPtrTy),
2377+
ATTRS(NoUnwind, WillReturn),
2378+
EFFECT(NoEffect))
2379+
23692380
// unsigned swift_singlePayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
23702381
// const Metadata *metadata);
23712382
FUNCTION(SinglePayloadEnumGenericGetEnumTag,

stdlib/public/runtime/BytecodeLayouts.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,41 @@ swift_multiPayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
746746
}
747747
}
748748

749+
extern "C" void swift_multiPayloadEnumGeneric_destructiveInjectEnumTag(
750+
swift::OpaqueValue *address, unsigned tag, const Metadata *metadata) {
751+
auto addr = reinterpret_cast<uint8_t *>(address);
752+
LayoutStringReader reader{metadata->getLayoutString(),
753+
layoutStringHeaderSize + sizeof(uint64_t)};
754+
755+
auto numTagBytes = reader.readBytes<size_t>();
756+
auto numPayloads = reader.readBytes<size_t>();
757+
reader.skip(sizeof(size_t));
758+
auto enumSize = reader.readBytes<size_t>();
759+
auto payloadSize = enumSize - numTagBytes;
760+
761+
if (tag < numPayloads) {
762+
// For a payload case, store the tag after the payload area.
763+
auto tagBytes = addr + payloadSize;
764+
storeEnumElement(tagBytes, tag, numTagBytes);
765+
} else {
766+
// For an empty case, factor out the parts that go in the payload and
767+
// tag areas.
768+
unsigned whichEmptyCase = tag - numPayloads;
769+
unsigned whichTag, whichPayloadValue;
770+
if (payloadSize >= 4) {
771+
whichTag = numPayloads;
772+
whichPayloadValue = whichEmptyCase;
773+
} else {
774+
unsigned numPayloadBits = payloadSize * CHAR_BIT;
775+
whichTag = numPayloads + (whichEmptyCase >> numPayloadBits);
776+
whichPayloadValue = whichEmptyCase & ((1U << numPayloadBits) - 1U);
777+
}
778+
auto tagBytes = addr + payloadSize;
779+
storeEnumElement(tagBytes, whichTag, numTagBytes);
780+
storeEnumElement(addr, whichPayloadValue, payloadSize);
781+
}
782+
}
783+
749784
template <typename T>
750785
static inline T handleSinglePayloadEnumGenericTag(
751786
LayoutStringReader &reader, uint8_t *addr,

stdlib/public/runtime/BytecodeLayouts.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ SWIFT_RUNTIME_EXPORT
130130
unsigned swift_multiPayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
131131
const Metadata *metadata);
132132
SWIFT_RUNTIME_EXPORT
133+
void swift_multiPayloadEnumGeneric_destructiveInjectEnumTag(
134+
swift::OpaqueValue *address, unsigned tag, const Metadata *metadata);
135+
SWIFT_RUNTIME_EXPORT
133136
unsigned swift_singlePayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
134137
const Metadata *metadata);
135138
SWIFT_RUNTIME_EXPORT

0 commit comments

Comments
 (0)