mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
2798 lines
110 KiB
Plaintext
2798 lines
110 KiB
Plaintext
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -gnone -emit-ir -disable-objc-attr-requires-foundation-module | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-runtime-%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 <{ %swift.refcounted* }>
|
|
|
|
// -- 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.
|
|
// CHECK: %T4enum20DynamicSinglePayloadO = type <{}>
|
|
// CHECK: [[DYNAMIC_SINGLE_EMPTY_PAYLOAD:%T4enum20DynamicSinglePayloadOyytG]] = type <{ [1 x i8] }>
|
|
|
|
// -- 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: [[DYNAMIC_SINGLETON:%T4enum16DynamicSingletonO.*]] = type <{}>
|
|
|
|
// CHECK: %T4enum40MultiPayloadLessThan32BitsWithEmptyCasesO = type <{ [1 x i8], [1 x i8] }>
|
|
|
|
// -- Dynamic metadata template carries a value witness table pattern
|
|
// we fill in on instantiation.
|
|
// The witness table pattern includes extra inhabitant witness
|
|
// implementations which are used if the instance has extra inhabitants.
|
|
// FIXME: Strings should be unnamed_addr. rdar://problem/22674524
|
|
// CHECK: [[DYNAMICSINGLETON_FIELD_NAMES:@.*]] = private constant [7 x i8] c"value\00\00"
|
|
// CHECK: [[DYNAMICSINGLETON_NAME:@.*]] = private constant [25 x i8] c"4enum16DynamicSingletonO\00"
|
|
// CHECK: @_T04enum16DynamicSingletonOMn = hidden constant <{ {{.*}} i32 }> <{
|
|
// CHECK-SAME: [25 x i8]* [[DYNAMICSINGLETON_NAME]]
|
|
// -- One payload
|
|
// CHECK-SAME: i32 1,
|
|
// -- No empty cases
|
|
// CHECK-SAME: i32 0,
|
|
// -- Case names
|
|
// CHECK-SAME: [[DYNAMICSINGLETON_FIELD_NAMES]]
|
|
// -- Case type accessor
|
|
// CHECK-SAME: @get_field_types_DynamicSingleton
|
|
// -- generic parameter vector offset
|
|
// CHECK-SAME: i32 2,
|
|
// -- generic parameter vector length; witness table counts
|
|
// CHECK-SAME: i32 1, i32 1
|
|
// -- nesting depth
|
|
// CHECK-SAME: i16 1
|
|
// -- flags
|
|
// CHECK-SAME: i16 0
|
|
// -- generic parameters at depth 0
|
|
// CHECK-SAME: i32 1
|
|
// CHECK-SAME: }>
|
|
|
|
// CHECK: @_T04enum16DynamicSingletonOMP = internal global <{ {{.*}}, [18 x i8*] }> <{
|
|
// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSingleton
|
|
// CHECK-SAME: @_T04enum16DynamicSingletonOMn
|
|
// CHECK-SAME: i8* null
|
|
// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum16DynamicSingletonOwxs to i8*)
|
|
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum16DynamicSingletonOwxg to i8*)
|
|
|
|
// -- No-payload enums have extra inhabitants in
|
|
// their value witness table.
|
|
// CHECK: @_T04enum10NoPayloadsOWV = internal constant [18 x i8*] [
|
|
// -- ...
|
|
// -- size
|
|
// CHECK-SAME: i8* inttoptr ([[WORD:i32|i64]] 1 to i8*),
|
|
// -- flags 0x24_0000 - alignment 1, has extra inhabitants and enum witnesses
|
|
// CHECK-SAME: i8* inttoptr ([[WORD]] 2359296 to i8*),
|
|
// -- stride
|
|
// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
|
|
// -- num extra inhabitants (256 - 3 valid states)
|
|
// CHECK-SAME: i8* inttoptr ([[WORD]] 253 to i8*)
|
|
// -- storeExtraInhabitant
|
|
// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum10NoPayloadsOwxs to i8*)
|
|
// -- getExtraInhabitantIndex
|
|
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum10NoPayloadsOwxg to i8*)
|
|
// CHECK-SAME: ]
|
|
|
|
// -- Single-payload enums take unused extra inhabitants from their payload
|
|
// as their own.
|
|
// CHECK: @_T04enum19SinglePayloadNestedOWV = internal constant [18 x i8*] [
|
|
// -- ...
|
|
// -- size
|
|
// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
|
|
// -- flags 0x4_0000 - alignment 1, has extra inhabitants
|
|
// CHECK-SAME: i8* inttoptr ([[WORD]] 2359296 to i8*),
|
|
// -- stride
|
|
// CHECK-SAME: i8* inttoptr ([[WORD]] 1 to i8*),
|
|
// -- num extra inhabitants (253 from payload - 3 empty cases)
|
|
// CHECK-SAME: i8* inttoptr ([[WORD]] 250 to i8*)
|
|
// -- storeExtraInhabitant
|
|
// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum19SinglePayloadNestedOwxs to i8*)
|
|
// -- getExtraInhabitantIndex
|
|
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum19SinglePayloadNestedOwxg to i8*)
|
|
// CHECK-SAME: ]
|
|
|
|
|
|
// CHECK: @_T04enum20DynamicSinglePayloadOMP = internal global <{ {{.*}}, [18 x i8*] }> <{
|
|
// CHECK-SAME: %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_DynamicSinglePayload
|
|
// CHECK-SAME: i8* null
|
|
// CHECK-SAME: i8* bitcast (void (%swift.opaque*, i32, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxs to i8*)
|
|
// CHECK-SAME: i8* bitcast (i32 (%swift.opaque*, %swift.type*)* @_T04enum20DynamicSinglePayloadOwxg to i8*)
|
|
|
|
// CHECK: @_T04enum18MultiPayloadNestedOWV = internal constant [18 x i8*] [
|
|
// -- size
|
|
// CHECK-32-SAME: i8* inttoptr ([[WORD]] 5 to i8*),
|
|
// CHECK-64-SAME: i8* inttoptr ([[WORD]] 9 to i8*),
|
|
// -- flags 0x250003 - alignment 4
|
|
// CHECK-32-SAME: i8* inttoptr ([[WORD]] {{2424835|2097155}} to i8*)
|
|
// -- flags 0x200007 - alignment 8
|
|
// CHECK-64-SAME: i8* inttoptr ([[WORD]] 2097159 to i8*)
|
|
// 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{{( protected)?}} swiftcc void @singleton_switch(i64, i64) {{.*}} {
|
|
// CHECK-32: define{{( protected)?}} swiftcc void @singleton_switch(%T4enum9SingletonO* noalias nocapture dereferenceable(16)) {{.*}} {
|
|
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.1: dest
|
|
|
|
// CHECK-64: ; <label>:[[DEST]]
|
|
// CHECK-32: ; <label>:[[DEST]]
|
|
dest:
|
|
// CHECK-64: ret void
|
|
// CHECK-32: ret void
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @singleton_switch_arg(i64, i64) {{.*}} {
|
|
// CHECK-32: define{{( protected)?}} swiftcc void @singleton_switch_arg(%T4enum9SingletonO* noalias nocapture dereferenceable(16)) {{.*}} {
|
|
sil @singleton_switch_arg : $(Singleton) -> () {
|
|
// CHECK-64: entry:
|
|
// CHECK-32: entry:
|
|
entry(%u : $Singleton):
|
|
// CHECK-32: call %T4enum9SingletonO* @_T04enum9SingletonOWb0_
|
|
// CHECK-64: br label %[[PREDEST:[0-9]+]]
|
|
// CHECK-32: br label %[[PREDEST:[0-9]+]]
|
|
switch_enum %u : $Singleton, case #Singleton.value!enumelt.1: dest
|
|
|
|
// CHECK-64: ; <label>:[[PREDEST]]
|
|
// CHECK-64: br label %[[DEST:[0-9]+]]
|
|
// CHECK-64: ; <label>:[[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{{( protected)?}} swiftcc void @singleton_switch_indirect(%T4enum9SingletonO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: br label %[[DEST:[0-9]+]]
|
|
// CHECK: ; <label>:[[DEST]]
|
|
// CHECK: [[ADDR:%.*]] = bitcast %T4enum9SingletonO* %0 to <{ i64, i64 }>*
|
|
// CHECK: ret void
|
|
// CHECK: }
|
|
sil @singleton_switch_indirect : $(@inout Singleton) -> () {
|
|
entry(%u : $*Singleton):
|
|
switch_enum_addr %u : $*Singleton, case #Singleton.value!enumelt.1: dest
|
|
dest:
|
|
%u2 = unchecked_take_enum_data_addr %u : $*Singleton, #Singleton.value!enumelt.1
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc { i64, i64 } @singleton_inject(i64, i64) {{.*}} {
|
|
// 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{{( protected)?}} swiftcc void @singleton_inject(%T4enum9SingletonO* noalias nocapture sret, i64, i64) {{.*}} {
|
|
// CHECK-32: entry:
|
|
// CHECK-32: [[CAST:%.*]] = bitcast %T4enum9SingletonO* %0 to <{ i64, i64 }>*
|
|
// CHECK-32: [[GEP1:%.*]] = getelementptr inbounds <{ i64, i64 }>, <{ i64, i64 }>* [[CAST]], i32 0, i32 0
|
|
// CHECK-32: store i64 %1, i64* [[GEP1]]
|
|
// CHECK-32: [[GEP2:%.*]] = getelementptr inbounds <{ i64, i64 }>, <{ i64, i64 }>* [[CAST]], i32 0, i32 1
|
|
// CHECK-32: store i64 %2, i64* [[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.1, %t : $(Builtin.Int64, Builtin.Int64)
|
|
return %u : $Singleton
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc void @singleton_inject_indirect(i64, i64, %T4enum9SingletonO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: [[DATA_ADDR:%.*]] = bitcast %T4enum9SingletonO* %2 to <{ i64, i64 }>*
|
|
// CHECK: [[DATA_0_ADDR:%.*]] = getelementptr inbounds <{ i64, i64 }>, <{ i64, i64 }>* [[DATA_ADDR]], i32 0, i32 0
|
|
// CHECK: store i64 %0, i64* [[DATA_0_ADDR]]
|
|
// CHECK: [[DATA_1_ADDR:%.*]] = getelementptr inbounds <{ i64, i64 }>, <{ i64, i64 }>* [[DATA_ADDR]], i32 0, i32 1
|
|
// CHECK: store i64 %1, i64* [[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.1
|
|
store %t to %a : $*(Builtin.Int64, Builtin.Int64)
|
|
inject_enum_addr %2 : $*Singleton, #Singleton.value!enumelt.1
|
|
%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{{( protected)?}} swiftcc void @no_payload_switch(i8) {{.*}} {
|
|
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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[END]]
|
|
// CHECK: ret void
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc void @no_payload_switch_indirect(%T4enum10NoPayloadsO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
sil @no_payload_switch_indirect : $@convention(thin) (@inout NoPayloads) -> () {
|
|
entry(%u : $*NoPayloads):
|
|
// CHECK: [[TAG_ADDR:%.*]] = getelementptr inbounds %T4enum10NoPayloadsO, %T4enum10NoPayloadsO* %0, i32 0, i32 0
|
|
// CHECK: [[TAG:%.*]] = load i8, i8* [[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{{( 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{{( 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{{( 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{{( protected)?}} swiftcc void @no_payload_inject_z_indirect(%T4enum10NoPayloadsO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: [[TAG_ADDR:%.*]] = getelementptr inbounds %T4enum10NoPayloadsO, %T4enum10NoPayloadsO* %0, i32 0, i32 0
|
|
// CHECK: store i8 2, i8* [[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{{( protected)?}} swiftcc void @no_payload_switch_2(i8) {{.*}} {
|
|
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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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-64: define{{( protected)?}} swiftcc void @single_payload_no_xi_switch([[WORD:i64]], i8) {{.*}} {
|
|
// CHECK-32: define{{( protected)?}} swiftcc void @single_payload_no_xi_switch([[WORD:i32]], i8) {{.*}} {
|
|
sil @single_payload_no_xi_switch : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
|
// CHECK: entry:
|
|
entry(%u : $SinglePayloadNoXI2):
|
|
// CHECK; %2 = trunc i8
|
|
// CHECK: br i1 %2, label %[[TAGS:[0-9]+]], label %[[X_DEST:[0-9]+]]
|
|
// CHECK: ; <label>:[[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: ; <label>:[[DFLT]]
|
|
// CHECK: unreachable
|
|
switch_enum %u : $SinglePayloadNoXI2, case #SinglePayloadNoXI2.x!enumelt.1: 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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[END]]
|
|
// CHECK: ret void
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc void @single_payload_no_xi_switch_arg([[WORD]], i8) {{.*}} {
|
|
sil @single_payload_no_xi_switch_arg : $@convention(thin) (SinglePayloadNoXI2) -> () {
|
|
// CHECK: entry:
|
|
entry(%u : $SinglePayloadNoXI2):
|
|
// CHECK: %2 = trunc i8
|
|
// CHECK: br i1 %2, label %[[TAGS:[0-9]+]], label %[[X_PREDEST:[0-9]+]]
|
|
// CHECK: ; <label>:[[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: ; <label>:[[DFLT]]
|
|
// CHECK: unreachable
|
|
switch_enum %u : $SinglePayloadNoXI2, case #SinglePayloadNoXI2.x!enumelt.1: x_dest, case #SinglePayloadNoXI2.y!enumelt: y_dest, case #SinglePayloadNoXI2.z!enumelt: z_dest, default end
|
|
|
|
// CHECK: ; <label>:[[X_PREDEST]]
|
|
// CHECK: br label %[[X_DEST:[0-9]+]]
|
|
// CHECK: ; <label>:[[SPLITEDGE]]
|
|
// CHECK: br label %[[END:[0-9]+]]
|
|
// CHECK: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[END]]
|
|
// CHECK: ret void
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc { [[WORD]], i8 } @single_payload_no_xi_inject_x([[WORD]]) {{.*}} {
|
|
// 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.1, %0 : $Builtin.Word
|
|
return %u : $SinglePayloadNoXI2
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc void @single_payload_no_xi_inject_x_indirect([[WORD]], %T4enum18SinglePayloadNoXI2O* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: [[DATA_ADDR:%.*]] = bitcast %T4enum18SinglePayloadNoXI2O* %1 to [[WORD]]*
|
|
// CHECK: store [[WORD]] %0, [[WORD]]* [[DATA_ADDR]]
|
|
// CHECK: [[T0:%.*]] = getelementptr inbounds %T4enum18SinglePayloadNoXI2O, %T4enum18SinglePayloadNoXI2O* %1, i32 0, i32 1
|
|
// CHECK: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
|
|
// CHECK: store i1 false, i1* [[TAG_ADDR]]
|
|
// 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.1
|
|
store %0 to %a : $*Builtin.Word
|
|
inject_enum_addr %1 : $*SinglePayloadNoXI2, #SinglePayloadNoXI2.x!enumelt.1
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK: define{{( 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{{( protected)?}} swiftcc void @single_payload_no_xi_inject_y_indirect(%T4enum18SinglePayloadNoXI2O* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum18SinglePayloadNoXI2O* %0 to [[WORD]]*
|
|
// CHECK: store [[WORD]] 0, [[WORD]]* [[PAYLOAD_ADDR]]
|
|
// CHECK: [[T0:%.*]] = getelementptr inbounds %T4enum18SinglePayloadNoXI2O, %T4enum18SinglePayloadNoXI2O* %0, i32 0, i32 1
|
|
// CHECK: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
|
|
// CHECK: store i1 true, i1* [[TAG_ADDR]]
|
|
// 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{{( 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{{( protected)?}} swiftcc void @aggregate_single_payload_unpack
|
|
// CHECK: ([[WORD]], [[WORD]], i8) {{.*}} {
|
|
sil @aggregate_single_payload_unpack : $@convention(thin) (AggregateSinglePayload) -> () {
|
|
entry(%u : $AggregateSinglePayload):
|
|
switch_enum %u : $AggregateSinglePayload, case #AggregateSinglePayload.x!enumelt.1: x_dest, default end
|
|
|
|
// 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
|
|
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc { [[WORD]], [[WORD]] } @aggregate_single_payload_unsafe_unpack([[WORD]], [[WORD]], i8) {{.*}} {
|
|
// 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.1
|
|
return %x : $(Builtin.Word, Builtin.Word)
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc { [[WORD]], [[WORD]], i8 } @aggregate_single_payload_inject([[WORD]], [[WORD]]) {{.*}} {
|
|
// 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.1, %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{{( protected)?}} swiftcc void @aggregate_single_payload_unpack_2([[WORD]], [[WORD]], [[WORD]], [[WORD]]) {{.*}} {
|
|
// CHECK-32: define{{( protected)?}} swiftcc void @aggregate_single_payload_unpack_2(%T4enum23AggregateSinglePayload2O* noalias nocapture dereferenceable(16)) {{.*}} {
|
|
sil @aggregate_single_payload_unpack_2 : $@convention(thin) (AggregateSinglePayload2) -> () {
|
|
entry(%u : $AggregateSinglePayload2):
|
|
switch_enum %u : $AggregateSinglePayload2, case #AggregateSinglePayload2.x!enumelt.1: x_dest, default end
|
|
|
|
// 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
|
|
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc { [[WORD]], [[WORD]], [[WORD]], [[WORD]] } @aggregate_single_payload_2_inject(i32, [[WORD]], [[WORD]], [[WORD]]) {{.*}} {
|
|
// 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{{( protected)?}} swiftcc void @aggregate_single_payload_2_inject(%T4enum23AggregateSinglePayload2O* noalias nocapture sret, i32, i32, i32, i32) {{.*}} {
|
|
// CHECK-32: [[TRUNC:%.*]] = trunc i32 %1 to i21
|
|
// CHECK-32: [[ZEXT:%.*]] = zext i21 [[TRUNC]] to i32
|
|
// CHECK-32: [[CAST:%.*]] = bitcast %T4enum23AggregateSinglePayload2O* %0 to { i32, i32, i32, i32 }*
|
|
// CHECK-32: [[GEP:%.*]] = getelementptr inbounds {{.*}} [[CAST]], i32 0, i32 0
|
|
// CHECK-32: store i32 [[ZEXT]], i32* [[GEP]]
|
|
// CHECK-32: store i32 %2, i32*
|
|
// CHECK-32: store i32 %3, i32*
|
|
// CHECK-32: store i32 %4, i32*
|
|
// 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.1, %t : $(CharLike, IntLike, RangeLike)
|
|
return %u : $AggregateSinglePayload2
|
|
}
|
|
|
|
enum AggregateSinglePayload3 {
|
|
case x(Builtin.Int21, Builtin.Word)
|
|
case y
|
|
case z
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc void @aggregate_single_payload_unpack_3([[WORD]], [[WORD]]) {{.*}} {
|
|
sil @aggregate_single_payload_unpack_3 : $@convention(thin) (AggregateSinglePayload3) -> () {
|
|
entry(%u : $AggregateSinglePayload3):
|
|
switch_enum %u : $AggregateSinglePayload3, case #AggregateSinglePayload3.x!enumelt.1: x_dest, default end
|
|
|
|
// 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
|
|
|
|
end:
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc { [[WORD]], [[WORD]] } @aggregate_single_payload_inject_x3(i32, [[WORD]]) {{.*}} {
|
|
// 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.1, %t : $(Builtin.Int21, Builtin.Word)
|
|
return %u : $AggregateSinglePayload3
|
|
}
|
|
|
|
// CHECK: define{{( 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{{( protected)?}} swiftcc void @single_payload_spare_bit_switch(i64) {{.*}} {
|
|
// CHECK-32: define{{( protected)?}} swiftcc void @single_payload_spare_bit_switch(i32, i32) {{.*}} {
|
|
sil @single_payload_spare_bit_switch : $@convention(thin) (SinglePayloadSpareBit) -> () {
|
|
// CHECK: entry:
|
|
entry(%u : $SinglePayloadSpareBit):
|
|
// CHECK-64: switch i64 %0, label %[[X_DEST:[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: ]
|
|
|
|
// CHECK-32: switch i32 %0, label %[[X_DEST:[0-9]+]] [
|
|
// CHECK-32: i32 0, label %[[Y_HIGH:[0-9]+]]
|
|
// CHECK-32: i32 1, label %[[Z_HIGH:[0-9]+]]
|
|
// CHECK-32: ]
|
|
// CHECK-32: ; <label>:[[Y_HIGH]]
|
|
// CHECK-32: [[IS_Y:%.*]] = icmp eq i32 %1, -2147483648
|
|
// CHECK-32: br i1 [[IS_Y]], label %[[Y_DEST:[0-9]+]], label %[[X_DEST]]
|
|
// CHECK-32: ; <label>:[[Z_HIGH]]
|
|
// CHECK-32: [[IS_Z:%.*]] = icmp eq i32 %1, -2147483648
|
|
// CHECK-32: br i1 [[IS_Z]], label %[[Z_DEST:[0-9]+]], label %[[X_DEST]]
|
|
switch_enum %u : $SinglePayloadSpareBit, case #SinglePayloadSpareBit.x!enumelt.1: x_dest, case #SinglePayloadSpareBit.y!enumelt: y_dest, case #SinglePayloadSpareBit.z!enumelt: z_dest
|
|
|
|
// CHECK: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[END]]
|
|
end:
|
|
// CHECK: ret void
|
|
%x = tuple ()
|
|
return %x : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @single_payload_spare_bit_switch_arg(i64) {{.*}} {
|
|
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.1: x_dest, case #SinglePayloadSpareBit.y!enumelt: y_dest, case #SinglePayloadSpareBit.z!enumelt: z_dest
|
|
|
|
// CHECK-64: ; <label>:[[X_PREDEST]]
|
|
// CHECK-64: [[TRUNC_PAYLOAD:%.*]] = trunc i64 %0 to i63
|
|
// CHECK-64: br label %[[X_DEST:[0-9]+]]
|
|
// CHECK-64: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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_ADDR:%.*]] = bitcast %T4enum21SinglePayloadSpareBitO* %0 to i64*
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
|
|
// CHECK-64: switch i64 [[PAYLOAD]]
|
|
switch_enum_addr %u : $*SinglePayloadSpareBit, case #SinglePayloadSpareBit.x!enumelt.1: x_dest, case #SinglePayloadSpareBit.y!enumelt: y_dest, case #SinglePayloadSpareBit.z!enumelt: z_dest
|
|
|
|
// CHECK-64: ; <label>:
|
|
// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum21SinglePayloadSpareBitO* %0 to i63*
|
|
x_dest:
|
|
%u2 = unchecked_take_enum_data_addr %u : $*SinglePayloadSpareBit, #SinglePayloadSpareBit.x!enumelt.1
|
|
%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{{( protected)?}} swiftcc i64 @single_payload_spare_bit_inject_x(i64) {{.*}} {
|
|
// 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.1, %0 : $Builtin.Int63
|
|
return %u : $SinglePayloadSpareBit
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @single_payload_spare_bit_inject_x_indirect(i64, %T4enum21SinglePayloadSpareBitO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[T:%.*]] = trunc i64 %0 to i63
|
|
// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum21SinglePayloadSpareBitO* %1 to i63*
|
|
// CHECK-64: store i63 [[T]], i63* [[DATA_ADDR]]
|
|
// 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.1
|
|
store %0 to %a : $*Builtin.Int63
|
|
inject_enum_addr %1 : $*SinglePayloadSpareBit, #SinglePayloadSpareBit.x!enumelt.1
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( 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{{( protected)?}} swiftcc void @single_payload_spare_bit_inject_y_indirect(%T4enum21SinglePayloadSpareBitO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum21SinglePayloadSpareBitO* %0 to i64*
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK-64: store i64 -9223372036854775808, i64* [[PAYLOAD_ADDR]]
|
|
// 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{{( 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{{( protected)?}} swiftcc void @single_payload_nested_switch(i8) {{.*}} {
|
|
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.1: 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.1: 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 @_T04enum1CCfD : $@convention(method) (C) -> ()
|
|
|
|
@objc class OC {}
|
|
sil_vtable OC {}
|
|
sil hidden @_T04enum2OCCACycfcTo : $@convention(thin) (OC) -> OC {
|
|
entry(%x : $OC):
|
|
return %x : $OC
|
|
}
|
|
|
|
enum SinglePayloadClass {
|
|
case x(C)
|
|
case y
|
|
case z
|
|
case w
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @single_payload_class_switch(i64) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: switch i64 %0, label {{%.*}} [
|
|
// CHECK-64: i64 0, label {{%.*}}
|
|
// CHECK-64: i64 2, label {{%.*}}
|
|
// CHECK-64: i64 4, label {{%.*}}
|
|
// CHECK-64: ]
|
|
// CHECK-64: ; <label>
|
|
// CHECK-64: inttoptr [[WORD]] %0 to %T4enum1CC*
|
|
|
|
// CHECK-32: define{{( protected)?}} swiftcc void @single_payload_class_switch(i32) {{.*}} {
|
|
// CHECK-32: entry:
|
|
// CHECK-32: switch i32 %0, label {{%.*}} [
|
|
// CHECK-32: i32 0, label {{%.*}}
|
|
// CHECK-32: i32 1, label {{%.*}}
|
|
// CHECK-32: i32 2, label {{%.*}}
|
|
// CHECK-32: ]
|
|
// CHECK-32: ; <label>
|
|
// CHECK-32: inttoptr [[WORD]] %0 to %T4enum1CC*
|
|
|
|
sil @single_payload_class_switch : $(SinglePayloadClass) -> () {
|
|
entry(%c : $SinglePayloadClass):
|
|
switch_enum %c : $SinglePayloadClass, case #SinglePayloadClass.x!enumelt.1: 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 {}
|
|
@objc protocol PO {}
|
|
|
|
enum SinglePayloadClassProtocol {
|
|
case x(PC)
|
|
case y, z, w
|
|
}
|
|
|
|
enum SinglePayloadObjCProtocol {
|
|
case x(PO)
|
|
case y, z, w
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @single_payload_class_protocol_switch(i64, i64) {{.*}} {
|
|
// CHECK-64: switch i64 %0, label {{%.*}} [
|
|
// CHECK-64: i64 0, label {{%.*}}
|
|
// CHECK-64: i64 2, label {{%.*}}
|
|
// CHECK-64: i64 4, label {{%.*}}
|
|
// CHECK-64: ]
|
|
|
|
// CHECK-objc-64: inttoptr i64 %0 to %objc_object*
|
|
// CHECK-native-64: inttoptr i64 %0 to %swift.refcounted*
|
|
// CHECK-64: inttoptr i64 %1 to i8**
|
|
|
|
// CHECK-32: define{{( protected)?}} swiftcc void @single_payload_class_protocol_switch(i32, i32) {{.*}} {
|
|
// 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 %objc_object*
|
|
// CHECK-native-32: inttoptr i32 %0 to %swift.refcounted*
|
|
// CHECK-32: inttoptr i32 %1 to i8**
|
|
|
|
sil @single_payload_class_protocol_switch : $(SinglePayloadClassProtocol) -> () {
|
|
entry(%c : $SinglePayloadClassProtocol):
|
|
switch_enum %c : $SinglePayloadClassProtocol, case #SinglePayloadClassProtocol.x!enumelt.1: 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 : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @single_payload_objc_protocol_switch(i64) {{.*}} {
|
|
// CHECK-64: switch i64 %0, label {{%.*}}
|
|
// CHECK-64: i64 0, label {{%.*}}
|
|
// CHECK-64: i64 2, label {{%.*}}
|
|
// CHECK-64: i64 4, label {{%.*}}
|
|
// CHECK-64: ]
|
|
// CHECK-objc-64: inttoptr i64 %0 to %objc_object*
|
|
// CHECK-native-64: inttoptr i64 %0 to %swift.refcounted*
|
|
|
|
// CHECK-32: define{{( protected)?}} swiftcc void @single_payload_objc_protocol_switch(i32) {{.*}} {
|
|
// 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 %objc_object*
|
|
// CHECK-native-32: inttoptr i32 %0 to %swift.refcounted*
|
|
|
|
sil @single_payload_objc_protocol_switch : $(SinglePayloadObjCProtocol) -> () {
|
|
entry(%c : $SinglePayloadObjCProtocol):
|
|
switch_enum %c : $SinglePayloadObjCProtocol, case #SinglePayloadObjCProtocol.x!enumelt.1: x_dest, case #SinglePayloadObjCProtocol.y!enumelt: y_dest, case #SinglePayloadObjCProtocol.z!enumelt: z_dest, case #SinglePayloadObjCProtocol.w!enumelt: w_dest
|
|
|
|
x_dest(%d : $PO):
|
|
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{{( protected)?}} swiftcc void @dynamic_single_payload_switch(%T4enum20DynamicSinglePayloadO* noalias nocapture, %swift.type* %T) {{.*}} {
|
|
// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T4enum20DynamicSinglePayloadO* %0 to %swift.opaque*
|
|
// CHECK: [[TMP:%.*]] = bitcast %swift.type* %T to i8***
|
|
// CHECK: [[TMP2:%.*]] = getelementptr inbounds i8**, i8*** [[TMP]], i{{.*}} -1
|
|
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[TMP2]]
|
|
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 7
|
|
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[ENUMADDR]]
|
|
// CHECK: %getEnumTagSinglePayload = bitcast i8* [[WITNESS]] to i32 (%swift.opaque*, i32, %swift.type*)*
|
|
// CHECK: [[CASE_INDEX:%.*]] = call i32 %getEnumTagSinglePayload(%swift.opaque* noalias [[OPAQUE_ENUM]], i32 3, %swift.type* %T)
|
|
// CHECK: switch i32 [[CASE_INDEX]], label {{%.*}} [
|
|
// CHECK: i32 -1, label {{%.*}}
|
|
// CHECK: i32 2, 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.1: 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{{( protected)?}} swiftcc void @dynamic_single_payload_inject_x(%T4enum20DynamicSinglePayloadO* noalias nocapture sret, %swift.opaque* noalias nocapture, %swift.type* %T) {{.*}} {
|
|
// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T4enum20DynamicSinglePayloadO* %0 to %swift.opaque*
|
|
// CHECK: [[TMP:%.*]] = bitcast %swift.type* %T to i8***
|
|
// CHECK: [[TMP2:%.*]] = getelementptr inbounds i8**, i8*** [[TMP]], i{{.*}} -1
|
|
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[TMP2]]
|
|
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
|
|
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[ENUMADDR]]
|
|
// CHECK: %storeEnumTagSinglePayload = bitcast i8* [[WITNESS]] to void (%swift.opaque*, i32, i32, %swift.type*)*
|
|
// CHECK: call void %storeEnumTagSinglePayload(%swift.opaque* noalias [[OPAQUE_ENUM]], i32 -1, i32 3, %swift.type* %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.1
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc void @dynamic_single_payload_inject_y(%T4enum20DynamicSinglePayloadO* noalias nocapture sret, %swift.type* %T) {{.*}} {
|
|
// CHECK: [[OPAQUE_ENUM:%.*]] = bitcast %T4enum20DynamicSinglePayloadO* %0 to %swift.opaque*
|
|
// CHECK: [[TMP:%.*]] = bitcast %swift.type* %T to i8***
|
|
// CHECK: [[TMP2:%.*]] = getelementptr inbounds i8**, i8*** [[TMP]], i{{.*}} -1
|
|
// CHECK: [[VWT:%.*]] = load i8**, i8*** [[TMP2]]
|
|
// CHECK: [[ENUMADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 8
|
|
// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[ENUMADDR]]
|
|
// CHECK: %storeEnumTagSinglePayload = bitcast i8* [[WITNESS]] to void (%swift.opaque*, i32, i32, %swift.type*)*
|
|
// CHECK: call void %storeEnumTagSinglePayload(%swift.opaque* noalias [[OPAQUE_ENUM]], i32 0, i32 3, %swift.type* %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{{( protected)?}} swiftcc void @dynamic_single_payload_empty_payload_switch(i8) {{.*}} {
|
|
// 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.1: 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{{( protected)?}} swiftcc i8 @dynamic_single_payload_empty_payload_load([[DYNAMIC_SINGLE_EMPTY_PAYLOAD]]* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: %1 = bitcast [[DYNAMIC_SINGLE_EMPTY_PAYLOAD]]* %0 to i8*
|
|
// CHECK: %2 = load i8, i8* %1
|
|
// CHECK: ret i8 %2
|
|
// CHECK: }
|
|
sil @dynamic_single_payload_empty_payload_load : $(@inout DynamicSinglePayload<()>) -> DynamicSinglePayload<()> {
|
|
entry(%p : $*DynamicSinglePayload<()>):
|
|
%x = load %p : $*DynamicSinglePayload<()>
|
|
return %x : $DynamicSinglePayload<()>
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} swiftcc void @dynamic_single_payload_empty_payload_store([[DYNAMIC_SINGLE_EMPTY_PAYLOAD]]* nocapture dereferenceable({{.*}}), i8) {{.*}} {
|
|
// CHECK: entry:
|
|
// CHECK: %2 = bitcast [[DYNAMIC_SINGLE_EMPTY_PAYLOAD]]* %0 to i8*
|
|
// CHECK: store i8 %1, i8* %2
|
|
// 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{{( 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{{( 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{{( protected)?}} swiftcc void @dynamic_single_payload_generic_destroy
|
|
// CHECK: br i1
|
|
// CHECK: <label>
|
|
// CHECK: call void %destroy
|
|
// CHECK: <label>
|
|
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{{( protected)?}} swiftcc void @multi_payload_no_spare_bits_switch(i64, i8) {{.*}} {
|
|
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: ; <label>:[[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: ; <label>:[[UNREACHABLE]]
|
|
// CHECK-64: unreachable
|
|
switch_enum %u : $MultiPayloadNoSpareBits, case #MultiPayloadNoSpareBits.x!enumelt.1: x_dest, case #MultiPayloadNoSpareBits.y!enumelt.1: y_dest, case #MultiPayloadNoSpareBits.z!enumelt.1: z_dest, case #MultiPayloadNoSpareBits.a!enumelt: a_dest, case #MultiPayloadNoSpareBits.b!enumelt: b_dest, case #MultiPayloadNoSpareBits.c!enumelt: c_dest
|
|
|
|
// CHECK-64: ; <label>:[[X_PREDEST]]
|
|
// CHECK-64: br label %[[X_DEST:[0-9]+]]
|
|
// CHECK-64: ; <label>:[[Y_PREDEST]]
|
|
// CHECK-64: [[Y_VALUE:%.*]] = trunc i64 %0 to i32
|
|
// CHECK-64: br label %[[Y_DEST:[0-9]+]]
|
|
// CHECK-64: ; <label>:[[Z_PREDEST]]
|
|
// CHECK-64: [[Z_VALUE:%.*]] = trunc i64 %0 to i63
|
|
// CHECK-64: br label %[[Z_DEST:[0-9]+]]
|
|
|
|
// CHECK-64: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[A_DEST]]
|
|
a_dest:
|
|
%d = function_ref @d : $@convention(thin) () -> ()
|
|
apply %d() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: ; <label>:[[B_DEST]]
|
|
b_dest:
|
|
%e = function_ref @e : $@convention(thin) () -> ()
|
|
apply %e() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: ; <label>:[[C_DEST]]
|
|
c_dest:
|
|
%f = function_ref @f : $@convention(thin) () -> ()
|
|
apply %f() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
end:
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_no_spare_bits_switch_indirect(%T4enum23MultiPayloadNoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
sil @multi_payload_no_spare_bits_switch_indirect : $(@inout MultiPayloadNoSpareBits) -> () {
|
|
entry(%u : $*MultiPayloadNoSpareBits):
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadNoSpareBitsO* %0 to i64*
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadNoSpareBitsO, %T4enum23MultiPayloadNoSpareBitsO* %0, i32 0, i32 1
|
|
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i8*
|
|
// CHECK-64: [[TAG:%.*]] = load i8, i8* [[TAG_ADDR]]
|
|
// CHECK-64: switch i8 [[TAG]]
|
|
// CHECK-64: switch i64 [[PAYLOAD]]
|
|
// CHECK-64: ; <label>:
|
|
// CHECK-64: unreachable
|
|
switch_enum_addr %u : $*MultiPayloadNoSpareBits, case #MultiPayloadNoSpareBits.x!enumelt.1: x_dest, case #MultiPayloadNoSpareBits.y!enumelt.1: y_dest, case #MultiPayloadNoSpareBits.z!enumelt.1: z_dest, case #MultiPayloadNoSpareBits.a!enumelt: a_dest, case #MultiPayloadNoSpareBits.b!enumelt: b_dest, case #MultiPayloadNoSpareBits.c!enumelt: c_dest
|
|
|
|
// CHECK-64: ; <label>:[[X_DEST:[0-9]+]]
|
|
// CHECK-64: bitcast %T4enum23MultiPayloadNoSpareBitsO* %0 to i64*
|
|
// CHECK-64: ; <label>:[[Y_DEST:[0-9]+]]
|
|
// CHECK-64: bitcast %T4enum23MultiPayloadNoSpareBitsO* %0 to i32*
|
|
// CHECK-64: ; <label>:[[Z_DEST:[0-9]+]]
|
|
// CHECK-64: bitcast %T4enum23MultiPayloadNoSpareBitsO* %0 to i63*
|
|
|
|
x_dest:
|
|
%x = unchecked_take_enum_data_addr %u : $*MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.x!enumelt.1
|
|
br end
|
|
|
|
y_dest:
|
|
%y = unchecked_take_enum_data_addr %u : $*MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.y!enumelt.1
|
|
br end
|
|
|
|
z_dest:
|
|
%z = unchecked_take_enum_data_addr %u : $*MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.z!enumelt.1
|
|
br end
|
|
|
|
a_dest:
|
|
br end
|
|
|
|
b_dest:
|
|
br end
|
|
|
|
c_dest:
|
|
br end
|
|
|
|
end:
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc { i64, i8 } @multi_payload_no_spare_bit_inject_x(i64) {{.*}} {
|
|
// 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.1, %0 : $Builtin.Int64
|
|
return %u : $MultiPayloadNoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_no_spare_bit_inject_x_indirect(i64, %T4enum23MultiPayloadNoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum23MultiPayloadNoSpareBitsO* %1 to i64*
|
|
// CHECK-64: store i64 %0, i64* [[DATA_ADDR]]
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadNoSpareBitsO, %T4enum23MultiPayloadNoSpareBitsO* %1, i32 0, i32 1
|
|
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i8*
|
|
// CHECK-64: store i8 0, i8* [[TAG_ADDR]]
|
|
// 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.1
|
|
store %0 to %a : $*Builtin.Int64
|
|
inject_enum_addr %1 : $*MultiPayloadNoSpareBits, #MultiPayloadNoSpareBits.x!enumelt.1
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc { i64, i8 } @multi_payload_no_spare_bit_inject_y(i32) {{.*}} {
|
|
// 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.1, %0 : $Builtin.Int32
|
|
return %u : $MultiPayloadNoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc { i64, i8 } @multi_payload_no_spare_bit_inject_z(i64) {{.*}} {
|
|
// 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.1, %0 : $Builtin.Int63
|
|
return %u : $MultiPayloadNoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( 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{{( protected)?}} swiftcc void @multi_payload_no_spare_bit_inject_a_indirect(%T4enum23MultiPayloadNoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadNoSpareBitsO* %0 to i64*
|
|
// CHECK-64: store i64 0, i64* [[PAYLOAD_ADDR]]
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadNoSpareBitsO, %T4enum23MultiPayloadNoSpareBitsO* %0, i32 0, i32 1
|
|
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i8*
|
|
// CHECK-64: store i8 3, i8* [[TAG_ADDR]]
|
|
// 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{{( 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{{( 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{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_switch(i64, i8) {{.*}} {
|
|
sil @multi_payload_one_spare_bit_switch : $(MultiPayloadOneSpareBit) -> () {
|
|
entry(%u : $MultiPayloadOneSpareBit):
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i8 %1 to i1
|
|
// 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_ZEXT:%.*]] = zext i1 [[NATIVECC_TRUNC]] to i8
|
|
// CHECK-64: [[EXTRA_TAG:%.*]] = shl i8 [[EXTRA_TAG_ZEXT]], 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: ; <label>:[[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: ; <label>:[[UNREACHABLE]]
|
|
// CHECK-64: unreachable
|
|
switch_enum %u : $MultiPayloadOneSpareBit, case #MultiPayloadOneSpareBit.x!enumelt.1: x_dest, case #MultiPayloadOneSpareBit.y!enumelt.1: y_dest, case #MultiPayloadOneSpareBit.z!enumelt.1: z_dest, case #MultiPayloadOneSpareBit.a!enumelt: a_dest, case #MultiPayloadOneSpareBit.b!enumelt: b_dest, case #MultiPayloadOneSpareBit.c!enumelt: c_dest
|
|
|
|
// CHECK-64: ; <label>:[[X_PREDEST]]
|
|
// CHECK-64: [[X_VALUE:%.*]] = trunc i64 %0 to i62
|
|
// CHECK-64: br label %[[X_DEST:[0-9]+]]
|
|
// CHECK-64: ; <label>:[[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: ; <label>:[[Z_PREDEST]]
|
|
// CHECK-64: [[Z_VALUE:%.*]] = trunc i64 %0 to i61
|
|
// CHECK-64: br label %[[Z_DEST:[0-9]+]]
|
|
|
|
// CHECK-64: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[A_DEST]]
|
|
a_dest:
|
|
%d = function_ref @d : $@convention(thin) () -> ()
|
|
apply %d() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: ; <label>:[[B_DEST]]
|
|
b_dest:
|
|
%e = function_ref @e : $@convention(thin) () -> ()
|
|
apply %e() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: ; <label>:[[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_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i64*
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, %T4enum23MultiPayloadOneSpareBitO* %0, i32 0, i32 1
|
|
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
|
|
// CHECK-64: [[TAG:%.*]] = load i1, i1* [[TAG_ADDR]]
|
|
// CHECK-64: switch i8 {{%.*}}
|
|
// CHECK-64: switch i64 [[PAYLOAD]]
|
|
// CHECK-64: ; <label>:
|
|
// CHECK-64: unreachable
|
|
switch_enum_addr %u : $*MultiPayloadOneSpareBit, case #MultiPayloadOneSpareBit.x!enumelt.1: x_dest, case #MultiPayloadOneSpareBit.y!enumelt.1: y_dest, case #MultiPayloadOneSpareBit.z!enumelt.1: z_dest, case #MultiPayloadOneSpareBit.a!enumelt: a_dest, case #MultiPayloadOneSpareBit.b!enumelt: b_dest, case #MultiPayloadOneSpareBit.c!enumelt: c_dest
|
|
|
|
// CHECK-64: ; <label>:[[X_PREDEST:[0-9]+]]
|
|
// CHECK-64: bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i62*
|
|
|
|
// CHECK-64: ; <label>:[[Y_PREDEST:[0-9]+]]
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i64*
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
|
|
// -- 0x7FFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i64*
|
|
// CHECK-64: store i64 [[PAYLOAD_MASKED]], i64* [[PAYLOAD_ADDR]]
|
|
// CHECK-64: bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i63*
|
|
|
|
// CHECK-64: ; <label>:[[Z_PREDEST:[0-9]+]]
|
|
// CHECK-64: bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i61*
|
|
|
|
x_dest:
|
|
%x = unchecked_take_enum_data_addr %u : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.x!enumelt.1
|
|
br end
|
|
|
|
y_dest:
|
|
%y = unchecked_take_enum_data_addr %u : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.y!enumelt.1
|
|
br end
|
|
|
|
z_dest:
|
|
%z = unchecked_take_enum_data_addr %u : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.z!enumelt.1
|
|
br end
|
|
|
|
a_dest:
|
|
br end
|
|
|
|
b_dest:
|
|
br end
|
|
|
|
c_dest:
|
|
br end
|
|
|
|
end:
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc { i64, i8 } @multi_payload_one_spare_bit_inject_x(i64) {{.*}} {
|
|
// 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.1, %0 : $Builtin.Int62
|
|
return %u : $MultiPayloadOneSpareBit
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_x_indirect(i64, %T4enum23MultiPayloadOneSpareBitO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62
|
|
// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i62*
|
|
// CHECK-64: store i62 [[NATIVECC_TRUNC]], i62* [[DATA_ADDR]]
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i64*
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
|
|
// -- 0x7FFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 9223372036854775807
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i64*
|
|
// CHECK-64: store i64 [[PAYLOAD_MASKED]], i64* [[PAYLOAD_ADDR]]
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, %T4enum23MultiPayloadOneSpareBitO* %1, i32 0, i32 1
|
|
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
|
|
// CHECK-64: store i1 false, i1* [[TAG_ADDR]]
|
|
// 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.1
|
|
store %0 to %a : $*Builtin.Int62
|
|
inject_enum_addr %1 : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.x!enumelt.1
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc { i64, i8 } @multi_payload_one_spare_bit_inject_y(i64) {{.*}} {
|
|
// 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.1, %0 : $Builtin.Int63
|
|
return %u : $MultiPayloadOneSpareBit
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_y_indirect(i64, %T4enum23MultiPayloadOneSpareBitO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i63
|
|
// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i63*
|
|
// CHECK-64: store i63 [[NATIVECC_TRUNC]], i63* [[DATA_ADDR]]
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i64*
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
|
|
// -- 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: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %1 to i64*
|
|
// CHECK-64: store i64 [[PAYLOAD_TAGGED]], i64* [[PAYLOAD_ADDR]]
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, %T4enum23MultiPayloadOneSpareBitO* %1, i32 0, i32 1
|
|
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
|
|
// CHECK-64: store i1 false, i1* [[TAG_ADDR]]
|
|
// 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.1
|
|
store %0 to %a : $*Builtin.Int63
|
|
inject_enum_addr %1 : $*MultiPayloadOneSpareBit, #MultiPayloadOneSpareBit.y!enumelt.1
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc { i64, i8 } @multi_payload_one_spare_bit_inject_z(i64) {{.*}} {
|
|
// 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.1, %0 : $Builtin.Int61
|
|
return %u : $MultiPayloadOneSpareBit
|
|
}
|
|
|
|
// CHECK-64: define{{( 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{{( protected)?}} swiftcc void @multi_payload_one_spare_bit_inject_a_indirect(%T4enum23MultiPayloadOneSpareBitO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum23MultiPayloadOneSpareBitO* %0 to i64*
|
|
// -- 0x8000_0000_0000_0000
|
|
// CHECK-64: store i64 -9223372036854775808, i64* [[PAYLOAD_ADDR]]
|
|
// CHECK-64: [[T0:%.*]] = getelementptr inbounds %T4enum23MultiPayloadOneSpareBitO, %T4enum23MultiPayloadOneSpareBitO* %0, i32 0, i32 1
|
|
// CHECK-64: [[TAG_ADDR:%.*]] = bitcast [1 x i8]* [[T0]] to i1*
|
|
// CHECK-64: store i1 true, i1* [[TAG_ADDR]]
|
|
// 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{{( 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{{( 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{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_switch(i64) {{.*}} {
|
|
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: ; <label>:[[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: ; <label>:[[UNREACHABLE]]
|
|
// CHECK-64: unreachable
|
|
switch_enum %u : $MultiPayloadTwoSpareBits, case #MultiPayloadTwoSpareBits.x!enumelt.1: x_dest, case #MultiPayloadTwoSpareBits.y!enumelt.1: y_dest, case #MultiPayloadTwoSpareBits.z!enumelt.1: z_dest, case #MultiPayloadTwoSpareBits.a!enumelt: a_dest, case #MultiPayloadTwoSpareBits.b!enumelt: b_dest, case #MultiPayloadTwoSpareBits.c!enumelt: c_dest
|
|
|
|
// CHECK-64: ; <label>:[[X_PREDEST]]
|
|
// CHECK-64: [[X_VALUE:%.*]] = trunc i64 %0 to i62
|
|
// CHECK-64: br label %[[X_DEST:[0-9]+]]
|
|
|
|
// CHECK-64: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[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: ; <label>:[[A_DEST]]
|
|
a_dest:
|
|
%d = function_ref @d : $@convention(thin) () -> ()
|
|
apply %d() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: ; <label>:[[B_DEST]]
|
|
b_dest:
|
|
%e = function_ref @e : $@convention(thin) () -> ()
|
|
apply %e() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
// CHECK-64: ; <label>:[[C_DEST]]
|
|
c_dest:
|
|
%f = function_ref @f : $@convention(thin) () -> ()
|
|
apply %f() : $@convention(thin) () -> ()
|
|
br end
|
|
|
|
end:
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc i64 @multi_payload_two_spare_bits_inject_x(i64) {{.*}} {
|
|
// 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.1, %0 : $Builtin.Int62
|
|
return %u : $MultiPayloadTwoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_x_indirect(i64, %T4enum24MultiPayloadTwoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i62
|
|
// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i62*
|
|
// CHECK-64: store i62 [[NATIVECC_TRUNC]], i62* [[DATA_ADDR]]
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i64*
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
|
|
// -- 0x3FFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: [[PAYLOAD_MASKED:%.*]] = and i64 [[PAYLOAD]], 4611686018427387903
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i64*
|
|
// CHECK-64: store i64 [[PAYLOAD_MASKED]], i64* [[PAYLOAD_ADDR]]
|
|
// 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.1
|
|
store %0 to %a : $*Builtin.Int62
|
|
inject_enum_addr %1 : $*MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.x!enumelt.1
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc i64 @multi_payload_two_spare_bits_inject_y(i64) {{.*}} {
|
|
// 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.1, %0 : $Builtin.Int60
|
|
return %u : $MultiPayloadTwoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_y_indirect(i64, %T4enum24MultiPayloadTwoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[NATIVECC_TRUNC:%.*]] = trunc i64 %0 to i60
|
|
// CHECK-64: [[DATA_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i60*
|
|
// CHECK-64: store i60 [[NATIVECC_TRUNC]], i60* [[DATA_ADDR]]
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i64*
|
|
// CHECK-64: [[PAYLOAD:%.*]] = load i64, i64* [[PAYLOAD_ADDR]]
|
|
// -- 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: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %1 to i64*
|
|
// CHECK-64: store i64 [[PAYLOAD_TAGGED]], i64* [[PAYLOAD_ADDR]]
|
|
// 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.1
|
|
store %0 to %a : $*Builtin.Int60
|
|
inject_enum_addr %1 : $*MultiPayloadTwoSpareBits, #MultiPayloadTwoSpareBits.y!enumelt.1
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
|
|
// CHECK-64: define{{( protected)?}} swiftcc i64 @multi_payload_two_spare_bits_inject_z(i64) {{.*}} {
|
|
// 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.1, %0 : $Builtin.Int61
|
|
return %u : $MultiPayloadTwoSpareBits
|
|
}
|
|
|
|
// CHECK-64: define{{( 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{{( protected)?}} swiftcc void @multi_payload_two_spare_bits_inject_a_indirect(%T4enum24MultiPayloadTwoSpareBitsO* nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: [[PAYLOAD_ADDR:%.*]] = bitcast %T4enum24MultiPayloadTwoSpareBitsO* %0 to i64*
|
|
// -- 0xC000_0000_0000_0000
|
|
// CHECK-64: store i64 -4611686018427387904, i64* [[PAYLOAD_ADDR]]
|
|
// 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{{( 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{{( 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 @_T04enum1DCfD : $@convention(method) (D) -> ()
|
|
|
|
enum MultiPayloadClasses {
|
|
case x(C)
|
|
case y(D)
|
|
case z
|
|
case w
|
|
}
|
|
|
|
// CHECK-64-LABEL: define{{( protected)?}} swiftcc void @multi_payload_classes_switch(i64) {{.*}} {
|
|
// 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 %T4enum1CC*
|
|
// -- Extract y(D)
|
|
// -- 0x3fffffffffffffff
|
|
// CHECK-64: [[MASKED:%.*]] = and i64 %0, 4611686018427387903
|
|
// CHECK-64: inttoptr i64 [[MASKED]] to %T4enum1DC*
|
|
|
|
// CHECK-32-LABEL: define{{( protected)?}} swiftcc void @multi_payload_classes_switch(i32) {{.*}} {
|
|
// 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 %T4enum1CC*
|
|
// -- Extract y(D)
|
|
// CHECK-32: [[MASKED:%.*]] = and i32 %0, -4
|
|
// CHECK-32: inttoptr i32 [[MASKED]] to %T4enum1DC*
|
|
|
|
sil @multi_payload_classes_switch : $(MultiPayloadClasses) -> () {
|
|
entry(%c : $MultiPayloadClasses):
|
|
switch_enum %c : $MultiPayloadClasses, case #MultiPayloadClasses.x!enumelt.1: x_dest, case #MultiPayloadClasses.y!enumelt.1: 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{{( protected)?}} swiftcc void @multi_payload_spare_bit_aggregate_switch(i64, i64) {{.*}} {
|
|
// 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: ; <label>:[[X_DEST]]
|
|
// CHECK-64: [[X_0:%.*]] = trunc i64 %0 to i32
|
|
// CHECK-64: ; <label>:[[Y_DEST]]
|
|
// -- 0x3fffffffffffffff
|
|
// CHECK-64: [[Y_MASKED:%.*]] = and i64 %0, 4611686018427387903
|
|
// CHECK-64: [[Y_0:%.*]] = inttoptr i64 [[Y_MASKED]] to %T4enum1CC*
|
|
// CHECK-64: [[Y_1:%.*]] = inttoptr i64 %1 to %T4enum1CC*
|
|
// CHECK-64: ; <label>:[[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.1: x_dest, case #MultiPayloadSpareBitAggregates.y!enumelt.1: y_dest, case #MultiPayloadSpareBitAggregates.z!enumelt.1: 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{{( protected)?}} swiftcc void @multi_payload_nested_switch
|
|
// CHECK: %1 = bitcast %T4enum18MultiPayloadNestedO* %0 to { [[WORD]], i8 }*
|
|
// CHECK: %2 = getelementptr
|
|
// CHECK: %3 = load [[WORD]], [[WORD]]* %2
|
|
// CHECK: %4 = getelementptr
|
|
// CHECK: %5 = load i8, i8* %4
|
|
// CHECK: %6 = lshr i8 %5, 7
|
|
// CHECK: %7 = trunc i8 %6 to i1
|
|
// CHECK: br i1 %7
|
|
sil @multi_payload_nested_switch : $(@in MultiPayloadNested) -> () {
|
|
entry(%c : $*MultiPayloadNested):
|
|
switch_enum_addr %c : $*MultiPayloadNested, case #MultiPayloadNested.A!enumelt.1: a_dest, case #MultiPayloadNested.B!enumelt.1: 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{{( protected)?}} swiftcc void @multi_payload_nested_spare_bits_switch(%T4enum27MultiPayloadNestedSpareBitsO* noalias nocapture dereferenceable({{.*}})) {{.*}} {
|
|
// CHECK-64: entry:
|
|
// CHECK-64: %1 = bitcast %T4enum27MultiPayloadNestedSpareBitsO* %0 to [[WORD]]*
|
|
// CHECK-64: %2 = load [[WORD]], [[WORD]]* %1
|
|
// CHECK-64: %3 = lshr [[WORD]] %2, 61
|
|
// CHECK-64: %4 = trunc [[WORD]] %3 to i1
|
|
// CHECK-64: br i1 %4
|
|
sil @multi_payload_nested_spare_bits_switch : $(@in MultiPayloadNestedSpareBits) -> () {
|
|
entry(%c : $*MultiPayloadNestedSpareBits):
|
|
switch_enum_addr %c : $*MultiPayloadNestedSpareBits, case #MultiPayloadNestedSpareBits.A!enumelt.1: a_dest, case #MultiPayloadNestedSpareBits.B!enumelt.1: 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.1: x_dest, case #OnlyPayloads.y!enumelt.1: y_dest, case #OnlyPayloads.z!enumelt.1: 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{{( protected)?}} swiftcc { i64, i64, i8 } @multi_payload_class_generic_no_spare_bits(i64, i64, i8, %swift.type* %T)
|
|
// CHECK-32-LABEL: define{{( protected)?}} swiftcc { i32, i32, i8 } @multi_payload_class_generic_no_spare_bits(i32, i32, i8, %swift.type* %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{{( protected)?}} swiftcc { i64, i64, i8 } @multi_payload_class_instance_no_spare_bits(i64, i64, i8)
|
|
// CHECK-32-LABEL: define{{( protected)?}} swiftcc { i32, i32, i8 } @multi_payload_class_instance_no_spare_bits(i32, i32, i8)
|
|
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{{( protected)?}} swiftcc void @multi_payload_address_only_destroy(%T4enum28MultiPayloadAddressOnlyFixedO* noalias nocapture dereferenceable({{.*}}))
|
|
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{{( protected)?}} swiftcc void @multi_payload_address_only_spare_bits(%T4enum32MultiPayloadAddressOnlySpareBitsO* noalias nocapture dereferenceable({{.*}}))
|
|
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{{( protected)?}} swiftcc void @dynamic_singleton_switch_indirect([[DYNAMIC_SINGLETON]]* noalias nocapture, %swift.type* %T) {{.*}} {
|
|
// CHECK: bitcast [[DYNAMIC_SINGLETON]]* %0 to %swift.opaque*
|
|
// 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.1: dest
|
|
|
|
dest:
|
|
%1 = unchecked_take_enum_data_addr %0 : $*DynamicSingleton<T>, #DynamicSingleton.value!enumelt.1
|
|
%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{{( protected)?}} swiftcc void @dynamic_singleton_instance_arg_1()
|
|
sil @dynamic_singleton_instance_arg_1 : $(DynamicSingleton<()>) -> () {
|
|
entry(%0 : $DynamicSingleton<()>):
|
|
%v = tuple ()
|
|
return %v : $()
|
|
}
|
|
// CHECK: define{{( protected)?}} swiftcc void @dynamic_singleton_instance_arg_2(i8)
|
|
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{{( protected)?}} swiftcc i1 @optional_optional_class_protocol(i64, i64)
|
|
// CHECK-64: icmp eq i64 %0, 2
|
|
// CHECK-32-LABEL: define{{( protected)?}} swiftcc i1 @optional_optional_class_protocol(i32, i32)
|
|
// 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.1: %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-64: ret { [[WORD]], [[WORD]], i8 } { [[WORD]] 0, [[WORD]] 0, i8 1 }
|
|
// CHECK-native-64: ret { [[WORD]], [[WORD]] } { [[WORD]] 0, [[WORD]] 2 }
|
|
// CHECK-objc-32: ret { [[WORD]], [[WORD]], i8 } { [[WORD]] 0, [[WORD]] 0, i8 1 }
|
|
// CHECK-native-32: 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-64: ret { [[WORD]], [[WORD]], i8 } { [[WORD]] 0, [[WORD]] 0, i8 1 }
|
|
// CHECK-native-64: ret { [[WORD]], [[WORD]] } { [[WORD]] 0, [[WORD]] 2 }
|
|
// CHECK-objc-32: ret { [[WORD]], [[WORD]], i8 } { [[WORD]] 0, [[WORD]] 0, i8 1 }
|
|
// CHECK-native-32: 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{{( protected)?}} swiftcc { i64, i8 } @empty_payload_enum_in_enum(i32)
|
|
sil @empty_payload_enum_in_enum : $@convention(thin) (Int32) -> Optional<(Optional<()>, Int32)> {
|
|
entry(%x : $Int32):
|
|
%a = tuple ()
|
|
%b = enum $Optional<()>, #Optional.some!enumelt.1, %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
|
|
// CHECK-64: [[COMBINE:%.*]] = or i64 0, [[INT_SHL]]
|
|
%d = enum $Optional<(Optional<()>, Int32)>, #Optional.some!enumelt.1, %c : $(Optional<()>, Int32)
|
|
// CHECK-64: [[BIT:%.*]] = trunc i64 [[COMBINE]] to i1
|
|
// CHECK-64: [[INT_SHR:%.*]] = lshr i64 [[COMBINE]], 32
|
|
// CHECK-64: [[INT:%.*]] = trunc i64 [[INT_SHR]] to i32
|
|
%e = unchecked_enum_data %d : $Optional<(Optional<()>, Int32)>, #Optional.some!enumelt.1
|
|
return %d : $Optional<(Optional<()>, Int32)>
|
|
}
|
|
|
|
sil @optional_float80 : $@convention(thin) Float80 -> () {
|
|
entry(%x : $Float80):
|
|
%y = enum $Optional<Float80>, #Optional.some!enumelt.1, %x : $Float80
|
|
return undef : $()
|
|
}
|
|
|
|
// rdar://problem/21126703
|
|
|
|
protocol delegateProtocol : AnyObject { }
|
|
|
|
struct StructWithWeakVar {
|
|
weak var delegate: delegateProtocol?
|
|
}
|
|
|
|
// CHECK-64-LABEL: define{{( protected)?}} swiftcc void @weak_optional(%T4enum17StructWithWeakVarVSg* noalias nocapture dereferenceable({{.*}}))
|
|
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.1: 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{{( 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 {{.*}} @_T04enum6ResultOMa
|
|
// CHECK: call void @swift_storeEnumTagMultiPayload
|
|
inject_enum_addr %0 : $*Result<T, AnyError>, #Result.success!enumelt.1
|
|
%r = tuple ()
|
|
// CHECK: ret void
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( 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{{( 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 [initialization] %stk : $*MyOptional
|
|
dealloc_stack %stk: $*MyOptional
|
|
%tuple = tuple ()
|
|
return %tuple : $()
|
|
}
|
|
|
|
// -- Fill function for dynamic singleton. The value witness table flags just
|
|
// get copied over from the element.
|
|
// CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_DynamicSingleton(%swift.type_pattern*, i8**) {{.*}} {
|
|
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
|
|
// CHECK: [[T:%T]] = load %swift.type*, %swift.type** [[T0]],
|
|
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata(%swift.type_pattern* %0, i8** %1)
|
|
// CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
|
|
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 2
|
|
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[T]] to i8*
|
|
// CHECK: store i8* [[T0]], i8** [[T1]]
|
|
// CHECK: [[VWT:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 3
|
|
// CHECK: [[T0:%.*]] = bitcast i8** [[VWT]] to i8*
|
|
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -1
|
|
// CHECK: store i8* [[T0]], i8** [[T1]]
|
|
// CHECK: [[T_VWTS:%.*]] = bitcast %swift.type* [[T]] to i8***
|
|
// CHECK: [[T_VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[T_VWTS]], [[WORD]] -1
|
|
// CHECK: [[T_VWT:%.*]] = load i8**, i8*** [[T_VWT_ADDR]]
|
|
// CHECK: [[T_LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[T_VWT]], i32 9
|
|
// CHECK: [[SIZE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
|
|
// CHECK: [[T_SIZE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[T_LAYOUT]], i32 0
|
|
// CHECK: [[T_SIZE:%.*]] = load i8*, i8** [[T_SIZE_ADDR]]
|
|
// CHECK: store i8* [[T_SIZE]], i8** [[SIZE_ADDR]]
|
|
// CHECK: [[STRIDE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 11
|
|
// CHECK: [[T_STRIDE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[T_LAYOUT]], i32 2
|
|
// CHECK: [[T_STRIDE:%.*]] = load i8*, i8** [[T_STRIDE_ADDR]]
|
|
// CHECK: store i8* [[T_STRIDE]], i8** [[STRIDE_ADDR]]
|
|
// CHECK: [[FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 10
|
|
// CHECK: [[T_FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[T_LAYOUT]], i32 1
|
|
// CHECK: [[T_FLAGS:%.*]] = load i8*, i8** [[T_FLAGS_ADDR]]
|
|
// CHECK: [[T_FLAGS_INT:%.*]] = ptrtoint i8* [[T_FLAGS]] to [[WORD]]
|
|
// CHECK: [[T_FLAGS_INT_2:%.*]] = or [[WORD]] [[T_FLAGS_INT]], 2097152
|
|
// CHECK: [[T_FLAGS_2:%.*]] = inttoptr [[WORD]] [[T_FLAGS_INT_2]] to i8*
|
|
// CHECK: store i8* [[T_FLAGS_2]], i8** [[FLAGS_ADDR]]
|
|
// -- Test the 'has extra inhabitants' bit and carry over the extra inhabitants
|
|
// flag if set.
|
|
// CHECK: [[T_FLAGS_VAL:%.*]] = ptrtoint i8* [[T_FLAGS]] to [[WORD]]
|
|
// CHECK: [[XI_FLAG:%.*]] = and [[WORD]] [[T_FLAGS_VAL]], 262144
|
|
// CHECK: [[XI_BIT:%.*]] = icmp ne [[WORD]] [[XI_FLAG]], 0
|
|
// CHECK: br i1 [[XI_BIT]], label %[[HAS_XI:[0-9]+]], label %[[HAS_NO_XI:[0-9]+]]
|
|
// CHECK: ; <label>:[[HAS_XI]]
|
|
// CHECK: [[XI_FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 12
|
|
// CHECK: [[T_XI_FLAGS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[T_LAYOUT]], i32 3
|
|
// CHECK: [[T_XI_FLAGS:%.*]] = load i8*, i8** [[T_XI_FLAGS_ADDR]]
|
|
// CHECK: store i8* [[T_XI_FLAGS]], i8** [[XI_FLAGS_ADDR]]
|
|
// CHECK: br label %[[HAS_NO_XI]]
|
|
// CHECK: ; <label>:[[HAS_NO_XI]]
|
|
// CHECK: ret %swift.type* [[METADATA]]
|
|
|
|
// -- Fill function for dynamic single-payload. Call into the runtime to
|
|
// calculate the size.
|
|
// CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_DynamicSinglePayload(%swift.type_pattern*, i8**) {{.*}} {
|
|
// CHECK: call void @swift_initEnumValueWitnessTableSinglePayload
|
|
|
|
// CHECK-64-LABEL: define linkonce_odr hidden void @_T04enum17StructWithWeakVarVwxs(%swift.opaque* noalias %dest, i32 %index, %swift.type* %StructWithWeakVar)
|
|
// -- TODO: some pointless masking here.
|
|
// -- TODO: should use EnumPayload word-chunking.
|
|
// CHECK-64: %1 = zext i32 %index to i128
|
|
// -- 0xFFFF_FFFF_FFFF_FFFF
|
|
// CHECK-64: %2 = and i128 %1, 18446744073709551615
|
|
// CHECK-64: %3 = shl i128 %1, 3
|
|
// -- 0xFFFF_FFFF_FFFF_FFF8__0000_0000_0000_0000
|
|
// CHECK-64: %4 = and i128 %3, 1329227995784915725329854470603931648
|
|
// CHECK-64: %5 = or i128 %2, %4
|
|
// -- 0x1__0000_0000_0000_0000
|
|
// CHECK-64: %6 = or i128 %5, 18446744073709551616
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden i32 @_T04enum40MultiPayloadLessThan32BitsWithEmptyCasesOwug(%swift.opaque* noalias %value
|
|
// CHECK: [[VAL00:%.*]] = bitcast %swift.opaque* %value to %T4enum40MultiPayloadLessThan32BitsWithEmptyCasesO*
|
|
// CHECK: [[VAL01:%.*]] = bitcast %T4enum40MultiPayloadLessThan32BitsWithEmptyCasesO* [[VAL00]] to i8*
|
|
// CHECK: [[VAL02:%.*]] = load {{.*}} [[VAL01]]
|
|
// CHECK: [[VAL03:%.*]] = getelementptr inbounds {{.*}} [[VAL00]], i32 0, i32 1
|
|
// CHECK: [[VAL04:%.*]] = bitcast {{.*}} [[VAL03]] to i8*
|
|
// CHECK: [[VAL05:%.*]] = load {{.*}} [[VAL04]]
|
|
// CHECK: [[VAL06:%.*]] = zext i8 [[VAL05]] to i32
|
|
// CHECK: [[VAL07:%.*]] = sub i32 [[VAL06]], 2
|
|
// CHECK: [[VAL08:%.*]] = zext i8 [[VAL02]] to i32
|
|
// CHECK: [[VAL09:%.*]] = and i32 [[VAL08]], 255
|
|
// CHECK: [[VAL10:%.*]] = icmp sge i32 [[VAL07]], 0
|
|
// CHECK: [[VAL11:%.*]] = select i1 [[VAL10]], i32 [[VAL09]], i32 [[VAL07]]
|
|
// CHECK: ret i32 [[VAL11]]
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden void @_T04enum40MultiPayloadLessThan32BitsWithEmptyCasesOwui(%swift.opaque* noalias %value, i32 %tag
|
|
// CHECK: entry:
|
|
// CHECK: [[VAL00:%.*]] = bitcast %swift.opaque* %value
|
|
// CHECK: [[VAL01:%.*]] = icmp sge i32 %tag, 0
|
|
// CHECK: br i1 [[VAL01]], label %[[TLABEL:.*]], label %[[FLABEL:.*]]
|
|
|
|
// CHECK: <label>:[[TLABEL]]
|
|
// CHECK: [[VAL03:%.*]] = trunc i32 %tag to i8
|
|
// CHECK: [[VAL04:%.*]] = bitcast %T4enum40MultiPayloadLessThan32BitsWithEmptyCasesO* [[VAL00]] to i8*
|
|
// CHECK: store i8 [[VAL03]], i8* [[VAL04]]
|
|
// CHECK: [[VAL05:%.*]] = getelementptr inbounds {{.*}} [[VAL00]], i32 0, i32 1
|
|
// CHECK: [[VAL06:%.*]] = bitcast [1 x i8]* [[VAL05]] to i8*
|
|
// CHECK: store i8 2, i8* [[VAL06]]
|
|
// CHECK: br label %[[RLABEL:.*]]
|
|
|
|
// CHECK: <label>:[[FLABEL]]
|
|
// CHECK: [[VAL08:%.*]] = add i32 %tag, 2
|
|
// CHECK: [[VAL09:%.*]] = trunc i32 [[VAL08]] to i8
|
|
// CHECK: [[VAL10:%.*]] = getelementptr inbounds {{.*}} [[VAL00]], i32 0, i32 1
|
|
// CHECK: [[VAL11:%.*]] = bitcast [1 x i8]* [[VAL10]] to i8*
|
|
// CHECK: store i8 [[VAL09]], i8* [[VAL11]]
|
|
// CHECK: br label %[[RLABEL]]
|
|
|
|
// CHECK: <label>:[[RLABEL]]
|
|
// CHECK: ret void
|
|
|
|
enum MultiPayloadLessThan32BitsWithEmptyCases {
|
|
case A
|
|
case B
|
|
case C(Builtin.Int8)
|
|
case D(Builtin.Int8)
|
|
}
|