mirror of
https://github.com/apple/swift.git
synced 2026-06-27 12:25:55 +02:00
9a4540e84d
The allocation phase is guaranteed to succeed and just puts enough of the structure together to make things work. The completion phase does any component metadata lookups that are necessary (for the superclass, fields, etc.) and performs layout; it can fail and require restart. Next up is to support this in the runtime; then we can start the process of making metadata accessors actually allow incomplete metadata to be fetched.
442 lines
18 KiB
Plaintext
442 lines
18 KiB
Plaintext
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -gnone -emit-ir -I %S/Inputs | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
|
|
|
|
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{{( protected)?}} swiftcc { i64, i8 } @fixed_instances_dont_use_spare_bits(i64, i8)
|
|
// CHECK-32-LABEL: define{{( protected)?}} swiftcc { i32, i8 } @fixed_instances_dont_use_spare_bits(i32, i8)
|
|
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{{( protected)?}} swiftcc void @empty_instance(i8) {{.*}} {
|
|
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: bitcast
|
|
// CHECK-NEXT: llvm.lifetime.start
|
|
%s = alloc_stack $Either<(), ()>
|
|
|
|
%l = enum $Either<(), ()>, #Either.Left!enumelt.1, undef : $()
|
|
// CHECK-NEXT: bitcast {{.*}} to i1*
|
|
// CHECK-NEXT: store i1 false
|
|
store %l to %s : $*Either<(), ()>
|
|
%r = enum $Either<(), ()>, #Either.Right!enumelt.1, undef : $()
|
|
// CHECK-NEXT: bitcast {{.*}} to i1*
|
|
// CHECK-NEXT: store i1 true
|
|
store %r to %s : $*Either<(), ()>
|
|
|
|
%a = unchecked_enum_data %l : $Either<(), ()>, #Either.Left!enumelt.1
|
|
%b = unchecked_enum_data %r : $Either<(), ()>, #Either.Right!enumelt.1
|
|
|
|
// CHECK-NEXT: br i1 {{%.*}}, label %7, label %6
|
|
// CHECK: <label>:6
|
|
// CHECK: br label %8
|
|
// CHECK: <label>:7
|
|
// CHECK: br label %9
|
|
switch_enum %e : $Either<(), ()>,
|
|
case #Either.Left!enumelt.1: left,
|
|
case #Either.Right!enumelt.1: 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, %9 ], [ 0, %8 ]
|
|
next(%z : $Builtin.Int8):
|
|
dealloc_stack %s : $*Either<(), ()>
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @empty_instance2(i8) {{.*}} {
|
|
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: bitcast
|
|
// CHECK-NEXT: llvm.lifetime.start
|
|
%s = alloc_stack $EitherOr<(), ()>
|
|
|
|
// CHECK-NEXT: bitcast {{.*}} to i8*
|
|
// CHECK-NEXT: store i8 0
|
|
%l = enum $EitherOr<(), ()>, #EitherOr.Left!enumelt.1, undef : $()
|
|
store %l to %s : $*EitherOr<(), ()>
|
|
// CHECK-NEXT: bitcast {{.*}} to i8*
|
|
// CHECK-NEXT: store i8 1
|
|
%r = enum $EitherOr<(), ()>, #EitherOr.Right!enumelt.1, undef : $()
|
|
store %r to %s : $*EitherOr<(), ()>
|
|
// CHECK-NEXT: bitcast {{.*}} to i8*
|
|
// CHECK-NEXT: store i8 2
|
|
%m = enum $EitherOr<(), ()>, #EitherOr.Middle!enumelt
|
|
store %m to %s : $*EitherOr<(), ()>
|
|
// CHECK-NEXT: bitcast {{.*}} to i8*
|
|
// 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.1
|
|
%b = unchecked_enum_data %r : $EitherOr<(), ()>, #EitherOr.Right!enumelt.1
|
|
|
|
// 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.1: left,
|
|
case #EitherOr.Middle!enumelt: middle,
|
|
case #EitherOr.Center!enumelt: center,
|
|
case #EitherOr.Right!enumelt.1: right
|
|
|
|
// CHECK: <label>:[[LEFT_PRE]]
|
|
// CHECK: br label [[LEFT:%[0-9]+]]
|
|
// CHECK: <label>:[[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{{( 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.1, %0 : $Builtin.Int64
|
|
%x = select_enum %a : $EitherOr<Builtin.Int64, Builtin.Int64>,
|
|
case #EitherOr.Left!enumelt.1: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
%b = enum $EitherOr<Builtin.Int64, Builtin.Int64>,
|
|
#EitherOr.Right!enumelt.1, %0 : $Builtin.Int64
|
|
%y = select_enum %b : $EitherOr<Builtin.Int64, Builtin.Int64>,
|
|
case #EitherOr.Right!enumelt.1: %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{{( 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.1, undef : $()
|
|
%x = select_enum %a : $EitherOr<(), ()>,
|
|
case #EitherOr.Left!enumelt.1: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
%b = enum $EitherOr<(), ()>,
|
|
#EitherOr.Right!enumelt.1, undef : $()
|
|
%y = select_enum %b : $EitherOr<(), ()>,
|
|
case #EitherOr.Right!enumelt.1: %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{{( 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.1: %t,
|
|
default %f : $Builtin.Int1
|
|
|
|
// CHECK: [[RIGHT:%.*]] = icmp eq i32 {{%.*}}, 1
|
|
%y = select_enum_addr %a : $*EitherOr<T, U>,
|
|
case #EitherOr.Right!enumelt.1: %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{{( protected)?}} swiftcc void @dynamic_inject
|
|
// CHECK: ([[EITHER_OR:%T26enum_dynamic_multi_payload8EitherOrO.*]]* noalias nocapture sret, %swift.type* %T)
|
|
sil @dynamic_inject : $@convention(thin) <T> () -> @out EitherOr<T, Builtin.Int64> {
|
|
entry(%e : $*EitherOr<T, Builtin.Int64>):
|
|
// CHECK: call void @swift_storeEnumTagMultiPayload(%swift.opaque* {{%.*}}, %swift.type* [[TYPE:%.*]], i32 0)
|
|
inject_enum_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Left!enumelt.1
|
|
// CHECK: call void @swift_storeEnumTagMultiPayload(%swift.opaque* {{%.*}}, %swift.type* [[TYPE]], i32 2)
|
|
inject_enum_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Middle!enumelt
|
|
// CHECK: call void @swift_storeEnumTagMultiPayload(%swift.opaque* {{%.*}}, %swift.type* [[TYPE]], i32 3)
|
|
inject_enum_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Center!enumelt
|
|
// CHECK: call void @swift_storeEnumTagMultiPayload(%swift.opaque* {{%.*}}, %swift.type* [[TYPE]], i32 1)
|
|
inject_enum_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Right!enumelt.1
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @dynamic_project
|
|
// CHECK: ([[EITHER_OR]]* noalias nocapture sret, %swift.type* %T)
|
|
sil @dynamic_project : $@convention(thin) <T> () -> @out EitherOr<T, Builtin.Int64> {
|
|
entry(%e : $*EitherOr<T, Builtin.Int64>):
|
|
// CHECK: bitcast [[EITHER_OR]]* %0 to %swift.opaque*
|
|
%l = unchecked_take_enum_data_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Left!enumelt.1
|
|
// CHECK: bitcast [[EITHER_OR]]* %0 to i64*
|
|
%r = unchecked_take_enum_data_addr %e : $*EitherOr<T, Builtin.Int64>, #EitherOr.Right!enumelt.1
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @dynamic_switch
|
|
// CHECK: ([[EITHER_OR]]* noalias nocapture sret, %swift.type* %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.1: left,
|
|
case #EitherOr.Middle!enumelt: middle,
|
|
case #EitherOr.Center!enumelt: center,
|
|
case #EitherOr.Right!enumelt.1: right
|
|
|
|
// CHECK: <label>:[[LEFT]]
|
|
left:
|
|
%0 = integer_literal $Builtin.Int8, 0
|
|
br next(%0 : $Builtin.Int8)
|
|
|
|
// CHECK: <label>:[[MIDDLE]]
|
|
middle:
|
|
%1 = integer_literal $Builtin.Int8, 1
|
|
br next(%1 : $Builtin.Int8)
|
|
|
|
// CHECK: <label>:[[CENTER]]
|
|
center:
|
|
%2 = integer_literal $Builtin.Int8, 2
|
|
br next(%2 : $Builtin.Int8)
|
|
|
|
// CHECK: <label>:[[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{{( protected)?}} swiftcc void @dynamic_value_semantics
|
|
// CHECK: ([[EITHER_OR]]* noalias nocapture sret, [[EITHER_OR]]* noalias nocapture, %swift.type* %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: <label>:[[LEFT]]
|
|
// CHECK: call void %destroy(%swift.opaque* noalias {{%.*}}, %swift.type* %T)
|
|
// CHECK: br label %[[NOOP]]
|
|
// CHECK: <label>:[[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: <label>:[[LEFT]]
|
|
// CHECK: call %swift.opaque* %initializeWithTake(%swift.opaque* noalias {{%.*}}, %swift.type* %T)
|
|
// CHECK: br label %[[DONE:[0-9]+]]
|
|
// CHECK: <label>:[[TRIVIAL]]
|
|
// CHECK: call void @llvm.memcpy
|
|
// CHECK: br label %[[DONE]]
|
|
// CHECK: <label>:[[DONE]]
|
|
copy_addr [take] %a to [initialization] %b : $*EitherOr<T, Builtin.Int64>
|
|
|
|
copy_addr [take] %a to %b : $*EitherOr<T, Builtin.Int64>
|
|
copy_addr %a to [initialization] %b : $*EitherOr<T, Builtin.Int64>
|
|
copy_addr %a to %b : $*EitherOr<T, Builtin.Int64>
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( protected)?}} swiftcc void @dynamic_value_semantics2
|
|
// CHECK: ([[EITHER_OR:%T26enum_dynamic_multi_payload8EitherOrO.*]]* noalias nocapture sret, [[EITHER_OR]]* noalias nocapture, %swift.type* %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: <label>:[[LEFT]]
|
|
// CHECK: call void %destroy(%swift.opaque* noalias {{%.*}}, %swift.type* %T)
|
|
// CHECK: br label %[[NOOP]]
|
|
// CHECK: <label>:[[RIGHT]]
|
|
// CHECK: call void {{.*}} @swift_release
|
|
// CHECK: <label>:[[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: <label>:[[LEFT]]
|
|
// CHECK: call %swift.opaque* %initializeWithTake(%swift.opaque* noalias {{%.*}}, %swift.type* %T)
|
|
// CHECK: br label %[[DONE:[0-9]+]]
|
|
// CHECK: <label>:[[TRIVIAL]]
|
|
// CHECK: call void @llvm.memcpy
|
|
// CHECK: br label %[[DONE]]
|
|
// CHECK: <label>:[[DONE]]
|
|
copy_addr [take] %a to [initialization] %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: <label>:[[LEFT]]
|
|
// CHECK: call %swift.opaque* %initializeWithCopy(%swift.opaque* noalias {{%.*}}, %swift.type* %T)
|
|
// CHECK: br label %[[DONE:[0-9]+]]
|
|
// CHECK: <label>:[[RIGHT]]
|
|
// CHECK: call %swift.refcounted* @swift_retain
|
|
// CHECK: br label %[[DONE:[0-9]+]]
|
|
// CHECK: <label>:[[TRIVIAL]]
|
|
// CHECK: call void @llvm.memcpy
|
|
// CHECK: br label %[[DONE]]
|
|
// CHECK: <label>:[[DONE]]
|
|
copy_addr %a to [initialization] %b : $*EitherOr<T, C>
|
|
|
|
return undef : $()
|
|
}
|
|
|
|
// CHECK: define{{( protected)?}} internal %swift.type* @"$S26enum_dynamic_multi_payload8EitherOrOMi"(%swift.type_descriptor*, i8**, i8**) {{.*}} {
|
|
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericValueMetadata
|
|
|
|
// CHECK: define{{( protected)?}} internal %swift.type* @"$S26enum_dynamic_multi_payload8EitherOrOMr"
|
|
// CHECK-SAME: (%swift.type* [[METADATA:%.*]], i8*, i8**) {{.*}} {
|
|
|
|
// CHECK: [[BUF:%.*]] = alloca [2 x i8**]
|
|
// CHECK: [[BUF0:%.*]] = getelementptr {{.*}} [[BUF]], i32 0, i32 0
|
|
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8***
|
|
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]]
|
|
// CHECK-NEXT: [[VALUE_WITNESSES:%.*]] = load i8**, i8*** [[T1]]
|
|
// CHECK-NEXT: [[LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[VALUE_WITNESSES]], i32 9
|
|
// CHECK-NEXT: store i8** [[LAYOUT]], {{.*}} [[BUF0]]
|
|
|
|
// CHECK: [[BUF1:%.*]] = getelementptr {{.*}} [[BUF]], i32 0, i32 1
|
|
// CHECK: [[T0:%.*]] = bitcast %swift.type* %U to i8***
|
|
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]]
|
|
// CHECK-NEXT: [[VALUE_WITNESSES:%.*]] = load i8**, i8*** [[T1]]
|
|
// CHECK-NEXT: [[LAYOUT:%.*]] = getelementptr inbounds i8*, i8** [[VALUE_WITNESSES]], i32 9
|
|
// CHECK-NEXT: store i8** [[LAYOUT]], {{.*}} [[BUF1]]
|
|
|
|
// CHECK: call void @swift_initEnumMetadataMultiPayload(%swift.type* [[METADATA]], {{i(32|64)}} 0, {{i(32|64)}} 2, i8*** [[BUF0]])
|