mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This attribute was introduced in 7eca38ce76d5d1915f4ab7e665964062c0b37697 (llvm-project). Match it using a wildcard regex, since it is not relevant to these tests. This is intended to reduce future conflicts with rebranch.
295 lines
15 KiB
Plaintext
295 lines
15 KiB
Plaintext
// RUN: %empty-directory(%t)
|
|
// RUN: %target-swift-frontend -target %target-pre-stable-abi-triple -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
|
|
|
|
// RUN: %target-swift-frontend -target %target-pre-stable-abi-triple -I %t -emit-ir -enable-library-evolution %s -read-legacy-type-info-path=%S/Inputs/legacy_type_info/a.yaml | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize -DINT=i%target-ptrsize
|
|
// RUN: %target-swift-frontend -target %target-pre-stable-abi-triple -I %t -emit-ir -enable-library-evolution %s -read-legacy-type-info-path=%S/Inputs/legacy_type_info/a.yaml
|
|
// RUN: %target-swift-frontend -target %target-pre-stable-abi-triple -I %t -emit-ir -enable-library-evolution -O %s -read-legacy-type-info-path=%S/Inputs/legacy_type_info/a.yaml
|
|
|
|
// Verify that this feature works with the VFS.
|
|
// RUN: sed -e "s|INPUT_DIR|%/S/Inputs|g" -e "s|OUT_DIR|%/t|g" %S/Inputs/legacy_type_info/vfsoverlay.yaml > %t/overlay.yaml
|
|
// RUN: %target-swift-frontend -target %target-pre-stable-abi-triple -vfsoverlay %/t/overlay.yaml -I %t -emit-ir -enable-library-evolution -O %s -read-legacy-type-info-path=%t/a_moved.yaml
|
|
|
|
// We only use fragile class layouts when Objective-C interop is enabled.
|
|
|
|
// REQUIRES: objc_interop
|
|
// REQUIRES: CPU=x86_64
|
|
// UNSUPPORTED: swift_only_stable_abi
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
import SwiftShims
|
|
|
|
import resilient_struct
|
|
|
|
public class ClassWithResilientField {
|
|
var first: Int
|
|
var second: Size
|
|
var third: Int
|
|
|
|
init(x: Int, y: Size, z: Int)
|
|
}
|
|
|
|
sil_vtable ClassWithResilientField {}
|
|
|
|
public class SubclassOfClassWithResilientField : ClassWithResilientField {}
|
|
|
|
sil_vtable SubclassOfClassWithResilientField {}
|
|
|
|
|
|
// Field offsets are statically known:
|
|
// CHECK-DAG: @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldC5firstSivpWvd" = hidden constant i64 16, align 8
|
|
// CHECK-DAG: @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldC6second16resilient_struct4SizeVvpWvd" = hidden global i64 24, align 8
|
|
// CHECK-DAG: @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldC5thirdSivpWvd" = hidden global i64 40, align 8
|
|
|
|
|
|
// RO-data for ClassWithResilientField:
|
|
// CHECK-LABEL: @_DATA__TtC39class_update_callback_with_fixed_layout23ClassWithResilientField = internal constant {
|
|
|
|
// -- flags: compiled with ARC, has update callback
|
|
// CHECK-SAME: i32 192,
|
|
|
|
// -- the update callback
|
|
// CHECK-SAME: @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldCMU"
|
|
|
|
// CHECK-SAME: }, section "__DATA, {{.*}}", align 8
|
|
|
|
// Class has static metadata:
|
|
// CHECK-LABEL: @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldCMf"
|
|
|
|
|
|
// Subclass also has static metadata:
|
|
// CHECK-LABEL: @"$s39class_update_callback_with_fixed_layout33SubclassOfClassWithResilientFieldCMf" = internal global <{{.*}}> <{
|
|
|
|
// Superclass field is filled in statically:
|
|
// CHECK-SAME: @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldCMf"
|
|
|
|
// CHECK-SAME: }>
|
|
|
|
|
|
// rdar://problem/41308521 -- enum lowering needs to pretend payloads are
|
|
// resilient and not use spare bits, even when bypassing resilience while
|
|
// lowering class fields.
|
|
|
|
// Because ResilientRef is resilient, the enum stores the tag out-of-line,
|
|
// rather than packing it into the spare bits of the payload. Make sure that
|
|
// this layout is maintained even when the enum is a class field, which
|
|
// forces it to be lowered without resilience.
|
|
enum EnumWithResilientPayload {
|
|
case none
|
|
case some(ClassWithResilientEnum)
|
|
case data(ResilientRef)
|
|
}
|
|
|
|
// Note that 'second' is at offset 25, which means 'first' is 9 bytes in size;
|
|
// an 8 byte payload and an out-of-line tag, as expected.
|
|
public class ClassWithResilientEnum {
|
|
var first: EnumWithResilientPayload
|
|
var second: Int8
|
|
|
|
init(x: EnumWithResilientPayload, y: Int8)
|
|
}
|
|
|
|
sil_vtable ClassWithResilientEnum {}
|
|
|
|
// Field offsets are statically known:
|
|
// CHECK-LABEL: @"$s39class_update_callback_with_fixed_layout22ClassWithResilientEnumC5firstAA0jhI7PayloadOvpWvd" = hidden global i64 16, align 8
|
|
// CHECK-LABEL: @"$s39class_update_callback_with_fixed_layout22ClassWithResilientEnumC6seconds4Int8VvpWvd" = hidden global i64 25, align 8
|
|
|
|
|
|
// Make sure extra inhabitants work when reading a legacy layout -- the
|
|
// Optional<ResilientRef> should be 8 bytes in size, not 9
|
|
public class ClassWithResilientRef {
|
|
var first: ResilientRef?
|
|
var second: Int
|
|
}
|
|
|
|
sil_vtable ClassWithResilientRef {}
|
|
|
|
// Field offsets are statically known:
|
|
// CHECK-LABEL: @"$s39class_update_callback_with_fixed_layout21ClassWithResilientRefC5first16resilient_struct0iJ0VSgvpWvd" = hidden global i64 16, align 8
|
|
// CHECK-LABEL: @"$s39class_update_callback_with_fixed_layout21ClassWithResilientRefC6secondSivpWvd" = hidden global i64 24, align 8
|
|
|
|
|
|
// When allocating a class with resiliently-sized fields, we must still load
|
|
// the size and alignment from metadata, because its metadata may have been
|
|
// re-initialized.
|
|
|
|
// CHECK-LABEL: define {{(dllexport )?}}{{(protected )?}}swiftcc void @allocClassWithResilientField()
|
|
sil @allocClassWithResilientField : $@convention(thin) () -> () {
|
|
bb0:
|
|
|
|
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldCMa"(i64 0)
|
|
// CHECK-NEXT: [[META:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK-NEXT: [[SIZE_ADDR:%.*]] = getelementptr inbounds i8, ptr [[META]], i32 48
|
|
// CHECK-NEXT: [[SIZE_2:%.*]] = load i32, ptr [[SIZE_ADDR]], align 8
|
|
// CHECK-NEXT: [[SIZE:%.*]] = zext i32 [[SIZE_2]] to i64
|
|
// CHECK-NEXT: [[ALIGN_ADDR:%.*]] = getelementptr inbounds i8, ptr [[META]], i32 52
|
|
// CHECK-NEXT: [[ALIGN_2:%.*]] = load i16, ptr [[ALIGN_ADDR]], align 4
|
|
// CHECK-NEXT: [[ALIGN:%.*]] = zext i16 [[ALIGN_2]] to i64
|
|
// CHECK-NEXT: [[ALLOC:%.*]] = call noalias ptr @swift_allocObject(ptr [[META]], i64 [[SIZE]], i64 [[ALIGN]])
|
|
%c = alloc_ref $ClassWithResilientField
|
|
|
|
// ... dealloc_ref also does the same thing.
|
|
|
|
// CHECK-NEXT: [[META:%.*]] = load ptr, ptr {{.*}}, align 8
|
|
// CHECK-NEXT: [[SIZE_ADDR:%.*]] = getelementptr inbounds i8, ptr [[META]], i32 48
|
|
// CHECK-NEXT: [[SIZE_2:%.*]] = load i32, ptr [[SIZE_ADDR]], align 8
|
|
// CHECK-NEXT: [[SIZE:%.*]] = zext i32 [[SIZE_2]] to i64
|
|
// CHECK-NEXT: [[ALIGN_ADDR:%.*]] = getelementptr inbounds i8, ptr [[META]], i32 52
|
|
// CHECK-NEXT: [[ALIGN_2:%.*]] = load i16, ptr [[ALIGN_ADDR]], align 4
|
|
// CHECK-NEXT: [[ALIGN:%.*]] = zext i16 [[ALIGN_2]] to i64
|
|
// CHECK-NEXT: call void @swift_deallocClassInstance(ptr [[ALLOC]], i64 [[SIZE]], i64 [[ALIGN]])
|
|
dealloc_ref %c : $ClassWithResilientField
|
|
|
|
%result = tuple ()
|
|
return %result : $()
|
|
}
|
|
|
|
|
|
// Metadata accessor for ClassWithResilientField uses singleton initialization:
|
|
|
|
// CHECK-LABEL: define swiftcc %swift.metadata_response @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldCMa
|
|
|
|
// CHECK: [[CACHE:%.*]] = load ptr, ptr @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldCMl"
|
|
// CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[CACHE]], null
|
|
// CHECK-NEXT: br i1 [[COND]], label %cacheIsNull, label %cont
|
|
|
|
// CHECK: cacheIsNull:
|
|
// CHECK-NEXT: [[RESPONSE:%.*]] = call swiftcc %swift.metadata_response @swift_getSingletonMetadata([[INT]] %0, ptr @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldCMn")
|
|
// CHECK-NEXT: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[RESPONSE]], 0
|
|
// CHECK-NEXT: [[STATUS:%.*]] = extractvalue %swift.metadata_response [[RESPONSE]], 1
|
|
// CHECK-NEXT: br label %cont
|
|
|
|
// CHECK: cont:
|
|
// CHECK-NEXT: [[NEW_METADATA:%.*]] = phi ptr [ [[CACHE]], %entry ], [ [[METADATA]], %cacheIsNull ]
|
|
// CHECK-NEXT: [[NEW_STATUS:%.*]] = phi [[INT]] [ 0, %entry ], [ [[STATUS]], %cacheIsNull ]
|
|
// CHECK-NEXT: [[T0:%.*]] = insertvalue %swift.metadata_response undef, ptr [[NEW_METADATA]], 0
|
|
// CHECK-NEXT: [[T1:%.*]] = insertvalue %swift.metadata_response [[T0]], [[INT]] [[NEW_STATUS]], 1
|
|
// CHECK-NEXT: ret %swift.metadata_response [[T1]]
|
|
|
|
|
|
// Accessing a field whose offset depends on resilient types should
|
|
// use the field offset global.
|
|
|
|
// CHECK-LABEL: define swiftcc {{(dllexport )?}}{{(protected )?}}i64 @accessClassWithResilientField(ptr %0)
|
|
sil @accessClassWithResilientField : $@convention(thin) (@guaranteed ClassWithResilientField) -> Int {
|
|
bb0(%0 : $ClassWithResilientField):
|
|
|
|
// CHECK: [[OFFSET:%.*]] = load i64, ptr @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldC5thirdSivpWvd", align 8
|
|
// CHECK-NEXT: [[FIELD_ADDR:%.*]] = getelementptr inbounds i8, ptr %0, i64 [[OFFSET]]
|
|
// CHECK-NEXT: [[FIELD_PTR:%.*]] = getelementptr inbounds{{.*}} %TSi, ptr [[FIELD_ADDR]], i32 0, i32 0
|
|
|
|
%1 = ref_element_addr %0 : $ClassWithResilientField, #ClassWithResilientField.third
|
|
|
|
// CHECK-NEXT: [[VALUE:%.*]] = load i64, ptr [[FIELD_PTR]], align 8
|
|
%2 = load %1 : $*Int
|
|
|
|
// CHECK-NEXT: ret i64 [[VALUE]]
|
|
return %2 : $Int
|
|
}
|
|
|
|
|
|
// Objective-C metadata update callback function for ClassWithResilientField:
|
|
|
|
// CHECK-LABEL: define internal ptr @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldCMU"(ptr %0, ptr %1)
|
|
// CHECK: entry:
|
|
// CHECK-NEXT: [[RESPONSE:%.*]] = call swiftcc %swift.metadata_response @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldCMa"(i64 0)
|
|
// CHECK-NEXT: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[RESPONSE]], 0
|
|
// CHECK-NEXT: ret ptr [[METADATA]]
|
|
|
|
|
|
// Metadata initialization function for ClassWithResilientField calls swift_updateClassMetadata2():
|
|
|
|
// CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldCMr"(ptr %0, ptr %1, ptr %2)
|
|
|
|
// CHECK: entry:
|
|
// CHECK-NEXT: [[FIELDS:%.*]] = alloca [3 x ptr]
|
|
// CHECK-NEXT: [[FIELDS_DEST:%.*]] = getelementptr inbounds [[INT]], ptr %0, [[INT]] {{10|13}}
|
|
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 {{12|24}}, ptr [[FIELDS]])
|
|
// CHECK-NEXT: [[FIELDS_PTR:%.*]] = getelementptr inbounds{{.*}} [3 x ptr], ptr [[FIELDS]], i32 0, i32 0
|
|
|
|
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s16resilient_struct4SizeVMa"([[INT]] 319)
|
|
// CHECK-NEXT: [[SIZE_METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK-NEXT: [[STATUS:%.*]] = extractvalue %swift.metadata_response [[T0]], 1
|
|
// CHECK-NEXT: [[RESULT:%.*]] = icmp ule [[INT]] [[STATUS]], 63
|
|
// CHECK-NEXT: br i1 [[RESULT]], label %dependency-satisfied, label %metadata-dependencies.cont
|
|
|
|
// CHECK: dependency-satisfied:
|
|
|
|
// -- ClassLayoutFlags = 0x100 (HasStaticVTable)
|
|
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @swift_updateClassMetadata2(ptr %0, [[INT]] 256, [[INT]] 3, ptr [[FIELDS_PTR]], ptr [[FIELDS_DEST]])
|
|
// CHECK-NEXT: [[INITDEP_METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK-NEXT: [[INITDEP_STATUS:%.*]] = extractvalue %swift.metadata_response [[T0]], 1
|
|
// CHECK-NEXT: [[INITDEP_PRESENT:%.*]] = icmp eq ptr [[INITDEP_METADATA]], null
|
|
// CHECK-NEXT: br i1 [[INITDEP_PRESENT]], label %dependency-satisfied1, label %metadata-dependencies.cont
|
|
|
|
// CHECK: dependency-satisfied1:
|
|
|
|
// CHECK-native: [[FIELD_OFFSET:%.*]] = load [[INT]], ptr {{.*}}
|
|
// CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], ptr @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldC1s16resilient_struct4SizeVvpWvd"
|
|
|
|
// CHECK-native: [[FIELD_OFFSET:%.*]] = load [[INT]], ptr {{.*}}
|
|
// CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], ptr @"$s39class_update_callback_with_fixed_layout23ClassWithResilientFieldC5colors5Int32VvpWvd"
|
|
|
|
// CHECK: br label %metadata-dependencies.cont
|
|
|
|
// CHECK: metadata-dependencies.cont:
|
|
|
|
// CHECK-NEXT: [[PENDING_METADATA:%.*]] = phi ptr [ [[SIZE_METADATA]], %entry ], [ [[INITDEP_METADATA]], %dependency-satisfied ], [ null, %dependency-satisfied1 ]
|
|
// CHECK-NEXT: [[NEW_STATUS:%.*]] = phi [[INT]] [ 63, %entry ], [ [[INITDEP_STATUS]], %dependency-satisfied ], [ 0, %dependency-satisfied1 ]
|
|
// CHECK-NEXT: [[T0:%.*]] = insertvalue %swift.metadata_response undef, ptr [[PENDING_METADATA]], 0
|
|
// CHECK-NEXT: [[T1:%.*]] = insertvalue %swift.metadata_response [[T0]], [[INT]] [[NEW_STATUS]], 1
|
|
// CHECK-NEXT: ret %swift.metadata_response [[T1]]
|
|
|
|
|
|
// Metadata initialization function for SubclassOfClassWithResilientField:
|
|
|
|
// CHECK-LABEL: define internal swiftcc %swift.metadata_response @"$s39class_update_callback_with_fixed_layout33SubclassOfClassWithResilientFieldCMr"(ptr %0, ptr %1, ptr %2)
|
|
|
|
// CHECK: entry:
|
|
// CHECK-NEXT: [[FIELDS:%.*]] = alloca [0 x ptr]
|
|
// CHECK-NEXT: [[FIELDS_DEST:%.*]] = getelementptr inbounds [[INT]], ptr %0, [[INT]] {{11|14}}
|
|
// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 0, ptr [[FIELDS]])
|
|
// CHECK-NEXT: [[FIELDS_PTR:%.*]] = getelementptr inbounds{{.*}} [0 x ptr], ptr [[FIELDS]], i32 0, i32 0
|
|
|
|
// -- ClassLayoutFlags = 0x100 (HasStaticVTable)
|
|
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @swift_updateClassMetadata2(ptr %0, [[INT]] 256, [[INT]] 0, ptr [[FIELDS_PTR]], ptr [[FIELDS_DEST]])
|
|
// CHECK-NEXT: [[INITDEP_METADATA:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK-NEXT: [[INITDEP_STATUS:%.*]] = extractvalue %swift.metadata_response [[T0]], 1
|
|
// CHECK-NEXT: [[INITDEP_PRESENT:%.*]] = icmp eq ptr [[INITDEP_METADATA]], null
|
|
// CHECK-NEXT: br i1 [[INITDEP_PRESENT]], label %dependency-satisfied, label %metadata-dependencies.cont
|
|
|
|
// CHECK: dependency-satisfied:
|
|
// CHECK: br label %metadata-dependencies.cont
|
|
|
|
// CHECK: metadata-dependencies.cont:
|
|
// CHECK-NEXT: [[PENDING_METADATA:%.*]] = phi ptr [ [[INITDEP_METADATA]], %entry ], [ null, %dependency-satisfied ]
|
|
// CHECK-NEXT: [[NEW_STATUS:%.*]] = phi [[INT]] [ [[INITDEP_STATUS]], %entry ], [ 0, %dependency-satisfied ]
|
|
// CHECK-NEXT: [[T0:%.*]] = insertvalue %swift.metadata_response undef, ptr [[PENDING_METADATA]], 0
|
|
// CHECK-NEXT: [[T1:%.*]] = insertvalue %swift.metadata_response [[T0]], [[INT]] [[NEW_STATUS]], 1
|
|
// CHECK-NEXT: ret %swift.metadata_response [[T1]]
|
|
|
|
// Metadata accessor for ClassWithResilientEnum looks like singleton initialization:
|
|
|
|
// CHECK-LABEL: define swiftcc %swift.metadata_response @"$s39class_update_callback_with_fixed_layout22ClassWithResilientEnumCMa
|
|
|
|
// CHECK: [[CACHE:%.*]] = load ptr, ptr @"$s39class_update_callback_with_fixed_layout22ClassWithResilientEnumCMl"
|
|
// CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[CACHE]], null
|
|
// CHECK-NEXT: br i1 [[COND]], label %cacheIsNull, label %cont
|
|
|
|
// CHECK: cacheIsNull:
|
|
// CHECK-NEXT: [[RESPONSE:%.*]] = call swiftcc %swift.metadata_response @swift_getSingletonMetadata([[INT]] %0, ptr @"$s39class_update_callback_with_fixed_layout22ClassWithResilientEnumCMn")
|
|
// CHECK-NEXT: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[RESPONSE]], 0
|
|
// CHECK-NEXT: [[STATUS:%.*]] = extractvalue %swift.metadata_response [[RESPONSE]], 1
|
|
// CHECK-NEXT: br label %cont
|
|
|
|
// CHECK: cont:
|
|
// CHECK-NEXT: [[NEW_METADATA:%.*]] = phi ptr [ [[CACHE]], %entry ], [ [[METADATA]], %cacheIsNull ]
|
|
// CHECK-NEXT: [[NEW_STATUS:%.*]] = phi [[INT]] [ 0, %entry ], [ [[STATUS]], %cacheIsNull ]
|
|
// CHECK-NEXT: [[T0:%.*]] = insertvalue %swift.metadata_response undef, ptr [[NEW_METADATA]], 0
|
|
// CHECK-NEXT: [[T1:%.*]] = insertvalue %swift.metadata_response [[T0]], [[INT]] [[NEW_STATUS]], 1
|
|
// CHECK-NEXT: ret %swift.metadata_response [[T1]]
|
|
|