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.
620 lines
26 KiB
Plaintext
620 lines
26 KiB
Plaintext
// RUN: %target-swift-frontend -disable-type-layout -prespecialize-generic-metadata %s -target %module-target-future -gnone -emit-ir -enable-objc-interop | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-objc --check-prefix=CHECK-objc-simulator-%target-is-simulator --check-prefix=CHECK-objc-%target-ptrsize --check-prefix=CHECK-%target-os --check-prefix=CHECK-objc-%target-os
|
|
// RUN: %target-swift-frontend -disable-type-layout -prespecialize-generic-metadata %s -target %module-target-future -gnone -emit-ir -disable-objc-interop | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-native --check-prefix=CHECK-native-%target-ptrsize --check-prefix=CHECK-%target-os --check-prefix=CHECK-native-%target-os
|
|
|
|
// REQUIRES: CPU=x86_64
|
|
// REQUIRES: VENDOR=apple || OS=linux-gnu
|
|
// UNSUPPORTED: CPU=i386 && OS=ios
|
|
// UNSUPPORTED: CPU=armv7 && OS=ios
|
|
// UNSUPPORTED: CPU=armv7s && OS=ios
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
enum NoPayload {
|
|
case a
|
|
case b
|
|
case c
|
|
}
|
|
|
|
enum SingletonPayload {
|
|
case S(Builtin.Int64, Builtin.Int64)
|
|
}
|
|
|
|
enum SinglePayloadTrivial {
|
|
case payload(Builtin.Int64)
|
|
case a
|
|
case b
|
|
case c
|
|
}
|
|
|
|
enum SinglePayloadNontrivial {
|
|
case payload(Builtin.NativeObject)
|
|
case a
|
|
case b
|
|
case c
|
|
}
|
|
|
|
sil @single_payload_nontrivial_user : $@convention(thin) (@owned SinglePayloadNontrivial) -> ()
|
|
|
|
enum MultiPayloadTrivial {
|
|
case payload1(Builtin.Int64)
|
|
case payload2(Builtin.Int32, Builtin.Int32)
|
|
case a
|
|
case b
|
|
case c
|
|
}
|
|
|
|
enum MultiPayloadNoEmptyCases {
|
|
case payload1(Builtin.Int64)
|
|
case payload2(Builtin.Int32, Builtin.Int32)
|
|
}
|
|
|
|
enum MultiPayloadEmptyPayload {
|
|
case payload1()
|
|
case payload2()
|
|
case a
|
|
case b
|
|
case c
|
|
}
|
|
|
|
// No spare bits
|
|
enum MultiPayloadNontrivial {
|
|
case payload1(Builtin.NativeObject)
|
|
case payload2(Builtin.Int64)
|
|
case payload3(Builtin.Int64, Builtin.NativeObject)
|
|
case payload4(Builtin.Int64, Builtin.Int64)
|
|
case a
|
|
case b
|
|
case c
|
|
}
|
|
|
|
enum MultiPayloadGeneric<T> {
|
|
case payload1(T)
|
|
case payload2(T)
|
|
case a
|
|
case b
|
|
case c
|
|
}
|
|
|
|
// Most significant bits of second 64-bit word of payload
|
|
// are spare bits
|
|
enum MultiPayloadNontrivialSpareBits {
|
|
case payload1(Builtin.NativeObject)
|
|
case payload2(Builtin.Int64)
|
|
case payload3(Builtin.Int64, Builtin.NativeObject)
|
|
case a
|
|
case b
|
|
case c
|
|
}
|
|
|
|
// We only have 1 spare bit but 3 payload cases
|
|
enum MultiPayloadSpareBitsAndExtraBits {
|
|
case payload1(Builtin.Int63)
|
|
case payload2(Builtin.NativeObject)
|
|
case payload3(Builtin.NativeObject)
|
|
}
|
|
|
|
enum GenericFixedLayout<T> {
|
|
case foo(Builtin.Int64)
|
|
case bar(Builtin.NativeObject)
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: @"$s27enum_value_semantics_future20SinglePayloadTrivialOWV" = internal constant %swift.enum_vwtable {
|
|
// CHECK: ptr @__swift_memcpy9_8,
|
|
// CHECK: ptr @__swift_noop_void_return,
|
|
// CHECK: ptr @__swift_memcpy9_8,
|
|
// CHECK: ptr @__swift_memcpy9_8,
|
|
// CHECK: ptr @__swift_memcpy9_8,
|
|
// CHECK: ptr @__swift_memcpy9_8,
|
|
// CHECK: ptr @"$s27enum_value_semantics_future20SinglePayloadTrivialOwet",
|
|
// CHECK: ptr @"$s27enum_value_semantics_future20SinglePayloadTrivialOwst",
|
|
// CHECK: i64 9,
|
|
// CHECK: i64 16,
|
|
// CHECK: i32 2097159,
|
|
// CHECK: i32 0,
|
|
// CHECK: ptr @"$s27enum_value_semantics_future20SinglePayloadTrivialOwug",
|
|
// CHECK: ptr @"$s27enum_value_semantics_future20SinglePayloadTrivialOwup",
|
|
// CHECK: ptr @"$s27enum_value_semantics_future20SinglePayloadTrivialOwui"
|
|
// CHECK: }
|
|
|
|
|
|
// CHECK-LABEL: @"$s27enum_value_semantics_future20SinglePayloadTrivialOMf" =
|
|
// CHECK-SAME: internal constant <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @"$s27enum_value_semantics_future20SinglePayloadTrivialOWV",
|
|
// CHECK-SAME: i64 513,
|
|
// CHECK-SAME: ptr @"$s27enum_value_semantics_future20SinglePayloadTrivialOMn"
|
|
// CHECK-SAME: }>
|
|
|
|
|
|
// CHECK-LABEL: @"$s27enum_value_semantics_future23SinglePayloadNontrivialOWV" = internal constant %swift.enum_vwtable {
|
|
// CHECK: ptr @"$s27enum_value_semantics_future23SinglePayloadNontrivialOwCP",
|
|
// CHECK: ptr @"$s27enum_value_semantics_future23SinglePayloadNontrivialOwxx",
|
|
// CHECK: ptr @"$s27enum_value_semantics_future23SinglePayloadNontrivialOwcp",
|
|
// CHECK: ptr @"$s27enum_value_semantics_future23SinglePayloadNontrivialOwca",
|
|
// CHECK: ptr @__swift_memcpy8_8,
|
|
// CHECK: ptr @"$s27enum_value_semantics_future23SinglePayloadNontrivialOwta",
|
|
// CHECK: i64 8,
|
|
// CHECK: i64 8,
|
|
// -- 0x210007
|
|
// CHECK: i32 2162695,
|
|
// -- On Darwin, the first 4 GiB are unmapped: 0x7ffffffc
|
|
// -- Otherwise, one can only assume the first page (4 KiB) is unmapped: 0xffd
|
|
// CHECK-ios: i32 2147483644
|
|
// CHECK-macosx: i32 2147483644
|
|
// CHECK-watchos: i32 2147483644
|
|
// CHECK-darwin: i32 2147483644
|
|
// CHECK-objc-linux-gnu: i32 2045
|
|
// CHECK-native-linux-gnu: i32 4093
|
|
// CHECK-objc-windows: i32 2045
|
|
// CHECK-native-windows: i32 4093
|
|
// CHECK: ptr @"$s27enum_value_semantics_future23SinglePayloadNontrivialOwug",
|
|
// CHECK: ptr @"$s27enum_value_semantics_future23SinglePayloadNontrivialOwup"
|
|
// CHECK: ptr @"$s27enum_value_semantics_future23SinglePayloadNontrivialOwui"
|
|
// CHECK: ]
|
|
|
|
|
|
// CHECK-LABEL: @"$s27enum_value_semantics_future23SinglePayloadNontrivialOMf" =
|
|
// CHECK-SAME: internal constant <{ {{.*}} }> <{
|
|
// CHECK-SAME: ptr @"$s27enum_value_semantics_future23SinglePayloadNontrivialOWV",
|
|
// CHECK-SAME: i64 513,
|
|
// CHECK-SAME: ptr @"$s27enum_value_semantics_future23SinglePayloadNontrivialOMn"
|
|
// CHECK-SAME: }>
|
|
|
|
// CHECK: @"$s27enum_value_semantics_future18GenericFixedLayoutOWV" = internal constant %swift.enum_vwtable
|
|
// CHECK: [[EXTRA_DATA_PATTERN:@[0-9]+]] = internal constant <{ i64 }> zeroinitializer
|
|
|
|
// CHECK-LABEL: @"$s27enum_value_semantics_future18GenericFixedLayoutOMn" = hidden constant
|
|
// CHECK-SAME: ptr @"$s27enum_value_semantics_future18GenericFixedLayoutOMI"
|
|
// CHECK-SAME: @"$s27enum_value_semantics_future18GenericFixedLayoutOMP"
|
|
|
|
// CHECK-LABEL: @"$s27enum_value_semantics_future18GenericFixedLayoutOMP" = internal constant <{ {{.*}} }> <{
|
|
// Instantiation function.
|
|
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr @"$s27enum_value_semantics_future18GenericFixedLayoutOMi" to i64), i64 ptrtoint (ptr @"$s27enum_value_semantics_future18GenericFixedLayoutOMP" to i64)) to i32),
|
|
// Completion function.
|
|
// CHECK-SAME: i32 0,
|
|
// Pattern flags. 0x4020_0003 == (MetadataKind::Enum << 21 | HasTrailingFlags | HasExtraDataPattern).
|
|
// CHECK-SAME: i32 1075838979,
|
|
// Value witness table.
|
|
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr @"$s27enum_value_semantics_future18GenericFixedLayoutOWV" to i64), i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32, i32, i32, i32, i16, i16 }>, ptr @"$s27enum_value_semantics_future18GenericFixedLayoutOMP", i32 0, i32 3) to i64)) to i32)
|
|
// Extra data pattern.
|
|
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (ptr [[EXTRA_DATA_PATTERN]] to i64), i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32, i32, i32, i32, i16, i16 }>, ptr @"$s27enum_value_semantics_future18GenericFixedLayoutOMP", i32 0, i32 4) to i64)) to i32)
|
|
// CHECK-SAME: }>
|
|
|
|
sil @single_payload_nontrivial_copy_destroy : $(@owned SinglePayloadNontrivial) -> () {
|
|
bb0(%0 : $SinglePayloadNontrivial):
|
|
retain_value %0 : $SinglePayloadNontrivial
|
|
%1 = function_ref @single_payload_nontrivial_user : $@convention(thin) (@owned SinglePayloadNontrivial) -> ()
|
|
apply %1(%0) : $@convention(thin) (@owned SinglePayloadNontrivial) -> ()
|
|
release_value %0 : $SinglePayloadNontrivial
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_nontrivial_copy_destroy(i64 %0)
|
|
// CHECK: call void @"$s27enum_value_semantics_future23SinglePayloadNontrivialOWOy"
|
|
// CHECK-NEXT: call swiftcc void @single_payload_nontrivial_user
|
|
// CHECK-NEXT: call void @"$s27enum_value_semantics_future23SinglePayloadNontrivialOWOe"
|
|
// CHECK-NEXT: ret void
|
|
|
|
//
|
|
// No payload enums
|
|
//
|
|
|
|
|
|
// -- NoPayload getEnumTag
|
|
// CHECK-LABEL: define internal i32 @"$s27enum_value_semantics_future9NoPayloadOwug"
|
|
// CHECK: [[TAG_ADDR:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future9NoPayloadO, ptr %value, i32 0, i32 0
|
|
// CHECK-NEXT: [[TAG:%.*]] = load i8, ptr [[TAG_ADDR]], align 1
|
|
// CHECK-NEXT: [[RESULT:%.*]] = zext i8 {{.*}} to i32
|
|
// CHECK-NEXT: ret i32 [[RESULT]]
|
|
|
|
|
|
// -- NoPayload destructiveProjectEnumData
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future9NoPayloadOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// -- NoPayload destructiveInjectEnumTag
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future9NoPayloadOwui"
|
|
// CHECK: [[TAG:%.*]] = trunc i32 %tag to i8
|
|
// CHECK-NEXT: [[TAG_ADDR:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future9NoPayloadO, ptr %value, i32 0, i32 0
|
|
// CHECK-NEXT: store i8 [[TAG]], ptr [[TAG_ADDR]], align 1
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Singleton payload enums
|
|
//
|
|
|
|
|
|
// -- SingletonPayload getEnumTag
|
|
// CHECK-LABEL: define internal i32 @"$s27enum_value_semantics_future16SingletonPayloadOwug"
|
|
// CHECK: ret i32 0
|
|
|
|
|
|
// -- SingletonPayload destructiveProjectEnumData
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future16SingletonPayloadOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// -- SingletonPayload destructiveInjectEnumTag
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future16SingletonPayloadOwui"
|
|
// CHECK: ret void
|
|
|
|
|
|
// -- SinglePayloadTrivial getEnumTag
|
|
// CHECK-LABEL: define internal i32 @"$s27enum_value_semantics_future20SinglePayloadTrivialOwug"
|
|
// CHECK: [[TAG:%.*]] = call i32 %{{.*}}(ptr noalias %value, i32 3, ptr getelementptr inbounds (%swift.full_existential_type, ptr @"$sBi64_N", i32 0, i32 1))
|
|
// CHECK: ret i32 [[TAG]]
|
|
|
|
|
|
// -- SinglePayloadTrivial destructiveProjectEnumData
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future20SinglePayloadTrivialOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
//
|
|
// Single-payload enums
|
|
//
|
|
|
|
|
|
// -- SinglePayloadTrivial destructiveInjectEnumTag
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future20SinglePayloadTrivialOwui"
|
|
// CHECK: call void %{{.*}}(ptr noalias %value, i32 %tag, i32 3, ptr getelementptr inbounds (%swift.full_existential_type, ptr @"$sBi64_N", i32 0, i32 1))
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
// -- SinglePayloadNontrivial destroyBuffer
|
|
// CHECK: define internal void @"$s27enum_value_semantics_future23SinglePayloadNontrivialOwxx"(ptr noalias [[OBJ:%.*]], ptr %SinglePayloadNontrivial) {{.*}} {
|
|
// CHECK: [[PAYLOAD:%.*]] = load i64, ptr [[OBJ]], align 8
|
|
// CHECK-NEXT: switch i64 {{.*}}, label %[[RELEASE_PAYLOAD:[0-9]+]] [
|
|
// CHECK: i64 0, label %[[DONE:[0-9]+]]
|
|
// CHECK-native: i64 1, label %[[DONE]]
|
|
// CHECK-native: i64 2, label %[[DONE]]
|
|
// CHECK-objc-simulator-false: i64 2, label %[[DONE]]
|
|
// CHECK-objc-simulator-false: i64 4, label %[[DONE]]
|
|
// CHECK-objc-simulator-true: i64 1, label %[[DONE]]
|
|
// CHECK-objc-simulator-true: i64 2, label %[[DONE]]
|
|
// CHECK: ]
|
|
|
|
// CHECK: [[RELEASE_PAYLOAD]]:
|
|
// CHECK-NEXT: [[DATA:%.*]] = load ptr, ptr [[OBJ]], align 8
|
|
// CHECK-NEXT: call void @swift_release(ptr [[DATA]])
|
|
// CHECK-NEXT: br label %[[DONE]]
|
|
|
|
// CHECK: [[DONE]]:
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enums
|
|
//
|
|
|
|
|
|
// -- MultiPayloadTrivial getEnumTag
|
|
// CHECK-LABEL: define internal i32 @"$s27enum_value_semantics_future19MultiPayloadTrivialOwug"
|
|
|
|
|
|
// -- Load the low bits of the tag from the payload area
|
|
// CHECK: [[NO_PAYLOAD_TAG_TMP:%.*]] = load i64, ptr %value, align 8
|
|
|
|
// -- Load the high bits of the tag from the extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future19MultiPayloadTrivialO, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i8, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
|
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i8 [[EXTRA_TAG_TMP]] to i32
|
|
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = trunc i64 [[NO_PAYLOAD_TAG_TMP]] to i32
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG2:%.*]] = add i32 [[NO_PAYLOAD_TAG]], 2
|
|
|
|
// -- Check if we have a payload or not
|
|
// CHECK-NEXT: [[IS_PAYLOAD:%.*]] = icmp uge i32 [[EXTRA_TAG]], 2
|
|
// CHECK-NEXT: [[TAG:%.*]] = select i1 [[IS_PAYLOAD]], i32 [[NO_PAYLOAD_TAG2]], i32 [[EXTRA_TAG]]
|
|
|
|
// -- Return the tag
|
|
// CHECK-NEXT: ret i32 [[TAG]]
|
|
|
|
// -- MultiPayloadTrivial destructiveProjectEnumData
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future19MultiPayloadTrivialOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// -- MultiPayloadTrivial destructiveInjectEnumTag
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future19MultiPayloadTrivialOwui"
|
|
// CHECK: [[IS_PAYLOAD:%.*]] = icmp uge i32 %tag, 2
|
|
// CHECK-NEXT: br i1 [[IS_PAYLOAD]], label %[[HAS_NO_PAYLOAD:.*]], label %[[HAS_PAYLOAD:.*]]
|
|
|
|
// CHECK: [[HAS_NO_PAYLOAD]]:
|
|
|
|
// -- Compute the no-payload tag
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = sub i32 %tag, 2
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG2:%.*]] = zext i32 [[NO_PAYLOAD_TAG]] to i64
|
|
|
|
// -- Store the low bits of the tag in the payload area
|
|
// CHECK-NEXT: store i64 [[NO_PAYLOAD_TAG2]], ptr %value, align 8
|
|
|
|
// -- Store the high bits of the tag in the extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future19MultiPayloadTrivialO, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: store i8 2, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
|
// CHECK-NEXT: br label %[[DONE:.*]]
|
|
|
|
// CHECK: [[HAS_PAYLOAD]]:
|
|
|
|
// -- Store the tag in the extra tag area
|
|
// CHECK-NEXT: [[TAG:%.*]] = trunc i32 %tag to i8
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future19MultiPayloadTrivialO, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: store i8 [[TAG]], ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
|
// CHECK-NEXT: br label %[[DONE]]
|
|
|
|
// CHECK: [[DONE]]:
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enums with no empty cases
|
|
//
|
|
|
|
|
|
// -- MultiPayloadNoEmptyCases getEnumTag
|
|
// CHECK-LABEL: define internal i32 @"$s27enum_value_semantics_future24MultiPayloadNoEmptyCasesOwug"
|
|
// CHECK: [[NO_PAYLOAD_TAG_TMP:%.*]] = load i64, ptr %value, align 8
|
|
|
|
// -- The payload has no spare bits and there are no empty cases, so the tag
|
|
// is entirely contained in the extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future24MultiPayloadNoEmptyCasesO, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i8, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
|
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i8 [[EXTRA_TAG_TMP]] to i32
|
|
// CHECK-NEXT: ret i32 [[EXTRA_TAG]]
|
|
|
|
// -- MultiPayloadNoEmptyCases destructiveProjectEnumData
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future24MultiPayloadNoEmptyCasesOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// -- MultiPayloadNoEmptyCases destructiveInjectEnumTag
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future24MultiPayloadNoEmptyCasesOwui"
|
|
// CHECK: [[TAG:%.*]] = trunc i32 %tag to i8
|
|
|
|
// -- Store the tag in the extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future24MultiPayloadNoEmptyCasesO, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: store i8 [[TAG]], ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enum with empty payloads -- payload tag is not used
|
|
//
|
|
|
|
|
|
// -- MultiPayloadEmptyPayload getEnumTag
|
|
// CHECK-LABEL: define internal i32 @"$s27enum_value_semantics_future017MultiPayloadEmptyF0Owug"
|
|
|
|
// -- Load the tag from the extra tag area
|
|
// CHECK: [[EXTRA_TAG_ADDR:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future017MultiPayloadEmptyF0O, ptr %value, i32 0, i32 0
|
|
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i8, ptr [[EXTRA_TAG_ADDR]], align 1
|
|
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i8 [[EXTRA_TAG_TMP]] to i32
|
|
// CHECK-NEXT: ret i32 [[EXTRA_TAG]]
|
|
|
|
|
|
// -- MultiPayloadEmptyPayload destructiveProjectEnumData
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future017MultiPayloadEmptyF0Owup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// -- MultiPayloadEmptyPayload destructiveInjectEnumTag
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future017MultiPayloadEmptyF0Owui"
|
|
|
|
// -- Store the tag in the extra tag area
|
|
// CHECK: [[TAG:%.*]] = trunc i32 %tag to i8
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future017MultiPayloadEmptyF0O, ptr %value, i32 0, i32 0
|
|
// CHECK-NEXT: store i8 [[TAG]], ptr [[EXTRA_TAG_ADDR]], align 1
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enum with non-POD payloads
|
|
//
|
|
|
|
|
|
// -- MultiPayloadNontrivial destroyBuffer
|
|
// CHECK: define internal void @"$s27enum_value_semantics_future22MultiPayloadNontrivialOwxx"(ptr noalias [[OBJ:%.*]], ptr %MultiPayloadNontrivial)
|
|
// CHECK: [[PAYLOAD_0_ADDR:%.*]] = getelementptr
|
|
// CHECK-NEXT: [[PAYLOAD_0:%.*]] = load i64, ptr [[PAYLOAD_0_ADDR]], align 8
|
|
// CHECK-NEXT: [[PAYLOAD_1_ADDR:%.*]] = getelementptr
|
|
// CHECK-NEXT: [[PAYLOAD_1:%.*]] = load i64, ptr [[PAYLOAD_1_ADDR]], align 8
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future22MultiPayloadNontrivialO, ptr {{.*}}, i32 0, i32 1
|
|
// CHECK-NEXT: [[TAG:%.*]] = load i8, ptr [[T0]], align 8
|
|
// CHECK-NEXT: @"$s27enum_value_semantics_future22MultiPayloadNontrivialOWOe"
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enum with generic layout -- spare bits are not used
|
|
//
|
|
|
|
|
|
// CHECK-LABEL: define internal i32 @"$s27enum_value_semantics_future19MultiPayloadGenericOwug"
|
|
// CHECK: [[TAG:%.*]] = call i32 @swift_getEnumCaseMultiPayload(ptr %value, ptr %"MultiPayloadGeneric<T>")
|
|
// CHECK-NEXT: ret i32 [[TAG]]
|
|
|
|
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future19MultiPayloadGenericOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future19MultiPayloadGenericOwui"
|
|
// CHECK: call void @swift_storeEnumTagMultiPayload(ptr %value, ptr %"MultiPayloadGeneric<T>", i32 %tag)
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enum with spare bits
|
|
//
|
|
|
|
|
|
// -- MultiPayloadNontrivialSpareBits destroyBuffer
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future31MultiPayloadNontrivialSpareBitsOwxx"
|
|
// CHECK-SAME: (ptr noalias [[OBJ:%.*]], ptr %MultiPayloadNontrivialSpareBits) {{.*}} {
|
|
// CHECK: [[PAYLOAD_0_ADDR:%.*]] = getelementptr
|
|
// CHECK-NEXT: [[PAYLOAD_0:%.*]] = load i64, ptr [[PAYLOAD_0_ADDR]], align 8
|
|
// CHECK-NEXT: [[PAYLOAD_1_ADDR:%.*]] = getelementptr
|
|
// CHECK-NEXT: [[PAYLOAD_1:%.*]] = load i64, ptr [[PAYLOAD_1_ADDR]], align 8
|
|
// CHECK: call void @"$s27enum_value_semantics_future31MultiPayloadNontrivialSpareBitsOWOe"
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
// CHECK-LABEL: define internal i32 @"$s27enum_value_semantics_future31MultiPayloadNontrivialSpareBitsOwug"
|
|
|
|
// -- Load the payload
|
|
// CHECK: [[FIRST_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 0
|
|
// CHECK-NEXT: [[FIRST:%.*]] = load i64, ptr [[FIRST_ADDR]], align 8
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: [[SECOND:%.*]] = load i64, ptr [[SECOND_ADDR]], align 8
|
|
|
|
// -- Get the high bits of the tag from the spare bits
|
|
// CHECK-NEXT: [[SPARE_TAG_TMP:%.*]] = lshr i64 [[SECOND]], 62
|
|
// CHECK-NEXT: [[SPARE_TAG_TMP2:%.*]] = trunc i64 [[SPARE_TAG_TMP]] to i8
|
|
// CHECK-NEXT: [[SPARE_TAG_TMP3:%.*]] = and i8 [[SPARE_TAG_TMP2]], 3
|
|
// CHECK-NEXT: [[SPARE_TAG:%.*]] = zext i8 [[SPARE_TAG_TMP3]] to i32
|
|
|
|
// -- Get the low bits of the tag from the payload area
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = trunc i64 [[FIRST]] to i32
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG2:%.*]] = add i32 [[NO_PAYLOAD_TAG]], 3
|
|
|
|
// -- Check if we have a payload or not
|
|
// CHECK-NEXT: [[IS_PAYLOAD:%.*]] = icmp uge i32 [[SPARE_TAG]], 3
|
|
|
|
// -- Return the tag
|
|
// CHECK-NEXT: [[TAG:%.*]] = select i1 [[IS_PAYLOAD]], i32 [[NO_PAYLOAD_TAG2]], i32 [[SPARE_TAG]]
|
|
// CHECK-NEXT: ret i32 [[TAG]]
|
|
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future31MultiPayloadNontrivialSpareBitsOwup"
|
|
|
|
// -- Load the payload
|
|
// CHECK: [[FIRST_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 0
|
|
// CHECK-NEXT: [[FIRST:%.*]] = load i64, ptr [[FIRST_ADDR]], align 8
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: [[SECOND:%.*]] = load i64, ptr [[SECOND_ADDR]], align 8
|
|
|
|
// -- Strip off spare bits
|
|
// CHECK-NEXT: [[SECOND_PROJ:%.*]] = and i64 [[SECOND]], 4611686018427387903
|
|
|
|
// -- Store the payload
|
|
// CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 0
|
|
// CHECK-NEXT: store i64 [[FIRST]], ptr [[FIRST_ADDR]], align 8
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: store i64 [[SECOND_PROJ]], ptr [[SECOND_ADDR]], align 8
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future31MultiPayloadNontrivialSpareBitsOwui"
|
|
// CHECK: [[IS_PAYLOAD:%.*]] = icmp uge i32 %tag, 3
|
|
// CHECK-NEXT: br i1 [[IS_PAYLOAD]], label %[[HAS_NO_PAYLOAD:.*]], label %[[HAS_PAYLOAD:.*]]
|
|
|
|
// CHECK: [[HAS_NO_PAYLOAD]]:
|
|
|
|
// -- Turn the case index into a no-payload case index
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = sub i32 %tag, 3
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG2:%.*]] = zext i32 [[NO_PAYLOAD_TAG]] to i64
|
|
|
|
// -- Store the low bits of the tag into the payload
|
|
// CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 0
|
|
// CHECK-NEXT: store i64 [[NO_PAYLOAD_TAG2]], ptr [[FIRST_ADDR]], align 8
|
|
|
|
// -- Store the high bits of the tag into the spare bits
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 1
|
|
// -- 0xc000000000000000
|
|
// CHECK-NEXT: store i64 -4611686018427387904, ptr [[SECOND_ADDR]], align 8
|
|
// CHECK-NEXT: br label %[[END:.*]]
|
|
|
|
// CHECK: [[HAS_PAYLOAD]]:
|
|
|
|
// -- Not really necessary
|
|
// CHECK-NEXT: [[TAG_TMP:%.*]] = and i32 %tag, 3
|
|
|
|
// -- Load the payload
|
|
// CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 0
|
|
// CHECK-NEXT: [[FIRST:%.*]] = load i64, ptr [[FIRST_ADDR]], align 8
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: [[SECOND:%.*]] = load i64, ptr [[SECOND_ADDR]], align 8
|
|
|
|
// -- Mask off spare bits in the payload -- 0x00fffffffffffff8
|
|
// CHECK-NEXT: [[SECOND_PROJ:%.*]] = and i64 [[SECOND]], 72057594037927928
|
|
|
|
// -- Store the low bits of the tag in the spare bits of the payload
|
|
// CHECK-NEXT: [[TAG:%.*]] = zext i32 [[TAG_TMP]] to i64
|
|
// CHECK-NEXT: [[SPARE_TAG_TMP2:%.*]] = shl i64 [[TAG]], 62
|
|
|
|
// -- Not really necessary -- 0xc000000000000000
|
|
// CHECK-NEXT: [[SPARE_TAG_TMP:%.*]] = and i64 [[SPARE_TAG_TMP2]], -4611686018427387904
|
|
|
|
// -- Apply the new spare bits
|
|
// CHECK-NEXT: [[SECOND_NEW:%.*]] = or i64 [[SPARE_TAG_TMP]], [[SECOND_PROJ]]
|
|
|
|
// -- Store the payload back
|
|
// CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 0
|
|
// CHECK-NEXT: store i64 [[FIRST]], ptr [[FIRST_ADDR]], align 8
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds{{.*}} { i64, i64 }, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: store i64 [[SECOND_NEW]], ptr [[SECOND_ADDR]], align 8
|
|
// CHECK-NEXT: br label %[[END]]
|
|
|
|
// CHECK: [[END]]:
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
// CHECK-LABEL: define internal i32 @"$s27enum_value_semantics_future029MultiPayloadSpareBitsAndExtraH0Owug"
|
|
|
|
// -- Load the payload
|
|
// CHECK: [[PAYLOAD:%.*]] = load i64, ptr %value, align 8
|
|
|
|
// -- Load the load bits of the tag from the extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future029MultiPayloadSpareBitsAndExtraH0O, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = load i8, ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
|
|
|
// -- Load the high bits of the tag from the spare bits area
|
|
// CHECK-NEXT: [[SPARE_BITS_TMP2:%.*]] = lshr i64 [[PAYLOAD]], 63
|
|
// CHECK-NEXT: [[SPARE_BITS_TMP:%.*]] = trunc i64 [[SPARE_BITS_TMP2]] to i8
|
|
// CHECK-NEXT: [[SPARE_BITS:%.*]] = and i8 [[SPARE_BITS_TMP]], 1
|
|
|
|
// -- Combine high bits and low bits to form tag
|
|
// CHECK-NEXT: [[TAG_TMP:%.*]] = shl i8 [[EXTRA_TAG]], 1
|
|
// CHECK-NEXT: [[TAG:%.*]] = or i8 [[SPARE_BITS]], [[TAG_TMP]]
|
|
// CHECK-NEXT: [[RESULT:%.*]] = zext i8 [[TAG]] to i32
|
|
// CHECK-NEXT: ret i32 [[RESULT]]
|
|
|
|
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future029MultiPayloadSpareBitsAndExtraH0Owup"
|
|
// CHECK: [[PAYLOAD:%.*]] = load i64, ptr %value, align 8
|
|
// -- 0x7fffffffffffffff
|
|
// CHECK-NEXT: [[PAYLOAD_PROJ:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
|
|
// CHECK-NEXT: store i64 [[PAYLOAD_PROJ]], ptr %value, align 8
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
// CHECK-LABEL: define internal void @"$s27enum_value_semantics_future029MultiPayloadSpareBitsAndExtraH0Owui"
|
|
// CHECK: [[SPARE_TAG_TMP3:%.*]] = and i32 %tag, 1
|
|
|
|
// -- Load the payload
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = load i64, ptr {{.*}}, align 8
|
|
|
|
// -- Mask off the spare bits
|
|
// -- 0x7fffffffffffffff
|
|
// CHECK-NEXT: [[PAYLOAD_PROJ:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
|
|
|
|
// -- Store low bits of tag in spare bits area
|
|
// CHECK-NEXT: [[SPARE_TAG_TMP2:%.*]] = zext i32 [[SPARE_TAG_TMP3]] to i64
|
|
// CHECK-NEXT: [[SPARE_TAG_TMP:%.*]] = shl i64 [[SPARE_TAG_TMP2]], 63
|
|
// -- 0x8000000000000000
|
|
// CHECK-NEXT: [[SPARE_TAG:%.*]] = and i64 [[SPARE_TAG_TMP:%.*]], -9223372036854775808
|
|
// CHECK-NEXT: [[PAYLOAD_NEW:%.*]] = or i64 [[SPARE_TAG]], [[PAYLOAD_PROJ]]
|
|
|
|
// -- Store the payload
|
|
// CHECK-NEXT: store i64 [[PAYLOAD_NEW]], ptr {{.*}}, align 8
|
|
|
|
// -- Store high bits of tag in extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = lshr i32 %tag, 1
|
|
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = trunc i32 [[EXTRA_TAG_TMP]] to i8
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds{{.*}} %T27enum_value_semantics_future029MultiPayloadSpareBitsAndExtraH0O, ptr %value, i32 0, i32 1
|
|
// CHECK-NEXT: store i8 [[EXTRA_TAG]], ptr [[EXTRA_TAG_ADDR_TMP]], align 8
|
|
// CHECK-NEXT: ret void
|