Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions include/swift/Runtime/RuntimeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,17 @@ FUNCTION(MultiPayloadEnumGenericGetEnumTag,
ATTRS(NoUnwind, WillReturn),
EFFECT(NoEffect))

// void swift_multiPayloadEnumGeneric_destructiveInjectEnumTag(swift::OpaqueValue *address,
// unsigned tag,
// const Metadata *metadata)
FUNCTION(MultiPayloadEnumGenericDestructiveInjectEnumTag,
swift_multiPayloadEnumGeneric_destructiveInjectEnumTag,
C_CC, AlwaysAvailable,
RETURNS(VoidTy),
ARGS(Int8PtrTy, Int32Ty, TypeMetadataPtrTy),
ATTRS(NoUnwind, WillReturn),
EFFECT(NoEffect))

// unsigned swift_singlePayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
// const Metadata *metadata);
FUNCTION(SinglePayloadEnumGenericGetEnumTag,
Expand Down
7 changes: 4 additions & 3 deletions lib/IRGen/GenValueWitness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -936,12 +936,13 @@ getDestructiveInjectEnumTagFunction(IRGenModule &IGM,
const EnumTypeLayoutEntry *typeLayoutEntry,
GenericSignature genericSig) {
if ((!typeLayoutEntry->layoutString(IGM, genericSig) &&
!isRuntimeInstatiatedLayoutString(IGM, typeLayoutEntry)) ||
typeLayoutEntry->isSingleton()) {
!isRuntimeInstatiatedLayoutString(IGM, typeLayoutEntry))) {
return nullptr;
} else if (typeLayoutEntry->isSingleton()) {
return nullptr;
} else if (!typeLayoutEntry->isFixedSize(IGM)) {
if (typeLayoutEntry->isMultiPayloadEnum()) {
return nullptr;
return IGM.getMultiPayloadEnumGenericDestructiveInjectEnumTagFn();
} else {
return IGM.getSinglePayloadEnumGenericDestructiveInjectEnumTagFn();
}
Expand Down
35 changes: 35 additions & 0 deletions stdlib/public/runtime/BytecodeLayouts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,41 @@ swift_multiPayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
}
}

extern "C" void swift_multiPayloadEnumGeneric_destructiveInjectEnumTag(
swift::OpaqueValue *address, unsigned tag, const Metadata *metadata) {
auto addr = reinterpret_cast<uint8_t *>(address);
LayoutStringReader reader{metadata->getLayoutString(),
layoutStringHeaderSize + sizeof(uint64_t)};

auto numTagBytes = reader.readBytes<size_t>();
auto numPayloads = reader.readBytes<size_t>();
reader.skip(sizeof(size_t));
auto enumSize = reader.readBytes<size_t>();
auto payloadSize = enumSize - numTagBytes;

if (tag < numPayloads) {
// For a payload case, store the tag after the payload area.
auto tagBytes = addr + payloadSize;
storeEnumElement(tagBytes, tag, numTagBytes);
} else {
// For an empty case, factor out the parts that go in the payload and
// tag areas.
unsigned whichEmptyCase = tag - numPayloads;
unsigned whichTag, whichPayloadValue;
if (payloadSize >= 4) {
whichTag = numPayloads;
whichPayloadValue = whichEmptyCase;
} else {
unsigned numPayloadBits = payloadSize * CHAR_BIT;
whichTag = numPayloads + (whichEmptyCase >> numPayloadBits);
whichPayloadValue = whichEmptyCase & ((1U << numPayloadBits) - 1U);
}
auto tagBytes = addr + payloadSize;
storeEnumElement(tagBytes, whichTag, numTagBytes);
storeEnumElement(addr, whichPayloadValue, payloadSize);
}
}

template <typename T>
static inline T handleSinglePayloadEnumGenericTag(
LayoutStringReader &reader, uint8_t *addr,
Expand Down
3 changes: 3 additions & 0 deletions stdlib/public/runtime/BytecodeLayouts.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ SWIFT_RUNTIME_EXPORT
unsigned swift_multiPayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
const Metadata *metadata);
SWIFT_RUNTIME_EXPORT
void swift_multiPayloadEnumGeneric_destructiveInjectEnumTag(
swift::OpaqueValue *address, unsigned tag, const Metadata *metadata);
SWIFT_RUNTIME_EXPORT
unsigned swift_singlePayloadEnumGeneric_getEnumTag(swift::OpaqueValue *address,
const Metadata *metadata);
SWIFT_RUNTIME_EXPORT
Expand Down
28 changes: 28 additions & 0 deletions test/Interpreter/layout_string_witnesses_dynamic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,34 @@ func testResilientSinglePayloadEnumGenericInjectTag() {

testResilientSinglePayloadEnumGenericInjectTag()

@inline(never)
func matchResilientMultiPayloadEnumGenericTag(_ x: ResilientMultiPayloadEnumGeneric<AnyObject>) -> Int {
return switch x {
case .nonEmpty0: 0
case .nonEmpty1: 1
case .empty0: 2
case .empty1: 3
}
}

func testResilientMultiPayloadEnumGenericInjectTag() {
let x = ResilientMultiPayloadEnumGeneric<AnyObject>.nonEmpty0(SimpleClass(x: 23))
let y = ResilientMultiPayloadEnumGeneric<AnyObject>.nonEmpty1(SimpleClass(x: 32))
let z = ResilientMultiPayloadEnumGeneric<AnyObject>.empty0
let w = ResilientMultiPayloadEnumGeneric<AnyObject>.empty1

// CHECK: Enum case: 0
print("Enum case: \(matchResilientMultiPayloadEnumGenericTag(x))")
// CHECK: Enum case: 1
print("Enum case: \(matchResilientMultiPayloadEnumGenericTag(y))")
// CHECK: Enum case: 2
print("Enum case: \(matchResilientMultiPayloadEnumGenericTag(z))")
// CHECK: Enum case: 3
print("Enum case: \(matchResilientMultiPayloadEnumGenericTag(w))")
}

testResilientMultiPayloadEnumGenericInjectTag()

#if os(macOS)

import Foundation
Expand Down