blob: 26eacb35976a036ad21ac6fe3dc469983994c155 [file] [log] [blame]
// RUN: %target-swift-frontend -module-name A -verify -emit-sil -import-objc-header %S/Inputs/Closure.h -disable-objc-attr-requires-foundation-module %s | %FileCheck %s
// RUN: %target-swift-frontend -module-name A -verify -emit-sil -import-objc-header %S/Inputs/Closure.h -disable-objc-attr-requires-foundation-module -Xllvm -sil-disable-convert-escape-to-noescape-switch-peephole %s | %FileCheck %s --check-prefix=NOPEEPHOLE
// REQUIRES: objc_interop
import Foundation
// Make sure that we keep the escaping closures alive accross the ultimate call.
// CHECK-LABEL: sil @$s1A19bridgeNoescapeBlock5optFn0D3Fn2yySSSgcSg_AFtF
// CHECK: bb0
// CHECK: retain_value %0
// CHECK: retain_value %0
// CHECK: bb1
// CHECK: convert_escape_to_noescape %
// CHECK: strong_release
// CHECK: bb5
// CHECK: retain_value %1
// CHECK: retain_value %1
// CHECK: bb6
// CHECK: convert_escape_to_noescape %
// CHECK: strong_release
// CHECK: bb10
// CHECK: [[F:%.*]] = function_ref @noescapeBlock3
// CHECK: apply [[F]]
// CHECK: release_value {{.*}} : $Optional<NSString>
// CHECK: release_value %1 : $Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>
// CHECK: release_value {{.*}} : $Optional<@convention(block) @noescape (Optional<NSString>) -> ()>
// CHECK: release_value %0 : $Optional<@callee_guaranteed (@guaranteed Optional<String>) -> ()>
// CHECK: release_value {{.*}} : $Optional<@convention(block) @noescape (Optional<NSString>)
public func bridgeNoescapeBlock( optFn: ((String?) -> ())?, optFn2: ((String?) -> ())?) {
noescapeBlock3(optFn, optFn2, "Foobar")
}
@_silgen_name("_returnOptionalEscape")
public func returnOptionalEscape() -> (() ->())?
// Make sure that we keep the escaping closure alive accross the ultimate call.
// CHECK-LABEL: sil @$s1A19bridgeNoescapeBlockyyF : $@convention(thin) () -> () {
// CHECK: bb0:
// CHECK: [[NONE:%.*]] = enum $Optional<{{.*}}>, #Optional.none!enumelt
// CHECK: [[V0:%.*]] = function_ref @_returnOptionalEscape
// CHECK: [[V1:%.*]] = apply [[V0]]
// CHECK: retain_value [[V1]]
// CHECK: switch_enum [[V1]] : $Optional<{{.*}}>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
//
// CHECK: [[SOME_BB]]([[V2:%.*]] : $@callee_guaranteed () -> ()):
// CHECK: [[CVT_MARK_DEP:%.*]] = mark_dependence [[V2]] : $@callee_guaranteed () -> () on [[V1]]
// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[CVT_MARK_DEP]]
// CHECK: [[SOME:%.*]] = enum $Optional<{{.*}}>, #Optional.some!enumelt.1, [[CVT]]
// CHECK: strong_release [[V2]]
// CHECK: br [[NEXT_BB:bb[0-9]+]]([[SOME]] :
//
// CHECK: [[NEXT_BB]]([[SOME_PHI:%.*]] :
// CHECK: switch_enum [[SOME_PHI]] : $Optional<{{.*}}>, case #Optional.some!enumelt.1: [[SOME_BB_2:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB_2:bb[0-9]+]]
//
// CHECK: [[SOME_BB_2]]([[SOME_PHI_PAYLOAD:%.*]] :
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[SOME_PHI_PAYLOAD]])
// CHECK: [[MDI:%.*]] = mark_dependence [[PAI]]
// CHECK: strong_retain [[MDI]]
// CHECK: [[BLOCK_SLOT:%.*]] = alloc_stack
// CHECK: [[BLOCK_PROJ:%.*]] = project_block_storage [[BLOCK_SLOT]]
// CHECK: store [[MDI]] to [[BLOCK_PROJ]]
// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_SLOT]]
// CHECK: release_value [[NONE]]
// CHECK: [[SOME_2:%.*]] = enum $Optional<{{.*}}>, #Optional.some!enumelt.1, [[MDI]]
// CHECK: [[BLOCK_COPY:%.*]] = copy_block [[BLOCK]]
// CHECK: [[BLOCK_SOME:%.*]] = enum $Optional<{{.*}}>, #Optional.some!enumelt.1, [[BLOCK_COPY]]
// CHECK: br bb5([[BLOCK_SOME]] : ${{.*}}, [[SOME_2]] :
//
// CHECK: bb4:
// CHECK: [[NONE_BLOCK:%.*]] = enum $Optional<{{.*}}>, #Optional.none!enumelt
// CHECK: br bb5([[NONE_BLOCK]] : {{.*}}, [[NONE]] :
//
// CHECK: bb5([[BLOCK_PHI:%.*]] : $Optional<{{.*}}>, [[SWIFT_CLOSURE_PHI:%.*]] :
// CHECK: [[F:%.*]] = function_ref @noescapeBlock
// CHECK: apply [[F]]([[BLOCK_PHI]])
// CHECK: release_value [[BLOCK_PHI]]
// CHECK: release_value [[SWIFT_CLOSURE_PHI]]
// CHECK-NEXT: return
// NOPEEPHOLE-LABEL: sil @$s1A19bridgeNoescapeBlockyyF : $@convention(thin) () -> () {
// NOPEEPHOLE: bb0:
// NOPEEPHOLE: [[NONE_1:%.*]] = enum $Optional<{{.*}}>, #Optional.none!enumelt
// NOPEEPHOLE: [[NONE_2:%.*]] = enum $Optional<{{.*}}>, #Optional.none!enumelt
// NOPEEPHOLE: [[V0:%.*]] = function_ref @_returnOptionalEscape
// NOPEEPHOLE: [[V1:%.*]] = apply [[V0]]
// NOPEEPHOLE: switch_enum [[V1]] : $Optional<{{.*}}>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
//
// NOPEEPHOLE: [[SOME_BB]]([[V2:%.*]]: $@callee_guaranteed () -> ()):
// NOPEEPHOLE-NEXT: release_value [[NONE_2]]
// NOPEEPHOLE-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[V2]]
// NOPEEPHOLE-NEXT: [[SOME:%.*]] = enum $Optional<{{.*}}>, #Optional.some!enumelt.1, [[V2]]
// NOPEEPHOLE-NEXT: [[NOESCAPE_SOME:%.*]] = enum $Optional<{{.*}}>, #Optional.some!enumelt.1, [[CVT]]
// NOPEEPHOLE-NEXT: br bb2([[NOESCAPE_SOME]] : $Optional<{{.*}}>, [[SOME]] :
//
// NOPEEPHOLE: bb2([[NOESCAPE_SOME:%.*]] : $Optional<{{.*}}>, [[SOME:%.*]] :
// NOPEEPHOLE: switch_enum [[NOESCAPE_SOME]] : $Optional<{{.*}}>, case #Optional.some!enumelt.1: [[SOME_BB_2:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB_2:bb[0-9]+]]
//
// NOPEEPHOLE: [[SOME_BB_2]](
// NOPEEPHOLE: br bb5
//
// NOPEEPHOLE: [[NONE_BB_2]]:
// NOPEEPHOLE: br bb5
//
// NOPEEPHOLE: bb5([[BLOCK_PHI:%.*]] : $Optional<{{.*}}>, [[SWIFT_CLOSURE_PHI:%.*]] :
// NOPEEPHOLE-NEXT: function_ref noescapeBlock
// NOPEEPHOLE-NEXT: [[F:%.*]] = function_ref @noescapeBlock :
// NOPEEPHOLE-NEXT: apply [[F]]([[BLOCK_PHI]])
// NOPEEPHOLE-NEXT: release_value [[BLOCK_PHI]]
// NOPEEPHOLE-NEXT: tuple
// NOPEEPHOLE-NEXT: release_value [[SOME]]
// NOPEEPHOLE-NEXT: release_value [[SWIFT_CLOSURE_PHI]]
// NOPEEPHOLE-NEXT: return
// NOPEEPHOLE: } // end sil function '$s1A19bridgeNoescapeBlockyyF'
public func bridgeNoescapeBlock() {
noescapeBlock(returnOptionalEscape())
}