Skip to content

Commit b71733d

Browse files
authored
Merge pull request #67171 from drexin/wip-sp-simp-inject
Support destructiveInjectEnumTag in simple single payload enums with layout strings
2 parents eb82df6 + 2f0726a commit b71733d

File tree

5 files changed

+96
-1
lines changed

5 files changed

+96
-1
lines changed

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,6 +2346,17 @@ FUNCTION(EnumSimpleGetEnumTag,
23462346
ATTRS(NoUnwind, WillReturn),
23472347
EFFECT(NoEffect))
23482348

2349+
// unsigned swift_enumSimple_destructiveInjectEnumTag(swift::OpaqueValue *address,
2350+
// unsigned tag,
2351+
// const Metadata *metadata)
2352+
FUNCTION(EnumSimpleDestructiveInjectEnumTag,
2353+
swift_enumSimple_destructiveInjectEnumTag,
2354+
C_CC, AlwaysAvailable,
2355+
RETURNS(VoidTy),
2356+
ARGS(Int8PtrTy, Int32Ty, TypeMetadataPtrTy),
2357+
ATTRS(NoUnwind, WillReturn),
2358+
EFFECT(NoEffect))
2359+
23492360
// unsigned swift_enumFn_getEnumTag(swift::OpaqueValue *address,
23502361
// const Metadata *metadata);
23512362
FUNCTION(EnumFnGetEnumTag,

lib/IRGen/GenValueWitness.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ getDestructiveInjectEnumTagFunction(IRGenModule &IGM,
960960
(tzCount % toCount != 0))) {
961961
return nullptr;
962962
} else {
963-
return nullptr;
963+
return IGM.getEnumSimpleDestructiveInjectEnumTagFn();
964964
}
965965
}
966966
}

stdlib/public/runtime/BytecodeLayouts.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,62 @@ extern "C" unsigned swift_enumSimple_getEnumTag(swift::OpaqueValue *address,
729729
reader, addr, extraTagBytesHandler, xihandler);
730730
}
731731

732+
extern "C" void swift_enumSimple_destructiveInjectEnumTag(
733+
swift::OpaqueValue *address, unsigned tag, const Metadata *metadata) {
734+
auto addr = reinterpret_cast<uint8_t *>(address);
735+
LayoutStringReader reader{metadata->getLayoutString(),
736+
layoutStringHeaderSize + sizeof(uint64_t)};
737+
738+
auto extraTagBytesHandler =
739+
[addr, tag](size_t payloadNumExtraInhabitants, size_t payloadSize,
740+
uint8_t numExtraTagBytes) -> std::optional<bool> {
741+
if (tag <= payloadNumExtraInhabitants) {
742+
return std::nullopt;
743+
}
744+
745+
unsigned noPayloadIndex = tag - 1;
746+
unsigned caseIndex = noPayloadIndex - payloadNumExtraInhabitants;
747+
unsigned payloadIndex, extraTagIndex;
748+
if (payloadSize >= 4) {
749+
extraTagIndex = 1;
750+
payloadIndex = caseIndex;
751+
} else {
752+
unsigned payloadBits = payloadSize * 8U;
753+
extraTagIndex = 1U + (caseIndex >> payloadBits);
754+
payloadIndex = caseIndex & ((1U << payloadBits) - 1U);
755+
}
756+
757+
// Store into the value.
758+
if (payloadSize)
759+
storeEnumElement(addr, payloadIndex, payloadSize);
760+
if (numExtraTagBytes)
761+
storeEnumElement(addr + payloadSize, extraTagIndex, numExtraTagBytes);
762+
763+
return true;
764+
};
765+
766+
auto xihandler = [addr, tag](size_t payloadNumExtraInhabitants,
767+
uint64_t zeroTagValue, uint8_t xiTagBytesPattern,
768+
unsigned xiTagBytesOffset, size_t payloadSize,
769+
uint8_t numExtraTagBytes) -> bool {
770+
auto xiTagBytes = 1 << (xiTagBytesPattern - 1);
771+
if (tag <= payloadNumExtraInhabitants) {
772+
if (numExtraTagBytes != 0)
773+
storeEnumElement(addr + payloadSize, 0, numExtraTagBytes);
774+
775+
if (tag == 0)
776+
return true;
777+
778+
storeEnumElement(addr + xiTagBytesOffset, tag - 1 + zeroTagValue,
779+
xiTagBytes);
780+
}
781+
return true;
782+
};
783+
784+
handleSinglePayloadEnumSimpleTag<bool>(reader, addr, extraTagBytesHandler,
785+
xihandler);
786+
}
787+
732788
extern "C"
733789
unsigned swift_enumFn_getEnumTag(swift::OpaqueValue *address,
734790
const Metadata *metadata) {

stdlib/public/runtime/BytecodeLayouts.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ SWIFT_RUNTIME_EXPORT
124124
unsigned swift_enumSimple_getEnumTag(swift::OpaqueValue *address,
125125
const Metadata *metadata);
126126
SWIFT_RUNTIME_EXPORT
127+
void swift_enumSimple_destructiveInjectEnumTag(swift::OpaqueValue *address,
128+
unsigned tag,
129+
const Metadata *metadata);
130+
SWIFT_RUNTIME_EXPORT
127131
unsigned swift_enumFn_getEnumTag(swift::OpaqueValue *address,
128132
const Metadata *metadata);
129133
SWIFT_RUNTIME_EXPORT

test/Interpreter/layout_string_witnesses_dynamic.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,30 @@ func testResilientMultiPayloadEnumGenericTag() {
594594

595595
testResilientMultiPayloadEnumGenericTag()
596596

597+
@inline(never)
598+
func matchResilientSinglePayloadEnumSimpleTag(_ x: ResilientSinglePayloadEnumSimple) -> Int {
599+
return switch x {
600+
case .nonEmpty: 0
601+
case .empty0: 1
602+
case .empty1: 2
603+
}
604+
}
605+
606+
func testResilientSinglePayloadEnumSimpleInjectTag() {
607+
let x = ResilientSinglePayloadEnumSimple.nonEmpty(SimpleClass(x: 23))
608+
let y = ResilientSinglePayloadEnumSimple.empty0
609+
let z = ResilientSinglePayloadEnumSimple.empty1
610+
611+
// CHECK: Enum case: 0
612+
print("Enum case: \(matchResilientSinglePayloadEnumSimpleTag(x))")
613+
// CHECK: Enum case: 1
614+
print("Enum case: \(matchResilientSinglePayloadEnumSimpleTag(y))")
615+
// CHECK: Enum case: 2
616+
print("Enum case: \(matchResilientSinglePayloadEnumSimpleTag(z))")
617+
}
618+
619+
testResilientSinglePayloadEnumSimpleInjectTag()
620+
597621
@inline(never)
598622
func matchResilientSinglePayloadEnumGenericTag(_ x: ResilientSinglePayloadEnumGeneric<AnyObject>) -> Int {
599623
return switch x {

0 commit comments

Comments
 (0)