Skip to content

Commit 89d37da

Browse files
committed
[Runtime] Add destructiveInjectEnumTag support for generic single payload enums with layout strings
1 parent 83ccdbb commit 89d37da

File tree

3 files changed

+86
-13
lines changed

3 files changed

+86
-13
lines changed

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2333,7 +2333,7 @@ FUNCTION(SingletonEnumGetEnumTag,
23332333
C_CC, AlwaysAvailable,
23342334
RETURNS(Int32Ty),
23352335
ARGS(Int8PtrTy, TypeMetadataPtrTy),
2336-
ATTRS(NoUnwind),
2336+
ATTRS(NoUnwind, WillReturn),
23372337
EFFECT(NoEffect))
23382338

23392339
// unsigned swift_enumSimple_getEnumTag(swift::OpaqueValue *address,
@@ -2343,7 +2343,7 @@ FUNCTION(EnumSimpleGetEnumTag,
23432343
C_CC, AlwaysAvailable,
23442344
RETURNS(Int32Ty),
23452345
ARGS(Int8PtrTy, TypeMetadataPtrTy),
2346-
ATTRS(NoUnwind),
2346+
ATTRS(NoUnwind, WillReturn),
23472347
EFFECT(NoEffect))
23482348

23492349
// unsigned swift_enumFn_getEnumTag(swift::OpaqueValue *address,
@@ -2353,7 +2353,7 @@ FUNCTION(EnumFnGetEnumTag,
23532353
C_CC, AlwaysAvailable,
23542354
RETURNS(Int32Ty),
23552355
ARGS(Int8PtrTy, TypeMetadataPtrTy),
2356-
ATTRS(NoUnwind),
2356+
ATTRS(NoUnwind, WillReturn),
23572357
EFFECT(NoEffect))
23582358

23592359
// unsigned swift_multiPayloadEnumGeneric_getEnumTag(opaque* address,
@@ -2363,7 +2363,7 @@ FUNCTION(MultiPayloadEnumGenericGetEnumTag,
23632363
C_CC, AlwaysAvailable,
23642364
RETURNS(Int32Ty),
23652365
ARGS(Int8PtrTy, TypeMetadataPtrTy),
2366-
ATTRS(NoUnwind),
2366+
ATTRS(NoUnwind, WillReturn),
23672367
EFFECT(NoEffect))
23682368

23692369
// unsigned swift_singlePayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
@@ -2373,7 +2373,18 @@ FUNCTION(SinglePayloadEnumGenericGetEnumTag,
23732373
C_CC, AlwaysAvailable,
23742374
RETURNS(Int32Ty),
23752375
ARGS(Int8PtrTy, TypeMetadataPtrTy),
2376-
ATTRS(NoUnwind),
2376+
ATTRS(NoUnwind, WillReturn),
2377+
EFFECT(NoEffect))
2378+
2379+
// void swift_singlePayloadEnumGeneric_destructiveInjectEnumTag(swift::OpaqueValue *address,
2380+
// unsigned tag,
2381+
// const Metadata *metadata)
2382+
FUNCTION(SinglePayloadEnumGenericDestructiveInjectEnumTag,
2383+
swift_singlePayloadEnumGeneric_destructiveInjectEnumTag,
2384+
C_CC, AlwaysAvailable,
2385+
RETURNS(VoidTy),
2386+
ARGS(Int8PtrTy, Int32Ty, TypeMetadataPtrTy),
2387+
ATTRS(NoUnwind, WillReturn),
23772388
EFFECT(NoEffect))
23782389

23792390
// void swift_generic_instantiateLayoutString(const uint8_t* layoutStr,

stdlib/public/runtime/BytecodeLayouts.cpp

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -751,29 +751,29 @@ static inline T handleSinglePayloadEnumGenericTag(
751751
LayoutStringReader &reader, uint8_t *addr,
752752
std::function<std::optional<T>(const Metadata *, size_t, uint8_t)>
753753
extraTagBytesHandler,
754-
std::function<T(const Metadata *, unsigned, unsigned)> xiHandler) {
754+
std::function<T(const Metadata *, unsigned, unsigned, size_t, uint8_t)>
755+
xiHandler) {
755756
auto tagBytesAndOffset = reader.readBytes<uint64_t>();
756757
auto extraTagBytesPattern = (uint8_t)(tagBytesAndOffset >> 62);
757758
auto xiTagBytesOffset =
758759
tagBytesAndOffset & std::numeric_limits<uint32_t>::max();
759-
const Metadata *xiType = nullptr;
760+
auto numExtraTagBytes = 1 << (extraTagBytesPattern - 1);
761+
auto payloadSize = reader.readBytes<size_t>();
762+
auto xiType = reader.readBytes<const Metadata *>();
760763

761764
if (extraTagBytesPattern) {
762-
auto numExtraTagBytes = 1 << (extraTagBytesPattern - 1);
763-
auto payloadSize = reader.readBytes<size_t>();
764-
xiType = reader.readBytes<const Metadata *>();
765765
if (auto result =
766766
extraTagBytesHandler(xiType, payloadSize, numExtraTagBytes)) {
767767
return *result;
768768
}
769769
} else {
770770
reader.skip(sizeof(size_t));
771-
xiType = reader.readBytes<const Metadata *>();
772771
}
773772

774773
auto numEmptyCases = reader.readBytes<unsigned>();
775774

776-
return xiHandler(xiType, xiTagBytesOffset, numEmptyCases);
775+
return xiHandler(xiType, xiTagBytesOffset, numEmptyCases, payloadSize,
776+
numExtraTagBytes);
777777
}
778778

