mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Without this fix, the new 'consuming' and 'borrowing' keywords cannot
be used with trivial types. Which means, for example, they can't be
used in macro expansions that work on various types.
Fixes patterns like:
public func test1(i: consuming Int) -> Int {
takeClosure { [i = copy i] in i }
}
public func test2(i: borrowing Int) -> Int {
takeClosure { [i = copy i] in i }
}
public func test3(i: consuming Int) -> Int {
takeClosure { i }
}
// Sadly, test4 is still incorrectly diagnosed.
public func test4(i: borrowing Int) -> Int {
takeClosure { i }
}
Fixes rdar://112795074 (Crash compiling function that has a macro annotation and uses `consuming`)
351 lines
25 KiB
Plaintext
351 lines
25 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all -sil-print-debuginfo -closure-lifetime-fixup %s | %FileCheck %s
|
|
|
|
sil_stage raw
|
|
|
|
import Swift
|
|
import Builtin
|
|
import SwiftShims
|
|
|
|
class FakeNSString {}
|
|
class Klass {}
|
|
|
|
sil @$sSSSgIgg_AAIegg_TR : $@convention(thin) (@guaranteed Optional<String>, @noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()) -> ()
|
|
sil @noescapeBlock3 : $@convention(c) (Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>, Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>, Optional<FakeNSString>) -> ()
|
|
sil @$sSS10FoundationE19_bridgeToObjectiveCSo8FakeNSStringCyF : $@convention(method) (@guaranteed String) -> @owned FakeNSString
|
|
sil @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
|
|
sil @$sSSSgIegg_So8FakeNSStringCSgIyBy_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@guaranteed Optional<String>) -> (), Optional<FakeNSString>) -> ()
|
|
|
|
// Just make sure that we perform the optimization and do not trigger the ownership verifier.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @test1 : $@convention(thin) (@guaranteed Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>, @guaranteed Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>) -> () {
|
|
// CHECK-NOT: convert_escape_to_noescape [not_guaranteed]
|
|
// CHECK: } // end sil function 'test1'
|
|
sil [ossa] @test1 : $@convention(thin) (@guaranteed Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>, @guaranteed Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>) -> () {
|
|
bb0(%0 : @guaranteed $Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>, %1 : @guaranteed $Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>):
|
|
%2 = copy_value %0 : $Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>
|
|
switch_enum %2 : $Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb12
|
|
|
|
bb1(%4 : @owned $@callee_guaranteed (@guaranteed Optional<String>) -> ()):
|
|
%5 = convert_escape_to_noescape [not_guaranteed] %4 : $@callee_guaranteed (@guaranteed Optional<String>) -> () to $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%6 = enum $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>, #Optional.some!enumelt, %5 : $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
destroy_value %4 : $@callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
br bb2(%6 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>)
|
|
|
|
bb2(%9 : @owned $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>):
|
|
switch_enum %9 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>, case #Optional.some!enumelt: bb3, case #Optional.none!enumelt: bb4
|
|
|
|
bb3(%11 : @owned $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()):
|
|
%b11 = copy_value %11 : $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%12 = function_ref @$sSSSgIgg_AAIegg_TR : $@convention(thin) (@guaranteed Optional<String>, @noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()) -> ()
|
|
%13 = partial_apply [callee_guaranteed] %12(%b11) : $@convention(thin) (@guaranteed Optional<String>, @noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()) -> ()
|
|
%14 = mark_dependence %13 : $@callee_guaranteed (@guaranteed Optional<String>) -> () on %11 : $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%15 = copy_value %14 : $@callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%16 = alloc_stack $@block_storage @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%17 = project_block_storage %16 : $*@block_storage @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
store %15 to [init] %17 : $*@callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%19 = function_ref @$sSSSgIegg_So8FakeNSStringCSgIyBy_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@guaranteed Optional<String>) -> (), Optional<FakeNSString>) -> ()
|
|
%20 = init_block_storage_header %16 : $*@block_storage @callee_guaranteed (@guaranteed Optional<String>) -> (), invoke %19 : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@guaranteed Optional<String>) -> (), Optional<FakeNSString>) -> (), type $@convention(block) @noescape (Optional<FakeNSString>) -> ()
|
|
%21 = copy_block_without_escaping %20 : $@convention(block) @noescape (Optional<FakeNSString>) -> () withoutEscaping %14 : $@callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%22 = enum $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>, #Optional.some!enumelt, %21 : $@convention(block) @noescape (Optional<FakeNSString>) -> ()
|
|
destroy_addr %17 : $*@callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
dealloc_stack %16 : $*@block_storage @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
destroy_value %11 : $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
br bb5(%22 : $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>)
|
|
|
|
bb4:
|
|
%26 = enum $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>, #Optional.none!enumelt
|
|
br bb5(%26 : $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>)
|
|
|
|
bb5(%28 : @owned $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>):
|
|
%29 = copy_value %1 : $Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>
|
|
switch_enum %29 : $Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>, case #Optional.some!enumelt: bb6, case #Optional.none!enumelt: bb11
|
|
|
|
bb6(%31 : @owned $@callee_guaranteed (@guaranteed Optional<String>) -> ()):
|
|
%32 = convert_escape_to_noescape [not_guaranteed] %31 : $@callee_guaranteed (@guaranteed Optional<String>) -> () to $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%33 = enum $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>, #Optional.some!enumelt, %32 : $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
destroy_value %31 : $@callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
br bb7(%33 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>)
|
|
|
|
bb7(%36 : @owned $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>):
|
|
switch_enum %36 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>, case #Optional.some!enumelt: bb8, case #Optional.none!enumelt: bb9
|
|
|
|
bb8(%38 : @owned $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()):
|
|
%b38 = copy_value %38 : $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%39 = function_ref @$sSSSgIgg_AAIegg_TR : $@convention(thin) (@guaranteed Optional<String>, @noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()) -> ()
|
|
%40 = partial_apply [callee_guaranteed] %39(%b38) : $@convention(thin) (@guaranteed Optional<String>, @noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()) -> ()
|
|
%41 = mark_dependence %40 : $@callee_guaranteed (@guaranteed Optional<String>) -> () on %38 : $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%42 = copy_value %41 : $@callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%43 = alloc_stack $@block_storage @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%44 = project_block_storage %43 : $*@block_storage @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
store %42 to [init] %44 : $*@callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%46 = function_ref @$sSSSgIegg_So8FakeNSStringCSgIyBy_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@guaranteed Optional<String>) -> (), Optional<FakeNSString>) -> ()
|
|
%47 = init_block_storage_header %43 : $*@block_storage @callee_guaranteed (@guaranteed Optional<String>) -> (), invoke %46 : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@guaranteed Optional<String>) -> (), Optional<FakeNSString>) -> (), type $@convention(block) @noescape (Optional<FakeNSString>) -> ()
|
|
%48 = copy_block_without_escaping %47 : $@convention(block) @noescape (Optional<FakeNSString>) -> () withoutEscaping %41 : $@callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
%49 = enum $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>, #Optional.some!enumelt, %48 : $@convention(block) @noescape (Optional<FakeNSString>) -> ()
|
|
destroy_addr %44 : $*@callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
dealloc_stack %43 : $*@block_storage @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
destroy_value %38 : $@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()
|
|
br bb10(%49 : $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>)
|
|
|
|
bb9:
|
|
%53 = enum $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>, #Optional.none!enumelt
|
|
br bb10(%53 : $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>)
|
|
|
|
bb10(%55 : @owned $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>):
|
|
%56 = string_literal utf8 "Foobar"
|
|
%57 = integer_literal $Builtin.Word, 6
|
|
%58 = integer_literal $Builtin.Int1, -1
|
|
%59 = metatype $@thin String.Type
|
|
%60 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
|
|
%61 = apply %60(%56, %57, %58, %59) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
|
|
%62 = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8FakeNSStringCyF : $@convention(method) (@guaranteed String) -> @owned FakeNSString
|
|
%63 = begin_borrow %61 : $String
|
|
%64 = apply %62(%63) : $@convention(method) (@guaranteed String) -> @owned FakeNSString
|
|
end_borrow %63 : $String
|
|
%66 = enum $Optional<FakeNSString>, #Optional.some!enumelt, %64 : $FakeNSString
|
|
destroy_value %61 : $String
|
|
%68 = function_ref @noescapeBlock3 : $@convention(c) (Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>, Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>, Optional<FakeNSString>) -> ()
|
|
%69 = apply %68(%28, %55, %66) : $@convention(c) (Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>, Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>, Optional<FakeNSString>) -> ()
|
|
destroy_value %66 : $Optional<FakeNSString>
|
|
destroy_value %55 : $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>
|
|
destroy_value %28 : $Optional<@convention(block) @noescape (Optional<FakeNSString>) -> ()>
|
|
%73 = tuple ()
|
|
return %73 : $()
|
|
|
|
bb11:
|
|
%75 = enum $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>, #Optional.none!enumelt
|
|
br bb7(%75 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>)
|
|
|
|
bb12:
|
|
%77 = enum $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>, #Optional.none!enumelt
|
|
br bb2(%77 : $Optional<@noescape @callee_guaranteed (@guaranteed Optional<String>) -> ()>)
|
|
}
|
|
|
|
sil @originalClosure : $@convention(thin) () -> ()
|
|
sil @noEscapeThunk : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
|
|
sil @blockThunk : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> ()
|
|
|
|
// Just make sure we apply the optimization. The ownership verifier will verify
|
|
// that we do not catch the leak.
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @ssaupdater_no_single_destroy_some_in_exit_block : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed () -> (), @guaranteed Klass, @guaranteed @callee_guaranteed () -> ()) -> () {
|
|
// CHECK-NOT: convert_escape_to_noescape [not_guaranteed]
|
|
// CHECK-NOT: copy_block_without_escaping
|
|
// CHECK: } // end sil function 'ssaupdater_no_single_destroy_some_in_exit_block'
|
|
sil [ossa] @ssaupdater_no_single_destroy_some_in_exit_block : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed () -> (), @guaranteed Klass, @guaranteed @callee_guaranteed () -> ()) -> () {
|
|
bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $@callee_guaranteed () -> (), %2 : @guaranteed $Klass, %3 : @guaranteed $@callee_guaranteed () -> ()):
|
|
// This basic block is needed to trigger the bug.
|
|
br bb1
|
|
|
|
bb1:
|
|
%39 = function_ref @originalClosure : $@convention(thin) () -> ()
|
|
%43 = partial_apply [callee_guaranteed] %39() : $@convention(thin) () -> ()
|
|
%44 = convert_escape_to_noescape [not_guaranteed] %43 : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
|
|
%b44 = copy_value %44 : $@noescape @callee_guaranteed () -> ()
|
|
%45 = function_ref @noEscapeThunk : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
|
|
%46 = partial_apply [callee_guaranteed] %45(%b44) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
|
|
%47 = mark_dependence %46 : $@callee_guaranteed () -> () on %44 : $@noescape @callee_guaranteed () -> ()
|
|
%48 = copy_value %47 : $@callee_guaranteed () -> ()
|
|
%49 = alloc_stack $@block_storage @callee_guaranteed () -> ()
|
|
%50 = project_block_storage %49 : $*@block_storage @callee_guaranteed () -> ()
|
|
store %48 to [init] %50 : $*@callee_guaranteed () -> ()
|
|
%52 = function_ref @blockThunk : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> ()
|
|
%53 = init_block_storage_header %49 : $*@block_storage @callee_guaranteed () -> (), invoke %52 : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> (), type $@convention(block) @noescape () -> ()
|
|
%54 = copy_block_without_escaping %53 : $@convention(block) @noescape () -> () withoutEscaping %47 : $@callee_guaranteed () -> ()
|
|
%55 = enum $Optional<@convention(block) @noescape () -> ()>, #Optional.some!enumelt, %54 : $@convention(block) @noescape () -> ()
|
|
destroy_addr %50 : $*@callee_guaranteed () -> ()
|
|
dealloc_stack %49 : $*@block_storage @callee_guaranteed () -> ()
|
|
destroy_value %44 : $@noescape @callee_guaranteed () -> ()
|
|
destroy_value %43 : $@callee_guaranteed () -> ()
|
|
destroy_value %55 : $Optional<@convention(block) @noescape () -> ()>
|
|
%86 = tuple ()
|
|
return %86 : $()
|
|
}
|
|
|
|
sil [ossa] @closureImpl : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> Bool
|
|
sil [ossa] @useClosure : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> ()
|
|
|
|
// Don't crash.
|
|
// CHECK-LABEL: sil hidden [ossa] @testUndefined
|
|
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [on_stack]
|
|
// CHECK: destroy_value [[PA]] : $@noescape @callee_guaranteed () -> Bool
|
|
// CHECK: destroy_value
|
|
sil hidden [ossa] @testUndefined : $@convention(method) (@guaranteed Klass, @guaranteed Klass) -> () {
|
|
bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass):
|
|
%4 = function_ref @closureImpl : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> Bool
|
|
%5 = copy_value %1 : $Klass
|
|
%6 = partial_apply [callee_guaranteed] %4(%5, undef) : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> Bool
|
|
%7 = convert_escape_to_noescape [not_guaranteed] %6 : $@callee_guaranteed () -> Bool to $@noescape @callee_guaranteed () -> Bool
|
|
%21 = function_ref @useClosure : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> ()
|
|
%22 = apply %21(%7) : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> ()
|
|
destroy_value %7 : $@noescape @callee_guaranteed () -> Bool
|
|
destroy_value %6 : $@callee_guaranteed () -> Bool
|
|
%42 = tuple ()
|
|
return %42 : $()
|
|
}
|
|
|
|
sil @simpleClosure : $@convention(thin) () -> ()
|
|
|
|
// Don't crash.
|
|
// CHECK-LABEL: sil [ossa] @testIteratorInvalidation
|
|
// CHECK: [[C:%.*]] = thin_to_thick_function
|
|
// CHECK: [[CC:%.*]] = copy_value [[C]]
|
|
// CHECK: [[NE:%.*]] = convert_escape_to_noescape [[CC]]
|
|
// CHECK: br bb3([[NE:%.*]]
|
|
// CHECK: } // end sil function 'testIteratorInvalidation'
|
|
sil [ossa] @testIteratorInvalidation : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> () {
|
|
bb0(%0 : @guaranteed $@noescape @callee_guaranteed () -> ()):
|
|
%2 = function_ref @simpleClosure : $@convention(thin) () -> ()
|
|
%3 = thin_to_thick_function %2 : $@convention(thin) () -> () to $@callee_guaranteed () -> ()
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%b0 = copy_value %0 : $@noescape @callee_guaranteed () -> ()
|
|
br bb3(%b0 : $@noescape @callee_guaranteed () -> ())
|
|
|
|
bb2:
|
|
%11 = convert_escape_to_noescape [not_guaranteed] %3 : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
|
|
br bb3(%11 : $@noescape @callee_guaranteed () -> ())
|
|
|
|
|
|
bb3(%13 : @owned $@noescape @callee_guaranteed () -> ()):
|
|
%15 = apply %13() : $@noescape @callee_guaranteed () -> ()
|
|
destroy_value %13 : $@noescape @callee_guaranteed () -> ()
|
|
%16 = tuple ()
|
|
return %16 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_lifetime_extension_until_function_exit :
|
|
// CHECK: [[NONE1:%.*]] = enum $Optional<@callee_guaranteed () -> ()>, #Optional.none!enumelt
|
|
// CHECK: [[NONE2:%.*]] = enum $Optional<@callee_guaranteed () -> ()>, #Optional.none!enumelt
|
|
// CHECK: [[BORROWNONE:%.*]] = begin_borrow [[NONE2]] : $Optional<@callee_guaranteed () -> ()>
|
|
// CHECK: cond_br undef, bb1, bb2
|
|
// CHECK: bb1:
|
|
// CHECK: [[ORIG:%.*]] = function_ref @originalClosure : $@convention(thin) () -> ()
|
|
// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed] [[ORIG]]() : $@convention(thin) () -> ()
|
|
// CHECK: [[COPY:%.*]] = copy_value [[PA1]] : $@callee_guaranteed () -> ()
|
|
// CHECK: [[NOESC:%.*]] = convert_escape_to_noescape [[COPY]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
|
|
// CHECK: [[SOME:%.*]] = enum $Optional<@callee_guaranteed () -> ()>, #Optional.some!enumelt, [[COPY]] : $@callee_guaranteed () -> ()
|
|
// CHECK: [[BORROW:%.*]] = begin_borrow [[SOME]] : $Optional<@callee_guaranteed () -> ()>
|
|
// CHECK: [[MDI:%.*]] = mark_dependence [[NOESC]] : $@noescape @callee_guaranteed () -> () on [[BORROW]] : $Optional<@callee_guaranteed () -> ()>
|
|
// CHECK: br bb3([[BORROW]] : $Optional<@callee_guaranteed () -> ()>, [[SOME]] : $Optional<@callee_guaranteed () -> ()>, {{.*}})
|
|
// CHECK-LABEL: } // end sil function 'test_lifetime_extension_until_function_exit'
|
|
sil [ossa] @test_lifetime_extension_until_function_exit : $@convention(thin) (@guaranteed Klass, @guaranteed @callee_guaranteed () -> (), @guaranteed Klass, @guaranteed @callee_guaranteed () -> ()) -> () {
|
|
bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $@callee_guaranteed () -> (), %2 : @guaranteed $Klass, %3 : @guaranteed $@callee_guaranteed () -> ()):
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%5 = function_ref @originalClosure : $@convention(thin) () -> ()
|
|
%6 = partial_apply [callee_guaranteed] %5() : $@convention(thin) () -> ()
|
|
%7 = convert_escape_to_noescape [not_guaranteed] %6 : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
|
|
%b7 = copy_value %7 : $@noescape @callee_guaranteed () -> ()
|
|
%8 = function_ref @noEscapeThunk : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
|
|
%9 = partial_apply [callee_guaranteed] %8(%b7) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
|
|
%10 = mark_dependence %9 : $@callee_guaranteed () -> () on %7 : $@noescape @callee_guaranteed () -> ()
|
|
%11 = copy_value %10 : $@callee_guaranteed () -> ()
|
|
%12 = alloc_stack $@block_storage @callee_guaranteed () -> ()
|
|
%13 = project_block_storage %12 : $*@block_storage @callee_guaranteed () -> ()
|
|
store %11 to [init] %13 : $*@callee_guaranteed () -> ()
|
|
%15 = function_ref @blockThunk : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> ()
|
|
%16 = init_block_storage_header %12 : $*@block_storage @callee_guaranteed () -> (), invoke %15 : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> ()) -> (), type $@convention(block) @noescape () -> ()
|
|
%17 = copy_block_without_escaping %16 : $@convention(block) @noescape () -> () withoutEscaping %10 : $@callee_guaranteed () -> ()
|
|
%18 = enum $Optional<@convention(block) @noescape () -> ()>, #Optional.some!enumelt, %17 : $@convention(block) @noescape () -> ()
|
|
destroy_addr %13 : $*@callee_guaranteed () -> ()
|
|
dealloc_stack %12 : $*@block_storage @callee_guaranteed () -> ()
|
|
destroy_value %7 : $@noescape @callee_guaranteed () -> ()
|
|
destroy_value %6 : $@callee_guaranteed () -> ()
|
|
destroy_value %18 : $Optional<@convention(block) @noescape () -> ()>
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%25 = tuple ()
|
|
return %25 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_alloc_stack_arg_with_frontier_outside_try_apply_successors : $@convention(thin) <Self> (@in_guaranteed Self) -> @error any Error {
|
|
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
|
|
// CHECK: [[STACK:%[^,]+]] = alloc_stack $Self
|
|
// CHECK: try_apply undef() {{.*}}, normal [[SUCCESS_1:bb[0-9]+]], error [[FAILURE_1:bb[0-9]+]]
|
|
// CHECK: [[SUCCESS_1]]
|
|
// CHECK: copy_addr [[INSTANCE]] to [init] [[STACK]] : $*Self, {{.*}} scope [[STACK_SCOPE:[0-9]+]]
|
|
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [on_stack] undef<Self>([[STACK]])
|
|
// CHECK: [[DEPENDENCY:%[^,]+]] = mark_dependence [[CLOSURE]] {{.*}} on [[STACK]]
|
|
// CHECK: try_apply undef([[DEPENDENCY]]) {{.*}}, normal [[SUCCESS_2:bb[0-9]+]], error [[FAILURE_2:bb[0-9]+]]
|
|
// CHECK: [[SUCCESS_2]]
|
|
// CHECK: destroy_value [[DEPENDENCY]]
|
|
// CHECK: destroy_addr [[STACK]]
|
|
// CHECK: dealloc_stack [[STACK]] : $*Self, {{.*}} scope [[STACK_SCOPE]]
|
|
// CHECK: [[FAILURE_1]]
|
|
// CHECK: dealloc_stack [[STACK]] : $*Self, {{.*}} scope [[STACK_SCOPE]]
|
|
// CHECK: throw
|
|
// CHECK: [[FAILURE_2]]
|
|
// CHECK-NOT: dealloc_stack
|
|
// CHECK: unreachable
|
|
// CHECK-LABEL: } // end sil function 'test_alloc_stack_arg_with_frontier_outside_try_apply_successors'
|
|
sil [ossa] @test_alloc_stack_arg_with_frontier_outside_try_apply_successors : $@convention(thin) <Self> (@in_guaranteed Self) -> (@error any Error) {
|
|
bb0(%2 : $*Self):
|
|
%4 = alloc_stack $Self
|
|
try_apply undef() : $@convention(thin) () -> (@error any Error), normal bb1, error bb3
|
|
|
|
bb1(%10 : $()):
|
|
copy_addr %2 to [init] %4 : $*Self
|
|
%13 = partial_apply [callee_guaranteed] undef<Self>(%4) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
|
|
%15 = convert_escape_to_noescape [not_guaranteed] %13 : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
|
|
try_apply undef(%15) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> (@error any Error), normal bb2, error bb4
|
|
|
|
bb2(%18 : $()):
|
|
destroy_value %15 : $@noescape @callee_guaranteed () -> ()
|
|
destroy_value %13 : $@callee_guaranteed () -> ()
|
|
%21 = tuple ()
|
|
dealloc_stack %4 : $*Self
|
|
return %21 : $()
|
|
|
|
bb3(%25 : @owned $any Error):
|
|
dealloc_stack %4 : $*Self
|
|
throw %25 : $any Error
|
|
|
|
bb4(%29 : @owned $any Error):
|
|
unreachable
|
|
}
|
|
|
|
sil @testTrivialBorrowClosure : $@convention(thin) (Int) -> Int
|
|
sil @testTrivialBorrowTakeClosure : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> Int) -> Int
|
|
|
|
// rdar://112795074 (Crash compiling function that has a macro annotation and uses `consuming`)
|
|
//
|
|
// CHECK-LABEL: sil [ossa] @testTrivialBorrow : $@convention(thin) (Int) -> Int {
|
|
// CHECK: [[ARG:%.*]] = moveonlywrapper_to_copyable [guaranteed]
|
|
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [on_stack] %{{.*}}([[ARG]]) : $@convention(thin) (Int) -> Int
|
|
// CHECK-NOT: destroy
|
|
// CHECK: destroy_value [[PA]] : $@noescape @callee_guaranteed () -> Int
|
|
// CHECK-NOT: destroy
|
|
// CHECK: destroy_addr
|
|
// CHECK-NEXT: dealloc_stack
|
|
// CHECK-NEXT: return
|
|
// CHECK-LABEL: } // end sil function 'testTrivialBorrow'
|
|
sil [ossa] @testTrivialBorrow : $@convention(thin) (Int) -> Int {
|
|
bb0(%0 : @noImplicitCopy @_eagerMove $Int):
|
|
%1 = alloc_stack $@moveOnly Int, var, name "i"
|
|
%2 = mark_must_check [consumable_and_assignable] %1 : $*@moveOnly Int
|
|
%3 = moveonlywrapper_to_copyable_addr %2 : $*@moveOnly Int
|
|
store %0 to [trivial] %3 : $*Int
|
|
%5 = begin_access [read] [static] %2 : $*@moveOnly Int
|
|
%6 = load_borrow %5 : $*@moveOnly Int
|
|
%7 = moveonlywrapper_to_copyable [guaranteed] %6 : $@moveOnly Int
|
|
end_borrow %6 : $@moveOnly Int
|
|
end_access %5 : $*@moveOnly Int
|
|
%10 = function_ref @testTrivialBorrowClosure : $@convention(thin) (Int) -> Int
|
|
%11 = partial_apply [callee_guaranteed] %10(%7) : $@convention(thin) (Int) -> Int
|
|
%12 = convert_escape_to_noescape [not_guaranteed] %11 : $@callee_guaranteed () -> Int to $@noescape @callee_guaranteed () -> Int
|
|
%13 = function_ref @testTrivialBorrowTakeClosure : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> Int) -> Int
|
|
%14 = apply %13(%12) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> Int) -> Int
|
|
destroy_value %12 : $@noescape @callee_guaranteed () -> Int
|
|
destroy_value %11 : $@callee_guaranteed () -> Int
|
|
destroy_addr %2 : $*@moveOnly Int
|
|
dealloc_stack %1 : $*@moveOnly Int
|
|
return %14 : $Int
|
|
}
|