Files
swift-mirror/test/SILOptimizer/closure-lifetime-fixup.sil
Andrew Trick 9c24933bd4 Fix compiler crashes with consuming and borrowing keywords.
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`)
2023-08-10 11:17:45 -07:00

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
}