mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
LoadableByAddress was accidentally changing ownership of direct_unowned values to @in (owned). This generates unsupported SIL for on-stack partial applies, which now breaks SIL verification. This also resulted in extra copies of values inside of closure contexts. Before calling the original function, the value would need to be copied onto the stack and the context would be destroyed. Now, we simply pass a pointer directly from the closure context. See IRGen/indirect_argument.sil+huge_partial_application. I'm pretty sure fixing this has no effect on the mangling of public symbols.
87 lines
4.0 KiB
Plaintext
87 lines
4.0 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all -closure-specialize %s | %FileCheck %s
|
|
|
|
import Builtin
|
|
|
|
class C {}
|
|
|
|
sil [ossa] @getC : $@convention(thin) () -> @owned C
|
|
|
|
class Storage {}
|
|
|
|
struct Val {}
|
|
|
|
// Verify that the argument to the specialized take_closure is still @_eagerMove.
|
|
|
|
// CHECK-LABEL: sil {{.*}}@$s12take_closure0B04main1CCTf1nc_n : {{.*}}{
|
|
// CHECK: {{bb[0-9]+}}({{%[^,]+}} : @_eagerMove @owned $C, {{%[^,]+}} :
|
|
// CHECK-LABEL: } // end sil function '$s12take_closure0B04main1CCTf1nc_n'
|
|
|
|
sil [ossa] [noinline] @take_closure : $@convention(thin) (@owned C, @guaranteed @noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()) -> () {
|
|
bb0(%c : @_eagerMove @owned $C, %0 : @guaranteed $@noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()):
|
|
%getC = function_ref @getC : $@convention(thin) () -> @owned C
|
|
%c1 = apply %getC() : $@convention(thin) () -> @owned C
|
|
%c2 = apply %getC() : $@convention(thin) () -> @owned C
|
|
%3 = apply %0(%c1, %c2) : $@noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()
|
|
destroy_value %c2 : $C
|
|
destroy_value %c1 : $C
|
|
destroy_value %c : $C
|
|
%retval = tuple()
|
|
return %retval : $()
|
|
}
|
|
|
|
sil shared [ossa] @closure : $@convention(thin) (@guaranteed C, @guaranteed C, @guaranteed C) -> () {
|
|
bb0(%0 : @guaranteed $C, %1 : @guaranteed $C, %2 : @guaranteed $C):
|
|
%15 = tuple ()
|
|
return %15 : $()
|
|
}
|
|
|
|
sil @caller : $@convention(thin) (@owned C) -> () {
|
|
bb0(%0 : $C):
|
|
%3 = function_ref @closure : $@convention(thin) (@guaranteed C, @guaranteed C, @guaranteed C) -> ()
|
|
%4 = partial_apply [callee_guaranteed] [on_stack] %3(%0) : $@convention(thin) (@guaranteed C, @guaranteed C, @guaranteed C) -> ()
|
|
%take_closure = function_ref @take_closure : $@convention(thin) (@owned C, @guaranteed @noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()) -> ()
|
|
strong_retain %0 : $C
|
|
%5 = apply %take_closure(%0, %4) : $@convention(thin) (@owned C, @guaranteed @noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()) -> ()
|
|
strong_release %0 : $C
|
|
dealloc_stack %4 : $@noescape @callee_guaranteed (@guaranteed C, @guaranteed C) -> ()
|
|
%retval = tuple()
|
|
return %retval : $()
|
|
}
|
|
|
|
// =============================================================================
|
|
// rdar://105887096: do not insert a retain inside a read-only function.
|
|
// For now, the specialization is disabled.
|
|
//
|
|
// TODO: A @noescape closure should never be converted to an @owned argument
|
|
// regardless of the function attribute.
|
|
|
|
// This should not be specialized until we support guaranteed arguments.
|
|
// CHECK-NOT: @$s20takesReadOnlyClosure
|
|
sil private [readonly] @takesReadOnlyClosure : $@convention(thin) (@noescape @callee_guaranteed (Val) -> Val) -> Val {
|
|
bb0(%2 : $@noescape @callee_guaranteed (Val) -> Val):
|
|
%46 = struct $Val ()
|
|
%261 = apply %2(%46) : $@noescape @callee_guaranteed (Val) -> Val
|
|
return %261 : $Val
|
|
}
|
|
|
|
sil private @readOnlyClosure : $@convention(thin) (Val, @guaranteed Storage) -> Val {
|
|
bb0(%0 : $Val, %1 : @closureCapture $Storage):
|
|
%46 = struct $Val ()
|
|
return %46 : $Val
|
|
}
|
|
|
|
// CHECK-LABEL: sil @testPassReadOnlyClosure : $@convention(method) (@guaranteed Storage) -> Val {
|
|
// CHECK-NOT: @owned Storage
|
|
// CHECK: apply %{{.*}} : $@convention(thin) (@noescape @callee_guaranteed (Val) -> Val) -> Val
|
|
// CHECK-LABEL: } // end sil function 'testPassReadOnlyClosure'
|
|
sil @testPassReadOnlyClosure : $@convention(method) (@guaranteed Storage) -> Val {
|
|
bb0(%0 : $Storage):
|
|
%176 = function_ref @readOnlyClosure : $@convention(thin) (Val, @guaranteed Storage) -> Val
|
|
%177 = partial_apply [callee_guaranteed] [on_stack] %176(%0) : $@convention(thin) (Val, @guaranteed Storage) -> Val
|
|
%178 = mark_dependence %177 : $@noescape @callee_guaranteed (Val) -> Val on %0 : $Storage
|
|
%188 = function_ref @takesReadOnlyClosure : $@convention(thin) (@noescape @callee_guaranteed (Val) -> Val) -> Val
|
|
%189 = apply %188(%178) : $@convention(thin) (@noescape @callee_guaranteed (Val) -> Val) -> Val
|
|
dealloc_stack %177 : $@noescape @callee_guaranteed (Val) -> Val
|
|
return %189 : $Val
|
|
}
|