@@ -29,6 +29,19 @@ class PointerWrapper {
2929
3030enum OneOfThree { case one, two, three }
3131
32+ final class Object {
33+ init()
34+ }
35+
36+ public struct ClassStorage {
37+ var ref: C
38+ }
39+ public struct ClassWrapper {
40+ var storage: ClassStorage
41+ }
42+
43+ sil @returnUnmanagedC : $@convention(method) (@guaranteed C) -> @sil_unmanaged C
44+
3245sil [ossa] @callee_guaranteed: $@convention(thin) (@guaranteed C) -> ()
3346sil [ossa] @get_owned_c : $@convention(thin) () -> (@owned C)
3447sil [ossa] @callee_owned : $@convention(thin) (@owned C) -> ()
@@ -1016,6 +1029,71 @@ exit(%copy_1_2 : @owned $C, %borrow_in : @guaranteed $C, %copy_2_2 : @owned $C):
10161029 return %copy_2_2 : $C
10171030}
10181031
1032+ // Do not hoist the end_borrow (or destroy_value) of Storage above the
1033+ // string_copy_unmanaged_value of the BridgeObject. Here, the initial
1034+ // ref_to_unmanaged is hidden by a call.
1035+ //
1036+ // rdar://90909833 (Extend deinit barriers to handle conversion to strong reference)
1037+ //
1038+ // CHECK-LABEL: sil [ossa] @testCopyUnmanagedCall : $@convention(method) (@inout ClassWrapper) -> () {
1039+ // CHECK: [[STORAGE:%.*]] = load [take] %1 : $*ClassStorage
1040+ // CHECK: [[BORROW:%.*]] = begin_borrow [[STORAGE]] : $ClassStorage
1041+ // CHECK: [[CALL:%.*]] = apply %{{.*}} : $@convention(method) (@guaranteed C) -> @sil_unmanaged C
1042+ // CHECK: strong_copy_unmanaged_value [[CALL]] : $@sil_unmanaged C
1043+ // CHECK: end_borrow [[BORROW]] : $ClassStorage
1044+ // CHECK: destroy_value [[STORAGE]] : $ClassStorage
1045+ // CHECK-LABEL: } // end sil function
1046+ sil [ossa] @testCopyUnmanagedCall : $@convention(method) (@inout ClassWrapper) -> () {
1047+ bb0(%0 : $*ClassWrapper):
1048+ %1 = struct_element_addr %0 : $*ClassWrapper, #ClassWrapper.storage
1049+ %2 = load [take] %1 : $*ClassStorage
1050+ %4 = begin_borrow %2 : $ClassStorage
1051+ %5 = struct_extract %4 : $ClassStorage, #ClassStorage.ref
1052+ %f = function_ref @returnUnmanagedC : $@convention(method) (@guaranteed C) -> @sil_unmanaged C
1053+ %call = apply %f(%5) : $@convention(method) (@guaranteed C) -> @sil_unmanaged C
1054+ %7 = strong_copy_unmanaged_value %call : $@sil_unmanaged C
1055+ end_borrow %4 : $ClassStorage
1056+ destroy_value %2 : $ClassStorage
1057+ %10 = struct $ClassStorage (%7 : $C)
1058+ %11 = struct $ClassWrapper (%10 : $ClassStorage)
1059+ store %11 to [init] %0 : $*ClassWrapper
1060+ %23 = tuple ()
1061+ return %23 : $()
1062+ }
1063+
1064+ // Do not hoist the end_borrow (or destroy_value) of Storage above the
1065+ // string_copy_unmanaged_value of the BridgeObject. Here, the initial
1066+ // ref_to_unmanaged is hidden by a call.
1067+ //
1068+ // rdar://90909833 (Extend deinit barriers to handle conversion to strong reference)
1069+ //
1070+ // The inlined case was already handled because the ref_to_unmanaged
1071+ // was considered a pointer escape. But in the future, this might not be considered a pointer escape.
1072+ //
1073+ // CHECK-LABEL: sil [ossa] @testCopyUnmanagedInlined : $@convention(method) (@inout ClassWrapper) -> () {
1074+ // CHECK: [[STORAGE:%.*]] = load [take] %1 : $*ClassStorage
1075+ // CHECK: [[BORROW:%.*]] = begin_borrow [[STORAGE]] : $ClassStorage
1076+ // CHECK: strong_copy_unmanaged_value
1077+ // CHECK: end_borrow [[BORROW]] : $ClassStorage
1078+ // CHECK: destroy_value [[STORAGE]] : $ClassStorage
1079+ // CHECK-LABEL: } // end sil function
1080+ sil [ossa] @testCopyUnmanagedInlined : $@convention(method) (@inout ClassWrapper) -> () {
1081+ bb0(%0 : $*ClassWrapper):
1082+ %1 = struct_element_addr %0 : $*ClassWrapper, #ClassWrapper.storage
1083+ %2 = load [take] %1 : $*ClassStorage
1084+ %4 = begin_borrow %2 : $ClassStorage
1085+ %5 = struct_extract %4 : $ClassStorage, #ClassStorage.ref
1086+ %6 = ref_to_unmanaged %5 : $C to $@sil_unmanaged C
1087+ %7 = strong_copy_unmanaged_value %6 : $@sil_unmanaged C
1088+ end_borrow %4 : $ClassStorage
1089+ destroy_value %2 : $ClassStorage
1090+ %10 = struct $ClassStorage (%7 : $C)
1091+ %11 = struct $ClassWrapper (%10 : $ClassStorage)
1092+ store %11 to [init] %0 : $*ClassWrapper
1093+ %23 = tuple ()
1094+ return %23 : $()
1095+ }
1096+
10191097// =============================================================================
10201098// instruction tests }}
10211099// =============================================================================
0 commit comments