blob: e16fc1c7b3ef16f4388b6eef0c195ee89f2d8cca [file] [log] [blame]
// RUN: %target-swift-frontend -disable-sil-perf-optzns -O -Xllvm -swiftmergefunc-threshold=0 -emit-ir %s | %FileCheck %s
// Check that IRGen lowers non-atomic reference counting instructions to
// proper runtime calls.
// Check that LLVM passes combine multiple retains/releases into
// retain_n/release_n and invoke a proper runtime function. Non-atomic runtime
// functions should be called only if all combined reference-counting
// instructions are non-atomic.
//
// Take into account that on Linux unknown_retain/unknown_release are not supported
// and native retain/release runtime functions are used instead.
sil_stage canonical
import Builtin
import Swift
import SwiftShims
public class C {
deinit
init()
}
public protocol P : class {
}
// foo(C) -> C
sil [noinline] @_TF28nonatomic_reference_counting3fooFCS_1CS0_ : $@convention(thin) (@owned C) -> @owned C {
bb0(%0 : $C):
return %0 : $C
}
sil @doSomething : $@convention(thin) () -> ()
// CHECK-LABEL: define {{.*}}@test_strong_nonatomic_rr
// CHECK: call {{.*}}@swift_nonatomic_retain
// CHECK: call {{.*}}@swift_nonatomic_release
// CHECK: ret
sil @test_strong_nonatomic_rr: $@convention(thin) () -> @owned C {
bb0:
%1 = alloc_ref $C
strong_retain [nonatomic] %1 : $C
%f = function_ref @doSomething : $@convention(thin) () -> ()
%r = apply %f () : $@convention(thin) () -> ()
strong_release [nonatomic] %1 : $C
return %1 : $C
}
// CHECK-LABEL: define {{.*}}@test_unknown_nonatomic_rr
// CHECK: call {{.*}}@{{(swift_nonatomic_unknownObjectRetain|swift_nonatomic_retain)}}
// CHECK: call {{.*}}@{{(swift_nonatomic_unknownObjectRelease|swift_nonatomic_release)}}
// CHECK: ret
sil @test_unknown_nonatomic_rr: $@convention(thin) <T where T : P> (@owned T) -> () {
bb0(%0 : $T):
strong_retain [nonatomic] %0 : $T
%f = function_ref @doSomething : $@convention(thin) () -> ()
%r = apply %f () : $@convention(thin) () -> ()
strong_release [nonatomic] %0 : $T
%9 = tuple ()
return %9 : $()
}
// CHECK-LABEL: define {{.*}}@test_strong_nonatomic_rr_n
// CHECK: call {{.*}}@swift_nonatomic_retain_n
// CHECK: call {{.*}}@swift_nonatomic_release_n
// CHECK: ret
sil @test_strong_nonatomic_rr_n: $@convention(thin) () -> @owned C {
bb0:
%1 = alloc_ref $C
strong_retain [nonatomic] %1 : $C
strong_retain [nonatomic] %1 : $C
%f = function_ref @doSomething : $@convention(thin) () -> ()
%r = apply %f () : $@convention(thin) () -> ()
strong_release [nonatomic] %1 : $C
strong_release [nonatomic] %1 : $C
return %1 : $C
}
// CHECK-LABEL: define {{.*}}@test_strong_mixed_rr_n
// CHECK: call {{.*}}@swift_retain_n
// CHECK: call {{.*}}@swift_release_n
// CHECK: ret
sil @test_strong_mixed_rr_n: $@convention(thin) () -> @owned C {
bb0:
%1 = alloc_ref $C
strong_retain [nonatomic] %1 : $C
strong_retain %1 : $C
%f = function_ref @doSomething : $@convention(thin) () -> ()
%r = apply %f () : $@convention(thin) () -> ()
strong_release %1 : $C
strong_release [nonatomic] %1 : $C
return %1 : $C
}
// CHECK-LABEL: define {{.*}}@test_unknown_nonatomic_rr_n
// CHECK: call {{.*}}@{{(swift_nonatomic_unknownObjectRetain_n|swift_nonatomic_retain_n)}}
// CHECK: call {{.*}}@{{(swift_nonatomic_unknownObjectRelease_n|swift_nonatomic_release_n)}}
// CHECK: ret
sil @test_unknown_nonatomic_rr_n: $@convention(thin) <T where T : P> (@owned T) -> () {
bb0(%0 : $T):
strong_retain [nonatomic] %0 : $T
strong_retain [nonatomic] %0 : $T
%f = function_ref @doSomething : $@convention(thin) () -> ()
%r = apply %f () : $@convention(thin) () -> ()
strong_release [nonatomic] %0 : $T
strong_release [nonatomic] %0 : $T
%9 = tuple ()
return %9 : $()
}
// CHECK-LABEL: define {{.*}}@test_unknown_mixed_rr_n
// CHECK: call {{.*}}@{{(swift_unknownObjectRetain_n|swift_retain_n)}}
// CHECK: call {{.*}}@{{(swift_unknownObjectRelease_n|swift_release_n)}}
// CHECK: ret
sil @test_unknown_mixed_rr_n: $@convention(thin) <T where T : P> (@owned T) -> () {
bb0(%0 : $T):
strong_retain [nonatomic] %0 : $T
strong_retain %0 : $T
%f = function_ref @doSomething : $@convention(thin) () -> ()
%r = apply %f () : $@convention(thin) () -> ()
strong_release %0 : $T
strong_release [nonatomic] %0 : $T
%9 = tuple ()
return %9 : $()
}
sil @test_unowned_nonatomic_rr: $@convention(thin) () -> () {
bb0:
%0 = alloc_ref $C
%1 = ref_to_unowned %0 : $C to $@sil_unowned C
unowned_retain [nonatomic] %1 : $@sil_unowned C
%f = function_ref @doSomething : $@convention(thin) () -> ()
%r = apply %f () : $@convention(thin) () -> ()
unowned_release [nonatomic] %1 : $@sil_unowned C
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: define {{.*}}@test_bridged_nonatomic_rr
// CHECK: call {{.*}}@swift_nonatomic_bridgeObjectRetain
// CHECK: call {{.*}}@swift_nonatomic_bridgeObjectRelease
// CHECK: ret
sil @test_bridged_nonatomic_rr: $@convention(thin) () -> () {
bb0:
%0 = alloc_ref $C
%1 = integer_literal $Builtin.Word, 0
%2 = ref_to_bridge_object %0 : $C, %1 : $Builtin.Word
strong_retain [nonatomic] %2 : $Builtin.BridgeObject
%f = function_ref @doSomething : $@convention(thin) () -> ()
%r = apply %f () : $@convention(thin) () -> ()
strong_release [nonatomic] %2 : $Builtin.BridgeObject
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: define {{.*}}@test_bridged_nonatomic_rr_n
// CHECK: call {{.*}}@swift_nonatomic_bridgeObjectRetain_n
// CHECK: call {{.*}}@swift_nonatomic_bridgeObjectRelease_n
// CHECK: ret
sil @test_bridged_nonatomic_rr_n: $@convention(thin) () -> () {
bb0:
%0 = alloc_ref $C
%1 = integer_literal $Builtin.Word, 0
%2 = ref_to_bridge_object %0 : $C, %1 : $Builtin.Word
strong_retain [nonatomic] %2 : $Builtin.BridgeObject
strong_retain [nonatomic] %2 : $Builtin.BridgeObject
%f = function_ref @doSomething : $@convention(thin) () -> ()
%r = apply %f () : $@convention(thin) () -> ()
//%f = function_ref @_TF28nonatomic_reference_counting3fooFCS_1CS0_ : $@convention(thin) (@owned C) -> @owned C
//%r = apply %f (%0) : $@convention(thin) (@owned C) -> @owned C
strong_release [nonatomic] %2 : $Builtin.BridgeObject
strong_release [nonatomic] %2 : $Builtin.BridgeObject
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: define {{.*}}@test_bridged_mixed_rr_n
// CHECK: call {{.*}}@swift_bridgeObjectRetain_n
// CHECK: call {{.*}}@swift_bridgeObjectRelease_n
// CHECK: ret
sil @test_bridged_mixed_rr_n: $@convention(thin) () -> () {
bb0:
%0 = alloc_ref $C
%1 = integer_literal $Builtin.Word, 0
%2 = ref_to_bridge_object %0 : $C, %1 : $Builtin.Word
strong_retain [nonatomic] %2 : $Builtin.BridgeObject
strong_retain %2 : $Builtin.BridgeObject
%f = function_ref @doSomething : $@convention(thin) () -> ()
%r = apply %f () : $@convention(thin) () -> ()
//%f = function_ref @_TF28nonatomic_reference_counting3fooFCS_1CS0_ : $@convention(thin) (@owned C) -> @owned C
//%r = apply %f (%0) : $@convention(thin) (@owned C) -> @owned C
strong_release %2 : $Builtin.BridgeObject
strong_release [nonatomic] %2 : $Builtin.BridgeObject
%3 = tuple ()
return %3 : $()
}
// C.__deallocating_deinit
sil @_TFC28nonatomic_reference_counting1CD : $@convention(method) (@owned C) -> () {
bb0(%0 : $C):
dealloc_ref %0 : $C
%4 = tuple ()
return %4 : $()
}
sil_vtable C {
#C.deinit!deallocator.1: @_TFC28nonatomic_reference_counting1CD // C.__deallocating_deinit
}