Files
swift-mirror/test/IRGen/nonatomic_reference_counting.sil
John McCall ab3f77baf2 Make SILInstruction no longer a subclass of ValueBase and
introduce a common superclass, SILNode.

This is in preparation for allowing instructions to have multiple
results.  It is also a somewhat more elegant representation for
instructions that have zero results.  Instructions that are known
to have exactly one result inherit from a class, SingleValueInstruction,
that subclasses both ValueBase and SILInstruction.  Some care must be
taken when working with SILNode pointers and testing for equality;
please see the comment on SILNode for more information.

A number of SIL passes needed to be updated in order to handle this
new distinction between SIL values and SIL instructions.

Note that the SIL parser is now stricter about not trying to assign
a result value from an instruction (like 'return' or 'strong_retain')
that does not produce any.
2017-09-25 02:06:26 -04:00

226 lines
7.9 KiB
Plaintext

// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -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_rt_swift_nonatomic_retain
// CHECK: call {{.*}}@swift_rt_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_unknownRetain|swift_rt_swift_nonatomic_retain)}}
// CHECK: call {{.*}}@{{(swift_nonatomic_unknownRelease|swift_rt_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_rt_swift_nonatomic_retain_n
// CHECK: call {{.*}}@swift_rt_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_rt_swift_retain_n
// CHECK: call {{.*}}@swift_rt_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_unknownRetain_n|swift_rt_swift_nonatomic_retain_n)}}
// CHECK: call {{.*}}@{{(swift_nonatomic_unknownRelease_n|swift_rt_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_unknownRetain_n|swift_rt_swift_retain_n)}}
// CHECK: call {{.*}}@{{(swift_unknownRelease_n|swift_rt_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 : $()
}
// CHECK-LABEL: define {{.*}}@test_nonatomic_pin_unpin
// CHECK: call {{.*}}@swift_rt_swift_nonatomic_tryPin
// CHECK: call {{.*}}@swift_rt_swift_nonatomic_unpin
// CHECK: ret
sil @test_nonatomic_pin_unpin: $@convention(thin) () -> () {
bb0:
%0 = alloc_ref $C
%1 = unchecked_ref_cast %0 : $C to $Builtin.NativeObject
%2 = strong_pin [nonatomic] %1 : $Builtin.NativeObject
%f = function_ref @doSomething : $@convention(thin) () -> ()
%r = apply %f () : $@convention(thin) () -> ()
strong_unpin [nonatomic] %2 : $Optional<Builtin.NativeObject>
%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: _TFC28nonatomic_reference_counting1CD // C.__deallocating_deinit
}