mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Both the syntax and relative order of the LLVM `nocapture` parameter attribute changed upstream in 29441e4f5fa5f5c7709f7cf180815ba97f611297. To reduce conflicts with rebranch, adjust FileCheck patterns to expect both syntaxes and orders anywhere the presence of the attribute is not critical to the test. These changes are temporary and will be cleaned up once rebranch is merged into main.
2694 lines
102 KiB
Plaintext
2694 lines
102 KiB
Plaintext
// #if directives don't work with SIL keywords, therefore please put ObjC tests
|
|
// in `enum_objc.sil`.
|
|
// RUN: %target-swift-frontend %s -Xllvm -sil-disable-pass=simplification -disable-type-layout -disable-generic-metadata-prespecialization -disable-generic-metadata-prespecialization -gnone -emit-ir -disable-diagnostic-passes -enable-objc-interop | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-objc --check-prefix=CHECK-objc-%target-ptrsize --check-prefix=CHECK-objc-%target-ptrsize-simulator-%target-is-simulator -DWORD=i%target-ptrsize
|
|
// RUN: %target-swift-frontend %s -Xllvm -sil-disable-pass=simplification -disable-type-layout -disable-generic-metadata-prespecialization -gnone -emit-ir -disable-diagnostic-passes -disable-objc-interop | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-native --check-prefix=CHECK-native-%target-ptrsize -DWORD=i%target-ptrsize
|
|
|
|
// REQUIRES: CPU=i386 || CPU=x86_64
|
|
|
|
// We have to claim this is raw SIL because there are critical edges from non
|
|
// cond_br instructions.
|
|
sil_stage raw
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
// -- Singleton enum. The representation is just the singleton payload.
|
|
// CHECK: %T4enum9SingletonO = type <{ <{ i64, i64 }> }>
|
|
|
|
// -- Singleton enum with heap object ref payload. <rdar://problem/15679353>
|
|
// CHECK: %T4enum12SingletonRefO = type <{ ptr }>
|
|
|
|
// -- No-payload enums. The representation is just an enum tag.
|
|
// CHECK: %T4enum10NoPayloadsO = type <{ i8 }>
|
|
// CHECK: %T4enum11NoPayloads2O = type <{ i8 }>
|
|
|
|
// -- Single-payload enum, no extra inhabitants in the payload type. The
|
|
// representation adds a tag bit to distinguish payload from enum tag:
|
|
// case x(i64): X0 X1 X2 ... X63 | 0, where X0...X63 are the payload bits
|
|
// case y: 0 0 0 ... 0 | 1
|
|
// case z: 1 0 0 ... 0 | 1
|
|
// CHECK-64: %T4enum17SinglePayloadNoXIO = type <{ [8 x i8], [1 x i8] }>
|
|
// CHECK-64: %T4enum18SinglePayloadNoXI2O = type <{ [8 x i8], [1 x i8] }>
|
|
// CHECK-32: %T4enum17SinglePayloadNoXIO = type <{ [4 x i8], [1 x i8] }>
|
|
// CHECK-32: %T4enum18SinglePayloadNoXI2O = type <{ [4 x i8], [1 x i8] }>
|
|
|
|
// -- Single-payload enum, spare bits. The representation uses a tag bit
|
|
// out of the payload to distinguish payload from enum tag:
|
|
// case x(i3): X0 X1 X2 0 0 0 0 0
|
|
// case y: 0 0 0 1 0 0 0 0
|
|
// case z: 1 0 0 1 0 0 0 0
|
|
// CHECK: %T4enum21SinglePayloadSpareBitO = type <{ [8 x i8] }>
|
|
|
|
// -- Single-payload enum containing a no-payload enum as its payload.
|
|
// The representation takes extra inhabitants starting after the greatest
|
|
// discriminator value used by the nested no-payload enum.
|
|
// CHECK: %T4enum19SinglePayloadNestedO = type <{ [1 x i8] }>
|
|
|
|
// -- Single-payload enum containing another single-payload enum as its
|
|
// payload.
|
|
// The representation takes extra inhabitants from the nested enum's payload
|
|
// that were unused by the nested enum.
|
|
// CHECK: %T4enum019SinglePayloadNestedD0O = type <{ [1 x i8] }>
|
|
|
|
// -- Multi-payload enum, no spare bits. The representation adds tag bits
|
|
// to discriminate payloads. No-payload cases all share a tag.
|
|
// case x(i8): X0 X1 X2 ... X7 X8 | 0 0
|
|
// case y(i7): Y0 Y1 Y2 ... Y7 0 | 1 0
|
|
// case z(i2): Z0 Z1 0 ... 0 0 | 0 1
|
|
// case a: 0 0 0 ... 0 0 | 1 1
|
|
// case b: 1 0 0 ... 0 0 | 1 1
|
|
// case c: 0 1 0 ... 0 0 | 1 1
|
|
// CHECK: %T4enum23MultiPayloadNoSpareBitsO = type <{ [8 x i8], [1 x i8] }>
|
|
|
|
// -- Multi-payload enum, one spare bit. The representation uses spare bits
|
|
// common to all payloads to partially discriminate payloads, with added
|
|
// tag bits to cover the gap. No-payload cases all share a tag.
|
|
// case x(i7): X0 X1 X2 X3 X4 X5 X6 0 | 0
|
|
// case y(i1): Y 0 0 0 0 0 0 1 | 0
|
|
// case z(i5): Z0 Z1 Z2 Z3 Z4 0 0 0 | 1
|
|
// case a: 0 0 0 0 0 0 0 1 | 1
|
|
// case b: 1 0 0 0 0 0 0 1 | 1
|
|
// case c: 0 1 0 0 0 0 0 1 | 1
|
|
// CHECK: %T4enum23MultiPayloadOneSpareBitO = type <{ [8 x i8], [1 x i8] }>
|
|
|
|
// -- Multi-payload enum, two spare bits. Same as above, except we have enough
|
|
// spare bits not to require any added tag bits.
|
|
// case x(i6): X0 X1 X2 X3 X4 X5 0 0
|
|
// case y(i1): Y 0 0 0 0 0 1 0
|
|
// case z(i5): Z0 Z1 Z2 Z3 Z4 0 0 1
|
|
// case a: 0 0 0 0 0 0 1 1
|
|
// case b: 1 0 0 0 0 0 1 1
|
|
// case c: 0 1 0 0 0 0 1 1
|
|
// CHECK: %T4enum24MultiPayloadTwoSpareBitsO = type <{ [8 x i8] }>
|
|
|
|
// CHECK-64: %T4enum30MultiPayloadSpareBitAggregatesO = type <{ [16 x i8] }>
|
|
|
|
// CHECK-64: %T4enum18MultiPayloadNestedO = type <{ [9 x i8] }>
|
|
// CHECK-32: %T4enum18MultiPayloadNestedO = type <{ [5 x i8] }>
|
|
|
|
// 32-bit object references don't have enough spare bits.
|
|
// CHECK-64: %T4enum27MultiPayloadNestedSpareBitsO = type <{ [8 x i8] }>
|
|
|
|
// -- Dynamic enums. The type layout is opaque; we dynamically bitcast to
|
|
// the element type.
|
|
|
|
// -- Address-only multi-payload enums. We can't use spare bits.
|
|
// CHECK-64: %T4enum32MultiPayloadAddressOnlySpareBitsO = type <{ [16 x i8], [1 x i8] }>
|
|
// CHECK-32: %T4enum32MultiPayloadAddressOnlySpareBitsO = type <{ [8 x i8], [1 x i8] }>
|
|
|
|
// CHECK: %T4enum40MultiPayloadLessThan32BitsWithEmptyCasesO = type <{ [1 x i8], [1 x i8] }>
|
|
|
|
// -- Dynamic metadata template carries a value witness table pattern
|
|
// we fill in on instantiation.
|
|
// FIXME: Strings should be unnamed_addr. rdar://problem/22674524
|
|
// CHECK: @"$s4enum16DynamicSingletonOWV" =
|
|
// CHECK-SAME: [[WORD]] 0,
|
|
// CHECK-SAME: [[WORD]] 0,
|
|
// 6291456 == 0x600000 (enum, incomplete)
|
|
// CHECK-SAME: i32 6291456,
|
|
// CHECK-SAME: i32 0,
|
|
// Enum witnesses.
|
|
// CHECK-SAME: ptr @"$s4enum16DynamicSingletonOwug"
|
|
// CHECK-SAME: ptr @"$s4enum16DynamicSingletonOwup"
|
|
// CHECK-SAME: ptr @"$s4enum16DynamicSingletonOwui"
|
|
|
|
// CHECK: [[DYNAMICSINGLETON_NAME:@.*]] = private constant [17 x i8] c"DynamicSingleton\00"
|
|
// CHECK: @"$s4enum16DynamicSingletonOMn" = hidden constant <{
|
|
// CHECK-SAME: ptr [[DYNAMICSINGLETON_NAME]]
|
|
// -- One payload
|
|
// CHECK-SAME: i32 1,
|
|
// -- No empty cases
|
|
// CHECK-SAME: i32 0,
|
|
// -- generic instantiation pattern
|
|
// CHECK-SAME: @"$s4enum16DynamicSingletonOMP"
|
|
// -- generic parameters, requirements, key, extra
|
|
// CHECK-SAME: i16 1, i16 0, i16 1, i16 0
|
|
// -- generic param
|
|
// CHECK-SAME: i8 -128,
|
|
// CHECK-SAME: }>
|
|
|
|
// CHECK: @"$s4enum16DynamicSingletonOMP" = internal constant <{ {{.*}} }> <{
|
|
// CHECK-SAME: @"$s4enum16DynamicSingletonOMi"
|
|
// CHECK-SAME: ptr @"$s4enum16DynamicSingletonOWV"
|
|
|
|
// -- No-payload enums have extra inhabitants in
|
|
// their value witness table.
|
|
// CHECK: @"$s4enum10NoPayloadsOWV" = internal constant %swift.enum_vwtable {
|
|
// -- ...
|
|
// -- size
|
|
// CHECK-SAME: [[WORD]] 1,
|
|
// -- stride
|
|
// CHECK-SAME: [[WORD]] 1,
|
|
// -- flags (0x20_0000: alignment 1 and enum witnesses)
|
|
// CHECK-SAME: i32 2097152,
|
|
// -- num extra inhabitants (256 - 3 valid states)
|
|
// CHECK-SAME: i32 253,
|
|
// CHECK-SAME: }, align
|
|
|
|
// -- Single-payload enums take unused extra inhabitants from their payload
|
|
// as their own.
|
|
// CHECK: @"$s4enum19SinglePayloadNestedOWV" = internal constant %swift.enum_vwtable {
|
|
// -- ...
|
|
// -- size
|
|
// CHECK-SAME: [[WORD]] 1,
|
|
// -- stride
|
|
// CHECK-SAME: [[WORD]] 1,
|
|
// -- flags (0x20_0000: alignment 1 and enum witnesses)
|
|
// CHECK-SAME: i32 2097152,
|
|
// -- num extra inhabitants (253 from payload - 3 empty cases)
|
|
// CHECK-SAME: i32 250,
|
|
// CHECK-SAME: }
|
|
|
|
// CHECK: @"$s4enum20DynamicSinglePayloadOWV" = internal constant %swift.enum_vwtable {
|
|
// -- flags (0x60_0000: alignment 1, incomplete, enum witnesses)
|
|
// CHECK-SAME: i32 6291456,
|
|
// -- num extra inhabitants (253 from payload - 3 empty cases)
|
|
// CHECK-SAME: i32 0,
|
|
|
|
// CHECK: @"$s4enum20DynamicSinglePayloadOMP" = internal constant <{ {{.*}} }> <{
|
|
// CHECK-SAME: @"$s4enum20DynamicSinglePayloadOMi"
|
|
// CHECK-SAME: ptr @"$s4enum20DynamicSinglePayloadOWV"
|
|
|
|
// CHECK: @"$s4enum18MultiPayloadNestedOWV" = internal constant %swift.enum_vwtable {
|
|
// -- size
|
|
// CHECK-32-SAME: [[WORD]] 5,
|
|
// CHECK-64-SAME: [[WORD]] 9,
|
|
// -- flags (0x250003: alignment 4, enum)
|
|
// -- flags (0x200007: alignment 8, enum)
|
|
// CHECK-32-SAME: i32 2097155,
|
|
// CHECK-64-SAME: i32 2097159,
|
|
// CHECK-SAME: }
|
|
|
|
enum Empty {}
|
|
|
|
enum EmptySingleton {
|
|
case foo
|
|
}
|
|
|
|
enum Singleton {
|
|
case value(Builtin.Int64, Builtin.Int64)
|
|
}
|
|
|
|
enum SingletonRef {
|
|
case value(Builtin.NativeObject)
|
|
}
|
|
|
|
enum DynamicSingleton<T> {
|
|
case value(T)
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @singleton_switch(i64 %0, i64 %1) {{.*}} {
|
|
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc void @singleton_switch(ptr noalias dereferenceable(16) %0) {{.*}} {
|
|
sil @singleton_switch : $(Singleton) -> () {
|
|
// CHECK-64: entry:
|
|
// CHECK-32: entry:
|
|
entry(%u : $Singleton):
|
|
// CHECK-64: br label %[[DEST:[0-9]+]]
|
|
// CHECK-32: br label %[[DEST:[0-9]+]]
|
|
switch_enum %u : $Singleton, case #Singleton.value!enumelt: dest
|
|
|
|
// CHECK-64: [[DEST]]:
|
|
// CHECK-32: [[DEST]]:
|
|
dest:
|
|
// CHECK-64: ret void
|
|
// CHECK-32: ret void
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @singleton_switch_arg(i64 %0, i64 %1) {{.*}} {
|
|
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc void @singleton_switch_arg(ptr noalias dereferenceable(16) %0) {{.*}} {
|
|
sil @singleton_switch_arg : $(Singleton) -> () {
|
|
// CHECK-64: entry:
|
|
// CHECK-32: entry:
|
|
entry(%u : $Singleton):
|
|
// CHECK-32: call ptr @"$s4enum9SingletonOWOb"
|
|
// CHECK-64: br label %[[PREDEST:[0-9]+]]
|
|
// CHECK-32: br label %[[PREDEST:[0-9]+]]
|
|
switch_enum %u : $Singleton, case #Singleton.value!enumelt: dest
|
|
|
|
// CHECK-64: [[PREDEST]]:
|
|
// CHECK-64: br label %[[DEST:[0-9]+]]
|
|
// CHECK-64: [[DEST]]:
|
|
dest(%u2 : $(Builtin.Int64, Builtin.Int64)):
|
|
// CHECK-64: {{%.*}} = phi i64 [ %0, %[[PREDEST]] ]
|
|
// CHECK-64: {{%.*}} = phi i64 [ %1, %[[PREDEST]] ]
|
|
// CHECK-64: ret void
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @singleton_switch_indirect(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: br label %[[DEST:[0-9]+]]
|
|
// CHECK: [[DEST]]:
|
|
// CHECK: ret void
|
|
// CHECK: }
|
|
sil @singleton_switch_indirect : $(@inout Singleton) -> () {
|
|
entry(%u : $*Singleton):
|
|
switch_enum_addr %u : $*Singleton, case #Singleton.value!enumelt: dest
|
|
dest:
|
|
%u2 = unchecked_take_enum_data_addr %u : $*Singleton, #Singleton.value!enumelt
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i64 } @singleton_inject(i64 %0, i64 %1) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[A:%.*]] = insertvalue { i64, i64 } undef, i64 %0, 0
|
|
// CHECK-64: [[B:%.*]] = insertvalue { i64, i64 } [[A]], i64 %1, 1
|
|
// CHECK-64: ret { i64, i64 } [[B]]
|
|
// CHECK-64: }
|
|
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc void @singleton_inject(ptr noalias sret({{.*}}) %0, i64 %1, i64 %2) {{.*}} {
|
|
// CHECK-32: entry:
|
|
// CHECK-32: [[GEP1:%.*]] = getelementptr inbounds <{ i64, i64 }>, ptr %0, i32 0, i32 0
|
|
// CHECK-32: store i64 %1, ptr [[GEP1]]
|
|
// CHECK-32: [[GEP2:%.*]] = getelementptr inbounds <{ i64, i64 }>, ptr %0, i32 0, i32 1
|
|
// CHECK-32: store i64 %2, ptr [[GEP2]]
|
|
// CHECK-32: ret void
|
|
// CHECK-32: }
|
|
sil @singleton_inject : $(Builtin.Int64, Builtin.Int64) -> Singleton {
|
|
entry(%0 : $Builtin.Int64, %1 : $Builtin.Int64):
|
|
%t = tuple (%0 : $Builtin.Int64, %1 : $Builtin.Int64)
|
|
%u = enum $Singleton, #Singleton.value!enumelt, %t : $(Builtin.Int64, Builtin.Int64)
|
|
return %u : $Singleton
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @singleton_inject_indirect(i64 %0, i64 %1, ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %2) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: [[DATA_0_ADDR:%.*]] = getelementptr inbounds{{.*}} <{ i64, i64 }>, ptr %2, i32 0, i32 0
|
|
// CHECK: store i64 %0, ptr [[DATA_0_ADDR]]
|
|
// CHECK: [[DATA_1_ADDR:%.*]] = getelementptr inbounds{{.*}} <{ i64, i64 }>, ptr %2, i32 0, i32 1
|
|
// CHECK: store i64 %1, ptr [[DATA_1_ADDR]]
|
|
// CHECK: ret void
|
|
// CHECK: }
|
|
sil @singleton_inject_indirect : $(Builtin.Int64, Builtin.Int64, @inout Singleton) -> () {
|
|
entry(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2 : $*Singleton):
|
|
%t = tuple (%0 : $Builtin.Int64, %1 : $Builtin.Int64)
|
|
%a = init_enum_data_addr %2 : $*Singleton, #Singleton.value!enumelt
|
|
store %t to %a : $*(Builtin.Int64, Builtin.Int64)
|
|
inject_enum_addr %2 : $*Singleton, #Singleton.value!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
|
|
enum NoPayloads {
|
|
case x
|
|
case y
|
|
case z
|
|
}
|
|
|
|
sil @a : $@convention(thin) () -> ()
|
|
sil @b : $@convention(thin) () -> ()
|
|
sil @c : $@convention(thin) () -> ()
|
|
sil @d : $@convention(thin) () -> ()
|
|
sil @e : $@convention(thin) () -> ()
|
|
sil @f : $@convention(thin) () -> ()
|
|
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @no_payload_switch(i8 %0) {{.*}} {
|
|
sil @no_payload_switch : $@convention(thin) (NoPayloads) -> () {
|
|
// CHECK: entry:
|
|
entry(%u : $NoPayloads):
|
|
// CHECK: switch i8 %0, label %[[DFLT:[0-9]+]] [
|
|
// CHECK: i8 0, label %[[X_DEST:[0-9]+]]
|
|
// CHECK: i8 1, label %[[Y_DEST:[0-9]+]]
|
|
// CHECK: i8 2, label %[[Z_DEST:[0-9]+]]
|
|
// CHECK: ]
|
|
// CHECK: [[DFLT]]:
|
|
// CHECK: unreachable
|
|
switch_enum %u : $NoPayloads, case #NoPayloads.x!enumelt: x_dest, case #NoPayloads.y!enumelt: y_dest, case #NoPayloads.z!enumelt: z_dest
|
|
|
|
// CHECK: [[X_DEST]]:
|
|
// CHECK: call swiftcc void @a()
|
|
// CHECK: br label %[[END:[0-9]+]]
|
|
x_dest:
|
|
%a = function_ref @a : $@convention(thin) () -> ()
|
|
apply %a() : $@convention(thin) () -> ()
|
|
br end
|
|
// CHECK: [[Y_DEST]]:
|
|
// CHECK: call swiftcc void @b()
|
|
// CHECK: br label %[[END]]
|
|
y_dest:
|
|
%b = function_ref @b : $@convention(thin) () -> ()
|
|
apply %b() : $@convention(thin) () -> ()
|
|
br end
|
|
// CHECK: [[Z_DEST]]:
|
|
// CHECK: call swiftcc void @c()
|
|
// CHECK: br label %[[END]]
|
|
z_dest:
|
|
%c = function_ref @c : $@convention(thin) () -> ()
|
|
apply %c() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK: [[END]]:
|
|
// CHECK: ret void
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @no_payload_switch_indirect(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
|
|
sil @no_payload_switch_indirect : $@convention(thin) (@inout NoPayloads) -> () {
|
|
entry(%u : $*NoPayloads):
|
|
// CHECK: [[TAG_ADDR:%.*]] = getelementptr inbounds{{.*}} %T4enum10NoPayloadsO, ptr %0, i32 0, i32 0
|
|
// CHECK: [[TAG:%.*]] = load i8, ptr [[TAG_ADDR]]
|
|
// CHECK: switch i8 [[TAG]]
|
|
switch_enum_addr %u : $*NoPayloads, case #NoPayloads.x!enumelt: x_dest, case #NoPayloads.y!enumelt: y_dest, case #NoPayloads.z!enumelt: z_dest
|
|
|
|
x_dest:
|
|
br end
|
|
y_dest:
|
|
br end
|
|
z_dest:
|
|
br end
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc i8 @no_payload_inject_x() {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: ret i8 0
|
|
// CHECK: }
|
|
sil @no_payload_inject_x : $() -> NoPayloads {
|
|
entry:
|
|
%u = enum $NoPayloads, #NoPayloads.x!enumelt
|
|
return %u : $NoPayloads
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc i8 @no_payload_inject_y() {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: ret i8 1
|
|
// CHECK: }
|
|
sil @no_payload_inject_y : $() -> NoPayloads {
|
|
entry:
|
|
%u = enum $NoPayloads, #NoPayloads.y!enumelt
|
|
return %u : $NoPayloads
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc i8 @no_payload_inject_z() {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: ret i8 2
|
|
// CHECK: }
|
|
sil @no_payload_inject_z : $() -> NoPayloads {
|
|
entry:
|
|
%u = enum $NoPayloads, #NoPayloads.z!enumelt
|
|
return %u : $NoPayloads
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @no_payload_inject_z_indirect(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: [[TAG_ADDR:%.*]] = getelementptr inbounds{{.*}} %T4enum10NoPayloadsO, ptr %0, i32 0, i32 0
|
|
// CHECK: store i8 2, ptr [[TAG_ADDR]]
|
|
// CHECK: ret void
|
|
// CHECK: }
|
|
sil @no_payload_inject_z_indirect : $(@inout NoPayloads) -> () {
|
|
entry(%0 : $*NoPayloads):
|
|
inject_enum_addr %0 : $*NoPayloads, #NoPayloads.z!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
|
|
enum NoPayloads2 {
|
|
case a
|
|
case e
|
|
case i
|
|
case o
|
|
case u
|
|
case y
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @no_payload_switch_2(i8 %0) {{.*}} {
|
|
sil @no_payload_switch_2 : $@convention(thin) (NoPayloads2) -> () {
|
|
// CHECK: entry:
|
|
entry(%u : $NoPayloads2):
|
|
// CHECK: [[COND:%.*]] = icmp ne i8 %0, 4
|
|
// CHECK: br i1 [[COND]], label %[[DEFAULT_DEST:[0-9]+]], label %[[U_DEST:[0-9]+]]
|
|
switch_enum %u : $NoPayloads2, case #NoPayloads2.u!enumelt: u_dest, default default_dest
|
|
|
|
// CHECK: [[U_DEST]]:
|
|
u_dest:
|
|
// CHECK: call swiftcc void @a()
|
|
%a = function_ref @a : $@convention(thin) () -> ()
|
|
apply %a() : $@convention(thin) () -> ()
|
|
// CHECK: br label %[[END:[0-9]+]]
|
|
br end
|
|
|
|
// CHECK: [[DEFAULT_DEST]]:
|
|
default_dest:
|
|
// CHECK: call swiftcc void @b()
|
|
%b = function_ref @b : $@convention(thin) () -> ()
|
|
apply %b() : $@convention(thin) () -> ()
|
|
// CHECK: br label %[[END]]
|
|
br end
|
|
|
|
// CHECK: [[END]]:
|
|
end:
|
|
// CHECK: ret void
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
|
|
enum SinglePayloadNoXI {
|
|
case x(Builtin.Word)
|
|
case y
|
|
}
|
|
|
|
enum SinglePayloadNoXI2 {
|
|
case x(Builtin.Word)
|
|
case y
|
|
case z
|
|
case w
|
|
case v
|
|
case u
|
|
}
|
|
|
|
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @select_enum([[WORD:i32]] %0, i8 %1)
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @select_enum([[WORD:i64]] %0, i8 %1)
|
|
// CHECK: entry:
|
|
// CHECK: [[PAYLOAD:%.*]] = icmp eq [[WORD]] %0, 1
|
|
// CHECK: [[TAG:%.*]] = icmp eq i8 %1, 1
|
|
// CHECK: [[COMBINED:%.*]] = and i1 [[TAG]], [[PAYLOAD]]
|
|
// CHECK: [[RES:%.*]] = select i1 [[COMBINED]], i1 false, i1 true
|
|
// CHECK: ret i1 [[RES]]
|
|
// CHECK: }
|
|
|
|
sil @select_enum : $@convention(method) (SinglePayloadNoXI2) -> Builtin.Int1 {
|
|
bb0(%0 : $SinglePayloadNoXI2):
|
|
%2 = integer_literal $Builtin.Int1, 0
|
|
%3 = integer_literal $Builtin.Int1, -1
|
|
%4 = select_enum %0 : $SinglePayloadNoXI2, case #SinglePayloadNoXI2.z!enumelt: %2, default %3 : $Builtin.Int1
|
|
return %4 : $Builtin.Int1
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_no_xi_switch([[WORD:i64]] %0, i8 %1) {{.*}} {
|
|
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_no_xi_switch([[WORD:i32]] %0, i8 %1) {{.*}} {
|
|
sil @single_payload_no_xi_switch : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
|
// CHECK: entry:
|
|
entry(%u : $SinglePayloadNoXI2):
|
|
// CHECK: %2 = icmp eq i8 %1, 1
|
|
// CHECK: br i1 %2, label %[[TAGS:[0-9]+]], label %[[X_DEST:[0-9]+]]
|
|
// CHECK: [[TAGS]]:
|
|
// CHECK: switch [[WORD]] %0, label %[[DFLT:[0-9]+]] [
|
|
// CHECK: [[WORD]] 0, label %[[Y_DEST:[0-9]+]]
|
|
// CHECK: [[WORD]] 1, label %[[Z_DEST:[0-9]+]]
|
|
// CHECK: [[WORD]] 2, label %[[W_DEST:[0-9]+]]
|
|
// CHECK: [[WORD]] 3, label %[[V_DEST:[0-9]+]]
|
|
// CHECK: [[WORD]] 4, label %[[U_DEST:[0-9]+]]
|
|
// CHECK: ]
|
|
// CHECK: [[DFLT]]:
|
|
// CHECK: unreachable
|
|
switch_enum %u : $SinglePayloadNoXI2, case #SinglePayloadNoXI2.x!enumelt: x_dest, case #SinglePayloadNoXI2.y!enumelt: y_dest, case #SinglePayloadNoXI2.z!enumelt: z_dest, case #SinglePayloadNoXI2.w!enumelt: w_dest, case #SinglePayloadNoXI2.v!enumelt: v_dest, case #SinglePayloadNoXI2.u!enumelt: u_dest
|
|
|
|
|
|
// CHECK: [[X_DEST]]:
|
|
// CHECK: call swiftcc void @a()
|
|
// CHECK: br label %[[END:[0-9]+]]
|
|
x_dest:
|
|
%a = function_ref @a : $@convention(thin) () -> ()
|
|
apply %a() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK: [[Y_DEST]]:
|
|
// CHECK: call swiftcc void @b()
|
|
// CHECK: br label %[[END]]
|
|
y_dest:
|
|
%b = function_ref @b : $@convention(thin) () -> ()
|
|
apply %b() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK: [[Z_DEST]]:
|
|
// CHECK: call swiftcc void @c()
|
|
// CHECK: br label %[[END]]
|
|
z_dest:
|
|
%c = function_ref @c : $@convention(thin) () -> ()
|
|
apply %c() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK: [[W_DEST]]:
|
|
// CHECK: call swiftcc void @a()
|
|
// CHECK: br label %[[END:[0-9]+]]
|
|
w_dest:
|
|
%d = function_ref @a : $@convention(thin) () -> ()
|
|
apply %d() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK: [[V_DEST]]:
|
|
// CHECK: call swiftcc void @b()
|
|
// CHECK: br label %[[END]]
|
|
v_dest:
|
|
%e = function_ref @b : $@convention(thin) () -> ()
|
|
apply %e() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK: [[U_DEST]]:
|
|
// CHECK: call swiftcc void @c()
|
|
// CHECK: br label %[[END]]
|
|
u_dest:
|
|
%f = function_ref @c : $@convention(thin) () -> ()
|
|
apply %f() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK: [[END]]:
|
|
// CHECK: ret void
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_no_xi_switch_arg([[WORD]] %0, i8 %1) {{.*}} {
|
|
sil @single_payload_no_xi_switch_arg : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
|
// CHECK: entry:
|
|
entry(%u : $SinglePayloadNoXI2):
|
|
// CHECK: %2 = icmp eq i8 %1, 1
|
|
// CHECK: br i1 %2, label %[[TAGS:[0-9]+]], label %[[X_PREDEST:[0-9]+]]
|
|
// CHECK: [[TAGS]]:
|
|
// CHECK: switch [[WORD]] %0, label %[[DFLT:[0-9]+]] [
|
|
// CHECK: [[WORD]] 0, label %[[Y_DEST:[0-9]+]]
|
|
// CHECK: [[WORD]] 1, label %[[Z_DEST:[0-9]+]]
|
|
// CHECK: [[WORD]] 2, label %[[SPLITEDGE:[0-9]+]]
|
|
// CHECK: [[WORD]] 3, label %[[SPLITEDGE]]
|
|
// CHECK: [[WORD]] 4, label %[[SPLITEDGE]]
|
|
// CHECK: ]
|
|
// CHECK: [[DFLT]]:
|
|
// CHECK: unreachable
|
|
switch_enum %u : $SinglePayloadNoXI2, case #SinglePayloadNoXI2.x!enumelt: x_dest, case #SinglePayloadNoXI2.y!enumelt: y_dest, case #SinglePayloadNoXI2.z!enumelt: z_dest, default default_dest
|
|
|
|
// CHECK: [[X_PREDEST]]:
|
|
// CHECK: br label %[[X_DEST:[0-9]+]]
|
|
// CHECK: [[X_DEST]]:
|
|
// CHECK: {{%.*}} = phi [[WORD]] [ %0, %[[X_PREDEST]] ]
|
|
x_dest(%u2 : $Builtin.Word):
|
|
// CHECK: call swiftcc void @a()
|
|
// CHECK: br label %[[END]]
|
|
%a = function_ref @a : $@convention(thin) () -> ()
|
|
apply %a() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK: [[Y_DEST]]:
|
|
y_dest:
|
|
// CHECK: call swiftcc void @b()
|
|
// CHECK: br label %[[END]]
|
|
%b = function_ref @b : $@convention(thin) () -> ()
|
|
apply %b() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK: [[Z_DEST]]:
|
|
z_dest:
|
|
// CHECK: call swiftcc void @c()
|
|
// CHECK: br label %[[END]]
|
|
%c = function_ref @c : $@convention(thin) () -> ()
|
|
apply %c() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK: [[SPLITEDGE]]:
|
|
// CHECK: br label %[[END:[0-9]+]]
|
|
default_dest:
|
|
br end
|
|
|
|
// CHECK: [[END]]:
|
|
// CHECK: ret void
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc { [[WORD]], i8 } @single_payload_no_xi_inject_x([[WORD]] %0) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: [[A:%.*]] = insertvalue { [[WORD]], i8 } undef, [[WORD]] %0, 0
|
|
// CHECK: [[B:%.*]] = insertvalue { [[WORD]], i8 } [[A]], i8 0, 1
|
|
// CHECK: ret { [[WORD]], i8 } [[B]]
|
|
// CHECK: }
|
|
sil @single_payload_no_xi_inject_x : $(Builtin.Word) -> SinglePayloadNoXI2 {
|
|
entry(%0 : $Builtin.Word):
|
|
%u = enum $SinglePayloadNoXI2, #SinglePayloadNoXI2.x!enumelt, %0 : $Builtin.Word
|
|
return %u : $SinglePayloadNoXI2
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_no_xi_inject_x_indirect([[WORD]] %0, ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %1) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: store [[WORD]] %0, ptr %1
|
|
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %T4enum18SinglePayloadNoXI2O, ptr %1, i32 0, i32 1
|
|
// CHECK: store i8 0, ptr [[T0]]
|
|
// CHECK: ret void
|
|
// CHECK: }
|
|
sil @single_payload_no_xi_inject_x_indirect : $(Builtin.Word, @inout SinglePayloadNoXI2) -> () {
|
|
entry(%0 : $Builtin.Word, %1 : $*SinglePayloadNoXI2):
|
|
%a = init_enum_data_addr %1 : $*SinglePayloadNoXI2, #SinglePayloadNoXI2.x!enumelt
|
|
store %0 to %a : $*Builtin.Word
|
|
inject_enum_addr %1 : $*SinglePayloadNoXI2, #SinglePayloadNoXI2.x!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc { [[WORD]], i8 } @single_payload_no_xi_inject_y() {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: ret { [[WORD]], i8 } { [[WORD]] 0, i8 1 }
|
|
// CHECK: }
|
|
sil @single_payload_no_xi_inject_y : $() -> SinglePayloadNoXI2 {
|
|
entry:
|
|
%u = enum $SinglePayloadNoXI2, #SinglePayloadNoXI2.y!enumelt
|
|
return %u : $SinglePayloadNoXI2
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_no_xi_inject_y_indirect(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: store [[WORD]] 0, ptr %0
|
|
// CHECK: [[T0:%.*]] = getelementptr inbounds{{.*}} %T4enum18SinglePayloadNoXI2O, ptr %0, i32 0, i32 1
|
|
// CHECK: store i8 1, ptr [[T0]]
|
|
// CHECK: ret void
|
|
// CHECK: }
|
|
sil @single_payload_no_xi_inject_y_indirect : $(@inout SinglePayloadNoXI2) -> () {
|
|
entry(%0 : $*SinglePayloadNoXI2):
|
|
inject_enum_addr %0 : $*SinglePayloadNoXI2, #SinglePayloadNoXI2.y!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc { [[WORD]], i8 } @single_payload_no_xi_inject_z() {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: ret { [[WORD]], i8 } { [[WORD]] 1, i8 1 }
|
|
// CHECK: }
|
|
sil @single_payload_no_xi_inject_z : $() -> SinglePayloadNoXI2 {
|
|
entry:
|
|
%u = enum $SinglePayloadNoXI2, #SinglePayloadNoXI2.z!enumelt
|
|
return %u : $SinglePayloadNoXI2
|
|
}
|
|
|
|
|
|
// -- Test packing and unpacking aggregates.
|
|
|
|
enum AggregateSinglePayload {
|
|
case x(Builtin.Word, Builtin.Word)
|
|
case y
|
|
case z
|
|
}
|
|
|
|
sil @int21_sink : $@convention(thin) (Builtin.Int21) -> ()
|
|
sil @int64_sink : $@convention(thin) (Builtin.Word) -> ()
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @aggregate_single_payload_unpack
|
|
// CHECK: ([[WORD]] %0, [[WORD]] %1, i8 %2) {{.*}} {
|
|
sil @aggregate_single_payload_unpack : $@convention(thin) (AggregateSinglePayload) -> () {
|
|
entry(%u : $AggregateSinglePayload):
|
|
switch_enum %u : $AggregateSinglePayload, case #AggregateSinglePayload.x!enumelt: x_dest, default default_dest
|
|
|
|
// CHECK: [[FIRST:%.*]] = phi [[WORD]] [ %0
|
|
// CHECK: [[SECOND:%.*]] = phi [[WORD]] [ %1
|
|
// CHECK: call swiftcc void @int64_sink([[WORD]] [[FIRST]])
|
|
// CHECK: call swiftcc void @int64_sink([[WORD]] [[SECOND]])
|
|
x_dest(%v : $(Builtin.Word, Builtin.Word)):
|
|
%f = function_ref @int64_sink : $@convention(thin) (Builtin.Word) -> ()
|
|
%a = tuple_extract %v : $(Builtin.Word, Builtin.Word), 0
|
|
%b = tuple_extract %v : $(Builtin.Word, Builtin.Word), 1
|
|
%c = apply %f(%a) : $@convention(thin) (Builtin.Word) -> ()
|
|
%d = apply %f(%b) : $@convention(thin) (Builtin.Word) -> ()
|
|
br end
|
|
|
|
default_dest:
|
|
br end
|
|
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc { [[WORD]], [[WORD]] } @aggregate_single_payload_unsafe_unpack([[WORD]] %0, [[WORD]] %1, i8 %2) {{.*}} {
|
|
// CHECK: [[A:%.*]] = insertvalue { [[WORD]], [[WORD]] } undef, [[WORD]] %0, 0
|
|
// CHECK: [[B:%.*]] = insertvalue { [[WORD]], [[WORD]] } [[A]], [[WORD]] %1, 1
|
|
// CHECK: ret { [[WORD]], [[WORD]] } [[B]]
|
|
sil @aggregate_single_payload_unsafe_unpack : $@convention(thin) (AggregateSinglePayload) -> (Builtin.Word, Builtin.Word) {
|
|
entry(%u : $AggregateSinglePayload):
|
|
%x = unchecked_enum_data %u : $AggregateSinglePayload, #AggregateSinglePayload.x!enumelt
|
|
return %x : $(Builtin.Word, Builtin.Word)
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc { [[WORD]], [[WORD]], i8 } @aggregate_single_payload_inject([[WORD]] %0, [[WORD]] %1) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: [[RES_0:%.*]] = insertvalue { [[WORD]], [[WORD]], i8 } undef, [[WORD]] %0, 0
|
|
// CHECK: [[RES_1:%.*]] = insertvalue { [[WORD]], [[WORD]], i8 } [[RES_0]], [[WORD]] %1, 1
|
|
// CHECK: [[RES:%.*]] = insertvalue { [[WORD]], [[WORD]], i8 } [[RES_1]], i8 0, 2
|
|
// CHECK: ret { [[WORD]], [[WORD]], i8 } [[RES]]
|
|
// CHECK: }
|
|
sil @aggregate_single_payload_inject : $(Builtin.Word, Builtin.Word) -> AggregateSinglePayload {
|
|
entry(%0 : $Builtin.Word, %1 : $Builtin.Word):
|
|
%t = tuple (%0 : $Builtin.Word, %1 : $Builtin.Word)
|
|
%u = enum $AggregateSinglePayload, #AggregateSinglePayload.x!enumelt, %t : $(Builtin.Word, Builtin.Word)
|
|
return %u : $AggregateSinglePayload
|
|
}
|
|
|
|
struct CharLike { var value : Builtin.Int21 }
|
|
struct IntLike { var value : Builtin.Word }
|
|
struct RangeLike { var from, to : Builtin.Word }
|
|
|
|
enum AggregateSinglePayload2 {
|
|
case x(CharLike, IntLike, RangeLike)
|
|
case y
|
|
case z
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @aggregate_single_payload_unpack_2([[WORD]] %0, [[WORD]] %1, [[WORD]] %2, [[WORD]] %3) {{.*}} {
|
|
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc void @aggregate_single_payload_unpack_2(ptr noalias dereferenceable(16) %0) {{.*}} {
|
|
sil @aggregate_single_payload_unpack_2 : $@convention(thin) (AggregateSinglePayload2) -> () {
|
|
entry(%u : $AggregateSinglePayload2):
|
|
switch_enum %u : $AggregateSinglePayload2, case #AggregateSinglePayload2.x!enumelt: x_dest, default default_dest
|
|
|
|
// CHECK-64: [[TRUNC:%.*]] = trunc [[WORD]] %0 to i21
|
|
// CHECK-64: phi i21 [ [[TRUNC]]
|
|
// CHECK-64: phi [[WORD]] [ %1
|
|
// CHECK-64: phi [[WORD]] [ %2
|
|
// CHECK-64: phi [[WORD]] [ %3
|
|
x_dest(%v : $(CharLike, IntLike, RangeLike)):
|
|
br end
|
|
|
|
default_dest:
|
|
br end
|
|
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { [[WORD]], [[WORD]], [[WORD]], [[WORD]] } @aggregate_single_payload_2_inject(i32 %0, [[WORD]] %1, [[WORD]] %2, [[WORD]] %3) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: %4 = trunc i32 %0 to i21
|
|
// CHECK-64: %5 = zext i21 %4 to [[WORD]]
|
|
// CHECK-64: %6 = insertvalue { [[WORD]], [[WORD]], [[WORD]], [[WORD]] } undef, [[WORD]] %5, 0
|
|
// CHECK-64: %7 = insertvalue { [[WORD]], [[WORD]], [[WORD]], [[WORD]] } %6, [[WORD]] %1, 1
|
|
// CHECK-64: %8 = insertvalue { [[WORD]], [[WORD]], [[WORD]], [[WORD]] } %7, [[WORD]] %2, 2
|
|
// CHECK-64: %9 = insertvalue { [[WORD]], [[WORD]], [[WORD]], [[WORD]] } %8, [[WORD]] %3, 3
|
|
// CHECK-64: ret { [[WORD]], [[WORD]], [[WORD]], [[WORD]] } %9
|
|
|
|
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc void @aggregate_single_payload_2_inject(ptr noalias sret({{.*}}) %0, i32 %1, i32 %2, i32 %3, i32 %4) {{.*}} {
|
|
// CHECK-32: [[TRUNC:%.*]] = trunc i32 %1 to i21
|
|
// CHECK-32: [[ZEXT:%.*]] = zext i21 [[TRUNC]] to i32
|
|
// CHECK-32: [[GEP:%.*]] = getelementptr inbounds {{.*}} %0, i32 0, i32 0
|
|
// CHECK-32: store i32 [[ZEXT]], ptr [[GEP]]
|
|
// CHECK-32: store i32 %2, ptr
|
|
// CHECK-32: store i32 %3, ptr
|
|
// CHECK-32: store i32 %4, ptr
|
|
// CHECK-32: ret void
|
|
sil @aggregate_single_payload_2_inject : $(CharLike, IntLike, RangeLike) -> AggregateSinglePayload2 {
|
|
entry(%0 : $CharLike, %1 : $IntLike, %2 : $RangeLike):
|
|
%t = tuple (%0 : $CharLike, %1 : $IntLike, %2 : $RangeLike)
|
|
%u = enum $AggregateSinglePayload2, #AggregateSinglePayload2.x!enumelt, %t : $(CharLike, IntLike, RangeLike)
|
|
return %u : $AggregateSinglePayload2
|
|
}
|
|
|
|
enum AggregateSinglePayload3 {
|
|
case x(Builtin.Int21, Builtin.Word)
|
|
case y
|
|
case z
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @aggregate_single_payload_unpack_3([[WORD]] %0, [[WORD]] %1) {{.*}} {
|
|
sil @aggregate_single_payload_unpack_3 : $@convention(thin) (AggregateSinglePayload3) -> () {
|
|
entry(%u : $AggregateSinglePayload3):
|
|
switch_enum %u : $AggregateSinglePayload3, case #AggregateSinglePayload3.x!enumelt: x_dest, default default_dest
|
|
|
|
// CHECK: [[TRUNC:%.*]] = trunc [[WORD]] %0 to i21
|
|
// CHECK: [[FIRST:%.*]] = phi i21 [ [[TRUNC]]
|
|
// CHECK: [[SECOND:%.*]] = phi [[WORD]] [ %1
|
|
// CHECK: [[ZEXT:%.*]] = zext i21 [[FIRST]] to i32
|
|
// CHECK: call swiftcc void @int21_sink(i32 [[ZEXT]])
|
|
// CHECK: call swiftcc void @int64_sink([[WORD]] [[SECOND]])
|
|
x_dest(%v : $(Builtin.Int21, Builtin.Word)):
|
|
%f = function_ref @int21_sink : $@convention(thin) (Builtin.Int21) -> ()
|
|
%g = function_ref @int64_sink : $@convention(thin) (Builtin.Word) -> ()
|
|
%a = tuple_extract %v : $(Builtin.Int21, Builtin.Word), 0
|
|
%b = tuple_extract %v : $(Builtin.Int21, Builtin.Word), 1
|
|
%c = apply %f(%a) : $@convention(thin) (Builtin.Int21) -> ()
|
|
%d = apply %g(%b) : $@convention(thin) (Builtin.Word) -> ()
|
|
br end
|
|
|
|
default_dest:
|
|
br end
|
|
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc { [[WORD]], [[WORD]] } @aggregate_single_payload_inject_x3(i32 %0, [[WORD]] %1) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: [[TRUNC:%.*]] = trunc i32 %0 to i21
|
|
// CHECK: [[ZEXT:%.*]] = zext i21 [[TRUNC]] to [[WORD]]
|
|
// CHECK: [[A:%.*]] = insertvalue { [[WORD]], [[WORD]] } undef, [[WORD]] [[ZEXT]], 0
|
|
// CHECK: [[B:%.*]] = insertvalue { [[WORD]], [[WORD]] } [[A]], [[WORD]] %1, 1
|
|
// CHECK: ret { [[WORD]], [[WORD]] } [[B]]
|
|
// CHECK: }
|
|
sil @aggregate_single_payload_inject_x3 : $(Builtin.Int21, Builtin.Word) -> AggregateSinglePayload3 {
|
|
entry(%0 : $Builtin.Int21, %1 : $Builtin.Word):
|
|
%t = tuple (%0 : $Builtin.Int21, %1 : $Builtin.Word)
|
|
%u = enum $AggregateSinglePayload3, #AggregateSinglePayload3.x!enumelt, %t : $(Builtin.Int21, Builtin.Word)
|
|
return %u : $AggregateSinglePayload3
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc { [[WORD]], [[WORD]] } @aggregate_single_payload_inject_y3() {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: ret { [[WORD]], [[WORD]] } { [[WORD]] 2097152, [[WORD]] 0 }
|
|
// CHECK: }
|
|
// 2097152 == 0x200000
|
|
sil @aggregate_single_payload_inject_y3 : $() -> AggregateSinglePayload3 {
|
|
entry:
|
|
%u = enum $AggregateSinglePayload3, #AggregateSinglePayload3.y!enumelt
|
|
return %u : $AggregateSinglePayload3
|
|
}
|
|
|
|
enum SinglePayloadSpareBit {
|
|
case x(Builtin.Int63)
|
|
case y
|
|
case z
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_spare_bit_switch(i64 %0) {{.*}} {
|
|
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_spare_bit_switch(i32 %0, i32 %1) {{.*}} {
|
|
sil @single_payload_spare_bit_switch : $@convention(thin) (SinglePayloadSpareBit) -> () {
|
|
// CHECK: entry:
|
|
entry(%u : $SinglePayloadSpareBit):
|
|
// CHECK: switch i64 %{{[0-9]+}}, label %[[X_DEST:[0-9]+]] [
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK: i64 -9223372036854775808, label %[[Y_DEST:[0-9]+]]
|
|
// -- 0x8000_0000_0000_0001
|
|
// CHECK: i64 -9223372036854775807, label %[[Z_DEST:[0-9]+]]
|
|
// CHECK: ]
|
|
switch_enum %u : $SinglePayloadSpareBit, case #SinglePayloadSpareBit.x!enumelt: x_dest, case #SinglePayloadSpareBit.y!enumelt: y_dest, case #SinglePayloadSpareBit.z!enumelt: z_dest
|
|
|
|
// CHECK: [[X_DEST]]:
|
|
x_dest:
|
|
// CHECK: call swiftcc void @a()
|
|
%a = function_ref @a : $@convention(thin) () -> ()
|
|
apply %a() : $@convention(thin) () -> ()
|
|
// CHECK: br label %[[END:[0-9]+]]
|
|
br end
|
|
|
|
// CHECK: [[Y_DEST]]:
|
|
y_dest:
|
|
// CHECK: call swiftcc void @b()
|
|
%b = function_ref @b : $@convention(thin) () -> ()
|
|
apply %b() : $@convention(thin) () -> ()
|
|
// CHECK: br label %[[END]]
|
|
br end
|
|
|
|
// CHECK: [[Z_DEST]]:
|
|
z_dest:
|
|
// CHECK: call swiftcc void @c()
|
|
%c = function_ref @c : $@convention(thin) () -> ()
|
|
apply %c() : $@convention(thin) () -> ()
|
|
// CHECK: br label %[[END]]
|
|
br end
|
|
|
|
// CHECK: [[END]]:
|
|
end:
|
|
// CHECK: ret void
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_spare_bit_switch_arg(i64 %0) {{.*}} {
|
|
sil @single_payload_spare_bit_switch_arg : $@convention(thin) (SinglePayloadSpareBit) -> () {
|
|
// CHECK: entry:
|
|
entry(%u : $SinglePayloadSpareBit):
|
|
// CHECK-64: switch i64 %0, label %[[X_PREDEST:[0-9]+]] [
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK-64: i64 -9223372036854775808, label %[[Y_DEST:[0-9]+]]
|
|
// -- 0x8000_0000_0000_0001
|
|
// CHECK-64: i64 -9223372036854775807, label %[[Z_DEST:[0-9]+]]
|
|
// CHECK-64: ]
|
|
switch_enum %u : $SinglePayloadSpareBit, case #SinglePayloadSpareBit.x!enumelt: x_dest, case #SinglePayloadSpareBit.y!enumelt: y_dest, case #SinglePayloadSpareBit.z!enumelt: z_dest
|
|
|
|
// CHECK-64: [[X_PREDEST]]:
|
|
// CHECK-64: [[TRUNC_PAYLOAD:%.*]] = trunc i64 %0 to i63
|
|
// CHECK-64: br label %[[X_DEST:[0-9]+]]
|
|
// CHECK-64: [[X_DEST]]:
|
|
// CHECK-64: {{%.*}} = phi i63 [ [[TRUNC_PAYLOAD]], %[[X_PREDEST]] ]
|
|
x_dest(%u2 : $Builtin.Int63):
|
|
// CHECK-64: call swiftcc void @a()
|
|
%a = function_ref @a : $@convention(thin) () -> ()
|
|
apply %a() : $@convention(thin) () -> ()
|
|
// CHECK-64: br label %[[END:[0-9]+]]
|
|
br end
|
|
|
|
// CHECK-64: [[Y_DEST]]:
|
|
y_dest:
|
|
// CHECK-64: call swiftcc void @b()
|
|
%b = function_ref @b : $@convention(thin) () -> ()
|
|
apply %b() : $@convention(thin) () -> ()
|
|
// CHECK-64: br label %[[END]]
|
|
br end
|
|
|
|
// CHECK-64: [[Z_DEST]]:
|
|
z_dest:
|
|
// CHECK-64: call swiftcc void @c()
|
|
%c = function_ref @c : $@convention(thin) () -> ()
|
|
apply %c() : $@convention(thin) () -> ()
|
|
// CHECK-64: br label %[[END]]
|
|
br end
|
|
|
|
// CHECK-64: [[END]]:
|
|
end:
|
|
// CHECK-64: ret void
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
sil @single_payload_spare_bit_switch_indirect : $@convention(thin) (@inout SinglePayloadSpareBit) -> () {
|
|
entry(%u : $*SinglePayloadSpareBit):
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, ptr %0
|
|
// CHECK-64: switch i64 [[PAYLOAD]], label %[[DFLT:[0-9]+]] [
|
|
switch_enum_addr %u : $*SinglePayloadSpareBit, case #SinglePayloadSpareBit.x!enumelt: x_dest, case #SinglePayloadSpareBit.y!enumelt: y_dest, case #SinglePayloadSpareBit.z!enumelt: z_dest
|
|
|
|
// CHECK-64: [[DFLT]]:
|
|
x_dest:
|
|
%u2 = unchecked_take_enum_data_addr %u : $*SinglePayloadSpareBit, #SinglePayloadSpareBit.x!enumelt
|
|
%a = function_ref @a : $@convention(thin) () -> ()
|
|
apply %a() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
y_dest:
|
|
br end
|
|
|
|
z_dest:
|
|
br end
|
|
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i64 @single_payload_spare_bit_inject_x(i64 %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[T:%.*]] = trunc i64 %0 to i63
|
|
// CHECK-64: [[A:%.*]] = zext i63 [[T]] to i64
|
|
// CHECK-64: ret i64 [[A]]
|
|
// CHECK-64: }
|
|
sil @single_payload_spare_bit_inject_x : $(Builtin.Int63) -> SinglePayloadSpareBit {
|
|
entry(%0 : $Builtin.Int63):
|
|
%u = enum $SinglePayloadSpareBit, #SinglePayloadSpareBit.x!enumelt, %0 : $Builtin.Int63
|
|
return %u : $SinglePayloadSpareBit
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_spare_bit_inject_x_indirect(i64 %0, ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %1) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[T:%.*]] = trunc i64 %0 to i63
|
|
// CHECK-64: [[BYTE:%.*]] = zext i63 [[T]] to i64
|
|
// CHECK-64: store i64 [[BYTE]], ptr %1
|
|
// CHECK-64: ret void
|
|
// CHECK-64: }
|
|
sil @single_payload_spare_bit_inject_x_indirect : $(Builtin.Int63, @inout SinglePayloadSpareBit) -> () {
|
|
entry(%0 : $Builtin.Int63, %1 : $*SinglePayloadSpareBit):
|
|
%a = init_enum_data_addr %1 : $*SinglePayloadSpareBit, #SinglePayloadSpareBit.x!enumelt
|
|
store %0 to %a : $*Builtin.Int63
|
|
inject_enum_addr %1 : $*SinglePayloadSpareBit, #SinglePayloadSpareBit.x!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i64 @single_payload_spare_bit_inject_y() {{.*}} {
|
|
// CHECK-64: entry:
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK-64: ret i64 -9223372036854775808
|
|
// CHECK-64: }
|
|
sil @single_payload_spare_bit_inject_y : $() -> SinglePayloadSpareBit {
|
|
entry:
|
|
%u = enum $SinglePayloadSpareBit, #SinglePayloadSpareBit.y!enumelt
|
|
return %u : $SinglePayloadSpareBit
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_spare_bit_inject_y_indirect(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK-64: store i64 -9223372036854775808, ptr %0
|
|
// CHECK-64: ret void
|
|
// CHECK-64: }
|
|
sil @single_payload_spare_bit_inject_y_indirect : $(@inout SinglePayloadSpareBit) -> () {
|
|
entry(%0 : $*SinglePayloadSpareBit):
|
|
inject_enum_addr %0 : $*SinglePayloadSpareBit, #SinglePayloadSpareBit.y!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i64 @single_payload_spare_bit_inject_z() {{.*}} {
|
|
// CHECK-64: entry:
|
|
// 0x8000_0000_0000_0001
|
|
// CHECK-64: ret i64 -9223372036854775807
|
|
// CHECK-64: }
|
|
sil @single_payload_spare_bit_inject_z : $() -> SinglePayloadSpareBit {
|
|
entry:
|
|
%u = enum $SinglePayloadSpareBit, #SinglePayloadSpareBit.z!enumelt
|
|
return %u : $SinglePayloadSpareBit
|
|
}
|
|
|
|
enum SinglePayloadNested {
|
|
case a(NoPayloads)
|
|
case b
|
|
case c
|
|
case d
|
|
}
|
|
|
|
enum SinglePayloadNestedNested {
|
|
case e(SinglePayloadNested)
|
|
case f
|
|
case g
|
|
case h
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_nested_switch(i8 %0) {{.*}} {
|
|
sil @single_payload_nested_switch : $(SinglePayloadNestedNested) -> () {
|
|
entry(%u : $SinglePayloadNestedNested):
|
|
// CHECK: switch i8 {{%.*}}, label {{%.*}} [
|
|
// CHECK: i8 6, label {{%.*}}
|
|
// CHECK: i8 7, label {{%.*}}
|
|
// CHECK: i8 8, label {{%.*}}
|
|
// CHECK: ]
|
|
switch_enum %u : $SinglePayloadNestedNested, case #SinglePayloadNestedNested.e!enumelt: e_dest, case #SinglePayloadNestedNested.f!enumelt: f_dest, case #SinglePayloadNestedNested.g!enumelt: g_dest, case #SinglePayloadNestedNested.h!enumelt: h_dest
|
|
|
|
e_dest(%v : $SinglePayloadNested):
|
|
// CHECK: switch i8 {{%.*}}, label {{%.*}} [
|
|
// CHECK: i8 3, label {{%.*}}
|
|
// CHECK: i8 4, label {{%.*}}
|
|
// CHECK: i8 5, label {{%.*}}
|
|
// CHECK: ]
|
|
switch_enum %v : $SinglePayloadNested, case #SinglePayloadNested.a!enumelt: a_dest, case #SinglePayloadNested.b!enumelt: b_dest, case #SinglePayloadNested.c!enumelt: c_dest, case #SinglePayloadNested.d!enumelt: d_dest
|
|
f_dest:
|
|
br end
|
|
g_dest:
|
|
br end
|
|
h_dest:
|
|
br end
|
|
|
|
a_dest(%w : $NoPayloads):
|
|
// CHECK: switch i8 {{%.*}}, label {{%.*}} [
|
|
// CHECK: i8 0, label {{%.*}}
|
|
// CHECK: i8 1, label {{%.*}}
|
|
// CHECK: i8 2, label {{%.*}}
|
|
// CHECK: ]
|
|
switch_enum %w : $NoPayloads, case #NoPayloads.x!enumelt: x_dest, case #NoPayloads.y!enumelt: y_dest, case #NoPayloads.z!enumelt: z_dest
|
|
b_dest:
|
|
br end
|
|
c_dest:
|
|
br end
|
|
d_dest:
|
|
br end
|
|
|
|
x_dest:
|
|
br end
|
|
y_dest:
|
|
br end
|
|
z_dest:
|
|
br end
|
|
|
|
end:
|
|
%x = tuple()
|
|
return %x : $()
|
|
}
|
|
|
|
class C {}
|
|
sil_vtable C {}
|
|
|
|
sil @$s4enum1CCfD : $@convention(method) (C) -> ()
|
|
|
|
enum SinglePayloadClass {
|
|
case x(C)
|
|
case y
|
|
case z
|
|
case w
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_class_switch(i64 %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: switch i64 %0, label %[[DFLT:[0-9]+]] [
|
|
// CHECK-64: i64 0, label {{%.*}}
|
|
// CHECK-objc-64-simulator-false: i64 2, label {{%.*}}
|
|
// CHECK-objc-64-simulator-false: i64 4, label {{%.*}}
|
|
// CHECK-objc-64-simulator-true: i64 1, label {{%.*}}
|
|
// CHECK-objc-64-simulator-true: i64 2, label {{%.*}}
|
|
// CHECK-native-64: i64 1, label {{%.*}}
|
|
// CHECK-native-64: i64 2, label {{%.*}}
|
|
// CHECK-64: ]
|
|
// CHECK-64: [[DFLT]]:
|
|
// CHECK-64: inttoptr [[WORD]] %0 to ptr
|
|
|
|
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_class_switch(i32 %0) {{.*}} {
|
|
// CHECK-32: entry:
|
|
// CHECK-32: switch i32 %0, label %[[DFLT:[0-9]+]] [
|
|
// CHECK-32: i32 0, label {{%.*}}
|
|
// CHECK-32: i32 1, label {{%.*}}
|
|
// CHECK-32: i32 2, label {{%.*}}
|
|
// CHECK-32: ]
|
|
// CHECK-32: [[DFLT]]:
|
|
// CHECK-32: inttoptr [[WORD]] %0 to ptr
|
|
|
|
sil @single_payload_class_switch : $(SinglePayloadClass) -> () {
|
|
entry(%c : $SinglePayloadClass):
|
|
switch_enum %c : $SinglePayloadClass, case #SinglePayloadClass.x!enumelt: x_dest, case #SinglePayloadClass.y!enumelt: y_dest, case #SinglePayloadClass.z!enumelt: z_dest, case #SinglePayloadClass.w!enumelt: w_dest
|
|
|
|
x_dest(%d : $C):
|
|
br end
|
|
y_dest:
|
|
br end
|
|
z_dest:
|
|
br end
|
|
w_dest:
|
|
br end
|
|
|
|
end:
|
|
return undef : $()
|
|
}
|
|
|
|
protocol PC : class {}
|
|
|
|
enum SinglePayloadClassProtocol {
|
|
case x(PC)
|
|
case y, z, w
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_class_protocol_switch(i64 %0, i64 %1) {{.*}} {
|
|
// CHECK-64: switch i64 %0, label {{%.*}} [
|
|
// CHECK-64: i64 0, label {{%.*}}
|
|
// CHECK-objc-64-simulator-false: i64 2, label {{%.*}}
|
|
// CHECK-objc-64-simulator-false: i64 4, label {{%.*}}
|
|
// CHECK-objc-64-simulator-true: i64 1, label {{%.*}}
|
|
// CHECK-objc-64-simulator-true: i64 2, label {{%.*}}
|
|
// CHECK-native-64: i64 1, label {{%.*}}
|
|
// CHECK-native-64: i64 2, label {{%.*}}
|
|
// CHECK-64: ]
|
|
|
|
// CHECK-objc-64: inttoptr i64 %0 to ptr
|
|
// CHECK-native-64: inttoptr i64 %0 to ptr
|
|
// CHECK-64: inttoptr i64 %1 to ptr
|
|
|
|
// CHECK-32: define{{( dllexport)?}}{{( protected)?}} swiftcc void @single_payload_class_protocol_switch(i32 %0, i32 %1) {{.*}} {
|
|
// CHECK-32: switch i32 %0, label {{%.*}} [
|
|
// CHECK-32: i32 0, label {{%.*}}
|
|
// CHECK-32: i32 1, label {{%.*}}
|
|
// CHECK-32: i32 2, label {{%.*}}
|
|
// CHECK-32: ]
|
|
|
|
// CHECK-objc-32: inttoptr i32 %0 to ptr
|
|
// CHECK-native-32: inttoptr i32 %0 to ptr
|
|
// CHECK-32: inttoptr i32 %1 to ptr
|
|
|
|
sil @single_payload_class_protocol_switch : $(SinglePayloadClassProtocol) -> () {
|
|
entry(%c : $SinglePayloadClassProtocol):
|
|
switch_enum %c : $SinglePayloadClassProtocol, case #SinglePayloadClassProtocol.x!enumelt: x_dest, case #SinglePayloadClassProtocol.y!enumelt: y_dest, case #SinglePayloadClassProtocol.z!enumelt: z_dest, case #SinglePayloadClassProtocol.w!enumelt: w_dest
|
|
|
|
x_dest(%d : $PC):
|
|
br end
|
|
y_dest:
|
|
br end
|
|
z_dest:
|
|
br end
|
|
w_dest:
|
|
br end
|
|
|
|
end:
|
|
return undef : $()
|
|
}
|
|
|
|
enum DynamicSinglePayload<T> {
|
|
case x(T)
|
|
case y
|
|
case z
|
|
case w
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_switch(ptr noalias %0, ptr %T) {{.*}} {
|
|
// CHECK: [[TMP2:%.*]] = getelementptr inbounds ptr, ptr %T, i{{.*}} -1
|
|
// CHECK: [[VWT:%.*]] = load ptr, ptr [[TMP2]]
|
|
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds ptr, ptr [[VWT]], i32 6
|
|
// CHECK: [[WITNESS:%.*]] = load ptr, ptr [[ENUMADDR]]
|
|
// CHECK: [[CASE_INDEX:%.*]] = call i32 [[WITNESS]](ptr noalias %0, i32 3, ptr %T)
|
|
// CHECK: switch i32 [[CASE_INDEX]], label {{%.*}} [
|
|
// CHECK: i32 0, label {{%.*}}
|
|
// CHECK: i32 3, label {{%.*}}
|
|
// CHECK: ]
|
|
sil @dynamic_single_payload_switch : $<T> (@in DynamicSinglePayload<T>) -> () {
|
|
entry(%u : $*DynamicSinglePayload<T>):
|
|
switch_enum_addr %u : $*DynamicSinglePayload<T>, case #DynamicSinglePayload.x!enumelt: x_dest, case #DynamicSinglePayload.w!enumelt: w_dest, default default_dest
|
|
|
|
x_dest:
|
|
br end
|
|
|
|
w_dest:
|
|
br end
|
|
|
|
default_dest:
|
|
br end
|
|
|
|
end:
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_inject_x(ptr noalias sret({{.*}}) %0, ptr noalias %1, ptr %T) {{.*}} {
|
|
// CHECK: [[TMP2:%.*]] = getelementptr inbounds ptr, ptr %T, i{{.*}} -1
|
|
// CHECK: [[VWT:%.*]] = load ptr, ptr [[TMP2]]
|
|
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds ptr, ptr [[VWT]], i32 7
|
|
// CHECK: [[WITNESS:%.*]] = load ptr, ptr [[ENUMADDR]]
|
|
// CHECK: call void [[WITNESS]](ptr noalias %0, i32 0, i32 3, ptr %T)
|
|
sil @dynamic_single_payload_inject_x : $<T> (@in T) -> @out DynamicSinglePayload<T> {
|
|
entry(%r : $*DynamicSinglePayload<T>, %t : $*T):
|
|
inject_enum_addr %r : $*DynamicSinglePayload<T>, #DynamicSinglePayload.x!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_inject_y(ptr noalias sret({{.*}}) %0, ptr %T) {{.*}} {
|
|
// CHECK: [[TMP2:%.*]] = getelementptr inbounds ptr, ptr %T, i{{.*}} -1
|
|
// CHECK: [[VWT:%.*]] = load ptr, ptr [[TMP2]]
|
|
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds ptr, ptr [[VWT]], i32 7
|
|
// CHECK: [[WITNESS:%.*]] = load ptr, ptr [[ENUMADDR]]
|
|
// CHECK: call void [[WITNESS]](ptr noalias %0, i32 1, i32 3, ptr %T)
|
|
sil @dynamic_single_payload_inject_y : $<T> () -> @out DynamicSinglePayload<T> {
|
|
entry(%r : $*DynamicSinglePayload<T>):
|
|
inject_enum_addr %r : $*DynamicSinglePayload<T>, #DynamicSinglePayload.y!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// -- Ensure instantiations of single-payload types with empty payloads work.
|
|
// Bug discovered by Greg Parker.
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_empty_payload_switch(i8 %0) {{.*}} {
|
|
// CHECK: switch i8 {{%.*}}, label {{.*}} [
|
|
// CHECK: i8 0, label {{.*}}
|
|
// CHECK: i8 1, label {{.*}}
|
|
// CHECK: i8 2, label {{.*}}
|
|
// CHECK: i8 3, label {{.*}}
|
|
// CHECK: ]
|
|
sil @dynamic_single_payload_empty_payload_switch : $(DynamicSinglePayload<()>) -> () {
|
|
entry(%x : $DynamicSinglePayload<()>):
|
|
switch_enum %x : $DynamicSinglePayload<()>, case #DynamicSinglePayload.x!enumelt: x_case, case #DynamicSinglePayload.y!enumelt: y_case, case #DynamicSinglePayload.z!enumelt: z_case, default default_case
|
|
|
|
x_case(%a : $()):
|
|
br end(%a : $())
|
|
|
|
y_case:
|
|
%b = tuple ()
|
|
br end(%b : $())
|
|
|
|
z_case:
|
|
%c = tuple ()
|
|
br end(%c : $())
|
|
|
|
default_case:
|
|
%d = tuple ()
|
|
br end(%d : $())
|
|
|
|
end(%z : $()):
|
|
return %z : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc i8 @dynamic_single_payload_empty_payload_load(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: %1 = load i8, ptr %0
|
|
// CHECK: ret i8 %1
|
|
// CHECK: }
|
|
sil @dynamic_single_payload_empty_payload_load : $(@inout DynamicSinglePayload<()>) -> DynamicSinglePayload<()> {
|
|
entry(%p : $*DynamicSinglePayload<()>):
|
|
%x = load %p : $*DynamicSinglePayload<()>
|
|
return %x : $DynamicSinglePayload<()>
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_empty_payload_store(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0, i8 %1) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: store i8 %1, ptr %0
|
|
// CHECK: ret void
|
|
// CHECK: }
|
|
sil @dynamic_single_payload_empty_payload_store : $(@inout DynamicSinglePayload<()>, DynamicSinglePayload<()>) -> () {
|
|
entry(%p : $*DynamicSinglePayload<()>, %x : $DynamicSinglePayload<()>):
|
|
store %x to %p : $*DynamicSinglePayload<()>
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc i8 @dynamic_single_payload_empty_payload_inject_payload() {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: ret i8 0
|
|
// CHECK: }
|
|
sil @dynamic_single_payload_empty_payload_inject_payload : $() -> DynamicSinglePayload<()> {
|
|
%v = tuple ()
|
|
%u = enum $DynamicSinglePayload<()>, #DynamicSinglePayload.x!enumelt, %v : $()
|
|
return %u : $DynamicSinglePayload<()>
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc i8 @dynamic_single_payload_empty_payload_inject_no_payload() {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: ret i8 1
|
|
// CHECK: }
|
|
sil @dynamic_single_payload_empty_payload_inject_no_payload : $() -> DynamicSinglePayload<()> {
|
|
%u = enum $DynamicSinglePayload<()>, #DynamicSinglePayload.y!enumelt
|
|
return %u : $DynamicSinglePayload<()>
|
|
}
|
|
|
|
// <rdar://problem/15383966>
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_single_payload_generic_destroy
|
|
// CHECK: br i1
|
|
// CHECK: {{[0-9]+}}:
|
|
// CHECK: call void
|
|
// CHECK: {{[0-9]+}}:
|
|
sil @dynamic_single_payload_generic_destroy : $@convention(thin) <T> (@in DynamicSinglePayload<T>) -> () {
|
|
entry(%x : $*DynamicSinglePayload<T>):
|
|
destroy_addr %x : $*DynamicSinglePayload<T>
|
|
%z = tuple ()
|
|
return %z : $()
|
|
}
|
|
|
|
enum MultiPayloadNoSpareBits {
|
|
case x(Builtin.Int64)
|
|
case y(Builtin.Int32)
|
|
case z(Builtin.Int63)
|
|
case a
|
|
case b
|
|
case c
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_no_spare_bits_switch(i64 %0, i8 %1) {{.*}} {
|
|
sil @multi_payload_no_spare_bits_switch : $(MultiPayloadNoSpareBits) -> () {
|
|
entry(%u : $MultiPayloadNoSpareBits):
|
|
// CHECK-64: switch i8 %1, label %[[UNREACHABLE:[0-9]+]] [
|
|
// CHECK-64: i8 0, label %[[X_PREDEST:[0-9]+]]
|
|
// CHECK-64: i8 1, label %[[Y_PREDEST:[0-9]+]]
|
|
// CHECK-64: i8 2, label %[[Z_PREDEST:[0-9]+]]
|
|
// CHECK-64: i8 3, label %[[EMPTY:[0-9]+]]
|
|
// CHECK-64: ]
|
|
// CHECK-64: [[EMPTY]]:
|
|
// CHECK-64: switch i64 %0, label %[[UNREACHABLE]] [
|
|
// CHECK-64: i64 0, label %[[A_DEST:[0-9]+]]
|
|
// CHECK-64: i64 1, label %[[B_DEST:[0-9]+]]
|
|
// CHECK-64: i64 2, label %[[C_DEST:[0-9]+]]
|
|
// CHECK-64: ]
|
|
// CHECK-64: [[UNREACHABLE]]:
|
|
// CHECK-64: unreachable
|
|
switch_enum %u : $MultiPayloadNoSpareBits, case #MultiPayloadNoSpareBits.x!enumelt: x_dest, case #MultiPayloadNoSpareBits.y!enumelt: y_dest, case #MultiPayloadNoSpareBits.z!enumelt: z_dest, case #MultiPayloadNoSpareBits.a!enumelt: a_dest, case #MultiPayloadNoSpareBits.b!enumelt: b_dest, case #MultiPayloadNoSpareBits.c!enumelt: c_dest
|
|
|
|
// CHECK-64: [[X_PREDEST]]:
|
|
// CHECK-64: br label %[[X_DEST:[0-9]+]]
|
|
// CHECK-64: [[Y_PREDEST]]:
|
|
// CHECK-64: [[Y_VALUE:%.*]] = trunc i64 %0 to i32
|
|
// CHECK-64: br label %[[Y_DEST:[0-9]+]]
|
|
// CHECK-64: [[Z_PREDEST]]:
|
|
// CHECK-64: [[Z_VALUE:%.*]] = trunc i64 %0 to i63
|
|
// CHECK-64: br label %[[Z_DEST:[0-9]+]]
|
|
|
|
// CHECK-64: [[X_DEST]]:
|
|
// CHECK-64: phi i64 [ %0, %[[X_PREDEST]] ]
|
|
x_dest(%x : $Builtin.Int64):
|
|
%a = function_ref @a : $@convention(thin) () -> ()
|
|
apply %a() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[Y_DEST]]:
|
|
// CHECK-64: phi i32 [ [[Y_VALUE]], %[[Y_PREDEST]] ]
|
|
y_dest(%y : $Builtin.Int32):
|
|
%b = function_ref @b : $@convention(thin) () -> ()
|
|
apply %b() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[Z_DEST]]:
|
|
// CHECK-64: phi i63 [ [[Z_VALUE]], %[[Z_PREDEST]] ]
|
|
z_dest(%z : $Builtin.Int63):
|
|
%c = function_ref @c : $@convention(thin) () -> ()
|
|
apply %c() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[A_DEST]]:
|
|
a_dest:
|
|
%d = function_ref @d : $@convention(thin) () -> ()
|
|
apply %d() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[B_DEST]]:
|
|
b_dest:
|
|
%e = function_ref @e : $@convention(thin) () -> ()
|
|
apply %e() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[C_DEST]]:
|
|
c_dest:
|
|
%f = function_ref @f : $@convention(thin) () -> ()
|
|
apply %f() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
end:
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_no_spare_bits_switch_indirect(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
|
|
sil @multi_payload_no_spare_bits_switch_indirect : $(@inout MultiPayloadNoSpareBits) -> () {
|
|
entry(%u : $*MultiPayloadNoSpareBits):
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, ptr %0
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds{{.*}} %T4enum23MultiPayloadNoSpareBitsO, ptr %0, i32 0, i32 1
|
|
// CHECK-64: [[TAG:%.*]] = load i8, ptr [[T0]]
|
|
// CHECK-64: switch i8 [[TAG]]
|
|
// CHECK-64: switch i64 [[PAYLOAD]]
|
|
// CHECK-64: {{[0-9]+}}:
|
|
// CHECK-64: unreachable
|
|
switch_enum_addr %u : $*MultiPayloadNoSpareBits, case #MultiPayloadNoSpareBits.x!enumelt: x_dest, case #MultiPayloadNoSpareBits.y!enumelt: y_dest, case #MultiPayloadNoSpareBits.z!enumelt: z_dest, case #MultiPayloadNoSpareBits.a!enumelt: a_dest, case #MultiPayloadNoSpareBits.b!enumelt: b_dest, case #MultiPayloadNoSpareBits.c!enumelt: c_dest
|
|
|
|
// CHECK-64: [[X_DEST:[0-9]+]]:
|
|
// CHECK-64: [[Y_DEST:[0-9]+]]:
|
|
// CHECK-64: [[Z_DEST:[0-9]+]]:
|
|
|
|
x_dest:
|
|
%x = unchecked_take_enum_data_addr %u : $*MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.x!enumelt
|
|
br end
|
|
|
|
y_dest:
|
|
%y = unchecked_take_enum_data_addr %u : $*MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.y!enumelt
|
|
br end
|
|
|
|
z_dest:
|
|
%z = unchecked_take_enum_data_addr %u : $*MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.z!enumelt
|
|
br end
|
|
|
|
a_dest:
|
|
br end
|
|
|
|
b_dest:
|
|
br end
|
|
|
|
c_dest:
|
|
br end
|
|
|
|
end:
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_no_spare_bit_inject_x(i64 %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[RES_0:%.*]] = insertvalue { i64, i8 } undef, i64 %0, 0
|
|
// CHECK-64: [[RES:%.*]] = insertvalue { i64, i8 } [[RES_0]], i8 0, 1
|
|
// CHECK-64: ret { i64, i8 } [[RES]]
|
|
// CHECK-64: }
|
|
sil @multi_payload_no_spare_bit_inject_x : $(Builtin.Int64) -> MultiPayloadNoSpareBits {
|
|
entry(%0 : $Builtin.Int64):
|
|
%u = enum $MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.x!enumelt, %0 : $Builtin.Int64
|
|
return %u : $MultiPayloadNoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_no_spare_bit_inject_x_indirect(i64 %0, ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %1) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: store i64 %0, ptr %1
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds{{.*}} %T4enum23MultiPayloadNoSpareBitsO, ptr %1, i32 0, i32 1
|
|
// CHECK-64: store i8 0, ptr [[T0]]
|
|
// CHECK-64: ret void
|
|
// CHECK-64: }
|
|
sil @multi_payload_no_spare_bit_inject_x_indirect : $(Builtin.Int64, @inout MultiPayloadNoSpareBits) -> () {
|
|
entry(%0 : $Builtin.Int64, %1 : $*MultiPayloadNoSpareBits):
|
|
%a = init_enum_data_addr %1 : $*MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.x!enumelt
|
|
store %0 to %a : $*Builtin.Int64
|
|
inject_enum_addr %1 : $*MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.x!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_no_spare_bit_inject_y(i32 %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[ZEXT:%.*]] = zext i32 %0 to i64
|
|
// CHECK-64: [[RES_0:%.*]] = insertvalue { i64, i8 } undef, i64 [[ZEXT]], 0
|
|
// CHECK-64: [[RES:%.*]] = insertvalue { i64, i8 } [[RES_0]], i8 1, 1
|
|
// CHECK-64: ret { i64, i8 } [[RES]]
|
|
// CHECK-64: }
|
|
sil @multi_payload_no_spare_bit_inject_y : $(Builtin.Int32) -> MultiPayloadNoSpareBits {
|
|
entry(%0 : $Builtin.Int32):
|
|
%u = enum $MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.y!enumelt, %0 : $Builtin.Int32
|
|
return %u : $MultiPayloadNoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_no_spare_bit_inject_z(i64 %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i63
|
|
// CHECK-64: [[ZEXT:%.*]] = zext i63 [[NATIVECC_TRUNC]] to i64
|
|
// CHECK-64: [[RES_0:%.*]] = insertvalue { i64, i8 } undef, i64 [[ZEXT]], 0
|
|
// CHECK-64: [[RES:%.*]] = insertvalue { i64, i8 } [[RES_0]], i8 2, 1
|
|
// CHECK-64: ret { i64, i8 } [[RES]]
|
|
// CHECK-64: }
|
|
sil @multi_payload_no_spare_bit_inject_z : $(Builtin.Int63) -> MultiPayloadNoSpareBits {
|
|
entry(%0 : $Builtin.Int63):
|
|
%u = enum $MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.z!enumelt, %0 : $Builtin.Int63
|
|
return %u : $MultiPayloadNoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_no_spare_bit_inject_a() {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: ret { i64, i8 } { i64 0, i8 3 }
|
|
// CHECK-64: }
|
|
sil @multi_payload_no_spare_bit_inject_a : $() -> MultiPayloadNoSpareBits {
|
|
entry:
|
|
%u = enum $MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.a!enumelt
|
|
return %u : $MultiPayloadNoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_no_spare_bit_inject_a_indirect(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: store i64 0, ptr %0
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds{{.*}} %T4enum23MultiPayloadNoSpareBitsO, ptr %0, i32 0, i32 1
|
|
// CHECK-64: store i8 3, ptr [[T0]]
|
|
// CHECK-64: ret void
|
|
// CHECK-64: }
|
|
sil @multi_payload_no_spare_bit_inject_a_indirect : $(@inout MultiPayloadNoSpareBits) -> () {
|
|
entry(%0 : $*MultiPayloadNoSpareBits):
|
|
inject_enum_addr %0 : $*MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.a!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_no_spare_bit_inject_b() {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: ret { i64, i8 } { i64 1, i8 3 }
|
|
// CHECK-64: }
|
|
sil @multi_payload_no_spare_bit_inject_b : $() -> MultiPayloadNoSpareBits {
|
|
entry:
|
|
%u = enum $MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.b!enumelt
|
|
return %u : $MultiPayloadNoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_no_spare_bit_inject_c() {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: ret { i64, i8 } { i64 2, i8 3 }
|
|
// CHECK-64: }
|
|
sil @multi_payload_no_spare_bit_inject_c : $() -> MultiPayloadNoSpareBits {
|
|
entry:
|
|
%u = enum $MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.c!enumelt
|
|
return %u : $MultiPayloadNoSpareBits
|
|
}
|
|
|
|
enum MultiPayloadOneSpareBit {
|
|
case x(Builtin.Int62)
|
|
case y(Builtin.Int63)
|
|
case z(Builtin.Int61)
|
|
case a
|
|
case b
|
|
case c
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_switch(i64 %0, i8 %1) {{.*}} {
|
|
sil @multi_payload_one_spare_bit_switch : $(MultiPayloadOneSpareBit) -> () {
|
|
entry(%u : $MultiPayloadOneSpareBit):
|
|
// CHECK-64: [[SPARE_TAG_LSHR:%.*]] = lshr i64 %0, 63
|
|
// CHECK-64: [[SPARE_TAG_TRUNC:%.*]] = trunc i64 [[SPARE_TAG_LSHR]] to i8
|
|
// CHECK-64: [[SPARE_TAG:%.*]] = and i8 [[SPARE_TAG_TRUNC]], 1
|
|
// CHECK-64: [[EXTRA_TAG:%.*]] = shl i8 %1, 1
|
|
// CHECK-64: [[TAG:%.*]] = or i8 [[SPARE_TAG]], [[EXTRA_TAG]]
|
|
// CHECK-64: switch i8 [[TAG]], label %[[UNREACHABLE:[0-9]+]] [
|
|
// CHECK-64: i8 0, label %[[X_PREDEST:[0-9]+]]
|
|
// CHECK-64: i8 1, label %[[Y_PREDEST:[0-9]+]]
|
|
// CHECK-64: i8 2, label %[[Z_PREDEST:[0-9]+]]
|
|
// CHECK-64: i8 3, label %[[EMPTY_DEST:[0-9]+]]
|
|
// CHECK-64: ]
|
|
|
|
// CHECK-64: [[EMPTY_DEST]]:
|
|
// CHECK-64: switch i64 %0, label %[[UNREACHABLE]] [
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK-64: i64 -9223372036854775808, label %[[A_DEST:[0-9]+]]
|
|
// -- 0x8000_0000_0000_0001
|
|
// CHECK-64: i64 -9223372036854775807, label %[[B_DEST:[0-9]+]]
|
|
// -- 0x8000_0000_0000_0002
|
|
// CHECK-64: i64 -9223372036854775806, label %[[C_DEST:[0-9]+]]
|
|
// CHECK-64: ]
|
|
|
|
// CHECK-64: [[UNREACHABLE]]:
|
|
// CHECK-64: unreachable
|
|
switch_enum %u : $MultiPayloadOneSpareBit, case #MultiPayloadOneSpareBit.x!enumelt: x_dest, case #MultiPayloadOneSpareBit.y!enumelt: y_dest, case #MultiPayloadOneSpareBit.z!enumelt: z_dest, case #MultiPayloadOneSpareBit.a!enumelt: a_dest, case #MultiPayloadOneSpareBit.b!enumelt: b_dest, case #MultiPayloadOneSpareBit.c!enumelt: c_dest
|
|
|
|
// CHECK-64: [[X_PREDEST]]:
|
|
// CHECK-64: [[X_VALUE:%.*]] = trunc i64 %0 to i62
|
|
// CHECK-64: br label %[[X_DEST:[0-9]+]]
|
|
// CHECK-64: [[Y_PREDEST]]:
|
|
// -- 0x7FFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[Y_MASKED:%.*]] = and i64 %0, 9223372036854775807
|
|
// CHECK-64: [[Y_VALUE:%.*]] = trunc i64 [[Y_MASKED]] to i63
|
|
// CHECK-64: br label %[[Y_DEST:[0-9]+]]
|
|
// CHECK-64: [[Z_PREDEST]]:
|
|
// CHECK-64: [[Z_VALUE:%.*]] = trunc i64 %0 to i61
|
|
// CHECK-64: br label %[[Z_DEST:[0-9]+]]
|
|
|
|
// CHECK-64: [[X_DEST]]:
|
|
// CHECK-64: phi i62 [ [[X_VALUE]], %[[X_PREDEST]] ]
|
|
x_dest(%x : $Builtin.Int62):
|
|
%a = function_ref @a : $@convention(thin) () -> ()
|
|
apply %a() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[Y_DEST]]:
|
|
// CHECK-64: phi i63 [ [[Y_VALUE]], %[[Y_PREDEST]] ]
|
|
y_dest(%y : $Builtin.Int63):
|
|
%b = function_ref @b : $@convention(thin) () -> ()
|
|
apply %b() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[Z_DEST]]:
|
|
// CHECK-64: phi i61 [ [[Z_VALUE]], %[[Z_PREDEST]] ]
|
|
z_dest(%z : $Builtin.Int61):
|
|
%c = function_ref @c : $@convention(thin) () -> ()
|
|
apply %c() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[A_DEST]]:
|
|
a_dest:
|
|
%d = function_ref @d : $@convention(thin) () -> ()
|
|
apply %d() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[B_DEST]]:
|
|
b_dest:
|
|
%e = function_ref @e : $@convention(thin) () -> ()
|
|
apply %e() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[C_DEST]]:
|
|
c_dest:
|
|
%f = function_ref @f : $@convention(thin) () -> ()
|
|
apply %f() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
end:
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
sil @multi_payload_one_spare_bit_switch_indirect : $(@inout MultiPayloadOneSpareBit) -> () {
|
|
entry(%u : $*MultiPayloadOneSpareBit):
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, ptr %0
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds{{.*}} %T4enum23MultiPayloadOneSpareBitO, ptr %0, i32 0, i32 1
|
|
// CHECK-64: [[TAG:%.*]] = load i8, ptr [[T0]]
|
|
// CHECK-64: switch i8 {{%.*}}
|
|
// CHECK-64: switch i64 [[PAYLOAD]]
|
|
// CHECK-64: {{[0-9]+}}:
|
|
// CHECK-64: unreachable
|
|
switch_enum_addr %u : $*MultiPayloadOneSpareBit, case #MultiPayloadOneSpareBit.x!enumelt: x_dest, case #MultiPayloadOneSpareBit.y!enumelt: y_dest, case #MultiPayloadOneSpareBit.z!enumelt: z_dest, case #MultiPayloadOneSpareBit.a!enumelt: a_dest, case #MultiPayloadOneSpareBit.b!enumelt: b_dest, case #MultiPayloadOneSpareBit.c!enumelt: c_dest
|
|
|
|
// CHECK-64: [[X_PREDEST:[0-9]+]]:
|
|
|
|
// CHECK-64: [[Y_PREDEST:[0-9]+]]:
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, ptr %0
|
|
// -- 0x7FFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
|
|
// CHECK-64: store i64 [[PAYLOAD_MASKED]], ptr %0
|
|
|
|
// CHECK-64: [[Z_PREDEST:[0-9]+]]:
|
|
|
|
x_dest:
|
|
%x = unchecked_take_enum_data_addr %u : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.x!enumelt
|
|
br end
|
|
|
|
y_dest:
|
|
%y = unchecked_take_enum_data_addr %u : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.y!enumelt
|
|
br end
|
|
|
|
z_dest:
|
|
%z = unchecked_take_enum_data_addr %u : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.z!enumelt
|
|
br end
|
|
|
|
a_dest:
|
|
br end
|
|
|
|
b_dest:
|
|
br end
|
|
|
|
c_dest:
|
|
br end
|
|
|
|
end:
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_one_spare_bit_inject_x(i64 %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62
|
|
// CHECK-64: [[ZEXT:%.*]] = zext i62 [[NATIVECC_TRUNC]] to i64
|
|
// CHECK-64: [[RES_0:%.*]] = insertvalue { i64, i8 } undef, i64 [[ZEXT]], 0
|
|
// CHECK-64: [[RES:%.*]] = insertvalue { i64, i8 } [[RES_0]], i8 0, 1
|
|
// CHECK-64: ret { i64, i8 } [[RES]]
|
|
// CHECK-64: }
|
|
sil @multi_payload_one_spare_bit_inject_x : $(Builtin.Int62) -> MultiPayloadOneSpareBit {
|
|
entry(%0 : $Builtin.Int62):
|
|
%u = enum $MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.x!enumelt, %0 : $Builtin.Int62
|
|
return %u : $MultiPayloadOneSpareBit
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_x_indirect(i64 %0, ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %1) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62
|
|
// CHECK-64: [[BYTE:%.*]] = zext i62 [[NATIVECC_TRUNC]] to i64
|
|
// CHECK-64: store i64 [[BYTE]], ptr %1
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, ptr %1
|
|
// -- 0x7FFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
|
|
// CHECK-64: store i64 [[PAYLOAD_MASKED]], ptr %1
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds{{.*}} %T4enum23MultiPayloadOneSpareBitO, ptr %1, i32 0, i32 1
|
|
// CHECK-64: store i8 0, ptr [[T0]]
|
|
// CHECK-64: ret void
|
|
// CHECK-64: }
|
|
sil @multi_payload_one_spare_bit_inject_x_indirect : $(Builtin.Int62, @inout MultiPayloadOneSpareBit) -> () {
|
|
entry(%0 : $Builtin.Int62, %1 : $*MultiPayloadOneSpareBit):
|
|
%a = init_enum_data_addr %1 : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.x!enumelt
|
|
store %0 to %a : $*Builtin.Int62
|
|
inject_enum_addr %1 : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.x!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_one_spare_bit_inject_y(i64 %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i63
|
|
// CHECK-64: [[ZEXT:%.*]] = zext i63 [[NATIVECC_TRUNC]] to i64
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK-64: [[TAGGED:%.*]] = or i64 [[ZEXT]], -9223372036854775808
|
|
// CHECK-64: [[RES_0:%.*]] = insertvalue { i64, i8 } undef, i64 [[TAGGED]], 0
|
|
// CHECK-64: [[RES:%.*]] = insertvalue { i64, i8 } [[RES_0]], i8 0, 1
|
|
// CHECK-64: ret { i64, i8 } [[RES]]
|
|
// CHECK-64: }
|
|
sil @multi_payload_one_spare_bit_inject_y : $(Builtin.Int63) -> MultiPayloadOneSpareBit {
|
|
entry(%0 : $Builtin.Int63):
|
|
%u = enum $MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.y!enumelt, %0 : $Builtin.Int63
|
|
return %u : $MultiPayloadOneSpareBit
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_y_indirect(i64 %0, ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %1) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i63
|
|
// CHECK-64: [[BYTE:%.*]] = zext i63 [[NATIVECC_TRUNC]] to i64
|
|
// CHECK-64: store i64 [[BYTE]], ptr %1
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, ptr %1
|
|
// -- 0x7FFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK-64: [[PAYLOAD_TAGGED:%.*]] = or i64 [[PAYLOAD_MASKED]], -9223372036854775808
|
|
// CHECK-64: store i64 [[PAYLOAD_TAGGED]], ptr %1
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds{{.*}} %T4enum23MultiPayloadOneSpareBitO, ptr %1, i32 0, i32 1
|
|
// CHECK-64: store i8 0, ptr [[T0]]
|
|
// CHECK-64: ret void
|
|
// CHECK-64: }
|
|
|
|
sil @multi_payload_one_spare_bit_inject_y_indirect : $(Builtin.Int63, @inout MultiPayloadOneSpareBit) -> () {
|
|
entry(%0 : $Builtin.Int63, %1 : $*MultiPayloadOneSpareBit):
|
|
%a = init_enum_data_addr %1 : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.y!enumelt
|
|
store %0 to %a : $*Builtin.Int63
|
|
inject_enum_addr %1 : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.y!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_one_spare_bit_inject_z(i64 %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i61
|
|
// CHECK-64: [[ZEXT:%.*]] = zext i61 [[NATIVECC_TRUNC]] to i64
|
|
// CHECK-64: [[RES_0:%.*]] = insertvalue { i64, i8 } undef, i64 [[ZEXT]], 0
|
|
// CHECK-64: [[RES:%.*]] = insertvalue { i64, i8 } [[RES_0]], i8 1, 1
|
|
// CHECK-64: ret { i64, i8 } [[RES]]
|
|
// CHECK-64: }
|
|
sil @multi_payload_one_spare_bit_inject_z : $(Builtin.Int61) -> MultiPayloadOneSpareBit {
|
|
entry(%0 : $Builtin.Int61):
|
|
%u = enum $MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.z!enumelt, %0 : $Builtin.Int61
|
|
return %u : $MultiPayloadOneSpareBit
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_one_spare_bit_inject_a() {{.*}} {
|
|
// CHECK-64: entry:
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK-64: ret { i64, i8 } { i64 -9223372036854775808, i8 1 }
|
|
// CHECK-64: }
|
|
sil @multi_payload_one_spare_bit_inject_a : $() -> MultiPayloadOneSpareBit {
|
|
entry:
|
|
%u = enum $MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.a!enumelt
|
|
return %u : $MultiPayloadOneSpareBit
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_a_indirect(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK-64: store i64 -9223372036854775808, ptr %0
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds{{.*}} %T4enum23MultiPayloadOneSpareBitO, ptr %0, i32 0, i32 1
|
|
// CHECK-64: store i8 1, ptr [[T0]]
|
|
// CHECK-64: ret void
|
|
// CHECK-64: }
|
|
sil @multi_payload_one_spare_bit_inject_a_indirect : $(@inout MultiPayloadOneSpareBit) -> () {
|
|
entry(%0 : $*MultiPayloadOneSpareBit):
|
|
inject_enum_addr %0 : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.a!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_one_spare_bit_inject_b() {{.*}} {
|
|
// CHECK-64: entry:
|
|
// -- 0x8000_0000_0000_0001
|
|
// CHECK-64: ret { i64, i8 } { i64 -9223372036854775807, i8 1 }
|
|
// CHECK-64: }
|
|
sil @multi_payload_one_spare_bit_inject_b : $() -> MultiPayloadOneSpareBit {
|
|
entry:
|
|
%u = enum $MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.b!enumelt
|
|
return %u : $MultiPayloadOneSpareBit
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @multi_payload_one_spare_bit_inject_c() {{.*}} {
|
|
// CHECK-64: entry:
|
|
// -- 0x8000_0000_0000_0002
|
|
// CHECK-64: ret { i64, i8 } { i64 -9223372036854775806, i8 1 }
|
|
// CHECK-64: }
|
|
sil @multi_payload_one_spare_bit_inject_c : $() -> MultiPayloadOneSpareBit {
|
|
entry:
|
|
%u = enum $MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.c!enumelt
|
|
return %u : $MultiPayloadOneSpareBit
|
|
}
|
|
|
|
|
|
enum MultiPayloadTwoSpareBits {
|
|
case x(Builtin.Int62)
|
|
case y(Builtin.Int60)
|
|
case z(Builtin.Int61)
|
|
case a
|
|
case b
|
|
case c
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_switch(i64 %0) {{.*}} {
|
|
sil @multi_payload_two_spare_bits_switch : $(MultiPayloadTwoSpareBits) -> () {
|
|
entry(%u : $MultiPayloadTwoSpareBits):
|
|
// CHECK-64: [[TAG_LSHR:%.*]] = lshr i64 %0, 62
|
|
// CHECK-64: [[TAG_BYTE:%.*]] = trunc i64 [[TAG_LSHR]] to i8
|
|
// CHECK-64: [[TAG:%.*]] = and i8 [[TAG_BYTE]], 3
|
|
// CHECK-64: switch i8 [[TAG]], label %[[UNREACHABLE:[0-9]+]] [
|
|
// CHECK-64: i8 0, label %[[X_PREDEST:[0-9]+]]
|
|
// CHECK-64: i8 1, label %[[Y_PREDEST:[0-9]+]]
|
|
// CHECK-64: i8 2, label %[[Z_PREDEST:[0-9]+]]
|
|
// CHECK-64: i8 3, label %[[EMPTY_DEST:[0-9]+]]
|
|
// CHECK-64: ]
|
|
// CHECK-64: [[EMPTY_DEST]]:
|
|
// CHECK-64: switch i64 %0, label %[[UNREACHABLE]] [
|
|
// -- 0xC000_0000_0000_0000
|
|
// CHECK-64: i64 -4611686018427387904, label %[[A_DEST:[0-9]+]]
|
|
// -- 0xC000_0000_0000_0001
|
|
// CHECK-64: i64 -4611686018427387903, label %[[B_DEST:[0-9]+]]
|
|
// -- 0xC000_0000_0000_0002
|
|
// CHECK-64: i64 -4611686018427387902, label %[[C_DEST:[0-9]+]]
|
|
// CHECK-64: ]
|
|
// CHECK-64: [[UNREACHABLE]]:
|
|
// CHECK-64: unreachable
|
|
switch_enum %u : $MultiPayloadTwoSpareBits, case #MultiPayloadTwoSpareBits.x!enumelt: x_dest, case #MultiPayloadTwoSpareBits.y!enumelt: y_dest, case #MultiPayloadTwoSpareBits.z!enumelt: z_dest, case #MultiPayloadTwoSpareBits.a!enumelt: a_dest, case #MultiPayloadTwoSpareBits.b!enumelt: b_dest, case #MultiPayloadTwoSpareBits.c!enumelt: c_dest
|
|
|
|
// CHECK-64: [[X_PREDEST]]:
|
|
// CHECK-64: [[X_VALUE:%.*]] = trunc i64 %0 to i62
|
|
// CHECK-64: br label %[[X_DEST:[0-9]+]]
|
|
|
|
// CHECK-64: [[Y_PREDEST]]:
|
|
// -- 0x3FFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[Y_MASKED:%.*]] = and i64 %0, 4611686018427387903
|
|
// CHECK-64: [[Y_VALUE:%.*]] = trunc i64 [[Y_MASKED]] to i60
|
|
// CHECK-64: br label %[[Y_DEST:[0-9]+]]
|
|
|
|
// CHECK-64: [[Z_PREDEST]]:
|
|
// -- 0x3FFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[Z_MASKED:%.*]] = and i64 %0, 4611686018427387903
|
|
// CHECK-64: [[Z_VALUE:%.*]] = trunc i64 [[Z_MASKED]] to i61
|
|
// CHECK-64: br label %[[Z_DEST:[0-9]+]]
|
|
|
|
// CHECK-64: [[X_DEST]]:
|
|
// CHECK-64: phi i62 [ [[X_VALUE]], %[[X_PREDEST]] ]
|
|
x_dest(%x : $Builtin.Int62):
|
|
%a = function_ref @a : $@convention(thin) () -> ()
|
|
apply %a() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[Y_DEST]]:
|
|
// CHECK-64: phi i60 [ [[Y_VALUE]], %[[Y_PREDEST]] ]
|
|
y_dest(%y : $Builtin.Int60):
|
|
%b = function_ref @b : $@convention(thin) () -> ()
|
|
apply %b() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[Z_DEST]]:
|
|
// CHECK-64: phi i61 [ [[Z_VALUE]], %[[Z_PREDEST]] ]
|
|
z_dest(%z : $Builtin.Int61):
|
|
%c = function_ref @c : $@convention(thin) () -> ()
|
|
apply %c() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[A_DEST]]:
|
|
a_dest:
|
|
%d = function_ref @d : $@convention(thin) () -> ()
|
|
apply %d() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[B_DEST]]:
|
|
b_dest:
|
|
%e = function_ref @e : $@convention(thin) () -> ()
|
|
apply %e() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: [[C_DEST]]:
|
|
c_dest:
|
|
%f = function_ref @f : $@convention(thin) () -> ()
|
|
apply %f() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
end:
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i64 @multi_payload_two_spare_bits_inject_x(i64 %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62
|
|
// CHECK-64: [[ZEXT:%.*]] = zext i62 [[NATIVECC_TRUNC]] to i64
|
|
// CHECK-64: ret i64 [[ZEXT]]
|
|
// CHECK-64: }
|
|
sil @multi_payload_two_spare_bits_inject_x : $(Builtin.Int62) -> MultiPayloadTwoSpareBits {
|
|
entry(%0 : $Builtin.Int62):
|
|
%u = enum $MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.x!enumelt, %0 : $Builtin.Int62
|
|
return %u : $MultiPayloadTwoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_x_indirect(i64 %0, ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %1) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62
|
|
// CHECK-64: [[BYTE:%.*]] = zext i62 [[NATIVECC_TRUNC]] to i64
|
|
// CHECK-64: store i64 [[BYTE]], ptr %1
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, ptr %1
|
|
// -- 0x3FFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 4611686018427387903
|
|
// CHECK-64: store i64 [[PAYLOAD_MASKED]], ptr %1
|
|
// CHECK-64: ret void
|
|
// CHECK-64: }
|
|
sil @multi_payload_two_spare_bits_inject_x_indirect : $(Builtin.Int62, @inout MultiPayloadTwoSpareBits) -> () {
|
|
entry(%0 : $Builtin.Int62, %1 : $*MultiPayloadTwoSpareBits):
|
|
%a = init_enum_data_addr %1 : $*MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.x!enumelt
|
|
store %0 to %a : $*Builtin.Int62
|
|
inject_enum_addr %1 : $*MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.x!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i64 @multi_payload_two_spare_bits_inject_y(i64 %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i60
|
|
// CHECK-64: [[ZEXT:%.*]] = zext i60 [[NATIVECC_TRUNC]] to i64
|
|
// -- 0x4000_0000_0000_0000
|
|
// CHECK-64: [[TAGGED:%.*]] = or i64 [[ZEXT]], 4611686018427387904
|
|
// CHECK-64: ret i64 [[TAGGED]]
|
|
// CHECK-64: }
|
|
sil @multi_payload_two_spare_bits_inject_y : $(Builtin.Int60) -> MultiPayloadTwoSpareBits {
|
|
entry(%0 : $Builtin.Int60):
|
|
%u = enum $MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.y!enumelt, %0 : $Builtin.Int60
|
|
return %u : $MultiPayloadTwoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_y_indirect(i64 %0, ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %1) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i60
|
|
// CHECK-64: [[BYTE:%.*]] = zext i60 [[NATIVECC_TRUNC]] to i64
|
|
// CHECK-64: store i64 [[BYTE]], ptr %1
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, ptr %1
|
|
// -- 0x3FFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 4611686018427387903
|
|
// -- 0x4000_0000_0000_0000
|
|
// CHECK-64: [[PAYLOAD_TAGGED:%.*]] = or i64 [[PAYLOAD_MASKED]], 4611686018427387904
|
|
// CHECK-64: store i64 [[PAYLOAD_TAGGED]], ptr %1
|
|
// CHECK-64: ret void
|
|
// CHECK-64: }
|
|
sil @multi_payload_two_spare_bits_inject_y_indirect : $(Builtin.Int60, @inout MultiPayloadTwoSpareBits) -> () {
|
|
entry(%0 : $Builtin.Int60, %1 : $*MultiPayloadTwoSpareBits):
|
|
%a = init_enum_data_addr %1 : $*MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.y!enumelt
|
|
store %0 to %a : $*Builtin.Int60
|
|
inject_enum_addr %1 : $*MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.y!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i64 @multi_payload_two_spare_bits_inject_z(i64 %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i61
|
|
// CHECK-64: [[ZEXT:%.*]] = zext i61 [[NATIVECC_TRUNC]] to i64
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK-64: [[TAGGED:%.*]] = or i64 [[ZEXT]], -9223372036854775808
|
|
// CHECK-64: ret i64 [[TAGGED]]
|
|
// CHECK-64: }
|
|
sil @multi_payload_two_spare_bits_inject_z : $(Builtin.Int61) -> MultiPayloadTwoSpareBits {
|
|
entry(%0 : $Builtin.Int61):
|
|
%u = enum $MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.z!enumelt, %0 : $Builtin.Int61
|
|
return %u : $MultiPayloadTwoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i64 @multi_payload_two_spare_bits_inject_a() {{.*}} {
|
|
// CHECK-64: entry:
|
|
// -- 0xC000_0000_0000_0000
|
|
// CHECK-64: ret i64 -4611686018427387904
|
|
// CHECK-64: }
|
|
sil @multi_payload_two_spare_bits_inject_a : $() -> MultiPayloadTwoSpareBits {
|
|
entry:
|
|
%u = enum $MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.a!enumelt
|
|
return %u : $MultiPayloadTwoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_a_indirect(ptr {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// -- 0xC000_0000_0000_0000
|
|
// CHECK-64: store i64 -4611686018427387904, ptr %0
|
|
// CHECK-64: ret void
|
|
// CHECK-64: }
|
|
sil @multi_payload_two_spare_bits_inject_a_indirect : $(@inout MultiPayloadTwoSpareBits) -> () {
|
|
entry(%0 : $*MultiPayloadTwoSpareBits):
|
|
inject_enum_addr %0 : $*MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.a!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i64 @multi_payload_two_spare_bits_inject_b() {{.*}} {
|
|
// CHECK-64: entry:
|
|
// -- 0xC000_0000_0000_0001
|
|
// CHECK-64: ret i64 -4611686018427387903
|
|
// CHECK-64: }
|
|
sil @multi_payload_two_spare_bits_inject_b : $() -> MultiPayloadTwoSpareBits {
|
|
entry:
|
|
%u = enum $MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.b!enumelt
|
|
return %u : $MultiPayloadTwoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( dllexport)?}}{{( protected)?}} swiftcc i64 @multi_payload_two_spare_bits_inject_c() {{.*}} {
|
|
// CHECK-64: entry:
|
|
// -- 0xC000_0000_0000_0002
|
|
// CHECK-64: ret i64 -4611686018427387902
|
|
// CHECK-64: }
|
|
sil @multi_payload_two_spare_bits_inject_c : $() -> MultiPayloadTwoSpareBits {
|
|
entry:
|
|
%u = enum $MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.c!enumelt
|
|
return %u : $MultiPayloadTwoSpareBits
|
|
}
|
|
|
|
class D {}
|
|
sil_vtable D {}
|
|
|
|
sil @$s4enum1DCfD : $@convention(method) (D) -> ()
|
|
|
|
enum MultiPayloadClasses {
|
|
case x(C)
|
|
case y(D)
|
|
case z
|
|
case w
|
|
}
|
|
|
|
// CHECK-64-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_classes_switch(i64 %0) {{.*}} {
|
|
// CHECK-64: %1 = lshr i64 %0, 62
|
|
// CHECK-64: %2 = trunc i64 %1 to i8
|
|
// CHECK-64: %3 = and i8 %2, 3
|
|
// CHECK-64: switch i8 %3, label {{%.*}} [
|
|
// CHECK-64: i8 0, label {{%.*}}
|
|
// CHECK-64: i8 1, label {{%.*}}
|
|
// CHECK-64: i8 2, label {{%.*}}
|
|
// CHECK-64: ]
|
|
// CHECK-64: switch i64 %0, label {{%.*}} [
|
|
// -- 0x8000000000000000
|
|
// CHECK-64: i64 -9223372036854775808, label {{%.*}}
|
|
// -- 0x8000000000000008
|
|
// CHECK-64: i64 -9223372036854775800, label {{%.*}}
|
|
// CHECK-64: ]
|
|
// -- Extract x(C)
|
|
// CHECK-64: inttoptr i64 %0 to ptr
|
|
// -- Extract y(D)
|
|
// -- 0x3fffffffffffffff
|
|
// CHECK-64: [[MASKED:%.*]] = and i64 %0, 4611686018427387903
|
|
// CHECK-64: inttoptr i64 [[MASKED]] to ptr
|
|
|
|
// CHECK-32-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_classes_switch(i32 %0) {{.*}} {
|
|
// CHECK-32: %1 = trunc i32 %0 to i8
|
|
// CHECK-32: %2 = and i8 %1, 3
|
|
// CHECK-32: switch i8 %2, label {{%.*}} [
|
|
// CHECK-32: i8 0, label {{%.*}}
|
|
// CHECK-32: i8 1, label {{%.*}}
|
|
// CHECK-32: i8 2, label {{%.*}}
|
|
// CHECK-32: ]
|
|
// CHECK-32: switch i32 %0, label {{%.*}} [
|
|
// CHECK-32: i32 2, label {{%.*}}
|
|
// CHECK-32: i32 6, label {{%.*}}
|
|
// CHECK-32: ]
|
|
// -- Extract x(C)
|
|
// CHECK-32: inttoptr i32 %0 to ptr
|
|
// -- Extract y(D)
|
|
// CHECK-32: [[MASKED:%.*]] = and i32 %0, -4
|
|
// CHECK-32: inttoptr i32 [[MASKED]] to ptr
|
|
|
|
sil @multi_payload_classes_switch : $(MultiPayloadClasses) -> () {
|
|
entry(%c : $MultiPayloadClasses):
|
|
switch_enum %c : $MultiPayloadClasses, case #MultiPayloadClasses.x!enumelt: x_dest, case #MultiPayloadClasses.y!enumelt: y_dest, case #MultiPayloadClasses.z!enumelt: z_dest, case #MultiPayloadClasses.w!enumelt: w_dest
|
|
|
|
x_dest(%x : $C):
|
|
br end
|
|
|
|
y_dest(%y : $D):
|
|
br end
|
|
|
|
z_dest:
|
|
br end
|
|
|
|
w_dest:
|
|
br end
|
|
|
|
end:
|
|
return undef : $()
|
|
}
|
|
|
|
struct S {
|
|
var a: CharLike
|
|
var b: IntLike
|
|
}
|
|
|
|
enum MultiPayloadSpareBitAggregates {
|
|
// Has spare bits in the padding between Int32 and Int64
|
|
case x(Builtin.Int32, Builtin.Int64)
|
|
// Has spare bits in the object pointers
|
|
case y(C, C)
|
|
// Has spare bits in the padding between struct fields
|
|
case z(S)
|
|
}
|
|
|
|
// CHECK-64-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_spare_bit_aggregate_switch(i64 %0, i64 %1) {{.*}} {
|
|
// CHECK-64: [[T0:%.*]] = lshr i64 %0, 62
|
|
// CHECK-64: [[TAG_BYTE:%.*]] = trunc i64 [[T0]] to i8
|
|
// CHECK-64: [[TAG:%.*]] = and i8 [[TAG_BYTE]], 3
|
|
// CHECK-64: switch i8 [[TAG]], label {{%.*}} [
|
|
// CHECK-64: i8 0, label %[[X_DEST:[0-9]+]]
|
|
// CHECK-64: i8 1, label %[[Y_DEST:[0-9]+]]
|
|
// CHECK-64: i8 2, label %[[Z_DEST:[0-9]+]]
|
|
// CHECK-64: ]
|
|
// CHECK-64: [[X_DEST]]:
|
|
// CHECK-64: [[X_0:%.*]] = trunc i64 %0 to i32
|
|
// CHECK-64: [[Y_DEST]]:
|
|
// -- 0x3fffffffffffffff
|
|
// CHECK-64: [[Y_MASKED:%.*]] = and i64 %0, 4611686018427387903
|
|
// CHECK-64: [[Y_0:%.*]] = inttoptr i64 [[Y_MASKED]] to ptr
|
|
// CHECK-64: [[Y_1:%.*]] = inttoptr i64 %1 to ptr
|
|
// CHECK-64: [[Z_DEST]]:
|
|
// -- 0x3fffffffffffffff
|
|
// CHECK-64: [[Z_MASKED:%.*]] = and i64 %0, 4611686018427387903
|
|
// CHECK-64: [[Z_A:%.*]] = trunc i64 [[Z_MASKED]] to i21
|
|
|
|
sil @multi_payload_spare_bit_aggregate_switch : $(MultiPayloadSpareBitAggregates) -> () {
|
|
entry(%c : $MultiPayloadSpareBitAggregates):
|
|
switch_enum %c : $MultiPayloadSpareBitAggregates, case #MultiPayloadSpareBitAggregates.x!enumelt: x_dest, case #MultiPayloadSpareBitAggregates.y!enumelt: y_dest, case #MultiPayloadSpareBitAggregates.z!enumelt: z_dest
|
|
|
|
x_dest(%x : $(Builtin.Int32, Builtin.Int64)):
|
|
br end
|
|
|
|
y_dest(%y : $(C, C)):
|
|
br end
|
|
|
|
z_dest(%z : $S):
|
|
br end
|
|
|
|
end:
|
|
return undef : $()
|
|
}
|
|
|
|
// <rdar://problem/15759464>
|
|
enum MultiPayloadInner {
|
|
case A(Builtin.Word)
|
|
case B(Builtin.Word)
|
|
}
|
|
|
|
enum MultiPayloadNested {
|
|
case A(MultiPayloadInner)
|
|
case B(MultiPayloadInner)
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_nested_switch
|
|
// CHECK: %1 = getelementptr
|
|
// CHECK: %2 = load [[WORD]], ptr %1
|
|
// CHECK: %3 = getelementptr
|
|
// CHECK: %4 = load i8, ptr %3
|
|
// CHECK: %5 = lshr i8 %4, 7
|
|
// CHECK: %6 = and i8 %5, 1
|
|
// CHECK: %7 = icmp ne i8 %6, 1
|
|
// CHECK: br i1 %7
|
|
sil @multi_payload_nested_switch : $(@in MultiPayloadNested) -> () {
|
|
entry(%c : $*MultiPayloadNested):
|
|
switch_enum_addr %c : $*MultiPayloadNested, case #MultiPayloadNested.A!enumelt: a_dest, case #MultiPayloadNested.B!enumelt: b_dest
|
|
|
|
a_dest:
|
|
br end
|
|
|
|
b_dest:
|
|
br end
|
|
|
|
end:
|
|
return undef : $()
|
|
}
|
|
|
|
enum MultiPayloadInnerSpareBits {
|
|
case A(Builtin.NativeObject)
|
|
case B(Builtin.NativeObject)
|
|
case C(Builtin.NativeObject)
|
|
case D(Builtin.NativeObject)
|
|
}
|
|
|
|
enum MultiPayloadNestedSpareBits {
|
|
case A(MultiPayloadInnerSpareBits)
|
|
case B(MultiPayloadInnerSpareBits)
|
|
}
|
|
|
|
// CHECK-64-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_nested_spare_bits_switch(ptr noalias {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: %1 = load [[WORD]], ptr %0
|
|
// CHECK-64: %2 = lshr [[WORD]] %1, 61
|
|
// CHECK-64: %3 = trunc [[WORD]] %2 to i8
|
|
// CHECK-64: %4 = and i8 %3, 1
|
|
// CHECK-64: %5 = icmp ne i8 %4, 1
|
|
// CHECK-64: br i1 %5
|
|
sil @multi_payload_nested_spare_bits_switch : $(@in MultiPayloadNestedSpareBits) -> () {
|
|
entry(%c : $*MultiPayloadNestedSpareBits):
|
|
switch_enum_addr %c : $*MultiPayloadNestedSpareBits, case #MultiPayloadNestedSpareBits.A!enumelt: a_dest, case #MultiPayloadNestedSpareBits.B!enumelt: b_dest
|
|
|
|
a_dest:
|
|
br end
|
|
|
|
b_dest:
|
|
br end
|
|
|
|
end:
|
|
return undef : $()
|
|
}
|
|
|
|
|
|
// -- test for a switch_enum bug for multi-payload, no-empty-case enums
|
|
// uncovered by Chris
|
|
enum OnlyPayloads {
|
|
case x(Builtin.Int64)
|
|
case y(Builtin.Int32)
|
|
case z(Builtin.Int16)
|
|
}
|
|
|
|
sil @only_payloads_switch : $(OnlyPayloads) -> () {
|
|
entry(%0 : $OnlyPayloads):
|
|
switch_enum %0 : $OnlyPayloads, case #OnlyPayloads.x!enumelt: x_dest, case #OnlyPayloads.y!enumelt: y_dest, case #OnlyPayloads.z!enumelt: z_dest
|
|
|
|
x_dest:
|
|
br end
|
|
y_dest:
|
|
br end
|
|
z_dest:
|
|
br end
|
|
|
|
end:
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// Should not use spare bits, because T may be a tagged ObjC pointer.
|
|
enum MultiPayloadClassGeneric<T: AnyObject> {
|
|
case A(C, Builtin.Word)
|
|
case B(T)
|
|
}
|
|
|
|
// CHECK-64-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i64, i8 } @multi_payload_class_generic_no_spare_bits(i64 %0, i64 %1, i8 %2, ptr %T)
|
|
// CHECK-32-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i32, i32, i8 } @multi_payload_class_generic_no_spare_bits(i32 %0, i32 %1, i8 %2, ptr %T)
|
|
sil @multi_payload_class_generic_no_spare_bits : $@convention(thin) <T: AnyObject> (@owned MultiPayloadClassGeneric<T>) -> MultiPayloadClassGeneric<T> {
|
|
entry(%e : $MultiPayloadClassGeneric<T>):
|
|
return %e : $MultiPayloadClassGeneric<T>
|
|
}
|
|
|
|
// CHECK-64-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i64, i8 } @multi_payload_class_instance_no_spare_bits(i64 %0, i64 %1, i8 %2)
|
|
// CHECK-32-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i32, i32, i8 } @multi_payload_class_instance_no_spare_bits(i32 %0, i32 %1, i8 %2)
|
|
sil @multi_payload_class_instance_no_spare_bits : $@convention(thin) (@owned MultiPayloadClassGeneric<C>) -> MultiPayloadClassGeneric<C> {
|
|
entry(%e : $MultiPayloadClassGeneric<C>):
|
|
return %e : $MultiPayloadClassGeneric<C>
|
|
}
|
|
|
|
enum MultiPayloadAddressOnlyFixed {
|
|
case X(Any)
|
|
case Y(Builtin.Int32)
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_address_only_destroy(ptr noalias {{(nocapture|captures\(none\))}} dereferenceable({{.*}}) %0)
|
|
sil @multi_payload_address_only_destroy : $@convention(thin) (@in MultiPayloadAddressOnlyFixed) -> () {
|
|
entry(%m : $*MultiPayloadAddressOnlyFixed):
|
|
destroy_addr %m : $*MultiPayloadAddressOnlyFixed
|
|
return undef : $()
|
|
}
|
|
|
|
// Even if spare bits are available in an address-only payload,
|
|
// we cannot use them.
|
|
|
|
struct AddressOnlySpareBitsPayload {
|
|
weak var x: C?
|
|
var y: C
|
|
}
|
|
|
|
enum MultiPayloadAddressOnlySpareBits {
|
|
case X(AddressOnlySpareBitsPayload)
|
|
case Y(AddressOnlySpareBitsPayload)
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @multi_payload_address_only_spare_bits(ptr noalias dereferenceable({{.*}}) %0)
|
|
sil @multi_payload_address_only_spare_bits : $@convention(thin) (@in MultiPayloadAddressOnlySpareBits) -> () {
|
|
entry(%m : $*MultiPayloadAddressOnlySpareBits):
|
|
destroy_addr %m : $*MultiPayloadAddressOnlySpareBits
|
|
return undef : $()
|
|
}
|
|
|
|
// Force the storage types to all be generated.
|
|
typealias AllConcreteTestEnums = (
|
|
Empty,
|
|
EmptySingleton,
|
|
Singleton,
|
|
SingletonRef,
|
|
NoPayloads,
|
|
NoPayloads2,
|
|
SinglePayloadNoXI,
|
|
SinglePayloadNoXI2,
|
|
SinglePayloadSpareBit,
|
|
SinglePayloadNested,
|
|
SinglePayloadNestedNested,
|
|
MultiPayloadNoSpareBits,
|
|
MultiPayloadOneSpareBit,
|
|
MultiPayloadTwoSpareBits,
|
|
MultiPayloadSpareBitAggregates,
|
|
MultiPayloadNested,
|
|
MultiPayloadNestedSpareBits)
|
|
|
|
sil_global @x : $AllConcreteTestEnums
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_singleton_switch_indirect(ptr noalias %0, ptr %T) {{.*}} {
|
|
// CHECK: ret void
|
|
// CHECK: }
|
|
sil @dynamic_singleton_switch_indirect : $<T> (@in DynamicSingleton<T>) -> () {
|
|
entry(%0 : $*DynamicSingleton<T>):
|
|
switch_enum_addr %0 : $*DynamicSingleton<T>, case #DynamicSingleton.value!enumelt: dest
|
|
|
|
dest:
|
|
%1 = unchecked_take_enum_data_addr %0 : $*DynamicSingleton<T>, #DynamicSingleton.value!enumelt
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// Verify that we can instantiate generic enum instances of dynamic size.
|
|
sil_global @aa : $DynamicSingleton<()>
|
|
sil_global @bb : $DynamicSingleton<NoPayloads>
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_singleton_instance_arg_1()
|
|
sil @dynamic_singleton_instance_arg_1 : $(DynamicSingleton<()>) -> () {
|
|
entry(%0 : $DynamicSingleton<()>):
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_singleton_instance_arg_2(i8 %0)
|
|
sil @dynamic_singleton_instance_arg_2 : $(DynamicSingleton<NoPayloads>) -> () {
|
|
entry(%0 : $DynamicSingleton<NoPayloads>):
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// Check that payloads get properly masked in nested single-payload enums.
|
|
// rdar://problem/18841262
|
|
// CHECK-64-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @optional_optional_class_protocol(i64 %0, i64 %1)
|
|
// CHECK-objc-64-simulator-false: icmp eq i64 %0, 2
|
|
// CHECK-objc-64-simulator-true: icmp eq i64 %0, 1
|
|
// CHECK-native-64: icmp eq i64 %0, 1
|
|
// CHECK-32-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc i1 @optional_optional_class_protocol(i32 %0, i32 %1)
|
|
// CHECK-32: icmp eq i32 %0, 1
|
|
enum Optionable<T> {
|
|
case some(T), none
|
|
}
|
|
sil @optional_optional_class_protocol : $@convention(thin) (Optionable<Optionable<PC>>) -> Builtin.Int1 {
|
|
entry(%o : $Optionable<Optionable<PC>>):
|
|
%t = integer_literal $Builtin.Int1, 1
|
|
%f = integer_literal $Builtin.Int1, 0
|
|
%r = select_enum %o : $Optionable<Optionable<PC>>, case #Optionable.some!enumelt: %t, case #Optionable.none!enumelt: %f : $Builtin.Int1
|
|
return %r : $Builtin.Int1
|
|
}
|
|
|
|
struct ContainsUnowned {
|
|
unowned let x: C
|
|
}
|
|
struct ContainsUnownedObjC {
|
|
unowned let x: C
|
|
}
|
|
// CHECK-LABEL: define {{.*}} @optional_unowned() {{.*}} {
|
|
// CHECK-objc: ret { [[WORD]], [[WORD]], i8 } { [[WORD]] 0, [[WORD]] 0, i8 1 }
|
|
// CHECK-native: ret { [[WORD]], [[WORD]] } { [[WORD]] 0, [[WORD]] 1 }
|
|
sil @optional_unowned : $@convention(thin) () -> (Optionable<ContainsUnowned>, Optionable<Optionable<ContainsUnowned>>) {
|
|
entry:
|
|
%a = enum $Optionable<ContainsUnowned>, #Optionable.none!enumelt
|
|
%b = enum $Optionable<Optionable<ContainsUnowned>>, #Optionable.none!enumelt
|
|
%t = tuple (%a : $Optionable<ContainsUnowned>, %b : $Optionable<Optionable<ContainsUnowned>>)
|
|
return %t : $(Optionable<ContainsUnowned>, Optionable<Optionable<ContainsUnowned>>)
|
|
}
|
|
// CHECK-LABEL: define {{.*}} @optional_unowned_objc() {{.*}} {
|
|
// CHECK-objc: ret { [[WORD]], [[WORD]], i8 } { [[WORD]] 0, [[WORD]] 0, i8 1 }
|
|
// CHECK-native: ret { [[WORD]], [[WORD]] } { [[WORD]] 0, [[WORD]] 1 }
|
|
sil @optional_unowned_objc : $@convention(thin) () -> (Optionable<ContainsUnownedObjC>, Optionable<Optionable<ContainsUnownedObjC>>) {
|
|
entry:
|
|
%a = enum $Optionable<ContainsUnownedObjC>, #Optionable.none!enumelt
|
|
%b = enum $Optionable<Optionable<ContainsUnownedObjC>>, #Optionable.none!enumelt
|
|
%t = tuple (%a : $Optionable<ContainsUnownedObjC>, %b : $Optionable<Optionable<ContainsUnownedObjC>>)
|
|
return %t : $(Optionable<ContainsUnownedObjC>, Optionable<Optionable<ContainsUnownedObjC>>)
|
|
}
|
|
|
|
// CHECK-64-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @empty_payload_enum_in_enum(i32 %0)
|
|
sil @empty_payload_enum_in_enum : $@convention(thin) (Int32) -> Optional<(Optional<()>, Int32)> {
|
|
entry(%x : $Int32):
|
|
%a = tuple ()
|
|
%b = enum $Optional<()>, #Optional.some!enumelt, %a : $()
|
|
%c = tuple (%b : $Optional<()>, %x : $Int32)
|
|
// CHECK-64: [[INT_ZEXT:%.*]] = zext i32 %0 to i64
|
|
// CHECK-64: [[INT_SHL:%.*]] = shl i64 [[INT_ZEXT]], 32
|
|
%d = enum $Optional<(Optional<()>, Int32)>, #Optional.some!enumelt, %c : $(Optional<()>, Int32)
|
|
// CHECK-64: [[BIT:%.*]] = trunc i64 [[INT_SHL]] to i8
|
|
// CHECK-64: [[INT_SHR:%.*]] = lshr i64 [[INT_SHL]], 32
|
|
// CHECK-64: [[INT:%.*]] = trunc i64 [[INT_SHR]] to i32
|
|
%e = unchecked_enum_data %d : $Optional<(Optional<()>, Int32)>, #Optional.some!enumelt
|
|
return %d : $Optional<(Optional<()>, Int32)>
|
|
}
|
|
|
|
sil @optional_float80 : $@convention(thin) (Float80) -> () {
|
|
entry(%x : $Float80):
|
|
%y = enum $Optional<Float80>, #Optional.some!enumelt, %x : $Float80
|
|
return undef : $()
|
|
}
|
|
|
|
// rdar://problem/21126703
|
|
|
|
protocol delegateProtocol : AnyObject { }
|
|
|
|
struct StructWithWeakVar {
|
|
weak var delegate: delegateProtocol?
|
|
}
|
|
|
|
// CHECK-64-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @weak_optional(ptr noalias dereferenceable({{.*}}) %0)
|
|
sil @weak_optional : $@convention(thin) (@in StructWithWeakVar?) -> () {
|
|
entry(%x : $*StructWithWeakVar?):
|
|
// CHECK-64: icmp eq [[WORD]] {{%.*}}, 0
|
|
// CHECK-64-NEXT: icmp eq [[WORD]] {{%.*}}, 1
|
|
switch_enum_addr %x : $*StructWithWeakVar?,
|
|
case #Optional.some!enumelt: a,
|
|
case #Optional.none!enumelt: b
|
|
a:
|
|
br x
|
|
b:
|
|
// CHECK-64: store [[WORD]] 0
|
|
// CHECK-64: store [[WORD]] 1
|
|
inject_enum_addr %x : $*StructWithWeakVar?, #Optional.none!enumelt
|
|
br x
|
|
|
|
x:
|
|
return undef : $()
|
|
}
|
|
|
|
public struct AnyError : Swift.Error { }
|
|
|
|
public enum Result<T, Error: Swift.Error> {
|
|
case success(T)
|
|
case failure(Error)
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_inject_enum_addr_with_bound_generic
|
|
sil @test_inject_enum_addr_with_bound_generic : $@convention(thin) <T> () -> @out Result<T, AnyError> {
|
|
bb0(%0 : $*Result<T, AnyError>):
|
|
// CHECK: call {{.*}} @"$s4enum6ResultOMa"
|
|
// CHECK: call void @swift_storeEnumTagMultiPayload
|
|
inject_enum_addr %0 : $*Result<T, AnyError>, #Result.success!enumelt
|
|
%r = tuple ()
|
|
// CHECK: ret void
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @force_global_variables_to_materialize
|
|
sil @force_global_variables_to_materialize : $() -> () {
|
|
entry:
|
|
// Force the global variables to materialize.
|
|
%x = global_addr @x : $*AllConcreteTestEnums
|
|
%y = load %x : $*AllConcreteTestEnums
|
|
%a = global_addr @aa : $*DynamicSingleton<()>
|
|
%q = load %a : $*DynamicSingleton<()>
|
|
%b = global_addr @bb : $*DynamicSingleton<NoPayloads>
|
|
%r = load %b : $*DynamicSingleton<NoPayloads>
|
|
%z = tuple ()
|
|
// CHECK: ret void
|
|
return %z : $()
|
|
}
|
|
|
|
enum Target {
|
|
case Public
|
|
case Friends
|
|
case SomeFriends([UInt])
|
|
}
|
|
|
|
// Ensure that we generate IR that does not run into verification
|
|
// issues for the case where there is a single tag bit and extra
|
|
// inhabitants.
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @generate_conditional_branch
|
|
sil @generate_conditional_branch : $@convention(thin) (@owned Target) -> () {
|
|
bb0(%0 : $Target):
|
|
debug_value %0 : $Target
|
|
retain_value %0 : $Target
|
|
switch_enum %0 : $Target, case #Target.Public!enumelt: bb1, default bb2
|
|
|
|
bb1:
|
|
br bb4
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
release_value %0 : $Target
|
|
br bb4
|
|
|
|
bb4:
|
|
release_value %0 : $Target
|
|
%9 = tuple ()
|
|
// CHECK: ret void
|
|
return %9 : $()
|
|
}
|
|
|
|
struct LargeStruct {
|
|
var x: Builtin.Int64
|
|
var x2: Builtin.Int64
|
|
var x3: Builtin.Int64
|
|
var x4: Builtin.Int64
|
|
var x5: Builtin.Int64
|
|
var x6: Builtin.NativeObject
|
|
}
|
|
|
|
enum MyOptional {
|
|
case None
|
|
case Some(LargeStruct)
|
|
}
|
|
|
|
// Make sure we use a memcpy for the none branch of the enum copy.
|
|
|
|
// CHECK-LABEL: define{{.*}} @test_large_optional
|
|
// CHECK: llvm.memcpy
|
|
// CHECK: ret void
|
|
sil @test_large_optional : $@convention(thin) (@in MyOptional) -> () {
|
|
entry(%x : $*MyOptional):
|
|
%stk = alloc_stack $MyOptional
|
|
copy_addr %x to [init] %stk : $*MyOptional
|
|
dealloc_stack %stk: $*MyOptional
|
|
%tuple = tuple ()
|
|
return %tuple : $()
|
|
}
|
|
|
|
// -- Fill function for dynamic singleton.
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} internal ptr @"$s4enum16DynamicSingletonOMi"(ptr %0, ptr %1, ptr %2) {{.*}} {
|
|
// CHECK: [[T:%T]] = load ptr, ptr %1,
|
|
// CHECK: [[METADATA:%.*]] = call ptr @swift_allocateGenericValueMetadata(ptr %0, ptr %1, ptr %2, [[WORD]] {{4|8}})
|
|
// CHECK-NEXT: ret ptr [[METADATA]]
|
|
|
|
// CHECK-LABEL: define{{( protected)?}} internal swiftcc %swift.metadata_response @"$s4enum16DynamicSingletonOMr"
|
|
// CHECK-SAME: (ptr [[METADATA:%.*]], ptr %0, ptr %1) {{.*}} {
|
|
// CHECK: [[T0:%.*]] = call{{( tail)?}} swiftcc %swift.metadata_response @swift_checkMetadataState([[WORD]] 319, ptr [[T]])
|
|
// CHECK: [[T_CHECKED:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK: [[T_STATUS:%.*]] = extractvalue %swift.metadata_response [[T0]], 1
|
|
// CHECK: [[T_OK:%.*]] = icmp ule [[WORD]] [[T_STATUS]], 63
|
|
// CHECK: br i1 [[T_OK]],
|
|
// CHECK: [[T_VWT_ADDR:%.*]] = getelementptr inbounds ptr, ptr [[T_CHECKED]], [[WORD]] -1
|
|
// CHECK: [[T_VWT:%.*]] = load ptr, ptr [[T_VWT_ADDR]]
|
|
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds ptr, ptr [[T_VWT]], i32 8
|
|
// CHECK: call void @swift_initEnumMetadataSingleCase(ptr [[METADATA]], [[WORD]] 0, ptr [[T_LAYOUT]])
|
|
// CHECK: [[PAYLOAD_EXTRAINHABITANTCNT:%.*]] = getelementptr inbounds{{.*}} %swift.type_layout, ptr [[T_LAYOUT]], i32 0, i32 3
|
|
// CHECK: [[CNT:%.*]] = load i32, ptr [[PAYLOAD_EXTRAINHABITANTCNT]]
|
|
// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds ptr, ptr [[METADATA]], [[WORD]] -1
|
|
// CHECK: [[VWT:%.*]] = load ptr, ptr [[VWT_ADDR]]
|
|
// CHECK: [[XIC_ADDR:%.*]] = getelementptr inbounds{{.*}} %swift.vwtable, ptr [[VWT]], i32 0, i32 11
|
|
// CHECK: store i32 [[CNT]], ptr [[XIC_ADDR]]
|
|
// CHECK: ret %swift.metadata_response
|
|
|
|
// -- Fill function for dynamic single-payload. Call into the runtime to
|
|
// calculate the size.
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} internal ptr @"$s4enum20DynamicSinglePayloadOMi"
|
|
// CHECK: [[METADATA:%.*]] = call ptr @swift_allocateGenericValueMetadata
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} internal swiftcc %swift.metadata_response @"$s4enum20DynamicSinglePayloadOMr"
|
|
// CHECK-SAME: (ptr [[METADATA:%.*]], ptr %0, ptr %1) {{.*}} {
|
|
// CHECK: [[T0:%.*]] = call{{( tail)?}} swiftcc %swift.metadata_response @swift_checkMetadataState([[WORD]] 319, ptr [[T]])
|
|
// CHECK: [[T_CHECKED:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK: [[T_STATUS:%.*]] = extractvalue %swift.metadata_response [[T0]], 1
|
|
// CHECK: [[T_OK:%.*]] = icmp ule [[WORD]] [[T_STATUS]], 63
|
|
// CHECK: br i1 [[T_OK]],
|
|
// CHECK: [[T_VWT_ADDR:%.*]] = getelementptr inbounds ptr, ptr [[T_CHECKED]], [[WORD]] -1
|
|
// CHECK: [[T_VWT:%.*]] = load ptr, ptr [[T_VWT_ADDR]]
|
|
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds ptr, ptr [[T_VWT]], i32 8
|
|
// CHECK: call void @swift_initEnumMetadataSinglePayload(ptr [[METADATA]], [[WORD]] 0, ptr [[T_LAYOUT]], i32 3)
|
|
|
|
// CHECK-64-LABEL: define internal void @"$s4enum17StructWithWeakVarVwst"(ptr noalias %value, i32 %whichCase, i32 %numEmptyCases, ptr %StructWithWeakVar)
|
|
// -- TODO: some pointless masking here.
|
|
// -- TODO: should use EnumPayload word-chunking.
|
|
// CHECK-64: [[INDEX:%.*]] = sub i32 %whichCase, 1
|
|
// CHECK-64: [[T0:%.*]] = zext i32 [[INDEX]] to i128
|
|
// -- 0xFFFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[T1:%.*]] = and i128 [[T0]], 18446744073709551615
|
|
// CHECK-64: [[T2:%.*]] = shl i128 [[T0]], 3
|
|
// -- 0xFFFF_FFFF_FFFF_FFF8__0000_0000_0000_0000
|
|
// CHECK-64: [[T3:%.*]] = and i128 [[T2]], 1329227995784915725329854470603931648
|
|
// CHECK-64: [[T4:%.*]] = or i128 [[T1]], [[T3]]
|
|
// -- 0x1__0000_0000_0000_0000
|
|
// CHECK-64: [[T5:%.*]] = or i128 [[T4]], 18446744073709551616
|
|
|
|
// CHECK-LABEL: define internal i32 @"$s4enum40MultiPayloadLessThan32BitsWithEmptyCasesOwug"(ptr noalias %value
|
|
// CHECK: [[VAL02:%.*]] = load {{.*}} %value
|
|
// CHECK: [[VAL03:%.*]] = getelementptr inbounds {{.*}} %value, i32 0, i32 1
|
|
// CHECK: [[VAL05:%.*]] = load {{.*}} [[VAL03]]
|
|
// CHECK: [[VAL06:%.*]] = zext i8 [[VAL05]] to i32
|
|
// CHECK: [[VAL07:%.*]] = zext i8 [[VAL02]] to i32
|
|
// CHECK: [[VAL08:%.*]] = and i32 [[VAL07]], 255
|
|
// CHECK: [[VAL09:%.*]] = add i32 [[VAL08]], 2
|
|
// CHECK: [[VAL10:%.*]] = icmp uge i32 [[VAL06]], 2
|
|
// CHECK: [[VAL11:%.*]] = select i1 [[VAL10]], i32 [[VAL09]], i32 [[VAL06]]
|
|
// CHECK: ret i32 [[VAL11]]
|
|
|
|
// CHECK-LABEL: define internal void @"$s4enum40MultiPayloadLessThan32BitsWithEmptyCasesOwui"(ptr noalias %value, i32 %tag
|
|
// CHECK: entry:
|
|
// CHECK: [[VAL01:%.*]] = icmp uge i32 %tag, 2
|
|
// CHECK: br i1 [[VAL01]], label %[[TLABEL:.*]], label %[[FLABEL:.*]]
|
|
|
|
// CHECK: [[TLABEL]]:
|
|
// CHECK: [[VAL02:%.*]] = sub i32 %tag, 2
|
|
// CHECK: [[VAL03:%.*]] = trunc i32 [[VAL02]] to i8
|
|
// CHECK: store i8 [[VAL03]], ptr %value
|
|
// CHECK: [[VAL05:%.*]] = getelementptr inbounds {{.*}} %value, i32 0, i32 1
|
|
// CHECK: store i8 2, ptr [[VAL05]]
|
|
// CHECK: br label %[[RLABEL:.*]]
|
|
|
|
// CHECK: [[FLABEL]]:
|
|
// CHECK: [[VAL09:%.*]] = trunc i32 %tag to i8
|
|
// CHECK: [[VAL10:%.*]] = getelementptr inbounds {{.*}} %value, i32 0, i32 1
|
|
// CHECK: store i8 [[VAL09]], ptr [[VAL10]]
|
|
// CHECK: br label %[[RLABEL]]
|
|
|
|
// CHECK: [[RLABEL]]:
|
|
// CHECK: ret void
|
|
|
|
enum MultiPayloadLessThan32BitsWithEmptyCases {
|
|
case A
|
|
case B
|
|
case C(Builtin.Int8)
|
|
case D(Builtin.Int8)
|
|
}
|