mirror of
https://github.com/apple/swift.git
synced 2026-06-27 12:25:55 +02:00
9c8bdf24a7
This regression wasn't caught by normal testing because the emission pattern substantially changed anyway, breaking tests that were looking for the field-offset vector, and because normal execution testing doesn't actually use the field-offset vector and enum payload size fields. Reflection, which does use these fields, was skating by for common types because metadata is typically allocated out of freshly zeroed pages and most such types have only one field. Also, don't emit a completion function for value metadata with fixed layout. We really shouldn't have to emit field-offset vectors for fixed-layout types; the layout should just go in the type descriptor. But for now, this is what we have to do.
676 lines
33 KiB
Plaintext
676 lines
33 KiB
Plaintext
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -gnone -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
|
|
|
|
// REQUIRES: CPU=x86_64
|
|
|
|
import Builtin
|
|
|
|
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.UnknownObject)
|
|
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.UnknownObject)
|
|
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: @"$S20enum_value_semantics20SinglePayloadTrivialOWV" = internal constant [18 x i8*] [
|
|
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
|
|
// CHECK: i8* bitcast (void (i8*, %swift.type*)* @__swift_noop_void_return to i8*),
|
|
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
|
|
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
|
|
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
|
|
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
|
|
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy9_8 to i8*),
|
|
// CHECK: i8* bitcast (i32 (%swift.opaque*, i32, %swift.type*)* @"$S20enum_value_semantics20SinglePayloadTrivialOwet" to i8*),
|
|
// CHECK: i8* bitcast (void (%swift.opaque*, i32, i32, %swift.type*)* @"$S20enum_value_semantics20SinglePayloadTrivialOwst" to i8*),
|
|
// CHECK: i8* inttoptr (i64 9 to i8*),
|
|
// CHECK: i8* inttoptr (i64 2097159 to i8*),
|
|
// CHECK: i8* inttoptr (i64 16 to i8*),
|
|
// CHECK: i8* null,
|
|
// CHECK: i8* null,
|
|
// CHECK: i8* null,
|
|
// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$S20enum_value_semantics20SinglePayloadTrivialOwug" to i8*),
|
|
// CHECK: i8* bitcast (void (%swift.opaque*, %swift.type*)* @"$S20enum_value_semantics20SinglePayloadTrivialOwup" to i8*),
|
|
// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$S20enum_value_semantics20SinglePayloadTrivialOwui" to i8*)
|
|
// CHECK: ]
|
|
|
|
|
|
// CHECK-LABEL: @"$S20enum_value_semantics20SinglePayloadTrivialOMf" =
|
|
// CHECK-SAME: internal constant <{ {{.*}} }> <{
|
|
// CHECK-SAME: i8** getelementptr inbounds ([18 x i8*], [18 x i8*]* @"$S20enum_value_semantics20SinglePayloadTrivialOWV", i32 0, i32 0),
|
|
// CHECK-SAME: i64 2,
|
|
// CHECK-SAME: {{.*}}* @"$S20enum_value_semantics20SinglePayloadTrivialOMn"
|
|
// CHECK-SAME: }>
|
|
|
|
|
|
// CHECK-LABEL: @"$S20enum_value_semantics23SinglePayloadNontrivialOWV" = internal constant [18 x i8*] [
|
|
// CHECK: i8* bitcast (%swift.opaque* ([24 x i8]*, [24 x i8]*, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwCP" to i8*),
|
|
// CHECK: i8* bitcast (void (%swift.opaque*, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwxx" to i8*),
|
|
// CHECK: i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwcp" to i8*),
|
|
// CHECK: i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwca" to i8*),
|
|
// CHECK: i8* bitcast (i8* (i8*, i8*, %swift.type*)* @__swift_memcpy8_8 to i8*),
|
|
// CHECK: i8* bitcast (%swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwta" to i8*),
|
|
// CHECK: i8* inttoptr (i64 8 to i8*),
|
|
// -- 0x250007
|
|
// CHECK: i8* inttoptr (i64 2424839 to i8*),
|
|
// CHECK: i8* inttoptr (i64 8 to i8*),
|
|
// -- on Darwin, first 4GB are unmapped: 0x7ffffffc
|
|
// -- on Linux, only safe to assume first 4KB: 0x7fd
|
|
// CHECK: i8* inttoptr (i64 {{2045|2147483644}} to i8*)
|
|
// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwxs" to i8*)
|
|
// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwxg" to i8*)
|
|
// CHECK: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwug" to i8*),
|
|
// CHECK: i8* bitcast (void (%swift.opaque*, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwup" to i8*)
|
|
// CHECK: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @"$S20enum_value_semantics23SinglePayloadNontrivialOwui" to i8*)
|
|
// CHECK: ]
|
|
|
|
|
|
// CHECK-LABEL: @"$S20enum_value_semantics23SinglePayloadNontrivialOMf" =
|
|
// CHECK-SAME: internal constant <{ {{.*}} }> <{
|
|
// CHECK-SAME: i8** getelementptr inbounds ([18 x i8*], [18 x i8*]* @"$S20enum_value_semantics23SinglePayloadNontrivialOWV", i32 0, i32 0),
|
|
// CHECK-SAME: i64 2,
|
|
// CHECK-SAME: {{.*}}* @"$S20enum_value_semantics23SinglePayloadNontrivialOMn"
|
|
// CHECK-SAME: }>
|
|
|
|
|
|
// CHECK-LABEL: @"$S20enum_value_semantics18GenericFixedLayoutOMn" = hidden constant
|
|
// CHECK-SAME: [16 x i8*]* @"$S20enum_value_semantics18GenericFixedLayoutOMI"
|
|
// CHECK-SAME: @"$S20enum_value_semantics18GenericFixedLayoutOMP"
|
|
|
|
// CHECK-LABEL: @"$S20enum_value_semantics18GenericFixedLayoutOMP" = internal constant <{ {{.*}} }> <{
|
|
// Instantiation function.
|
|
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint (%swift.type* (%swift.type_descriptor*, i8**, i8**)* @"$S20enum_value_semantics18GenericFixedLayoutOMi" to i64), i64 ptrtoint (<{ i32, i32, i32, i32 }>* @"$S20enum_value_semantics18GenericFixedLayoutOMP" to i64)) to i32),
|
|
// Completion function.
|
|
// CHECK-SAME: i32 0,
|
|
// Pattern flags. 0x400000 == (MetadataKind::Enum << 21).
|
|
// CHECK-SAME: i32 4194304,
|
|
// Value witness table.
|
|
// CHECK-SAME: i32 trunc (i64 sub (i64 ptrtoint ([18 x i8*]* @"$S20enum_value_semantics18GenericFixedLayoutOWV" to i64), i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32, i32, i32 }>, <{ i32, i32, i32, i32 }>* @"$S20enum_value_semantics18GenericFixedLayoutOMP", i32 0, i32 3) 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{{( protected)?}} swiftcc void @single_payload_nontrivial_copy_destroy(i64)
|
|
// CHECK: call void @"$S20enum_value_semantics23SinglePayloadNontrivialOWy"
|
|
// CHECK-NEXT: call swiftcc void @single_payload_nontrivial_user
|
|
// CHECK-NEXT: call void @"$S20enum_value_semantics23SinglePayloadNontrivialOWe"
|
|
// CHECK-NEXT: ret void
|
|
|
|
//
|
|
// No payload enums
|
|
//
|
|
|
|
|
|
// -- NoPayload getExtraInhabitants
|
|
// CHECK-LABEL: define linkonce_odr hidden i32 @"$S20enum_value_semantics9NoPayloadOwxg"
|
|
// CHECK: [[VALUE:%.*]] = load i8, i8* {{%.*}}, align 1
|
|
// CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[VALUE]] to i32
|
|
// CHECK-NEXT: [[SUB:%.*]] = sub i32 [[ZEXT]], 3
|
|
// CHECK-NEXT: [[EXTRA:%.*]] = icmp slt i32 [[SUB]], 0
|
|
// CHECK-NEXT: [[RES:%.*]] = select i1 [[EXTRA]], i32 -1, i32 [[SUB]]
|
|
// CHECK-NEXT: ret i32 [[RES]]
|
|
|
|
|
|
// -- NoPayload getEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden i32 @"$S20enum_value_semantics9NoPayloadOwug"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics9NoPayloadO*
|
|
// CHECK-NEXT: [[TAG_ADDR:%.*]] = getelementptr inbounds %T20enum_value_semantics9NoPayloadO, %T20enum_value_semantics9NoPayloadO* [[SELF]], i32 0, i32 0
|
|
// CHECK-NEXT: [[TAG:%.*]] = load i8, i8* [[TAG_ADDR]], align 1
|
|
// CHECK-NEXT: [[RESULT:%.*]] = zext i8 %2 to i32
|
|
// CHECK-NEXT: ret i32 [[RESULT]]
|
|
|
|
|
|
// -- NoPayload destructiveProjectEnumData
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics9NoPayloadOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// -- NoPayload destructiveInjectEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics9NoPayloadOwui"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics9NoPayloadO*
|
|
// CHECK-NEXT: [[TAG:%.*]] = trunc i32 %tag to i8
|
|
// CHECK-NEXT: [[TAG_ADDR:%.*]] = getelementptr inbounds %T20enum_value_semantics9NoPayloadO, %T20enum_value_semantics9NoPayloadO* [[SELF]], i32 0, i32 0
|
|
// CHECK-NEXT: store i8 [[TAG]], i8* [[TAG_ADDR]], align 1
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Singleton payload enums
|
|
//
|
|
|
|
|
|
// -- SingletonPayload getEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden i32 @"$S20enum_value_semantics16SingletonPayloadOwug"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics16SingletonPayloadO*
|
|
// CHECK-NEXT: ret i32 -1
|
|
|
|
|
|
// -- SingletonPayload destructiveProjectEnumData
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics16SingletonPayloadOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// -- SingletonPayload destructiveInjectEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics16SingletonPayloadOwui"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics16SingletonPayloadO*
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
// -- SinglePayloadTrivial getEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden i32 @"$S20enum_value_semantics20SinglePayloadTrivialOwug"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics20SinglePayloadTrivialO*
|
|
// CHECK: [[OPAQUE:%.*]] = bitcast %T20enum_value_semantics20SinglePayloadTrivialO* [[SELF]] to %swift.opaque*
|
|
// CHECK: [[TAG:%.*]] = call i32 %getEnumTagSinglePayload(%swift.opaque* noalias [[OPAQUE]], i32 3, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @"$SBi64_N", i32 0, i32 1))
|
|
// CHECK: ret i32 [[TAG]]
|
|
|
|
|
|
// -- SinglePayloadTrivial destructiveProjectEnumData
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics20SinglePayloadTrivialOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
//
|
|
// Single-payload enums
|
|
//
|
|
|
|
|
|
// -- SinglePayloadTrivial destructiveInjectEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics20SinglePayloadTrivialOwui"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics20SinglePayloadTrivialO*
|
|
// CHECK-NEXT: [[OPAQUE:%.*]] = bitcast %T20enum_value_semantics20SinglePayloadTrivialO* [[SELF]] to %swift.opaque*
|
|
// CHECK: call void %storeEnumTagSinglePayload(%swift.opaque* noalias [[OPAQUE]], i32 %tag, i32 3, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @"$SBi64_N", i32 0, i32 1))
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
// -- SinglePayloadNontrivial destroyBuffer
|
|
// CHECK: define linkonce_odr hidden void @"$S20enum_value_semantics23SinglePayloadNontrivialOwxx"(%swift.opaque* noalias [[OBJ:%.*]], %swift.type* %SinglePayloadNontrivial) {{.*}} {
|
|
// CHECK: [[ADDR:%.*]] = bitcast %swift.opaque* [[OBJ]] to %T20enum_value_semantics23SinglePayloadNontrivialO*
|
|
// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %T20enum_value_semantics23SinglePayloadNontrivialO* [[ADDR]] to i64*
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]], align 8
|
|
// CHECK-NEXT: switch i64 %2, label %[[RELEASE_PAYLOAD:[0-9]+]] [
|
|
// CHECK: i64 0, label %[[DONE:[0-9]+]]
|
|
// CHECK: i64 2, label %[[DONE]]
|
|
// CHECK: i64 4, label %[[DONE]]
|
|
// CHECK: ]
|
|
|
|
// CHECK: ; <label>:[[RELEASE_PAYLOAD]]
|
|
// CHECK-NEXT: [[DATA_ADDR:%.*]] = bitcast %T20enum_value_semantics23SinglePayloadNontrivialO* [[ADDR]] to %swift.refcounted**
|
|
// CHECK-NEXT: [[DATA:%.*]] = load %swift.refcounted*, %swift.refcounted** [[DATA_ADDR]], align 8
|
|
// CHECK-NEXT: call void @swift_release(%swift.refcounted* [[DATA]])
|
|
// CHECK-NEXT: br label %[[DONE]]
|
|
|
|
// CHECK: ; <label>:[[DONE]]
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enums
|
|
//
|
|
|
|
|
|
// -- MultiPayloadTrivial getEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden i32 @"$S20enum_value_semantics19MultiPayloadTrivialOwug"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics19MultiPayloadTrivialO*
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %T20enum_value_semantics19MultiPayloadTrivialO* [[SELF]] to i64*
|
|
|
|
|
|
// -- Load the low bits of the tag from the payload area
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG_TMP:%.*]] = load i64, i64* [[PAYLOAD]], align 8
|
|
|
|
// -- Load the high bits of the tag from the extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T20enum_value_semantics19MultiPayloadTrivialO, %T20enum_value_semantics19MultiPayloadTrivialO* [[SELF]], i32 0, i32 1
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i8*
|
|
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i8, i8* [[EXTRA_TAG_ADDR]], align 8
|
|
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i8 [[EXTRA_TAG_TMP]] to i32
|
|
|
|
// -- Form tag for the payload case, or the high bits of no-payload case
|
|
// CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = sub i32 [[EXTRA_TAG]], 2
|
|
|
|
// -- Combine them to form the tag for the no-payload case
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = trunc i64 [[NO_PAYLOAD_TAG_TMP]] to i32
|
|
|
|
// -- Check if we have a payload or not
|
|
// CHECK-NEXT: [[IS_PAYLOAD:%.*]] = icmp sge i32 [[PAYLOAD_TAG]], 0
|
|
// CHECK-NEXT: [[TAG:%.*]] = select i1 [[IS_PAYLOAD]], i32 [[NO_PAYLOAD_TAG]], i32 [[PAYLOAD_TAG]]
|
|
|
|
// -- Return the tag
|
|
// CHECK-NEXT: ret i32 [[TAG]]
|
|
|
|
// -- MultiPayloadTrivial destructiveProjectEnumData
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics19MultiPayloadTrivialOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// -- MultiPayloadTrivial destructiveInjectEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics19MultiPayloadTrivialOwui"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics19MultiPayloadTrivialO*
|
|
// CHECK-NEXT: [[IS_PAYLOAD:%.*]] = icmp sge i32 %tag, 0
|
|
// CHECK-NEXT: br i1 [[IS_PAYLOAD]], label %[[HAS_NO_PAYLOAD:.*]], label %[[HAS_PAYLOAD:.*]]
|
|
|
|
// CHECK: ; <label>:[[HAS_NO_PAYLOAD]]
|
|
|
|
// -- Compute the no-payload tag
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = zext i32 %tag to i64
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %T20enum_value_semantics19MultiPayloadTrivialO* [[SELF]] to i64*
|
|
|
|
// -- Store the low bits of the tag in the payload area
|
|
// CHECK-NEXT: store i64 [[NO_PAYLOAD_TAG]], i64* [[PAYLOAD]], align 8
|
|
|
|
// -- Store the high bits of the tag in the extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T20enum_value_semantics19MultiPayloadTrivialO, %T20enum_value_semantics19MultiPayloadTrivialO* [[SELF]], i32 0, i32 1
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i8*
|
|
// CHECK-NEXT: store i8 2, i8* [[EXTRA_TAG_ADDR]], align 8
|
|
// CHECK-NEXT: br label %[[DONE:.*]]
|
|
|
|
// CHECK: ; <label>:[[HAS_PAYLOAD]]
|
|
|
|
// -- Store the tag in the extra tag area
|
|
// CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = add i32 %tag, 2
|
|
// CHECK-NEXT: [[TAG:%.*]] = trunc i32 [[PAYLOAD_TAG]] to i8
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T20enum_value_semantics19MultiPayloadTrivialO, %T20enum_value_semantics19MultiPayloadTrivialO* [[SELF]], i32 0, i32 1
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i8*
|
|
// CHECK-NEXT: store i8 [[TAG]], i8* [[EXTRA_TAG_ADDR]], align 8
|
|
// CHECK-NEXT: br label %[[DONE]]
|
|
|
|
// CHECK: ; <label>:[[DONE]]
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enums with no empty cases
|
|
//
|
|
|
|
|
|
// -- MultiPayloadNoEmptyCases getEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden i32 @"$S20enum_value_semantics24MultiPayloadNoEmptyCasesOwug"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics24MultiPayloadNoEmptyCasesO*
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %T20enum_value_semantics24MultiPayloadNoEmptyCasesO* [[SELF]] to i64*
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG_TMP:%.*]] = load i64, i64* [[PAYLOAD]], 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 %T20enum_value_semantics24MultiPayloadNoEmptyCasesO, %T20enum_value_semantics24MultiPayloadNoEmptyCasesO* [[SELF]], i32 0, i32 1
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i1*
|
|
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i1, i1* [[EXTRA_TAG_ADDR]], align 8
|
|
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i1 [[EXTRA_TAG_TMP]] to i32
|
|
// CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = sub i32 [[EXTRA_TAG]], 2
|
|
// CHECK-NEXT: ret i32 [[PAYLOAD_TAG]]
|
|
|
|
// -- MultiPayloadNoEmptyCases destructiveProjectEnumData
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics24MultiPayloadNoEmptyCasesOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// -- MultiPayloadNoEmptyCases destructiveInjectEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics24MultiPayloadNoEmptyCasesOwui"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics24MultiPayloadNoEmptyCasesO*
|
|
// CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = add i32 %tag, 2
|
|
// CHECK-NEXT: [[TAG:%.*]] = trunc i32 [[PAYLOAD_TAG]] to i1
|
|
|
|
// -- Store the tag in the extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T20enum_value_semantics24MultiPayloadNoEmptyCasesO, %T20enum_value_semantics24MultiPayloadNoEmptyCasesO* [[SELF]], i32 0, i32 1
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i1*
|
|
// CHECK-NEXT: store i1 [[TAG]], i1* [[EXTRA_TAG_ADDR]], align 8
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enum with empty payloads -- payload tag is not used
|
|
//
|
|
|
|
|
|
// -- MultiPayloadEmptyPayload getEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden i32 @"$S20enum_value_semantics017MultiPayloadEmptyE0Owug"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics017MultiPayloadEmptyE0O*
|
|
|
|
// -- Load the tag from the extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = getelementptr inbounds %T20enum_value_semantics017MultiPayloadEmptyE0O, %T20enum_value_semantics017MultiPayloadEmptyE0O* [[SELF]], i32 0, i32 0
|
|
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i8, i8* [[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 linkonce_odr hidden void @"$S20enum_value_semantics017MultiPayloadEmptyE0Owup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// -- MultiPayloadEmptyPayload destructiveInjectEnumTag
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics017MultiPayloadEmptyE0Owui"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics017MultiPayloadEmptyE0O*
|
|
|
|
// -- Store the tag in the extra tag area
|
|
// CHECK-NEXT: [[TAG:%.*]] = trunc i32 %tag to i8
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = getelementptr inbounds %T20enum_value_semantics017MultiPayloadEmptyE0O, %T20enum_value_semantics017MultiPayloadEmptyE0O* [[SELF]], i32 0, i32 0
|
|
// CHECK-NEXT: store i8 [[TAG]], i8* [[EXTRA_TAG_ADDR]], align 1
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enum with non-POD payloads
|
|
//
|
|
|
|
|
|
// -- MultiPayloadNontrivial destroyBuffer
|
|
// CHECK: define linkonce_odr hidden void @"$S20enum_value_semantics22MultiPayloadNontrivialOwxx"(%swift.opaque* noalias [[OBJ:%.*]], %swift.type* %MultiPayloadNontrivial)
|
|
// CHECK: [[ADDR:%.*]] = bitcast %swift.opaque* [[OBJ]] to %T20enum_value_semantics22MultiPayloadNontrivialO*
|
|
// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %T20enum_value_semantics22MultiPayloadNontrivialO* [[ADDR]] to { i64, i64 }*
|
|
// CHECK-NEXT: [[PAYLOAD_0_ADDR:%.*]] = getelementptr
|
|
// CHECK-NEXT: [[PAYLOAD_0:%.*]] = load i64, i64* [[PAYLOAD_0_ADDR]], align 8
|
|
// CHECK-NEXT: [[PAYLOAD_1_ADDR:%.*]] = getelementptr
|
|
// CHECK-NEXT: [[PAYLOAD_1:%.*]] = load i64, i64* [[PAYLOAD_1_ADDR]], align 8
|
|
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %T20enum_value_semantics22MultiPayloadNontrivialO, %T20enum_value_semantics22MultiPayloadNontrivialO* %0, i32 0, i32 1
|
|
// CHECK-NEXT: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i8*
|
|
// CHECK-NEXT: [[TAG:%.*]] = load i8, i8* [[TAG_ADDR]], align 8
|
|
// CHECK-NEXT: @"$S20enum_value_semantics22MultiPayloadNontrivialOWe"
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enum with generic layout -- spare bits are not used
|
|
//
|
|
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden i32 @"$S20enum_value_semantics19MultiPayloadGenericOwug"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics19MultiPayloadGenericO*
|
|
// CHECK-NEXT: [[OPAQUE:%.*]] = bitcast %T20enum_value_semantics19MultiPayloadGenericO* [[SELF]] to %swift.opaque*
|
|
// CHECK-NEXT: [[TAG:%.*]] = call i32 @swift_getEnumCaseMultiPayload(%swift.opaque* [[OPAQUE]], %swift.type* %"MultiPayloadGeneric<T>")
|
|
// CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = sub i32 [[TAG]], 2
|
|
// CHECK-NEXT: ret i32 [[PAYLOAD_TAG]]
|
|
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics19MultiPayloadGenericOwup"
|
|
// CHECK: ret void
|
|
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics19MultiPayloadGenericOwui"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics19MultiPayloadGenericO*
|
|
// CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = add i32 %tag, 2
|
|
// CHECK: [[OPAQUE:%.*]] = bitcast %T20enum_value_semantics19MultiPayloadGenericO* [[SELF]] to %swift.opaque*
|
|
// CHECK-NEXT: call void @swift_storeEnumTagMultiPayload(%swift.opaque* [[OPAQUE]], %swift.type* %"MultiPayloadGeneric<T>", i32 [[PAYLOAD_TAG]])
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
//
|
|
// Multi-payload enum with spare bits
|
|
//
|
|
|
|
|
|
// -- MultiPayloadNontrivialSpareBits destroyBuffer
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics31MultiPayloadNontrivialSpareBitsOwxx"
|
|
// CHECK-SAME: (%swift.opaque* noalias [[OBJ:%.*]], %swift.type* %MultiPayloadNontrivialSpareBits) {{.*}} {
|
|
// CHECK: [[ADDR:%.*]] = bitcast %swift.opaque* [[OBJ]] to %T20enum_value_semantics31MultiPayloadNontrivialSpareBitsO*
|
|
// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %T20enum_value_semantics31MultiPayloadNontrivialSpareBitsO* [[ADDR]] to { i64, i64 }*
|
|
// CHECK-NEXT: [[PAYLOAD_0_ADDR:%.*]] = getelementptr
|
|
// CHECK-NEXT: [[PAYLOAD_0:%.*]] = load i64, i64* [[PAYLOAD_0_ADDR]], align 8
|
|
// CHECK-NEXT: [[PAYLOAD_1_ADDR:%.*]] = getelementptr
|
|
// CHECK-NEXT: [[PAYLOAD_1:%.*]] = load i64, i64* [[PAYLOAD_1_ADDR]], align 8
|
|
// CHECK: call void @"$S20enum_value_semantics31MultiPayloadNontrivialSpareBitsOWe"
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden i32 @"$S20enum_value_semantics31MultiPayloadNontrivialSpareBitsOwug"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics31MultiPayloadNontrivialSpareBitsO*
|
|
|
|
// -- Load the payload
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %T20enum_value_semantics31MultiPayloadNontrivialSpareBitsO* [[SELF]] to { i64, i64 }*
|
|
// CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 0
|
|
// CHECK-NEXT: [[FIRST:%.*]] = load i64, i64* [[FIRST_ADDR]], align 8
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 1
|
|
// CHECK-NEXT: [[SECOND:%.*]] = load i64, i64* [[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
|
|
// CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = sub i32 [[SPARE_TAG]], 3
|
|
|
|
// -- Get the low bits of the tag from the payload area
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = trunc i64 [[FIRST]] to i32
|
|
|
|
// -- Check if we have a payload or not
|
|
// CHECK-NEXT: [[IS_PAYLOAD:%.*]] = icmp sge i32 [[PAYLOAD_TAG]], 0
|
|
|
|
// -- Return the tag
|
|
// CHECK-NEXT: [[TAG:%.*]] = select i1 [[IS_PAYLOAD]], i32 [[NO_PAYLOAD_TAG]], i32 [[PAYLOAD_TAG]]
|
|
// CHECK-NEXT: ret i32 [[TAG]]
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics31MultiPayloadNontrivialSpareBitsOwup"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to { i64, i64 }*
|
|
|
|
// -- Load the payload
|
|
// CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[SELF]], i32 0, i32 0
|
|
// CHECK-NEXT: [[FIRST:%.*]] = load i64, i64* [[FIRST_ADDR]], align 8
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[SELF]], i32 0, i32 1
|
|
// CHECK-NEXT: [[SECOND:%.*]] = load i64, i64* [[SECOND_ADDR]], align 8
|
|
|
|
// -- Strip off spare bits
|
|
// CHECK-NEXT: [[SECOND_PROJ:%.*]] = and i64 [[SECOND]], 4611686018427387903
|
|
|
|
// -- Store the payload
|
|
// CHECK-NEXT: [[SELF:%.*]] = bitcast %swift.opaque* %value to { i64, i64 }*
|
|
// CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[SELF]], i32 0, i32 0
|
|
// CHECK-NEXT: store i64 [[FIRST]], i64* [[FIRST_ADDR]], align 8
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[SELF]], i32 0, i32 1
|
|
// CHECK-NEXT: store i64 [[SECOND_PROJ]], i64* [[SECOND_ADDR]], align 8
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics31MultiPayloadNontrivialSpareBitsOwui"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics31MultiPayloadNontrivialSpareBitsO*
|
|
// CHECK-NEXT: [[IS_PAYLOAD:%.*]] = icmp sge i32 %tag, 0
|
|
// CHECK-NEXT: br i1 [[IS_PAYLOAD]], label %[[HAS_NO_PAYLOAD:.*]], label %[[HAS_PAYLOAD:.*]]
|
|
|
|
// CHECK: ; <label>:[[HAS_NO_PAYLOAD]]
|
|
|
|
// -- Turn the case index into a no-payload case index
|
|
// CHECK-NEXT: [[NO_PAYLOAD_TAG:%.*]] = zext i32 %tag to i64
|
|
|
|
// -- Store the low bits of the tag into the payload
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %T20enum_value_semantics31MultiPayloadNontrivialSpareBitsO* [[SELF]] to { i64, i64 }*
|
|
// CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 0
|
|
// CHECK-NEXT: store i64 [[NO_PAYLOAD_TAG]], i64* [[FIRST_ADDR]], align 8
|
|
|
|
// -- Store the high bits of the tag into the spare bits
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 1
|
|
// -- 0xc000000000000000
|
|
// CHECK-NEXT: store i64 -4611686018427387904, i64* [[SECOND_ADDR]], align 8
|
|
// CHECK-NEXT: br label %[[END:.*]]
|
|
|
|
// CHECK: ; <label>:[[HAS_PAYLOAD]]
|
|
|
|
// CHECK-NEXT: [[TAG_TMP2:%.*]] = add i32 %tag, 3
|
|
|
|
// -- Not really necessary
|
|
// CHECK-NEXT: [[TAG_TMP:%.*]] = and i32 [[TAG_TMP2]], 3
|
|
|
|
// -- Load the payload
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %T20enum_value_semantics31MultiPayloadNontrivialSpareBitsO* [[SELF]] to { i64, i64 }*
|
|
// CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 0
|
|
// CHECK-NEXT: [[FIRST:%.*]] = load i64, i64* [[FIRST_ADDR]], align 8
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 1
|
|
// CHECK-NEXT: [[SECOND:%.*]] = load i64, i64* [[SECOND_ADDR]], align 8
|
|
|
|
// -- Mask off spare bits in the payload -- 0x3fffffffffffffff
|
|
// CHECK-NEXT: [[SECOND_PROJ:%.*]] = and i64 [[SECOND]], 4611686018427387903
|
|
|
|
// -- 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 [[SECOND_PROJ]], [[SPARE_TAG_TMP]]
|
|
|
|
// -- Store the payload back
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = bitcast %T20enum_value_semantics31MultiPayloadNontrivialSpareBitsO* [[SELF]] to { i64, i64 }*
|
|
// CHECK-NEXT: [[FIRST_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 0
|
|
// CHECK-NEXT: store i64 [[FIRST]], i64* [[FIRST_ADDR]], align 8
|
|
// CHECK-NEXT: [[SECOND_ADDR:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[PAYLOAD]], i32 0, i32 1
|
|
// CHECK-NEXT: store i64 [[SECOND_NEW]], i64* [[SECOND_ADDR]], align 8
|
|
// CHECK-NEXT: br label %[[END]]
|
|
|
|
// CHECK: ; <label>:[[END]]
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden i32 @"$S20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0Owug"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0O*
|
|
|
|
// -- Load the payload
|
|
// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %T20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0O* [[SELF]] to i64*
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]], align 8
|
|
|
|
// -- Load the load bits of the tag from the extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0O, %T20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0O* [[SELF]], i32 0, i32 1
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i1*
|
|
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = load i1, i1* [[EXTRA_TAG_ADDR]], 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
|
|
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = zext i1 [[EXTRA_TAG_TMP]] to i8
|
|
|
|
// -- 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: [[PAYLOAD_TAG:%.*]] = sub i32 [[RESULT]],
|
|
// CHECK-NEXT: ret i32 [[PAYLOAD_TAG]]
|
|
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0Owup"
|
|
// CHECK: [[PAYLOAD_ADDR:%.*]] = bitcast %swift.opaque* %value to i64*
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]], align 8
|
|
// -- 0x7fffffffffffffff
|
|
// CHECK-NEXT: [[PAYLOAD_PROJ:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
|
|
// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %swift.opaque* %value to i64*
|
|
// CHECK-NEXT: store i64 [[PAYLOAD_PROJ]], i64* [[PAYLOAD_ADDR]], align 8
|
|
// CHECK-NEXT: ret void
|
|
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden void @"$S20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0Owui"
|
|
// CHECK: [[SELF:%.*]] = bitcast %swift.opaque* %value to %T20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0O*
|
|
// CHECK-NEXT: [[PAYLOAD_TAG:%.*]] = add i32 %tag, 3
|
|
// CHECK-NEXT: [[SPARE_TAG_TMP3:%.*]] = and i32 [[PAYLOAD_TAG]], 1
|
|
|
|
// -- Load the payload
|
|
// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %T20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0O* %0 to i64*
|
|
// CHECK-NEXT: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]], 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 [[PAYLOAD_PROJ]], [[SPARE_TAG]]
|
|
|
|
// -- Store the payload
|
|
// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = bitcast %T20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0O* %0 to i64*
|
|
// CHECK-NEXT: store i64 [[PAYLOAD_NEW]], i64* [[PAYLOAD_ADDR]], align 8
|
|
|
|
// -- Store high bits of tag in extra tag area
|
|
// CHECK-NEXT: [[EXTRA_TAG_TMP:%.*]] = lshr i32 [[PAYLOAD_TAG]], 1
|
|
// CHECK-NEXT: [[EXTRA_TAG:%.*]] = trunc i32 [[EXTRA_TAG_TMP]] to i1
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR_TMP:%.*]] = getelementptr inbounds %T20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0O, %T20enum_value_semantics029MultiPayloadSpareBitsAndExtraG0O* [[SELF]], i32 0, i32 1
|
|
// CHECK-NEXT: [[EXTRA_TAG_ADDR:%.*]] = bitcast [1 x i8]* [[EXTRA_TAG_ADDR_TMP]] to i1*
|
|
// CHECK-NEXT: store i1 [[EXTRA_TAG]], i1* [[EXTRA_TAG_ADDR]], align 8
|
|
// CHECK-NEXT: ret void
|