mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
456 lines
19 KiB
Plaintext
456 lines
19 KiB
Plaintext
// RUN: %target-swift-frontend -disable-type-layout %s -gnone -emit-ir -I %S/Inputs | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize -DINT=i%target-ptrsize --check-prefix=CHECK-%target-cpu
|
|
|
|
import Builtin
|
|
|
|
sil_stage canonical
|
|
|
|
enum Either<T, U> {
|
|
case Left(T)
|
|
case Right(U)
|
|
}
|
|
|
|
enum EitherOr<T, U> {
|
|
case Left(T)
|
|
case Middle
|
|
case Center
|
|
case Right(U)
|
|
}
|
|
|
|
class C {}
|
|
|
|
sil_vtable C {}
|
|
|
|
// -- The runtime doesn't track spare bits, so fixed instances of the dynamic
|
|
// type can't use them.
|
|
// CHECK-64-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @fixed_instances_dont_use_spare_bits(i64 %0, i8 %1)
|
|
// CHECK-32-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc { i32, i8 } @fixed_instances_dont_use_spare_bits(i32 %0, i8 %1)
|
|
sil @fixed_instances_dont_use_spare_bits : $@convention(thin) (@owned Either<C, C>) -> @owned Either<C, C> {
|
|
entry(%e : $Either<C, C>):
|
|
return %e : $Either<C, C>
|
|
}
|
|
|
|
// -- Handle case where all of the payloads become empty.
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @empty_instance(i8 %0) {{.*}} {
|
|
sil @empty_instance : $@convention(thin) (Either<(), ()>) -> () {
|
|
// CHECK-NEXT: entry:
|
|
entry(%e : $Either<(), ()>):
|
|
|
|
retain_value %e : $Either<(), ()>
|
|
release_value %e : $Either<(), ()>
|
|
fix_lifetime %e : $Either<(), ()>
|
|
|
|
// CHECK-NEXT: alloca
|
|
// CHECK-NEXT: trunc i8 {{.*}} to i1
|
|
// CHECK-NEXT: llvm.lifetime.start
|
|
%s = alloc_stack $Either<(), ()>
|
|
|
|
%l = enum $Either<(), ()>, #Either.Left!enumelt, undef : $()
|
|
// CHECK-NEXT: store i1 false
|
|
store %l to %s : $*Either<(), ()>
|
|
%r = enum $Either<(), ()>, #Either.Right!enumelt, undef : $()
|
|
// CHECK-NEXT: store i1 true
|
|
store %r to %s : $*Either<(), ()>
|
|
|
|
%a = unchecked_enum_data %l : $Either<(), ()>, #Either.Left!enumelt
|
|
%b = unchecked_enum_data %r : $Either<(), ()>, #Either.Right!enumelt
|
|
|
|
// CHECK-NEXT: br i1 {{%.*}}, label %[[RIGHT_PRE:[0-9]+]], label %[[LEFT_PRE:[0-9]+]]
|
|
// CHECK: [[LEFT_PRE]]:
|
|
// CHECK: br label [[LEFT:%[0-9]+]]
|
|
// CHECK: [[RIGHT_PRE]]:
|
|
// CHECK: br label [[RIGHT:%[0-9]+]]
|
|
switch_enum %e : $Either<(), ()>,
|
|
case #Either.Left!enumelt: left,
|
|
case #Either.Right!enumelt: right
|
|
|
|
left(%x : $()):
|
|
%0 = integer_literal $Builtin.Int8, 0
|
|
br next(%0 : $Builtin.Int8)
|
|
|
|
right(%y : $()):
|
|
%1 = integer_literal $Builtin.Int8, 1
|
|
br next(%1 : $Builtin.Int8)
|
|
|
|
// CHECK: phi i8 [ 1, [[RIGHT]] ], [ 0, [[LEFT]] ]
|
|
next(%z : $Builtin.Int8):
|
|
dealloc_stack %s : $*Either<(), ()>
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @empty_instance2(i8 %0) {{.*}} {
|
|
sil @empty_instance2 : $@convention(thin) (EitherOr<(), ()>) -> () {
|
|
// CHECK-NEXT: entry:
|
|
entry(%e : $EitherOr<(), ()>):
|
|
|
|
retain_value %e : $EitherOr<(), ()>
|
|
release_value %e : $EitherOr<(), ()>
|
|
fix_lifetime %e : $EitherOr<(), ()>
|
|
|
|
// CHECK-NEXT: alloca
|
|
// CHECK-NEXT: llvm.lifetime.start
|
|
%s = alloc_stack $EitherOr<(), ()>
|
|
|
|
// CHECK-NEXT: store i8 0
|
|
%l = enum $EitherOr<(), ()>, #EitherOr.Left!enumelt, undef : $()
|
|
store %l to %s : $*EitherOr<(), ()>
|
|
// CHECK-NEXT: store i8 1
|
|
%r = enum $EitherOr<(), ()>, #EitherOr.Right!enumelt, undef : $()
|
|
store %r to %s : $*EitherOr<(), ()>
|
|
// CHECK-NEXT: store i8 2
|
|
%m = enum $EitherOr<(), ()>, #EitherOr.Middle!enumelt
|
|
store %m to %s : $*EitherOr<(), ()>
|
|
// CHECK-NEXT: store i8 3
|
|
%k = enum $EitherOr<(), ()>, #EitherOr.Center!enumelt
|
|
store %k to %s : $*EitherOr<(), ()>
|
|
|
|
%a = unchecked_enum_data %l : $EitherOr<(), ()>, #EitherOr.Left!enumelt
|
|
%b = unchecked_enum_data %r : $EitherOr<(), ()>, #EitherOr.Right!enumelt
|
|
|
|
// CHECK-NEXT: switch
|
|
// CHECK-NEXT: i8 0, label %[[LEFT_PRE:[0-9]+]]
|
|
// CHECK-NEXT: i8 1, label %[[RIGHT_PRE:[0-9]+]]
|
|
// CHECK-NEXT: i8 2, label [[MIDDLE:%[0-9]+]]
|
|
// CHECK-NEXT: i8 3, label [[CENTER:%[0-9]+]]
|
|
switch_enum %e : $EitherOr<(), ()>,
|
|
case #EitherOr.Left!enumelt: left,
|
|
case #EitherOr.Middle!enumelt: middle,
|
|
case #EitherOr.Center!enumelt: center,
|
|
case #EitherOr.Right!enumelt: right
|
|
|
|
// CHECK: [[LEFT_PRE]]:
|
|
// CHECK: br label [[LEFT:%[0-9]+]]
|
|
// CHECK: [[RIGHT_PRE]]:
|
|
// CHECK: br label [[RIGHT:%[0-9]+]]
|
|
|
|
left(%x : $()):
|
|
%0 = integer_literal $Builtin.Int8, 0
|
|
br next(%0 : $Builtin.Int8)
|
|
|
|
middle:
|
|
%1 = integer_literal $Builtin.Int8, 1
|
|
br next(%1 : $Builtin.Int8)
|
|
|
|
center:
|
|
%2 = integer_literal $Builtin.Int8, 2
|
|
br next(%2 : $Builtin.Int8)
|
|
|
|
right(%y : $()):
|
|
%3 = integer_literal $Builtin.Int8, 3
|
|
br next(%3 : $Builtin.Int8)
|
|
|
|
next(%z : $Builtin.Int8):
|
|
// CHECK: phi i8 [ 3, [[RIGHT]] ], [ 2, [[CENTER]] ], [ 1, [[MIDDLE]] ], [ 0, [[LEFT]] ]
|
|
dealloc_stack %s : $*EitherOr<(), ()>
|
|
return undef : $()
|
|
}
|
|
|
|
sil hidden_external @consume_case_test_result : $@convention(thin) (Builtin.Int1, Builtin.Int1, Builtin.Int1, Builtin.Int1) -> ()
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @static_multi_payload_case_test
|
|
// CHECK: call swiftcc void @consume_case_test_result(i1 true, i1 true, i1 true, i1 true)
|
|
sil @static_multi_payload_case_test : $@convention(thin) () -> () {
|
|
entry:
|
|
%0 = integer_literal $Builtin.Int64, 0
|
|
%t = integer_literal $Builtin.Int1, 1
|
|
%f = integer_literal $Builtin.Int1, 0
|
|
|
|
%a = enum $EitherOr<Builtin.Int64, Builtin.Int64>,
|
|
#EitherOr.Left!enumelt, %0 : $Builtin.Int64
|
|
%x = select_enum %a : $EitherOr<Builtin.Int64, Builtin.Int64>,
|
|
case #EitherOr.Left!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
%b = enum $EitherOr<Builtin.Int64, Builtin.Int64>,
|
|
#EitherOr.Right!enumelt, %0 : $Builtin.Int64
|
|
%y = select_enum %b : $EitherOr<Builtin.Int64, Builtin.Int64>,
|
|
case #EitherOr.Right!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
%c = enum $EitherOr<Builtin.Int64, Builtin.Int64>,
|
|
#EitherOr.Middle!enumelt
|
|
%z = select_enum %c : $EitherOr<Builtin.Int64, Builtin.Int64>,
|
|
case #EitherOr.Middle!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
%d = enum $EitherOr<Builtin.Int64, Builtin.Int64>,
|
|
#EitherOr.Center!enumelt
|
|
%w = select_enum %d : $EitherOr<Builtin.Int64, Builtin.Int64>,
|
|
case #EitherOr.Center!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
%g = function_ref @consume_case_test_result : $@convention(thin) (Builtin.Int1, Builtin.Int1, Builtin.Int1, Builtin.Int1) -> ()
|
|
%r = apply %g(%x, %y, %z, %w) : $@convention(thin) (Builtin.Int1, Builtin.Int1, Builtin.Int1, Builtin.Int1) -> ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @static_multi_payload_case_test_empty
|
|
// CHECK: call swiftcc void @consume_case_test_result(i1 true, i1 true, i1 true, i1 true)
|
|
sil @static_multi_payload_case_test_empty : $@convention(thin) () -> () {
|
|
entry:
|
|
%t = integer_literal $Builtin.Int1, 1
|
|
%f = integer_literal $Builtin.Int1, 0
|
|
|
|
%a = enum $EitherOr<(), ()>,
|
|
#EitherOr.Left!enumelt, undef : $()
|
|
%x = select_enum %a : $EitherOr<(), ()>,
|
|
case #EitherOr.Left!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
%b = enum $EitherOr<(), ()>,
|
|
#EitherOr.Right!enumelt, undef : $()
|
|
%y = select_enum %b : $EitherOr<(), ()>,
|
|
case #EitherOr.Right!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
%c = enum $EitherOr<(), ()>,
|
|
#EitherOr.Middle!enumelt
|
|
%z = select_enum %c : $EitherOr<(), ()>,
|
|
case #EitherOr.Middle!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
%d = enum $EitherOr<(), ()>,
|
|
#EitherOr.Center!enumelt
|
|
%w = select_enum %d : $EitherOr<(), ()>,
|
|
case #EitherOr.Center!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
%g = function_ref @consume_case_test_result : $@convention(thin) (Builtin.Int1, Builtin.Int1, Builtin.Int1, Builtin.Int1) -> ()
|
|
%r = apply %g(%x, %y, %z, %w) : $@convention(thin) (Builtin.Int1, Builtin.Int1, Builtin.Int1, Builtin.Int1) -> ()
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_multi_payload_case_test
|
|
sil @dynamic_multi_payload_case_test : $@convention(thin) <T, U> () -> () {
|
|
entry:
|
|
%t = integer_literal $Builtin.Int1, 1
|
|
%f = integer_literal $Builtin.Int1, 0
|
|
|
|
%a = alloc_stack $EitherOr<T, U>
|
|
|
|
// CHECK: [[LEFT:%.*]] = icmp eq i32 {{%.*}}, 0
|
|
%x = select_enum_addr %a : $*EitherOr<T, U>,
|
|
case #EitherOr.Left!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
// CHECK: [[RIGHT:%.*]] = icmp eq i32 {{%.*}}, 1
|
|
%y = select_enum_addr %a : $*EitherOr<T, U>,
|
|
case #EitherOr.Right!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
// CHECK: [[MIDDLE:%.*]] = icmp eq i32 {{%.*}}, 2
|
|
%z = select_enum_addr %a : $*EitherOr<T, U>,
|
|
case #EitherOr.Middle!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
// CHECK: [[CENTER:%.*]] = icmp eq i32 {{%.*}}, 3
|
|
%w = select_enum_addr %a : $*EitherOr<T, U>,
|
|
case #EitherOr.Center!enumelt: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
// CHECK: call swiftcc void @consume_case_test_result(i1 [[LEFT]], i1 [[RIGHT]], i1 [[MIDDLE]], i1 [[CENTER]])
|
|
%g = function_ref @consume_case_test_result : $@convention(thin) (Builtin.Int1, Builtin.Int1, Builtin.Int1, Builtin.Int1) -> ()
|
|
%r = apply %g(%x, %y, %z, %w) : $@convention(thin) (Builtin.Int1, Builtin.Int1, Builtin.Int1, Builtin.Int1) -> ()
|
|
|
|
dealloc_stack %a : $*EitherOr<T, U>
|
|
return %r : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_inject
|
|
// CHECK: (ptr noalias sret({{.*}}) %0, ptr %T)
|
|
sil @dynamic_inject : $@convention(thin) <T> () -> @out EitherOr<T, Builtin.Int64> {
|
|
entry(%e : $*EitherOr<T, Builtin.Int64>):
|
|
// CHECK: call void @swift_storeEnumTagMultiPayload(ptr {{%.*}}, ptr [[TYPE:%.*]], i32 0)
|
|
inject_enum_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Left!enumelt
|
|
// CHECK: call void @swift_storeEnumTagMultiPayload(ptr {{%.*}}, ptr [[TYPE]], i32 2)
|
|
inject_enum_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Middle!enumelt
|
|
// CHECK: call void @swift_storeEnumTagMultiPayload(ptr {{%.*}}, ptr [[TYPE]], i32 3)
|
|
inject_enum_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Center!enumelt
|
|
// CHECK: call void @swift_storeEnumTagMultiPayload(ptr {{%.*}}, ptr [[TYPE]], i32 1)
|
|
inject_enum_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Right!enumelt
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_project
|
|
// CHECK: (ptr noalias sret({{.*}}) %0, ptr %T)
|
|
sil @dynamic_project : $@convention(thin) <T> () -> @out EitherOr<T, Builtin.Int64> {
|
|
entry(%e : $*EitherOr<T, Builtin.Int64>):
|
|
%l = unchecked_take_enum_data_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Left!enumelt
|
|
%r = unchecked_take_enum_data_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Right!enumelt
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_switch
|
|
// CHECK: (ptr noalias sret({{.*}}) %0, ptr %T)
|
|
sil @dynamic_switch : $@convention(thin) <T> () -> @out EitherOr<T, Builtin.Int64> {
|
|
entry(%e : $*EitherOr<T, Builtin.Int64>):
|
|
// CHECK: [[TAG:%.*]] = call i32 @swift_getEnumCaseMultiPayload
|
|
// CHECK: switch i32 [[TAG]]
|
|
// CHECK-NEXT: i32 0, label %[[LEFT:[0-9]+]]
|
|
// CHECK-NEXT: i32 1, label %[[RIGHT:[0-9]+]]
|
|
// CHECK-NEXT: i32 2, label %[[MIDDLE:[0-9]+]]
|
|
// CHECK-NEXT: i32 3, label %[[CENTER:[0-9]+]]
|
|
switch_enum_addr %e : $*EitherOr<T, Builtin.Int64>,
|
|
case #EitherOr.Left!enumelt: left,
|
|
case #EitherOr.Middle!enumelt: middle,
|
|
case #EitherOr.Center!enumelt: center,
|
|
case #EitherOr.Right!enumelt: right
|
|
|
|
// CHECK: [[LEFT]]:
|
|
left:
|
|
%0 = integer_literal $Builtin.Int8, 0
|
|
br next(%0 : $Builtin.Int8)
|
|
|
|
// CHECK: [[MIDDLE]]:
|
|
middle:
|
|
%1 = integer_literal $Builtin.Int8, 1
|
|
br next(%1 : $Builtin.Int8)
|
|
|
|
// CHECK: [[CENTER]]:
|
|
center:
|
|
%2 = integer_literal $Builtin.Int8, 2
|
|
br next(%2 : $Builtin.Int8)
|
|
|
|
// CHECK: [[RIGHT]]:
|
|
right:
|
|
%3 = integer_literal $Builtin.Int8, 3
|
|
br next(%3 : $Builtin.Int8)
|
|
|
|
// CHECK: phi i8 [ 3, %[[RIGHT]] ], [ 2, %[[CENTER]] ], [ 1, %[[MIDDLE]] ], [ 0, %[[LEFT]] ]
|
|
next(%x : $Builtin.Int8):
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_value_semantics
|
|
// CHECK: (ptr noalias sret({{.*}}) %0, ptr noalias %1, ptr %T)
|
|
sil @dynamic_value_semantics : $@convention(thin) <T> (@in EitherOr<T, Builtin.Int64>) -> @out EitherOr<T, Builtin.Int64> {
|
|
entry(%a : $*EitherOr<T, Builtin.Int64>, %b : $*EitherOr<T, Builtin.Int64>):
|
|
// CHECK: [[TAG:%.*]] = call i32 @swift_getEnumCaseMultiPayload
|
|
// -- only the Left branch of this instance needs cleanup
|
|
// CHECK: [[COND:%.*]] = icmp ne i32 [[TAG]], 0
|
|
// CHECK-NEXT: br i1 [[COND]], label %[[NOOP:[0-9]+]], label %[[LEFT:[0-9]+]]
|
|
// CHECK: [[LEFT]]:
|
|
// CHECK: [[DESTROYADDR:%[0-9]+]] = getelementptr inbounds ptr, ptr {{.*}}, i32 1
|
|
// CHECK: [[DESTROY:%[^,]+]] = load ptr, ptr [[DESTROYADDR]]
|
|
// CHECK: call void [[DESTROY]](ptr noalias {{%[0-9]+}}, ptr %T)
|
|
// CHECK: br label %[[NOOP]]
|
|
// CHECK: [[NOOP]]:
|
|
destroy_addr %a : $*EitherOr<T, Builtin.Int64>
|
|
|
|
// CHECK: [[TAG:%.*]] = call i32 @swift_getEnumCaseMultiPayload
|
|
// -- only the Left branch of this instance needs nontrivial take
|
|
// CHECK: [[COND:%.*]] = icmp ne i32 [[TAG]], 0
|
|
// CHECK-NEXT: br i1 [[COND]], label %[[TRIVIAL:[0-9]+]], label %[[LEFT:[0-9]+]]
|
|
// CHECK: [[LEFT]]:
|
|
// CHECK: [[INITWITHTAKEADDR:%[0-9]+]] = getelementptr inbounds ptr, ptr {{.*}}, i32 4
|
|
// CHECK: [[INITWITHTAKE:%[^,]+]] = load ptr, ptr [[INITWITHTAKEADDR]]
|
|
// CHECK: {{%[0-9]+}} = call ptr [[INITWITHTAKE]](ptr noalias {{%[0-9]+}}, ptr noalias {{%[0-9]+}}, ptr %T)
|
|
// CHECK: br label %[[DONE:[0-9]+]]
|
|
// CHECK: [[TRIVIAL]]:
|
|
// CHECK: call void @llvm.memcpy
|
|
// CHECK: br label %[[DONE]]
|
|
// CHECK: [[DONE]]:
|
|
copy_addr [take] %a to [init] %b : $*EitherOr<T, Builtin.Int64>
|
|
|
|
copy_addr [take] %a to %b : $*EitherOr<T, Builtin.Int64>
|
|
copy_addr %a to [init] %b : $*EitherOr<T, Builtin.Int64>
|
|
copy_addr %a to %b : $*EitherOr<T, Builtin.Int64>
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @dynamic_value_semantics2
|
|
// CHECK: (ptr noalias sret({{.*}}) %0, ptr noalias %1, ptr %T)
|
|
sil @dynamic_value_semantics2 : $@convention(thin) <T> (@in EitherOr<T, C>) -> @out EitherOr<T, C> {
|
|
entry(%a : $*EitherOr<T, C>, %b : $*EitherOr<T, C>):
|
|
// CHECK: [[TAG:%.*]] = call i32 @swift_getEnumCaseMultiPayload
|
|
// CHECK: switch i32 [[TAG]], label %[[NOOP:[0-9]+]] [
|
|
// CHECK-NEXT: i32 0, label %[[LEFT:[0-9]+]]
|
|
// CHECK-NEXT: i32 1, label %[[RIGHT:[0-9]+]]
|
|
// CHECK-NEXT: ]
|
|
// CHECK: [[LEFT]]:
|
|
// CHECK: [[DESTROYADDR:%[0-9]+]] = getelementptr inbounds ptr, ptr {{.*}}, i32 1
|
|
// CHECK: [[DESTROY:%[^,]+]] = load ptr, ptr [[DESTROYADDR]]
|
|
// CHECK: call void [[DESTROY]](ptr noalias {{%[0-9]+}}, ptr %T)
|
|
// CHECK: br label %[[NOOP]]
|
|
// CHECK: [[RIGHT]]:
|
|
// CHECK: call void @swift_release
|
|
// CHECK: [[NOOP]]:
|
|
destroy_addr %a : $*EitherOr<T, C>
|
|
|
|
// CHECK: [[TAG:%.*]] = call i32 @swift_getEnumCaseMultiPayload
|
|
// -- only the Left branch of this instance needs cleanup
|
|
// CHECK: [[COND:%.*]] = icmp ne i32 [[TAG]], 0
|
|
// CHECK-NEXT: br i1 [[COND]], label %[[TRIVIAL:[0-9]+]], label %[[LEFT:[0-9]+]]
|
|
// CHECK: [[LEFT]]:
|
|
// CHECK: [[INITWITHTAKEADDR:%[0-9]+]] = getelementptr inbounds ptr, ptr {{.*}}, i32 4
|
|
// CHECK: [[INITWITHTAKE:%[^,]+]] = load ptr, ptr [[INITWITHTAKEADDR]]
|
|
// CHECK: {{%[0-9]+}} = call ptr [[INITWITHTAKE]](ptr noalias {{%[0-9]+}}, ptr noalias {{%[0-9]+}}, ptr %T)
|
|
// CHECK: br label %[[DONE:[0-9]+]]
|
|
// CHECK: [[TRIVIAL]]:
|
|
// CHECK: call void @llvm.memcpy
|
|
// CHECK: br label %[[DONE]]
|
|
// CHECK: [[DONE]]:
|
|
copy_addr [take] %a to [init] %b : $*EitherOr<T, C>
|
|
|
|
// CHECK: [[TAG:%.*]] = call i32 @swift_getEnumCaseMultiPayload
|
|
// CHECK: switch i32 [[TAG]], label %[[TRIVIAL:[0-9]+]] [
|
|
// -- both branches have nontrivial copy
|
|
// CHECK-NEXT: i32 0, label %[[LEFT:[0-9]+]]
|
|
// CHECK-NEXT: i32 1, label %[[RIGHT:[0-9]+]]
|
|
// CHECK-NEXT: ]
|
|
// CHECK: [[LEFT]]:
|
|
// CHECK: [[INITWITHCOPYADDR:%[0-9]+]] = getelementptr inbounds ptr, ptr {{.*}}, i32 2
|
|
// CHECK: [[INITWITHCOPY:%[^,]+]] = load ptr, ptr [[INITWITHCOPYADDR]]
|
|
// CHECK: {{%[0-9]+}} = call ptr [[INITWITHCOPY]](ptr noalias {{%[0-9]+}}, ptr noalias {{%[0-9]+}}, ptr %T)
|
|
// CHECK: br label %[[DONE:[0-9]+]]
|
|
// CHECK: [[RIGHT]]:
|
|
// CHECK: call ptr @swift_retain
|
|
// CHECK: br label %[[DONE:[0-9]+]]
|
|
// CHECK: [[TRIVIAL]]:
|
|
// CHECK: call void @llvm.memcpy
|
|
// CHECK: br label %[[DONE]]
|
|
// CHECK: [[DONE]]:
|
|
copy_addr %a to [init] %b : $*EitherOr<T, C>
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK: define{{( dllexport)?}}{{( protected)?}} internal ptr @"$s26enum_dynamic_multi_payload8EitherOrOMi"(ptr %0, ptr %1, ptr %2) {{.*}} {
|
|
// CHECK: [[METADATA:%.*]] = call ptr @swift_allocateGenericValueMetadata
|
|
|
|
// CHECK: define{{( protected)?}} internal swiftcc %swift.metadata_response @"$s26enum_dynamic_multi_payload8EitherOrOMr"
|
|
// CHECK-SAME: (ptr [[METADATA:%.*]], ptr %0, ptr %1) {{.*}} {
|
|
|
|
// CHECK: [[BUF:%.*]] = alloca [2 x ptr]
|
|
// CHECK: [[BUF0:%.*]] = getelementptr {{.*}} [[BUF]], i32 0, i32 0
|
|
// CHECK: [[T0:%.*]] = call{{( tail)?}} swiftcc %swift.metadata_response @swift_checkMetadataState([[INT]] 319, ptr %T)
|
|
// CHECK-NEXT: [[T_CHECKED:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK-NEXT: [[T_STATUS:%.*]] = extractvalue %swift.metadata_response [[T0]], 1
|
|
// CHECK-NEXT: [[T_OK:%.*]] = icmp ule [[INT]] [[T_STATUS]], 63
|
|
// CHECK-NEXT: br i1 [[T_OK]],
|
|
// CHECK: [[T1:%.*]] = getelementptr inbounds ptr, ptr [[T_CHECKED]]
|
|
// CHECK-NEXT: [[VALUE_WITNESSES:%.*]] = load ptr, ptr [[T1]]
|
|
// CHECK-arm64e-NEXT: ptrtoint ptr [[T1]] to i64
|
|
// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend
|
|
// CHECK-arm64e: [[VALUE_WITNESSES:%.*]] = inttoptr i64 {{%.*}} to ptr
|
|
// CHECK-NEXT: [[LAYOUT:%.*]] = getelementptr inbounds ptr, ptr [[VALUE_WITNESSES]], i32 8
|
|
// CHECK-NEXT: store ptr [[LAYOUT]], {{.*}} [[BUF0]]
|
|
|
|
// CHECK: [[BUF1:%.*]] = getelementptr {{.*}} [[BUF]], i32 0, i32 1
|
|
// CHECK: [[T0:%.*]] = call{{( tail)?}} swiftcc %swift.metadata_response @swift_checkMetadataState([[INT]] 319, ptr %U)
|
|
// CHECK-NEXT: [[U_CHECKED:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK-NEXT: [[U_STATUS:%.*]] = extractvalue %swift.metadata_response [[T0]], 1
|
|
// CHECK-NEXT: [[U_OK:%.*]] = icmp ule [[INT]] [[U_STATUS]], 63
|
|
// CHECK-NEXT: br i1 [[U_OK]],
|
|
// CHECK: [[T1:%.*]] = getelementptr inbounds ptr, ptr [[U_CHECKED]]
|
|
// CHECK-NEXT: [[VALUE_WITNESSES:%.*]] = load ptr, ptr [[T1]]
|
|
// CHECK-arm64e-NEXT: ptrtoint ptr [[T1]] to i64
|
|
// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend
|
|
// CHECK-arm64e: [[VALUE_WITNESSES:%.*]] = inttoptr i64 {{%.*}} to ptr
|
|
// CHECK-NEXT: [[LAYOUT:%.*]] = getelementptr inbounds ptr, ptr [[VALUE_WITNESSES]], i32 8
|
|
// CHECK-NEXT: store ptr [[LAYOUT]], {{.*}} [[BUF1]]
|
|
|
|
// CHECK: call void @swift_initEnumMetadataMultiPayload(ptr [[METADATA]], {{i(32|64)}} 0, {{i(32|64)}} 2, ptr [[BUF0]])
|