mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[IRGen] Handle complex single payload enum cases (#66289)
* [IRGen] Handle complex single payload enum cases rdar://110138498 Handles single payload enum cases with more complex bit patterns (e.g. >64 bits or scattered) by storing a relative pointer to a function that reads the tag. * Use proper symbol for enum tag helper
This commit is contained in:
@@ -400,6 +400,16 @@ std::string IRGenMangler::mangleSymbolNameForMangledConformanceAccessorString(
|
||||
return finalize();
|
||||
}
|
||||
|
||||
std::string IRGenMangler::mangleSymbolNameForMangledGetEnumTagForLayoutString(
|
||||
CanType type) {
|
||||
beginManglingWithoutPrefix();
|
||||
Buffer << "get_enum_tag_for_layout_string"
|
||||
<< " ";
|
||||
|
||||
appendType(type, nullptr);
|
||||
return finalize();
|
||||
}
|
||||
|
||||
std::string IRGenMangler::mangleSymbolNameForUnderlyingTypeAccessorString(
|
||||
OpaqueTypeDecl *opaque, unsigned index) {
|
||||
beginManglingWithoutPrefix();
|
||||
|
||||
@@ -633,6 +633,8 @@ public:
|
||||
CanType type,
|
||||
ProtocolConformanceRef conformance);
|
||||
|
||||
std::string mangleSymbolNameForMangledGetEnumTagForLayoutString(CanType type);
|
||||
|
||||
std::string
|
||||
mangleSymbolNameForUnderlyingTypeAccessorString(OpaqueTypeDecl *opaque,
|
||||
unsigned index);
|
||||
|
||||
@@ -76,6 +76,8 @@ public:
|
||||
Existential = 0x0e,
|
||||
Resilient = 0x0f,
|
||||
SinglePayloadEnumSimple = 0x10,
|
||||
SinglePayloadEnumFN = 0x11,
|
||||
SinglePayloadEnumFNResolved = 0x12,
|
||||
|
||||
Skip = 0x80,
|
||||
// We may use the MSB as flag that a count follows,
|
||||
@@ -93,12 +95,19 @@ private:
|
||||
const TypeLayoutEntry *payload;
|
||||
};
|
||||
|
||||
struct SinglePayloadEnumFN {
|
||||
llvm::Function *tagFn;
|
||||
unsigned extraTagByteCount;
|
||||
const TypeLayoutEntry *payload;
|
||||
};
|
||||
|
||||
struct RefCounting {
|
||||
RefCountingKind kind;
|
||||
union {
|
||||
size_t size;
|
||||
llvm::Function* metaTypeRef;
|
||||
SinglePayloadEnumSimple singlePayloadEnumSimple;
|
||||
SinglePayloadEnumFN singlePayloadEnumFN;
|
||||
};
|
||||
|
||||
RefCounting() = default;
|
||||
@@ -132,6 +141,16 @@ public:
|
||||
refCountings.push_back(op);
|
||||
}
|
||||
|
||||
void addSinglePayloadEnumFN(llvm::Function *tagFn, unsigned extraTagByteCount,
|
||||
const TypeLayoutEntry *payload) {
|
||||
RefCounting op;
|
||||
op.kind = RefCountingKind::SinglePayloadEnumFN;
|
||||
op.singlePayloadEnumFN.tagFn = tagFn;
|
||||
op.singlePayloadEnumSimple.extraTagByteCount = extraTagByteCount;
|
||||
op.singlePayloadEnumFN.payload = payload;
|
||||
refCountings.push_back(op);
|
||||
}
|
||||
|
||||
void addSkip(size_t size) {
|
||||
if (refCountings.empty() ||
|
||||
refCountings.back().kind != RefCountingKind::Skip) {
|
||||
@@ -227,6 +246,40 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
case RefCountingKind::SinglePayloadEnumFN: {
|
||||
uint64_t op = (static_cast<uint64_t>(refCounting.kind) << 56) | skip;
|
||||
B.addInt64(op);
|
||||
|
||||
skip = 0;
|
||||
size_t nestedRefCountBytes = 0;
|
||||
|
||||
auto enumData = refCounting.singlePayloadEnumFN;
|
||||
|
||||
B.addRelativeOffset(IGM.IntPtrTy, enumData.tagFn);
|
||||
|
||||
auto nestedRefCountBytesPlaceholder =
|
||||
B.addPlaceholderWithSize(IGM.SizeTy);
|
||||
auto skipBytesPlaceholder = B.addPlaceholderWithSize(IGM.SizeTy);
|
||||
|
||||
LayoutStringBuilder nestedBuilder{};
|
||||
enumData.payload->refCountString(IGM, nestedBuilder, genericSig);
|
||||
addRefCountings(IGM, B, genericSig, nestedBuilder.refCountings, skip,
|
||||
nestedRefCountBytes, flags);
|
||||
|
||||
auto nestedSkip = enumData.payload->fixedSize(IGM)->getValue() - skip;
|
||||
B.fillPlaceholderWithInt(nestedRefCountBytesPlaceholder, IGM.SizeTy,
|
||||
nestedRefCountBytes);
|
||||
B.fillPlaceholderWithInt(skipBytesPlaceholder, IGM.SizeTy, nestedSkip);
|
||||
|
||||
refCountBytes += (sizeof(uint64_t)) +
|
||||
(3 * IGM.getPointerSize().getValue()) +
|
||||
nestedRefCountBytes;
|
||||
skip += enumData.extraTagByteCount;
|
||||
|
||||
flags |= LayoutStringFlags::HasRelativePointers;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
uint64_t op = (static_cast<uint64_t>(refCounting.kind) << 56) | skip;
|
||||
B.addInt64(op);
|
||||
@@ -362,6 +415,30 @@ llvm::Function *createMetatypeAccessorFunction(IRGenModule &IGM, SILType ty,
|
||||
return static_cast<llvm::Function *>(helperFn);
|
||||
}
|
||||
|
||||
llvm::Function *createFixedEnumLoadTag(IRGenModule &IGM,
|
||||
const EnumTypeLayoutEntry &entry) {
|
||||
assert(entry.isFixedSize(IGM));
|
||||
|
||||
IRGenMangler mangler;
|
||||
auto symbol = mangler.mangleSymbolNameForMangledGetEnumTagForLayoutString(
|
||||
entry.ty.getASTType());
|
||||
|
||||
auto helperFn = IGM.getOrCreateHelperFunction(
|
||||
symbol, IGM.Int32Ty /*retTy*/, IGM.Int8PtrTy /*argTys*/,
|
||||
[&](IRGenFunction &IGF) {
|
||||
auto enumPtr = IGF.collectParameters().claimNext();
|
||||
auto *typeInfo = *entry.fixedTypeInfo;
|
||||
auto enumType = typeInfo->getStorageType()->getPointerTo();
|
||||
auto castEnumPtr = IGF.Builder.CreateBitCast(enumPtr, enumType);
|
||||
auto enumAddr = typeInfo->getAddressForPointer(castEnumPtr);
|
||||
|
||||
auto tag = entry.getEnumTag(IGF, enumAddr);
|
||||
IGF.Builder.CreateRet(tag);
|
||||
});
|
||||
|
||||
return static_cast<llvm::Function *>(helperFn);
|
||||
}
|
||||
|
||||
TypeLayoutEntry::~TypeLayoutEntry() {}
|
||||
|
||||
void TypeLayoutEntry::computeProperties() {
|
||||
@@ -2069,6 +2146,7 @@ bool EnumTypeLayoutEntry::buildSinglePayloadRefCountString(
|
||||
uint64_t zeroTagValue = 0;
|
||||
unsigned xiBitCount = 0;
|
||||
unsigned xiOffset = 0;
|
||||
bool isSimple = true;
|
||||
|
||||
auto &payloadTI = **cases[0]->getFixedTypeInfo();
|
||||
|
||||
@@ -2088,12 +2166,12 @@ bool EnumTypeLayoutEntry::buildSinglePayloadRefCountString(
|
||||
(tzCount % toCount != 0)) {
|
||||
// We currently don't handle cases with non-contiguous or > 64 bits of
|
||||
// extra inhabitants
|
||||
return false;
|
||||
isSimple = false;
|
||||
} else {
|
||||
xiBitCount = std::min(64u, mask.countPopulation());
|
||||
xiOffset = mask.countTrailingZeros();
|
||||
zeroTagValue = lowValue.extractBitsAsZExtValue(xiBitCount, xiOffset);
|
||||
}
|
||||
|
||||
xiBitCount = std::min(64u, mask.countPopulation());
|
||||
xiOffset = mask.countTrailingZeros();
|
||||
zeroTagValue = lowValue.extractBitsAsZExtValue(xiBitCount, xiOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2119,8 +2197,13 @@ bool EnumTypeLayoutEntry::buildSinglePayloadRefCountString(
|
||||
return false;
|
||||
}
|
||||
|
||||
B.addSinglePayloadEnumSimple(zeroTagValue, xiTagValues, extraTagByteCount,
|
||||
xiBitCount / 8, xiOffset, cases[0]);
|
||||
if (isSimple) {
|
||||
B.addSinglePayloadEnumSimple(zeroTagValue, xiTagValues, extraTagByteCount,
|
||||
xiBitCount / 8, xiOffset, cases[0]);
|
||||
} else {
|
||||
auto tagFn = createFixedEnumLoadTag(IGM, *this);
|
||||
B.addSinglePayloadEnumFN(tagFn, extraTagByteCount, cases[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "llvm/Support/SwapByteOrder.h"
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
#include "swift/Runtime/ObjCBridge.h"
|
||||
#include <Block.h>
|
||||
@@ -60,24 +61,33 @@ static Metadata *getExistentialTypeMetadata(OpaqueValue *object) {
|
||||
return reinterpret_cast<Metadata**>(object)[NumWords_ValueBuffer];
|
||||
}
|
||||
|
||||
typedef Metadata* (*MetadataAccessor)(const Metadata* const *);
|
||||
template <typename FnTy>
|
||||
static const FnTy readRelativeFunctionPointer(const uint8_t *layoutStr,
|
||||
size_t &offset) {
|
||||
static_assert(std::is_pointer<FnTy>::value);
|
||||
|
||||
static const Metadata *getResilientTypeMetadata(const Metadata* metadata,
|
||||
const uint8_t *layoutStr,
|
||||
size_t &offset) {
|
||||
auto absolute = layoutStr + offset;
|
||||
auto relativeOffset =
|
||||
(uintptr_t)(intptr_t)(int32_t)readBytes<intptr_t>(layoutStr, offset);
|
||||
MetadataAccessor fn;
|
||||
FnTy fn;
|
||||
|
||||
#if SWIFT_PTRAUTH
|
||||
fn = (MetadataAccessor)ptrauth_sign_unauthenticated(
|
||||
fn = (FnTy)ptrauth_sign_unauthenticated(
|
||||
(void *)((uintptr_t)absolute + relativeOffset),
|
||||
ptrauth_key_function_pointer, 0);
|
||||
#else
|
||||
fn = (MetadataAccessor)((uintptr_t)absolute + relativeOffset);
|
||||
fn = (FnTy)((uintptr_t)absolute + relativeOffset);
|
||||
#endif
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
typedef Metadata *(*MetadataAccessor)(const Metadata *const *);
|
||||
|
||||
static const Metadata *getResilientTypeMetadata(const Metadata *metadata,
|
||||
const uint8_t *layoutStr,
|
||||
size_t &offset) {
|
||||
auto fn = readRelativeFunctionPointer<MetadataAccessor>(layoutStr, offset);
|
||||
return fn(metadata->getGenericArgs());
|
||||
}
|
||||
|
||||
@@ -117,6 +127,13 @@ inline static bool handleNextRefCount(const Metadata *metadata, const uint8_t *t
|
||||
} else if (SWIFT_UNLIKELY(tag ==
|
||||
RefCountingKind::SinglePayloadEnumSimple)) {
|
||||
Handler::handleSinglePayloadEnumSimple(typeLayout, offset, addrOffset, std::forward<Params>(params)...);
|
||||
} else if (SWIFT_UNLIKELY(tag == RefCountingKind::SinglePayloadEnumFN)) {
|
||||
Handler::handleSinglePayloadEnumFN(typeLayout, offset, false, addrOffset,
|
||||
std::forward<Params>(params)...);
|
||||
} else if (SWIFT_UNLIKELY(tag ==
|
||||
RefCountingKind::SinglePayloadEnumFNResolved)) {
|
||||
Handler::handleSinglePayloadEnumFN(typeLayout, offset, true, addrOffset,
|
||||
std::forward<Params>(params)...);
|
||||
} else {
|
||||
Handler::handleReference(tag, addrOffset, std::forward<Params>(params)...);
|
||||
}
|
||||
@@ -154,8 +171,9 @@ static uint64_t readTagBytes(uint8_t *addr, uint8_t byteCount) {
|
||||
}
|
||||
}
|
||||
|
||||
static void handleSinglePayloadEnumSimple(const uint8_t *typeLayout, size_t &offset,
|
||||
uint8_t *addr, size_t &addrOffset) {
|
||||
static void handleSinglePayloadEnumSimple(const uint8_t *typeLayout,
|
||||
size_t &offset, uint8_t *addr,
|
||||
size_t &addrOffset) {
|
||||
auto byteCountsAndOffset = readBytes<uint64_t>(typeLayout, offset);
|
||||
auto extraTagBytesPattern = (uint8_t)(byteCountsAndOffset >> 62);
|
||||
auto xiTagBytesPattern = ((uint8_t)(byteCountsAndOffset >> 59)) & 0x7;
|
||||
@@ -198,6 +216,30 @@ noPayload:
|
||||
addrOffset += skip;
|
||||
}
|
||||
|
||||
typedef unsigned (*GetEnumTagFn)(const uint8_t *);
|
||||
|
||||
static void handleSinglePayloadEnumFN(const uint8_t *typeLayout, size_t &offset,
|
||||
bool resolved, uint8_t *addr,
|
||||
size_t &addrOffset) {
|
||||
GetEnumTagFn getEnumTag;
|
||||
if (resolved) {
|
||||
getEnumTag = readBytes<GetEnumTagFn>(typeLayout, offset);
|
||||
} else {
|
||||
getEnumTag = readRelativeFunctionPointer<GetEnumTagFn>(typeLayout, offset);
|
||||
}
|
||||
|
||||
unsigned enumTag = getEnumTag(addr + addrOffset);
|
||||
|
||||
if (enumTag == 0) {
|
||||
offset += sizeof(size_t) * 2;
|
||||
} else {
|
||||
auto refCountBytes = readBytes<size_t>(typeLayout, offset);
|
||||
auto skip = readBytes<size_t>(typeLayout, offset);
|
||||
offset += refCountBytes;
|
||||
addrOffset += skip;
|
||||
}
|
||||
}
|
||||
|
||||
const DestroyFuncAndMask destroyTable[] = {
|
||||
{(DestrFn)&skipDestroy, false},
|
||||
{(DestrFn)&swift_errorRelease, true},
|
||||
@@ -232,6 +274,13 @@ struct DestroyHandler {
|
||||
::handleSinglePayloadEnumSimple(typeLayout, offset, addr, addrOffset);
|
||||
}
|
||||
|
||||
static inline void handleSinglePayloadEnumFN(const uint8_t *typeLayout,
|
||||
size_t &offset, bool resolved,
|
||||
size_t &addrOffset,
|
||||
uint8_t *addr) {
|
||||
::handleSinglePayloadEnumFN(typeLayout, offset, resolved, addr, addrOffset);
|
||||
}
|
||||
|
||||
static inline void handleReference(RefCountingKind tag, uintptr_t addrOffset, uint8_t *addr) {
|
||||
const auto &destroyFunc = destroyTable[static_cast<uint8_t>(tag)];
|
||||
if (SWIFT_LIKELY(destroyFunc.isIndirect)) {
|
||||
@@ -305,6 +354,14 @@ struct CopyHandler {
|
||||
::handleSinglePayloadEnumSimple(typeLayout, offset, (uint8_t *)src, addrOffset);
|
||||
}
|
||||
|
||||
static inline void handleSinglePayloadEnumFN(const uint8_t *typeLayout,
|
||||
size_t &offset, bool resolved,
|
||||
size_t &addrOffset,
|
||||
uint8_t *dest, uint8_t *src) {
|
||||
::handleSinglePayloadEnumFN(typeLayout, offset, resolved, (uint8_t *)src,
|
||||
addrOffset);
|
||||
}
|
||||
|
||||
static inline void handleReference(RefCountingKind tag, uintptr_t addrOffset, uint8_t *dest, uint8_t *src) {
|
||||
const auto &retainFunc = retainTable[static_cast<uint8_t>(tag)];
|
||||
if (SWIFT_LIKELY(retainFunc.isSingle)) {
|
||||
@@ -388,6 +445,18 @@ swift_generic_initWithTake(swift::OpaqueValue *dest, swift::OpaqueValue *src,
|
||||
break;
|
||||
}
|
||||
|
||||
case RefCountingKind::SinglePayloadEnumFN: {
|
||||
handleSinglePayloadEnumFN(typeLayout, offset, false, (uint8_t *)src,
|
||||
addrOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
case RefCountingKind::SinglePayloadEnumFNResolved: {
|
||||
handleSinglePayloadEnumFN(typeLayout, offset, true, (uint8_t *)src,
|
||||
addrOffset);
|
||||
break;
|
||||
}
|
||||
|
||||
case RefCountingKind::End:
|
||||
return dest;
|
||||
default:
|
||||
@@ -439,6 +508,25 @@ void swift::swift_resolve_resilientAccessors(
|
||||
case RefCountingKind::SinglePayloadEnumSimple:
|
||||
i += (3 * sizeof(uint64_t)) + (4 * sizeof(size_t));
|
||||
break;
|
||||
|
||||
case RefCountingKind::SinglePayloadEnumFN: {
|
||||
auto getEnumTag =
|
||||
readRelativeFunctionPointer<GetEnumTagFn>(fieldLayoutStr, i);
|
||||
size_t writeOffset =
|
||||
layoutStrOffset + currentOffset - layoutStringHeaderSize;
|
||||
uint64_t tagAndOffset =
|
||||
(((uint64_t)RefCountingKind::SinglePayloadEnumFNResolved) << 56) |
|
||||
size;
|
||||
writeBytes(layoutStr, writeOffset, tagAndOffset);
|
||||
writeBytes(layoutStr, writeOffset, getEnumTag);
|
||||
i += 2 * sizeof(size_t);
|
||||
break;
|
||||
}
|
||||
|
||||
case RefCountingKind::SinglePayloadEnumFNResolved:
|
||||
i += 3 * sizeof(size_t);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ enum class RefCountingKind : uint8_t {
|
||||
Resilient = 0x0f,
|
||||
|
||||
SinglePayloadEnumSimple = 0x10,
|
||||
SinglePayloadEnumFN = 0x11,
|
||||
SinglePayloadEnumFNResolved = 0x12,
|
||||
|
||||
Skip = 0x80,
|
||||
// We may use the MSB as flag that a count follows,
|
||||
|
||||
@@ -442,6 +442,17 @@ public struct InternalEnumWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
public enum SinglePayloadEnumManyXI {
|
||||
case empty0
|
||||
case empty1
|
||||
case empty2
|
||||
case empty3
|
||||
case empty4
|
||||
case empty5
|
||||
case empty6
|
||||
case nonEmpty(Builtin.Int127, SimpleClass)
|
||||
}
|
||||
|
||||
public struct PrespecializedStruct<T> {
|
||||
let y: Int = 0
|
||||
let x: T
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -prespecialize-generic-metadata -enable-experimental-feature LayoutStringValueWitnesses -enable-experimental-feature LayoutStringValueWitnessesInstantiation -enable-layout-string-value-witnesses -enable-layout-string-value-witnesses-instantiation -enable-type-layout -enable-autolinking-runtime-compatibility-bytecode-layouts -emit-module -emit-module-path=%t/layout_string_witnesses_types.swiftmodule %S/Inputs/layout_string_witnesses_types.swift
|
||||
// RUN: %target-swift-frontend -prespecialize-generic-metadata -enable-experimental-feature LayoutStringValueWitnesses -enable-experimental-feature LayoutStringValueWitnessesInstantiation -enable-layout-string-value-witnesses -enable-layout-string-value-witnesses-instantiation -enable-type-layout -enable-autolinking-runtime-compatibility-bytecode-layouts -parse-stdlib -emit-module -emit-module-path=%t/layout_string_witnesses_types.swiftmodule %S/Inputs/layout_string_witnesses_types.swift
|
||||
// RUN: %target-build-swift-dylib(%t/%target-library-name(layout_string_witnesses_types)) -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-layout-string-value-witnesses-instantiation -Xfrontend -enable-type-layout -Xfrontend -parse-stdlib -parse-as-library %S/Inputs/layout_string_witnesses_types.swift
|
||||
// RUN: %target-codesign %t/%target-library-name(layout_string_witnesses_types)
|
||||
// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-experimental-feature LayoutStringValueWitnessesInstantiation -enable-layout-string-value-witnesses -enable-layout-string-value-witnesses-instantiation -enable-library-evolution -enable-autolinking-runtime-compatibility-bytecode-layouts -emit-module -emit-module-path=%t/layout_string_witnesses_types_resilient.swiftmodule %S/Inputs/layout_string_witnesses_types_resilient.swift
|
||||
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-layout-string-value-witnesses-instantiation -Xfrontend -enable-library-evolution -c -parse-as-library -o %t/layout_string_witnesses_types_resilient.o %S/Inputs/layout_string_witnesses_types_resilient.swift
|
||||
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-layout-string-value-witnesses-instantiation -Xfrontend -enable-type-layout -Xfrontend -enable-autolinking-runtime-compatibility-bytecode-layouts -module-name layout_string_witnesses_dynamic -llayout_string_witnesses_types -L%t %t/layout_string_witnesses_types_resilient.o -I %t -o %t/main %s %target-rpath(%t)
|
||||
// RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnessesInstantiation -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-layout-string-value-witnesses-instantiation -Xfrontend -enable-type-layout -parse-stdlib -module-name layout_string_witnesses_dynamic -llayout_string_witnesses_types -L%t %t/layout_string_witnesses_types_resilient.o -I %t -o %t/main %s %target-rpath(%t)
|
||||
// RUN: %target-codesign %t/main
|
||||
// RUN: %target-run %t/main %t/%target-library-name(layout_string_witnesses_types) | %FileCheck %s --check-prefix=CHECK -check-prefix=CHECK-%target-os
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
// UNSUPPORTED: back_deployment_runtime
|
||||
|
||||
import Swift
|
||||
import layout_string_witnesses_types
|
||||
import layout_string_witnesses_types_resilient
|
||||
|
||||
@@ -431,6 +432,34 @@ func testMixedEnumWrapperWrapperGeneric() {
|
||||
|
||||
testMixedEnumWrapperWrapperGeneric()
|
||||
|
||||
func testGenericSinglePayloadEnumManyXI() {
|
||||
let ptr = allocateInternalGenericPtr(of: SinglePayloadEnumManyXI.self)
|
||||
|
||||
do {
|
||||
let x = SinglePayloadEnumManyXI.nonEmpty(Builtin.zeroInitializer(), SimpleClass(x: 23))
|
||||
testGenericInit(ptr, to: x)
|
||||
}
|
||||
|
||||
do {
|
||||
let y = SinglePayloadEnumManyXI.nonEmpty(Builtin.zeroInitializer(), SimpleClass(x: 23))
|
||||
// CHECK: Before deinit
|
||||
print("Before deinit")
|
||||
|
||||
// CHECK-NEXT: SimpleClass deinitialized!
|
||||
testGenericAssign(ptr, from: y)
|
||||
}
|
||||
|
||||
// CHECK-NEXT: Before deinit
|
||||
print("Before deinit")
|
||||
|
||||
// CHECK-NEXT: SimpleClass deinitialized!
|
||||
testGenericDestroy(ptr, of: SinglePayloadEnumManyXI.self)
|
||||
|
||||
ptr.deallocate()
|
||||
}
|
||||
|
||||
testGenericSinglePayloadEnumManyXI()
|
||||
|
||||
#if os(macOS)
|
||||
|
||||
import Foundation
|
||||
|
||||
@@ -542,6 +542,62 @@ func testSinglePayloadEnumExtraTagBytesWrapper() {
|
||||
|
||||
testSinglePayloadEnumExtraTagBytesWrapper()
|
||||
|
||||
func testSinglePayloadEnumManyXI() {
|
||||
let ptr = UnsafeMutablePointer<SinglePayloadEnumManyXI>.allocate(capacity: 1)
|
||||
|
||||
do {
|
||||
let x = SinglePayloadEnumManyXI.nonEmpty(Builtin.zeroInitializer(), SimpleClass(x: 23))
|
||||
testInit(ptr, to: x)
|
||||
}
|
||||
|
||||
do {
|
||||
let y = SinglePayloadEnumManyXI.nonEmpty(Builtin.zeroInitializer(), SimpleClass(x: 28))
|
||||
|
||||
// CHECK: Before deinit
|
||||
print("Before deinit")
|
||||
|
||||
// CHECK-NEXT: SimpleClass deinitialized!
|
||||
testAssign(ptr, from: y)
|
||||
}
|
||||
|
||||
// CHECK-NEXT: Before deinit
|
||||
print("Before deinit")
|
||||
|
||||
// CHECK-NEXT: SimpleClass deinitialized!
|
||||
testDestroy(ptr)
|
||||
|
||||
ptr.deallocate()
|
||||
}
|
||||
|
||||
testSinglePayloadEnumManyXI()
|
||||
|
||||
func testSinglePayloadEnumManyXIEmpty() {
|
||||
let ptr = UnsafeMutablePointer<SinglePayloadEnumManyXI>.allocate(capacity: 1)
|
||||
|
||||
do {
|
||||
let x = SinglePayloadEnumManyXI.empty0
|
||||
testInit(ptr, to: x)
|
||||
}
|
||||
|
||||
do {
|
||||
let y = SinglePayloadEnumManyXI.empty1
|
||||
|
||||
// CHECK: Before deinit
|
||||
print("Before deinit")
|
||||
|
||||
testAssign(ptr, from: y)
|
||||
}
|
||||
|
||||
// CHECK-NEXT: Before deinit
|
||||
print("Before deinit")
|
||||
|
||||
testDestroy(ptr)
|
||||
|
||||
ptr.deallocate()
|
||||
}
|
||||
|
||||
testSinglePayloadEnumManyXIEmpty()
|
||||
|
||||
#if os(macOS)
|
||||
func testObjc() {
|
||||
let ptr = UnsafeMutablePointer<ObjcWrapper>.allocate(capacity: 1)
|
||||
|
||||
Reference in New Issue
Block a user