blob: 58e50ff403474b791a53aa7aaaf09c66472cf32b [file] [log] [blame]
// RUN: %target-sil-opt -module-name Swift -enable-sil-verify-all -enable-sil-ownership -semantic-arc-opts %s | %FileCheck %s
sil_stage canonical
import Builtin
//////////////////
// Declarations //
//////////////////
sil @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
struct NativeObjectPair {
var obj1 : Builtin.NativeObject
var obj2 : Builtin.NativeObject
}
///////////
// Tests //
///////////
// CHECK-LABEL: sil @argument_only_destroy_user_test : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
// CHECK-NOT: copy_value
// CHECK-NOT: destroy_value
sil @argument_only_destroy_user_test : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = copy_value %0 : $Builtin.NativeObject
destroy_value %1 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @argument_diamond_test_case : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned Builtin.NativeObject {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $Builtin.NativeObject):
// CHECK-NEXT: [[RESULT:%.*]] = copy_value [[ARG]]
// CHECK-NEXT: cond_br undef, [[LHSBB:bb[0-9]+]], [[RHSBB:bb[0-9]+]]
//
// CHECK: [[LHSBB]]:
// CHECK-NEXT: br [[EPILOGBB:bb[0-9]+]]
//
// CHECK: [[RHSBB]]:
// CHECK-NEXT: br [[EPILOGBB]]
//
// CHECK: [[EPILOGBB]]:
// CHECK-NEXT: return [[RESULT]]
sil @argument_diamond_test_case : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned Builtin.NativeObject {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = copy_value %0 : $Builtin.NativeObject
%2 = copy_value %1 : $Builtin.NativeObject
cond_br undef, bb1, bb2
bb1:
destroy_value %1 : $Builtin.NativeObject
br bb3
bb2:
destroy_value %1 : $Builtin.NativeObject
br bb3
bb3:
return %2 : $Builtin.NativeObject
}
// CHECK-LABEL: sil @argument_copy_borrow_test_case : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $Builtin.NativeObject
// CHECK-NOT: copy_value
// CHECK-NOT: begin_borrow
// CHECK: apply {{%.*}}([[ARG]])
// CHECK-NOT: end_borrow
// CHECK-NOT: destroy_value
// CHECK: } // end sil function 'argument_copy_borrow_test_case'
sil @argument_copy_borrow_test_case : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = copy_value %0 : $Builtin.NativeObject
%2 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
%3 = begin_borrow %1 : $Builtin.NativeObject
apply %2(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
end_borrow %3 : $Builtin.NativeObject
destroy_value %1 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @argument_copy_of_copy : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
// CHECK: bb0
// CHECK-NEXT: tuple
// CHECK-NEXT: return
// CHECK-NEXT: } // end sil function 'argument_copy_of_copy'
sil @argument_copy_of_copy : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = copy_value %0 : $Builtin.NativeObject
%2 = begin_borrow %1 : $Builtin.NativeObject
%3 = copy_value %2 : $Builtin.NativeObject
%4 = begin_borrow %3 : $Builtin.NativeObject
end_borrow %4 : $Builtin.NativeObject
destroy_value %3 : $Builtin.NativeObject
end_borrow %2 : $Builtin.NativeObject
destroy_value %1 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @copy_struct_extract_guaranteed_use : $@convention(thin) (@guaranteed NativeObjectPair) -> () {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $NativeObjectPair):
// CHECK-NOT: copy_value
// CHECK-NOT: begin_borrow
// CHECK: [[FIELD:%.*]] = struct_extract [[ARG]]
// CHECK: apply {{%.*}}([[FIELD]]) :
// CHECK-NEXT: tuple
// CHECK-NEXT: return
// CHECK: } // end sil function 'copy_struct_extract_guaranteed_use'
sil @copy_struct_extract_guaranteed_use : $@convention(thin) (@guaranteed NativeObjectPair) -> () {
bb0(%0 : @guaranteed $NativeObjectPair):
%1 = copy_value %0 : $NativeObjectPair
%2 = begin_borrow %1 : $NativeObjectPair
%3 = struct_extract %2 : $NativeObjectPair, #NativeObjectPair.obj1
%4 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
apply %4(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
end_borrow %2 : $NativeObjectPair
destroy_value %1 : $NativeObjectPair
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @struct_extract_copy_guaranteed_use : $@convention(thin) (@guaranteed NativeObjectPair) -> () {
// CHECK: bb0([[ARG:%.*]] : @guaranteed $NativeObjectPair):
// CHECK: [[FIELD:%.*]] = struct_extract [[ARG]]
// CHECK: apply {{%.*}}([[FIELD]])
// CHECK-NOT: destroy_value
// CHECK: } // end sil function 'struct_extract_copy_guaranteed_use'
sil @struct_extract_copy_guaranteed_use : $@convention(thin) (@guaranteed NativeObjectPair) -> () {
bb0(%0 : @guaranteed $NativeObjectPair):
%1 = struct_extract %0 : $NativeObjectPair, #NativeObjectPair.obj1
%2 = copy_value %1 : $Builtin.NativeObject
%3 = begin_borrow %2 : $Builtin.NativeObject
%4 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
apply %4(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
end_borrow %3 : $Builtin.NativeObject
destroy_value %2 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// For now we do not support recreating forwarding instructions since we do not
// dynamically recompute ownership.
// CHECK-LABEL: sil @do_not_process_forwarding_uses : $@convention(thin) (@guaranteed NativeObjectPair) -> () {
// CHECK: copy_value
// CHECK: } // end sil function 'do_not_process_forwarding_uses'
sil @do_not_process_forwarding_uses : $@convention(thin) (@guaranteed NativeObjectPair) -> () {
bb0(%0 : @guaranteed $NativeObjectPair):
%1 = copy_value %0 : $NativeObjectPair
(%2, %3) = destructure_struct %1 : $NativeObjectPair
%4 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
apply %4(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
apply %4(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
destroy_value %2 : $Builtin.NativeObject
destroy_value %3 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// CHECK-LABEL: sil @do_not_process_forwarding_uses_2 : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
// CHECK: copy_value
// CHECK: } // end sil function 'do_not_process_forwarding_uses_2'
sil @do_not_process_forwarding_uses_2 : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () {
bb0(%0 : @guaranteed $Builtin.NativeObject):
%1 = copy_value %0 : $Builtin.NativeObject
%2 = unchecked_ref_cast %1 : $Builtin.NativeObject to $Builtin.NativeObject
%4 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
apply %4(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
destroy_value %2 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}
// Do not eliminate a copy from an unowned value. This will cause us to pass the
// unowned value as guaranteed... =><=.
//
// CHECK-LABEL: sil @unowned_arg_copy : $@convention(thin) (Builtin.NativeObject) -> () {
// CHECK: copy_value
// CHECK: } // end sil function 'unowned_arg_copy'
sil @unowned_arg_copy : $@convention(thin) (Builtin.NativeObject) -> () {
bb0(%0 : @unowned $Builtin.NativeObject):
%1 = copy_value %0 : $Builtin.NativeObject
%2 = function_ref @guaranteed_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
apply %2(%1) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
destroy_value %1 : $Builtin.NativeObject
%9999 = tuple()
return %9999 : $()
}