mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
449 lines
31 KiB
Plaintext
449 lines
31 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types -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>) -> ()
|
|
sil @nothrower : $@convention(thin) () -> Int
|
|
sil @rethrower : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> (Int, @error any Error)) -> (Int, @error any Error)
|
|
|
|
// 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: try_apply undef() {{.*}}, normal [[SUCCESS_1:bb[0-9]+]], error [[FAILURE_1:bb[0-9]+]]
|
|
// CHECK: [[SUCCESS_1]]
|
|
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [on_stack] undef<Self>([[INSTANCE]])
|
|
// CHECK: [[DEPENDENCY:%[^,]+]] = mark_dependence [nonescaping] [[CLOSURE]] {{.*}} on [[INSTANCE]]
|
|
// 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: [[FAILURE_1]]
|
|
// CHECK: throw
|
|
// CHECK: [[FAILURE_2]]
|
|
// 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_unresolved_non_copyable_value [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
|
|
}
|
|
|
|
protocol P {}
|
|
extension Int: P {}
|
|
struct _UnsafeContinuation<T: P, R> {}
|
|
|
|
sil @testCapturedUndefClosure : $@convention(thin) @substituted <τ_0_0: P> (_UnsafeContinuation<τ_0_0, any Error>, Int) -> () for <Int>
|
|
sil @testCapturedUndefTakeClosure : $@convention(thin) <τ_0_0: P> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0: P> (_UnsafeContinuation<τ_0_0, any Error>) -> () for <τ_0_0>) -> (@out τ_0_0, @error any Error)
|
|
|
|
// insertDestroyOfCapturedArguments should not crash on 'undef'
|
|
//
|
|
// CHECK-LABEL: sil hidden [ossa] @testCapturedUndef : $@convention(thin) (Int) -> (Int, @error any Error) {
|
|
// CHECK: partial_apply [callee_guaranteed] [on_stack] %{{.*}}(undef)
|
|
// CHECK-LABEL: } // end sil function 'testCapturedUndef'
|
|
sil hidden [ossa] @testCapturedUndef : $@convention(thin) (Int) -> (Int, @error any Error) {
|
|
bb0(%0 : $Int):
|
|
%5 = alloc_stack $Int
|
|
%6 = function_ref @testCapturedUndefClosure : $@convention(thin) @substituted <τ_0_0: P> (_UnsafeContinuation<τ_0_0, any Error>, Int) -> () for <Int>
|
|
%7 = partial_apply [callee_guaranteed] %6(undef) : $@convention(thin) @substituted <τ_0_0: P> (_UnsafeContinuation<τ_0_0, any Error>, Int) -> () for <Int>
|
|
%8 = convert_escape_to_noescape [not_guaranteed] %7 : $@callee_guaranteed @substituted <τ_0_0: P> (_UnsafeContinuation<τ_0_0, any Error>) -> () for <Int> to $@noescape @callee_guaranteed @substituted <τ_0_0: P> (_UnsafeContinuation<τ_0_0, any Error>) -> () for <Int>
|
|
destroy_value %7 : $@callee_guaranteed @substituted <τ_0_0: P> (_UnsafeContinuation<τ_0_0, any Error>) -> () for <Int>
|
|
|
|
%10 = function_ref @testCapturedUndefTakeClosure : $@convention(thin) <τ_0_0: P> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0: P> (_UnsafeContinuation<τ_0_0, any Error>) -> () for <τ_0_0>) -> (@out τ_0_0, @error any Error)
|
|
try_apply %10<Int>(%5, %8) : $@convention(thin) <τ_0_0: P> (@guaranteed @noescape @callee_guaranteed @substituted <τ_0_0: P> (_UnsafeContinuation<τ_0_0, any Error>) -> () for <τ_0_0>) -> (@out τ_0_0, @error any Error), normal bb1, error bb2
|
|
|
|
bb1(%12 : $()):
|
|
destroy_value %8 : $@noescape @callee_guaranteed @substituted <τ_0_0: P> (_UnsafeContinuation<τ_0_0, any Error>) -> () for <Int>
|
|
%15 = load [trivial] %5 : $*Int
|
|
dealloc_stack %5 : $*Int
|
|
return %15 : $Int
|
|
|
|
bb2(%19 : @owned $any Error):
|
|
destroy_value %8 : $@noescape @callee_guaranteed @substituted <τ_0_0: P> (_UnsafeContinuation<τ_0_0, any Error>) -> () for <Int>
|
|
dealloc_stack %5 : $*Int
|
|
throw %19 : $any Error
|
|
}
|
|
|
|
// The destroy that's created in the dead-end should be flagged [dead_end].
|
|
// CHECK-LABEL: sil [ossa] @testRethrowingNonthrowing : {{.*}} {
|
|
// CHECK: [[NOTHROWER:%[^,]+]] = function_ref @nothrower
|
|
// CHECK: [[THICK_NOTHROWER:%[^,]+]] = thin_to_thick_function [[NOTHROWER]]
|
|
// CHECK: [[THROWING_NOTHROWER:%[^,]+]] = convert_function [[THICK_NOTHROWER]]
|
|
// CHECK: [[NOTHROWER_COPY:%[^,]+]] = copy_value [[THROWING_NOTHROWER]]
|
|
// CHECK: {{bb[0-9]+}}
|
|
// CHECK: destroy_value [[NOTHROWER_COPY]]
|
|
// CHECK: {{bb[0-9]+}}
|
|
// CHECK: destroy_value [dead_end] [[NOTHROWER_COPY]]
|
|
// CHECK-LABEL: } // end sil function 'testRethrowingNonthrowing'
|
|
sil [ossa] @testRethrowingNonthrowing : $@convention(thin) () -> () {
|
|
bb0:
|
|
%nothrower = function_ref @nothrower : $@convention(thin) () -> Int
|
|
%thick_nothrower = thin_to_thick_function %nothrower : $@convention(thin) () -> Int to $@callee_guaranteed () -> Int
|
|
%throwing_nothrower = convert_function %thick_nothrower : $@callee_guaranteed () -> Int to $@callee_guaranteed () -> (Int, @error any Error)
|
|
%nonescaping_nothrower = convert_escape_to_noescape [not_guaranteed] %throwing_nothrower : $@callee_guaranteed () -> (Int, @error any Error) to $@noescape @callee_guaranteed () -> (Int, @error any Error)
|
|
%rethrower = function_ref @rethrower : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> (Int, @error any Error)) -> (Int, @error any Error)
|
|
try_apply %rethrower(%nonescaping_nothrower) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> (Int, @error any Error)) -> (Int, @error any Error), normal bb1, error bb2
|
|
|
|
bb1(%val : $Int):
|
|
destroy_value %nonescaping_nothrower : $@noescape @callee_guaranteed () -> (Int, @error any Error)
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
|
|
bb2(%error : @owned $any Error):
|
|
destroy_value [dead_end] %error : $any Error
|
|
destroy_value [dead_end] %nonescaping_nothrower : $@noescape @callee_guaranteed () -> (Int, @error any Error)
|
|
unreachable
|
|
}
|
|
|
|
|
|
sil @nonthrowing : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> (Int, @error any Error)) -> ()
|
|
sil @throwsfn : $@convention(thin) () -> ((), @error any Error)
|
|
|
|
// Ensure no ownership verification error
|
|
// CHECK-LABEL: sil [ossa] @testRethrowing : {{.*}} {
|
|
// CHECK: [[NOTHROWER:%[^,]+]] = function_ref @nothrower
|
|
// CHECK: [[THICK_NOTHROWER:%[^,]+]] = thin_to_thick_function [[NOTHROWER]]
|
|
// CHECK: [[THROWING_NOTHROWER:%[^,]+]] = convert_function [[THICK_NOTHROWER]]
|
|
// CHECK: [[NOTHROWER_COPY:%[^,]+]] = copy_value [[THROWING_NOTHROWER]]
|
|
// CHECK: {{bb[0-9]+}}
|
|
// CHECK: destroy_value [[NOTHROWER_COPY]]
|
|
// CHECK: {{bb[0-9]+}}
|
|
// CHECK: destroy_value [[NOTHROWER_COPY]]
|
|
// CHECK-LABEL: } // end sil function 'testRethrowing'
|
|
sil [ossa] @testRethrowing : $@convention(thin) () -> ((), @error any Error) {
|
|
bb0:
|
|
%nothrower = function_ref @nothrower : $@convention(thin) () -> Int
|
|
%thick_nothrower = thin_to_thick_function %nothrower : $@convention(thin) () -> Int to $@callee_guaranteed () -> Int
|
|
%throwing_nothrower = convert_function %thick_nothrower : $@callee_guaranteed () -> Int to $@callee_guaranteed () -> (Int, @error any Error)
|
|
%nonescaping_nothrower = convert_escape_to_noescape [not_guaranteed] %throwing_nothrower : $@callee_guaranteed () -> (Int, @error any Error) to $@noescape @callee_guaranteed () -> (Int, @error any Error)
|
|
%throwsfnref = function_ref @throwsfn : $@convention(thin) () -> ((), @error any Error)
|
|
try_apply %throwsfnref() : $@convention(thin) () -> ((), @error any Error), normal bb1, error bb2
|
|
|
|
bb1(%arg : $()):
|
|
%nonthrower = function_ref @nonthrowing : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> (Int, @error any Error)) -> ()
|
|
apply %nonthrower(%nonescaping_nothrower) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> (Int, @error any Error)) -> ()
|
|
destroy_value %nonescaping_nothrower : $@noescape @callee_guaranteed () -> (Int, @error any Error)
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
|
|
bb2(%error : @owned $any Error):
|
|
destroy_value %nonescaping_nothrower : $@noescape @callee_guaranteed () -> (Int, @error any Error)
|
|
throw %error
|
|
}
|