779779
extern "C" unsigned
@@ -803,7 +803,8 @@ swift_singlePayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
803803
};
804804

805805
auto xihandler = [addr](const Metadata *xiType, unsigned xiTagBytesOffset,
806-
unsigned numEmptyCases) -> unsigned {
806+
unsigned numEmptyCases, size_t payloadSize,
807+
uint8_t numExtraTagBytes) -> unsigned {
807808
if (xiType) {
808809
return xiType->vw_getEnumTagSinglePayload(
809810
(const OpaqueValue *)(addr + xiTagBytesOffset), numEmptyCases);
@@ -816,6 +817,64 @@ swift_singlePayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
816817
reader, addr, extraTagBytesHandler, xihandler);
817818
}
818819

820+
extern "C" void swift_singlePayloadEnumGeneric_destructiveInjectEnumTag(
821+
swift::OpaqueValue *address, unsigned tag, const Metadata *metadata) {
822+
auto addr = reinterpret_cast<uint8_t *>(address);
823+
LayoutStringReader reader{metadata->getLayoutString(),
824+
layoutStringHeaderSize + sizeof(uint64_t)};
825+
826+
auto extraTagBytesHandler =
827+
[=](const Metadata *xiType, size_t payloadSize,
828+
uint8_t numExtraTagBytes) -> std::optional<bool> {
829+
unsigned payloadNumExtraInhabitants =
830+
xiType ? xiType->vw_getNumExtraInhabitants() : 0;
831+
if (tag <= payloadNumExtraInhabitants) {
832+
return std::nullopt;
833+
}
834+
835+
unsigned noPayloadIndex = tag - 1;
836+
unsigned caseIndex = noPayloadIndex - payloadNumExtraInhabitants;
837+
unsigned payloadIndex, extraTagIndex;
838+
if (payloadSize >= 4) {
839+
extraTagIndex = 1;
840+
payloadIndex = caseIndex;
841+
} else {
842+
unsigned payloadBits = payloadSize * 8U;
843+
extraTagIndex = 1U + (caseIndex >> payloadBits);
844+
payloadIndex = caseIndex & ((1U << payloadBits) - 1U);
845+
}
846+
847+
// Store into the value.
848+
if (payloadSize)
849+
storeEnumElement(addr, payloadIndex, payloadSize);
850+
if (numExtraTagBytes)
851+
storeEnumElement(addr + payloadSize, extraTagIndex, numExtraTagBytes);
852+
853+
return true;
854+
};
855+
856+
auto xihandler = [=](const Metadata *xiType, unsigned xiTagBytesOffset,
857+
unsigned numEmptyCases, size_t payloadSize,
858+
uint8_t numExtraTagBytes) -> bool {
859+
unsigned payloadNumExtraInhabitants =
860+
xiType ? xiType->vw_getNumExtraInhabitants() : 0;
861+
if (tag <= payloadNumExtraInhabitants) {
862+
if (numExtraTagBytes != 0)
863+
storeEnumElement(addr + payloadSize, 0, numExtraTagBytes);
864+
865+
if (tag == 0)
866+
return true;
867+
868+
xiType->vw_storeEnumTagSinglePayload(
869+
(swift::OpaqueValue *)(addr + xiTagBytesOffset), tag, numEmptyCases);
870+
}
871+
return true;
872+
};
873+
874+
handleSinglePayloadEnumGenericTag<bool>(reader, addr, extraTagBytesHandler,
875+
xihandler);
876+
}
877+
819878
extern "C" swift::OpaqueValue *
820879
swift_generic_initializeBufferWithCopyOfBuffer(swift::ValueBuffer *dest,
821880
swift::ValueBuffer *src,

stdlib/public/runtime/BytecodeLayouts.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ SWIFT_RUNTIME_EXPORT
133133
unsigned swift_singlePayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
134134
const Metadata *metadata);
135135
SWIFT_RUNTIME_EXPORT
136+
void swift_singlePayloadEnumGeneric_destructiveInjectEnumTag(
137+
swift::OpaqueValue *address, unsigned tag, const Metadata *metadata);
138+
SWIFT_RUNTIME_EXPORT
136139
void swift_generic_instantiateLayoutString(const uint8_t *layoutStr,
137140
Metadata *type);
138141

0 commit comments

Comments
 (0)