mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Don't support self-recursive functions because that would result in mapping troubles when cloning.
975 lines
46 KiB
Plaintext
975 lines
46 KiB
Plaintext
// RUN: %target-sil-opt -sil-print-types -enable-sil-verify-all -closure-specialization %s | %FileCheck %s
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
// CHECK-LABEL: sil shared [noinline] [ossa] @$s7specgen12take_closureyyySi_SitcF023$s7specgen6calleryySiFyE8_SitcfU_SiTf1c_n : $@convention(thin) (Int) -> () {
|
|
|
|
// CHECK: bb0(%0 : $Int)
|
|
// CHECK: function_ref @$s7specgen6calleryySiFySi_SitcfU_
|
|
// CHECK: partial_apply
|
|
|
|
// CHECK-LABEL: sil shared [noinline] [ossa] @$s7specgen12take_closureyyySi_SitcF26$s7specgen6calleeyySi_SitFTf1c_n : $@convention(thin) () -> () {
|
|
// CHECK-NEXT: bb0:
|
|
// CHECK: [[FUN:%.*]] = function_ref @$s7specgen6calleeyySi_SitF : $@convention(thin) (Int, Int) -> ()
|
|
// CHECK: thin_to_thick_function [[FUN]] : $@convention(thin) (Int, Int) -> () to $@callee_owned (Int, Int) -> ()
|
|
|
|
// CHECK-LABEL: sil [noinline] [ossa] @$s7specgen12take_closureyyySi_SitcF : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> () {
|
|
sil [ossa] [noinline] @$s7specgen12take_closureyyySi_SitcF : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> () {
|
|
bb0(%0 : @owned $@callee_owned (Int, Int) -> ()):
|
|
%2 = load [trivial] undef : $*Int
|
|
%3 = apply %0(%2, %2) : $@callee_owned (Int, Int) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil shared [noinline] [ossa] @$s7specgen13take_closure2yyySi_SitcF023$s7specgen6calleryySiFyE8_SitcfU_SiTf1c_n : $@convention(thin) (Int) -> () {
|
|
// CHECK: bb0(%0 : $Int)
|
|
// CHECK: [[FUN:%.*]] = function_ref @$s7specgen6calleryySiFySi_SitcfU_
|
|
// CHECK: partial_apply [[FUN]](
|
|
|
|
// CHECK-LABEL: sil shared [noinline] [ossa] @$s7specgen13take_closure2yyySi_SitcF26$s7specgen6calleeyySi_SitFTf1c_n : $@convention(thin) () -> () {
|
|
// CHECK-NEXT: bb0:
|
|
// CHECK: [[FUN:%.*]] = function_ref @$s7specgen6calleeyySi_SitF : $@convention(thin) (Int, Int) -> ()
|
|
// CHECK: thin_to_thick_function [[FUN]] : $@convention(thin) (Int, Int) -> () to $@callee_owned (Int, Int) -> ()
|
|
|
|
// CHECK-LABEL: sil [noinline] [ossa] @$s7specgen13take_closure2yyySi_SitcF : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> () {
|
|
sil [ossa] [noinline] @$s7specgen13take_closure2yyySi_SitcF : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> () {
|
|
bb0(%0 : @owned $@callee_owned (Int, Int) -> ()):
|
|
%2 = load [trivial] undef : $*Int
|
|
%3 = apply %0(%2, %2) : $@callee_owned (Int, Int) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [noinline] [ossa] @$s7specgen6calleeyySi_S2itF : $@convention(thin) (Int, Int, Int) -> () {
|
|
// specgen.callee (Swift.Int, Swift.Int, Swift.Int) -> ()
|
|
sil [ossa] [noinline] @$s7specgen6calleeyySi_S2itF : $@convention(thin) (Int, Int, Int) -> () {
|
|
bb0(%0 : $Int, %1 : $Int, %2 : $Int):
|
|
%6 = tuple () // user: %7
|
|
return %6 : $() // id: %7
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s7specgen6calleryySiF : $@convention(thin) (Int) -> () {
|
|
// CHECK: [[ID2:%[0-9]+]] = function_ref @$s7specgen12take_closureyyySi_SitcF023$s7specgen6calleryySiFyE8_SitcfU_SiTf1c_n : $@convention(thin) (Int) -> ()
|
|
// CHECK: apply [[ID2]](%0) : $@convention(thin) (Int) -> ()
|
|
// CHECK: [[ID1:%[0-9]+]] = function_ref @$s7specgen13take_closure2yyySi_SitcF023$s7specgen6calleryySiFyE8_SitcfU_SiTf1c_n : $@convention(thin) (Int) -> ()
|
|
// CHECK: apply [[ID1]](%0) : $@convention(thin) (Int) -> ()
|
|
sil [ossa] @$s7specgen6calleryySiF : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
// function_ref specgen.take_closure ((Swift.Int, Swift.Int) -> ()) -> ()
|
|
%2 = function_ref @$s7specgen12take_closureyyySi_SitcF : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> () // user: %5
|
|
// function_ref specgen.(caller (Swift.Int) -> ()).(closure #1)
|
|
%3 = function_ref @$s7specgen6calleryySiFySi_SitcfU_ : $@convention(thin) (Int, Int, Int) -> () // user: %4
|
|
%4 = partial_apply %3(%0) : $@convention(thin) (Int, Int, Int) -> () // user: %5
|
|
%4a = copy_value %4
|
|
%5 = apply %2(%4a) : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> ()
|
|
%6 = function_ref @$s7specgen13take_closure2yyySi_SitcF : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> () // user: %5
|
|
%4b = copy_value %4
|
|
%7 = apply %6(%4b) : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> ()
|
|
destroy_value %4
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil shared [ossa] @$s7specgen6calleryySiFySi_SitcfU_ : $@convention(thin) (Int, Int, Int) -> () {
|
|
sil shared [ossa] @$s7specgen6calleryySiFySi_SitcfU_ : $@convention(thin) (Int, Int, Int) -> () {
|
|
bb0(%0 : $Int, %1 : $Int, %2 : $Int):
|
|
%5 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>, var, name "p" // users: %6, %10, %14
|
|
%5a = project_box %5 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
store %0 to [trivial] %5a : $*Int // id: %6
|
|
%7 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>, var, name "q" // users: %8, %11, %13
|
|
%7a = project_box %7 : $<τ_0_0> { var τ_0_0 } <Int>, 0
|
|
store %1 to [trivial] %7a : $*Int // id: %8
|
|
// function_ref specgen.callee (Swift.Int, Swift.Int, Swift.Int) -> ()
|
|
%9 = function_ref @$s7specgen6calleeyySi_S2itF : $@convention(thin) (Int, Int, Int) -> () // user: %12
|
|
%10 = load [trivial] %5a : $*Int // user: %12
|
|
%11 = load [trivial] %7a : $*Int // user: %12
|
|
%12 = apply %9(%10, %11, %2) : $@convention(thin) (Int, Int, Int) -> ()
|
|
destroy_value %7
|
|
destroy_value %5
|
|
%15 = tuple () // user: %16
|
|
return %15 : $() // id: %16
|
|
}
|
|
|
|
//////////////////////////////////
|
|
// Thin To Thick Function Tests //
|
|
//////////////////////////////////
|
|
|
|
// CHECK-LABEL: sil [noinline] [ossa] @$s7specgen6calleeyySi_SitF : $@convention(thin) (Int, Int) -> () {
|
|
// specgen.callee (Swift.Int, Swift.Int) -> ()
|
|
sil [noinline] [ossa] @$s7specgen6calleeyySi_SitF : $@convention(thin) (Int, Int) -> () {
|
|
bb0(%0 : $Int, %1 : $Int):
|
|
%6 = tuple () // user: %7
|
|
return %6 : $() // id: %7
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s7specgen11tttficalleryySiF : $@convention(thin) (Int) -> () {
|
|
// CHECK: [[ID2:%[0-9]+]] = function_ref @$s7specgen12take_closureyyySi_SitcF26$s7specgen6calleeyySi_SitFTf1c_n : $@convention(thin) () -> ()
|
|
// CHECK: apply [[ID2]]() : $@convention(thin) () -> ()
|
|
// CHECK: [[ID1:%[0-9]+]] = function_ref @$s7specgen13take_closure2yyySi_SitcF26$s7specgen6calleeyySi_SitFTf1c_n : $@convention(thin) () -> ()
|
|
// CHECK: apply [[ID1]]() : $@convention(thin) () -> ()
|
|
sil [ossa] @$s7specgen11tttficalleryySiF : $@convention(thin) (Int) -> () {
|
|
bb0(%0 : $Int):
|
|
// function_ref specgen.take_closure ((Swift.Int, Swift.Int) -> ()) -> ()
|
|
%2 = function_ref @$s7specgen12take_closureyyySi_SitcF : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> () // user: %5
|
|
// function_ref specgen.(caller (Swift.Int) -> ()).(closure #1)
|
|
%3 = function_ref @$s7specgen6calleeyySi_SitF : $@convention(thin) (Int, Int) -> () // user: %4
|
|
%4 = thin_to_thick_function %3 : $@convention(thin) (Int, Int) -> () to $@callee_owned (Int, Int) -> () // user: %5
|
|
%5 = apply %2(%4) : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> ()
|
|
%6 = function_ref @$s7specgen13take_closure2yyySi_SitcF : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> ()
|
|
%7 = apply %6(%4) : $@convention(thin) (@owned @callee_owned (Int, Int) -> ()) -> ()
|
|
%9999 = tuple () // user: %7
|
|
return %9999 : $() // id: %7
|
|
}
|
|
|
|
// We don't handle closures that close over address types (*NOTE* this includes
|
|
// address and non-address only types) taken as @in or @in_guaranteed.
|
|
|
|
// This is a temporary limitation.
|
|
// CHECK-LABEL: sil [ossa] @address_closure : $@convention(thin) (@in Int) -> () {
|
|
sil [ossa] @address_closure : $@convention(thin) (@in Int) -> () {
|
|
bb0(%0 : $*Int):
|
|
%6 = tuple()
|
|
return %6 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @address_closure_user : $@convention(thin) (@owned @callee_owned () -> ()) -> () {
|
|
sil [ossa] @address_closure_user : $@convention(thin) (@owned @callee_owned () -> ()) -> () {
|
|
bb0(%0 : @owned $@callee_owned () -> ()):
|
|
%1 = apply %0() : $@callee_owned () -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @address_caller : $@convention(thin) (@in Int) -> () {
|
|
// CHECK-NOT: _TTSf1cl15address_closureSi__address_closure_user
|
|
sil [ossa] @address_caller : $@convention(thin) (@in Int) -> () {
|
|
bb0(%0 : $*Int):
|
|
%1 = function_ref @address_closure : $@convention(thin) (@in Int) -> ()
|
|
%2 = partial_apply %1(%0) : $@convention(thin) (@in Int) -> ()
|
|
%3 = function_ref @address_closure_user : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
|
|
%4 = apply %3(%2) : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
|
|
%9999 = tuple()
|
|
return %9999 : $()
|
|
}
|
|
|
|
class A {}
|
|
|
|
sil hidden [ossa] [noinline] @closure : $@convention(thin) (@owned A, @owned A) -> () {
|
|
bb0(%0 : @owned $A, %1 : @owned $A):
|
|
destroy_value %1
|
|
destroy_value %0
|
|
%4 = tuple ()
|
|
return %4 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil shared {{.*}} @$s11use_closure{{.*}}Tf{{.*}} : $@convention(thin) (@owned A) -> () {
|
|
sil hidden [ossa] [noinline] @use_closure : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> () {
|
|
bb0(%0 : @owned $@callee_owned (@owned A) -> ()):
|
|
%1 = alloc_ref $A
|
|
%2 = apply %0(%1) : $@callee_owned (@owned A) -> ()
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil shared {{.*}} @$s17use_closure_throw{{.*}}Tf{{.*}} : $@convention(thin) (@owned A) -> @error any Error {
|
|
sil hidden [ossa] [noinline] @use_closure_throw : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> @error any Error {
|
|
bb0(%0 : @owned $@callee_owned (@owned A) -> ()):
|
|
%1 = alloc_ref $A
|
|
%2 = apply %0(%1) : $@callee_owned (@owned A) -> ()
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil {{.*}} @different_execution_counts
|
|
// CHECK: bb0([[ARG:%.*]] : @guaranteed $A
|
|
// CHECK: %1 = copy_value %0
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: [[C:%.*]] = copy_value %1
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: integer_literal $Builtin.Int64, 0
|
|
// CHECK: br bb2
|
|
|
|
// CHECK: bb1:
|
|
// CHECK: destroy_value [[C]]
|
|
// CHECK: destroy_value %1
|
|
// CHECK: return
|
|
|
|
// CHECK: bb2({{.*}}):
|
|
// Match the partial_apply consume of arg.
|
|
// CHECK: [[C2:%.*]] = copy_value [[C]]
|
|
// CHECK: [[SPECIALIZED_CLOSURE_USER:%.*]] = function_ref @$s11use_closure{{.*}}Tf
|
|
// CHECK: apply [[SPECIALIZED_CLOSURE_USER]]([[C2]])
|
|
// CHECK: cond_br {{.*}}, bb1, bb3
|
|
|
|
sil hidden [ossa] [noinline] @different_execution_counts : $@convention(thin) (@guaranteed A) -> () {
|
|
bb0(%0 : @guaranteed $A):
|
|
%1 = copy_value %0
|
|
%2 = function_ref @closure : $@convention(thin) (@owned A, @owned A) -> ()
|
|
%3 = partial_apply %2(%1) : $@convention(thin) (@owned A, @owned A) -> ()
|
|
%4 = integer_literal $Builtin.Int64, 0
|
|
%5 = integer_literal $Builtin.Int64, 5
|
|
%6 = integer_literal $Builtin.Int64, 1
|
|
%7 = integer_literal $Builtin.Int1, 0
|
|
%8 = function_ref @use_closure : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> ()
|
|
br bb2(%4 : $Builtin.Int64)
|
|
|
|
bb1:
|
|
destroy_value %3
|
|
%11 = tuple ()
|
|
return %11 : $()
|
|
|
|
bb2(%13 : $Builtin.Int64):
|
|
%14 = builtin "sadd_with_overflow_Int64"(%13 : $Builtin.Int64, %6 : $Builtin.Int64, %7 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
|
|
%15 = tuple_extract %14 : $(Builtin.Int64, Builtin.Int1), 0
|
|
%16 = copy_value %3
|
|
%17 = apply %8(%16) : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> ()
|
|
%18 = builtin "cmp_eq_Int64"(%15 : $Builtin.Int64, %5 : $Builtin.Int64) : $Builtin.Int1
|
|
cond_br %18, bb1, bb3
|
|
|
|
bb3:
|
|
br bb2(%15 : $Builtin.Int64)
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @insert_release_in_liverange_exit_block
|
|
// CHECK: bb0(%0 : @guaranteed $A):
|
|
// CHECK: %1 = copy_value %0
|
|
// CHECK: [[C:%.*]] = copy_value %1
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: destroy_value [[C]]
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK-NEXT: br bb3
|
|
// CHECK: bb2:
|
|
// CHECK: apply %{{[0-9]+}}([[C]])
|
|
// CHECK: bb3:
|
|
// CHECK-NOT: %0
|
|
// CHECK: return
|
|
sil [ossa] @insert_release_in_liverange_exit_block : $@convention(thin) (@guaranteed A) -> () {
|
|
bb0(%0 : @guaranteed $A):
|
|
%1 = copy_value %0
|
|
%2 = function_ref @closure : $@convention(thin) (@owned A, @owned A) -> ()
|
|
%3 = partial_apply %2(%1) : $@convention(thin) (@owned A, @owned A) -> ()
|
|
%8 = function_ref @use_closure : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> ()
|
|
%4 = copy_value %3
|
|
%5 = partial_apply %8(%3) : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> ()
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
destroy_value %4
|
|
br bb3
|
|
|
|
bb2:
|
|
%17 = apply %8(%4) : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> ()
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_value %5
|
|
%11 = tuple ()
|
|
return %11 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @insert_release_in_loop_exit_block
|
|
// CHECK: bb0(%0 : @guaranteed $A):
|
|
// CHECK: %1 = copy_value %0
|
|
// CHECK: [[C:%.*]] = copy_value %1
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: br bb2
|
|
// CHECK: bb2:
|
|
// CHECK: [[C2:%.*]] = copy_value [[C]]
|
|
// CHECK: apply %{{[0-9]+}}([[C2]])
|
|
// CHECK-NOT: %0
|
|
// CHECK: bb4:
|
|
// CHECK-NEXT: destroy_value [[C]]
|
|
// CHECK-NEXT: destroy_value
|
|
// CHECK-NOT: %0
|
|
// CHECK: return
|
|
sil [ossa] @insert_release_in_loop_exit_block : $@convention(thin) (@guaranteed A) -> () {
|
|
bb0(%0 : @guaranteed $A):
|
|
%1 = copy_value %0
|
|
%2 = function_ref @closure : $@convention(thin) (@owned A, @owned A) -> ()
|
|
%3 = partial_apply %2(%1) : $@convention(thin) (@owned A, @owned A) -> ()
|
|
%8 = function_ref @use_closure : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> ()
|
|
%4 = copy_value %3
|
|
%5 = partial_apply %8(%3) : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> ()
|
|
cond_br undef, bb4, bb1
|
|
|
|
bb1:
|
|
br bb2
|
|
|
|
bb2:
|
|
%16 = copy_value %4
|
|
%17 = apply %8(%16) : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> ()
|
|
cond_br undef, bb3, bb5
|
|
|
|
bb3:
|
|
br bb2
|
|
|
|
bb4:
|
|
destroy_value %4
|
|
br bb6
|
|
|
|
bb5:
|
|
destroy_value %4
|
|
br bb6
|
|
|
|
bb6:
|
|
destroy_value %5
|
|
%11 = tuple ()
|
|
return %11 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @insert_release_after_try_apply
|
|
// CHECK: bb0(%0 : @guaranteed $A):
|
|
// CHECK: %1 = copy_value %0
|
|
// CHECK: [[C:%.*]] = copy_value %1
|
|
// CHECK: bb1:
|
|
// CHECK-NEXT: destroy_value %1
|
|
// CHECK: try_apply %{{[0-9]+}}([[C]])
|
|
// CHECK: bb2(%{{[0-9]+}} : $()):
|
|
// CHECK-NEXT: br bb4
|
|
// CHECK: bb3(%{{[0-9]+}} : $any Error):
|
|
// CHECK-NEXT: br bb4
|
|
// CHECK: bb4:
|
|
// CHECK-NOT: %0
|
|
// CHECK: return
|
|
sil [ossa] @insert_release_after_try_apply : $@convention(thin) (@guaranteed A) -> () {
|
|
bb0(%0 : @guaranteed $A):
|
|
%1 = copy_value %0
|
|
%2 = function_ref @closure : $@convention(thin) (@owned A, @owned A) -> ()
|
|
%3 = partial_apply %2(%1) : $@convention(thin) (@owned A, @owned A) -> ()
|
|
%8 = function_ref @use_closure_throw : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> @error Error
|
|
br bb1
|
|
|
|
bb1:
|
|
try_apply %8(%3) : $@convention(thin) (@owned @callee_owned (@owned A) -> ()) -> @error Error, normal bb2, error bb3
|
|
|
|
bb2(%n : $()):
|
|
br bb4
|
|
|
|
bb3(%e : $Error):
|
|
br bb4
|
|
|
|
bb4:
|
|
%11 = tuple ()
|
|
return %11 : $()
|
|
}
|
|
|
|
|
|
// Ensure that we can specialize and properly mangle functions that take closures with <τ_0_0> { var τ_0_0 } <arguments>.
|
|
|
|
// CHECK-LABEL: sil shared [noinline] [ossa] @$s4main5inneryys5Int32Vz_yADctF25closure_with_box_argumentxz_Bi32__lXXTf1nc_n : $@convention(thin) (@inout Builtin.Int32, @owned <τ_0_0> { var τ_0_0 } <Builtin.Int32>) -> ()
|
|
// CHECK: bb0
|
|
// CHECK: [[FN:%.*]] = function_ref @closure_with_box_argument
|
|
// CHECK: [[PARTIAL:%.*]] = partial_apply [[FN]](%1)
|
|
// CHECK: [[C:%.*]] = copy_value [[PARTIAL]]
|
|
// CHECK: [[ARG:%.*]] = load [trivial] %0
|
|
// CHECK: apply [[C]]([[ARG]])
|
|
|
|
// CHECK-LABEL: {{.*}} @$s4main5inneryys5Int32Vz_yADctF
|
|
sil hidden [ossa] [noinline] @$s4main5inneryys5Int32Vz_yADctF : $@convention(thin) (@inout Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> ()) -> () {
|
|
bb0(%0 : $*Builtin.Int32, %1 : @owned $@callee_owned (Builtin.Int32) -> ()):
|
|
%5 = load [trivial] %0 : $*Builtin.Int32
|
|
%6 = apply %1(%5) : $@callee_owned (Builtin.Int32) -> ()
|
|
%11 = tuple ()
|
|
return %11 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @pass_a_closure
|
|
sil [ossa] @pass_a_closure: $@convention(thin) () -> Builtin.Int32 {
|
|
bb0:
|
|
%0 = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.Int32>, var, name "i"
|
|
%0a = project_box %0 : $<τ_0_0> { var τ_0_0 } <Builtin.Int32>, 0
|
|
%1 = integer_literal $Builtin.Int32, 0
|
|
store %1 to [trivial] %0a : $*Builtin.Int32
|
|
%4 = function_ref @closure_with_box_argument : $@convention(thin) (Builtin.Int32, @owned <τ_0_0> { var τ_0_0 } <Builtin.Int32>) -> ()
|
|
%5 = copy_value %0
|
|
%6 = partial_apply %4(%5) : $@convention(thin) (Builtin.Int32, @owned <τ_0_0> { var τ_0_0 } <Builtin.Int32>) -> ()
|
|
%7 = alloc_stack $Builtin.Int32
|
|
%9 = integer_literal $Builtin.Int32, 1
|
|
store %9 to [trivial] %7 : $*Builtin.Int32
|
|
%12 = function_ref @$s4main5inneryys5Int32Vz_yADctF: $@convention(thin) (@inout Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> ()) -> ()
|
|
%13 = copy_value %6
|
|
%14 = apply %12(%7, %13) : $@convention(thin) (@inout Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> ()) -> ()
|
|
destroy_value %6
|
|
%16 = tuple ()
|
|
dealloc_stack %7 : $*Builtin.Int32
|
|
%18 = load [trivial] %0a : $*Builtin.Int32
|
|
destroy_value %0
|
|
return %18 : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil shared [ossa] @closure_with_box_argument
|
|
sil shared [ossa] @closure_with_box_argument : $@convention(thin) (Builtin.Int32, @owned <τ_0_0> { var τ_0_0 } <Builtin.Int32>) -> () {
|
|
bb0(%0 : $Builtin.Int32, %1 : @owned $<τ_0_0> { var τ_0_0 } <Builtin.Int32>):
|
|
%3 = project_box %1 : $<τ_0_0> { var τ_0_0 } <Builtin.Int32>, 0
|
|
store %0 to [trivial] %3 : $*Builtin.Int32
|
|
destroy_value %1
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
// Check that we don't crash with this:
|
|
// CHECK-LABEL: sil [ossa] @test_box_with_named_elements_tuple
|
|
sil [ossa] @test_box_with_named_elements_tuple: $@convention(thin) () -> Builtin.Int32 {
|
|
bb0:
|
|
%0 = alloc_box ${ let (first: Builtin.Int32, second: Builtin.Int32) }
|
|
%0p = project_box %0 : ${ let (first: Builtin.Int32, second: Builtin.Int32) }, 0
|
|
%0a = tuple_element_addr %0p : $*(first: Builtin.Int32, second: Builtin.Int32), 0
|
|
%0b = tuple_element_addr %0p : $*(first: Builtin.Int32, second: Builtin.Int32), 1
|
|
%1 = integer_literal $Builtin.Int32, 0
|
|
store %1 to [trivial] %0a : $*Builtin.Int32
|
|
store %1 to [trivial] %0b : $*Builtin.Int32
|
|
%4 = function_ref @closure_with_named_elements_tuple : $@convention(thin) (Builtin.Int32, @owned { let (first: Builtin.Int32, second: Builtin.Int32) }) -> ()
|
|
%5 = copy_value %0
|
|
%6 = partial_apply %4(%5) : $@convention(thin) (Builtin.Int32, @owned { let (first: Builtin.Int32, second: Builtin.Int32) }) -> ()
|
|
%7 = alloc_stack $Builtin.Int32
|
|
%9 = integer_literal $Builtin.Int32, 1
|
|
store %9 to [trivial] %7 : $*Builtin.Int32
|
|
%12 = function_ref @$s4main5inneryys5Int32Vz_yADctF: $@convention(thin) (@inout Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> ()) -> ()
|
|
%13 = copy_value %6
|
|
%14 = apply %12(%7, %13) : $@convention(thin) (@inout Builtin.Int32, @owned @callee_owned (Builtin.Int32) -> ()) -> ()
|
|
destroy_value %6
|
|
%16 = tuple ()
|
|
dealloc_stack %7 : $*Builtin.Int32
|
|
%18 = load [trivial] %0a : $*Builtin.Int32
|
|
destroy_value %0
|
|
return %18 : $Builtin.Int32
|
|
}
|
|
|
|
// CHECK-LABEL: sil shared [ossa] @closure_with_named_elements_tuple
|
|
sil shared [ossa] @closure_with_named_elements_tuple : $@convention(thin) (Builtin.Int32, @owned { let (first: Builtin.Int32, second: Builtin.Int32) }) -> () {
|
|
bb0(%0 : $Builtin.Int32, %1 : @owned ${ let (first: Builtin.Int32, second: Builtin.Int32) }):
|
|
%3 = project_box %1 : ${ let (first: Builtin.Int32, second: Builtin.Int32) }, 0
|
|
%4 = tuple_element_addr %3 : $*(first: Builtin.Int32, second: Builtin.Int32), 0
|
|
store %0 to [trivial] %4 : $*Builtin.Int32
|
|
destroy_value %1
|
|
%7 = tuple ()
|
|
return %7 : $()
|
|
}
|
|
|
|
|
|
// The specialized function should always be a thin function, regardless of the
|
|
// representation of the original function.
|
|
|
|
public protocol P {
|
|
static func foo(cl: () -> Int) -> Int
|
|
}
|
|
|
|
public struct S : P {
|
|
public static func foo(cl: () -> Int) -> Int
|
|
init()
|
|
}
|
|
|
|
// CHECK-LABEL: sil shared [ossa] @$s4test1SVAA1PA2aDP3fooyS2iycFZTW8closure2SiTf1cn_n : $@convention(thin) (@thick S.Type, Int) -> Int
|
|
sil [ossa] @$s4test1SVAA1PA2aDP3fooyS2iycFZTW : $@convention(witness_method: P) (@guaranteed @noescape @callee_guaranteed () -> Int, @thick S.Type) -> Int {
|
|
bb0(%0 : @guaranteed $@noescape @callee_guaranteed () -> Int, %1 : $@thick S.Type):
|
|
%3 = apply %0() : $@noescape @callee_guaranteed () -> Int
|
|
return %3 : $Int
|
|
}
|
|
|
|
sil shared [ossa] @closure2 : $@convention(thin) (Int) -> Int {
|
|
bb0(%0 : $Int):
|
|
return %0 : $Int
|
|
}
|
|
|
|
sil [ossa] @call_witness_method : $@convention(thin) (Int, S) -> Int {
|
|
bb0(%0 : $Int, %1 : $S):
|
|
%3 = function_ref @closure2 : $@convention(thin) (Int) -> Int
|
|
%4 = partial_apply [callee_guaranteed] %3(%0) : $@convention(thin) (Int) -> Int
|
|
%4a = convert_escape_to_noescape %4 : $@callee_guaranteed () -> Int to $@noescape @callee_guaranteed () -> Int
|
|
%5 = metatype $@thick S.Type
|
|
%6 = function_ref @$s4test1SVAA1PA2aDP3fooyS2iycFZTW : $@convention(witness_method: P) (@guaranteed @noescape @callee_guaranteed () -> Int, @thick S.Type) -> Int
|
|
%7 = apply %6(%4a, %5) : $@convention(witness_method: P) (@guaranteed @noescape @callee_guaranteed () -> Int, @thick S.Type) -> Int
|
|
destroy_value %4a
|
|
destroy_value %4
|
|
return %7 : $Int
|
|
}
|
|
|
|
sil_witness_table S: P module test {
|
|
method #P.foo: @$s4test1SVAA1PA2aDP3fooyS2iycFZTW
|
|
}
|
|
|
|
// Test partial_apply -> convert_function -> convert_function -> try_apply.
|
|
sil [ossa] @testClosureConvertHelper : $(Int) -> ()
|
|
|
|
// specialized testClosureConvertThunk
|
|
// FIXME: Need to handle closures with multiple exceptional exits.
|
|
// CHECK-LABEL: sil shared [ossa] @$s23testClosureConvertThunk0abC6HelperSiTf1nc_n : $@convention(thin) (Int) -> (@out (), @error any Error) {
|
|
// CHECK: bb0(%0 : $*(), %1 : $Int):
|
|
// CHECK: [[F:%.*]] = function_ref @testClosureConvertHelper : $@convention(thin) (Int) -> ()
|
|
// CHECK: [[PA:%.*]] = partial_apply [[F]](%1) : $@convention(thin) (Int) -> ()
|
|
// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_owned () -> () to $@noescape @callee_owned () -> ()
|
|
// CHECK: [[CVT2:%.*]] = convert_function [[CVT1]] : $@noescape @callee_owned () -> () to $@noescape @callee_owned () -> @error any Error
|
|
// CHECK: [[C:%.*]] = copy_value [[CVT2]]
|
|
// CHECK: try_apply [[C]]() : $@noescape @callee_owned () -> @error any Error, normal bb1, error bb2
|
|
// CHECK: bb1
|
|
// CHECK: destroy_value [[CVT2]]
|
|
// CHECK: destroy_value [[PA]]
|
|
// CHECK: return
|
|
// CHECK: bb2
|
|
// CHECK: destroy_value [[CVT2]]
|
|
// CHECK: destroy_value [[PA]]
|
|
// CHECK: throw
|
|
// CHECK-LABEL: } // end sil function '$s23testClosureConvertThunk0abC6HelperSiTf1nc_n'
|
|
sil [ossa] @testClosureConvertThunk : $@convention(thin) (@guaranteed @noescape @callee_owned () -> @error Error) -> (@out (), @error Error) {
|
|
bb0(%0 : $*(), %1 : @guaranteed $@noescape @callee_owned () -> @error Error):
|
|
%2 = copy_value %1
|
|
try_apply %2() : $@noescape @callee_owned () -> @error Error, normal bb1, error bb2
|
|
|
|
bb1(%7 : $()):
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
|
|
bb2(%10 : $Error):
|
|
throw %10 : $Error
|
|
}
|
|
|
|
// Test closure specialization when the closure type is converted before application.
|
|
sil [ossa] @testClosureConvert : $(Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%48 = alloc_stack $()
|
|
%49 = function_ref @testClosureConvertHelper : $@convention(thin) (Int) -> ()
|
|
%50 = partial_apply %49(%0) : $@convention(thin) (Int) -> ()
|
|
%51 = convert_escape_to_noescape %50 : $@callee_owned () -> () to $@noescape @callee_owned () -> ()
|
|
%52 = convert_function %51 : $@noescape @callee_owned () -> () to $@noescape @callee_owned () -> @error Error
|
|
%53 = function_ref @testClosureConvertThunk : $@convention(thin) (@guaranteed @noescape @callee_owned () -> @error Error) -> (@out (), @error Error)
|
|
try_apply %53(%48, %52) : $@convention(thin) (@guaranteed @noescape @callee_owned () -> @error Error) -> (@out (), @error Error), normal bb7, error bb11
|
|
|
|
bb7(%callret : $()):
|
|
br bb99
|
|
|
|
bb11(%128 : $Error):
|
|
br bb99
|
|
|
|
bb99:
|
|
destroy_value %52
|
|
destroy_value %50
|
|
dealloc_stack %48 : $*()
|
|
%empty = tuple ()
|
|
return %empty : $()
|
|
}
|
|
|
|
sil [ossa] @testClosureThunkNoEscape : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> () {
|
|
bb0(%0 : @guaranteed $@noescape @callee_guaranteed () -> ()):
|
|
apply %0() : $@noescape @callee_guaranteed () -> ()
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil shared [ossa] @$s24testClosureThunkNoEscape0aB13ConvertHelperSiTf1c_n : $@convention(thin) (Int) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : $Int):
|
|
// CHECK: [[F:%.*]] = function_ref @testClosureConvertHelper : $@convention(thin) (Int) -> ()
|
|
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[F]]([[ARG]]) : $@convention(thin) (Int) -> ()
|
|
// CHECK: [[E:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
|
|
// CHECK: apply [[E]]() : $@noescape @callee_guaranteed () -> ()
|
|
// CHECK: destroy_value [[E]]
|
|
// CHECK: destroy_value [[PA]]
|
|
// CHECK: return
|
|
// CHECK: }
|
|
// CHECK-LABEL: sil [ossa] @testClosureNoEscape : $@convention(thin) (Int) -> () {
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: [[FN:%.*]] = function_ref @$s24testClosureThunkNoEscape0aB13ConvertHelperSiTf1c_n : $@convention(thin) (Int) -> ()
|
|
// CHECK-NOT: partial_apply
|
|
// CHECK: %5 = apply [[FN]](%0) : $@convention(thin) (Int) -> ()
|
|
// CHECK-NOT: release
|
|
// CHECK: return
|
|
// CHECK: }
|
|
|
|
sil [ossa] @testClosureNoEscape : $(Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%48 = alloc_stack $()
|
|
%49 = function_ref @testClosureConvertHelper : $@convention(thin) (Int) -> ()
|
|
%50 = partial_apply [callee_guaranteed] %49(%0) : $@convention(thin) (Int) -> ()
|
|
%51 = convert_escape_to_noescape %50 : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
|
|
%53 = function_ref @testClosureThunkNoEscape : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
|
|
apply %53(%51) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
|
|
destroy_value %50
|
|
destroy_value %51
|
|
dealloc_stack %48 : $*()
|
|
%empty = tuple ()
|
|
return %empty : $()
|
|
}
|
|
|
|
|
|
sil [ossa] @testClosureConvertHelper2 : $(Int) -> Int
|
|
|
|
sil [ossa] @testClosureThunkNoEscape2 : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> @out Int) -> @out Int {
|
|
bb0(%0 : $*Int, %1 : @guaranteed $@noescape @callee_guaranteed () -> @out Int):
|
|
apply %1(%0) : $@noescape @callee_guaranteed () -> @out Int
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
|
|
sil [reabstraction_thunk] @reabstractionThunk : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
|
|
|
|
// CHECK-LABEL: sil shared [ossa] @$s25testClosureThunkNoEscape20aB14ConvertHelper2SiTf1nc_n : $@convention(thin) (Int) -> @out Int
|
|
// CHECK: [[PA1:%.*]] = partial_apply
|
|
// CHECK: convert_escape_to_noescape
|
|
// CHECK: [[PA2:%.*]] = partial_apply
|
|
// CHECK: [[CE:%.*]] = convert_escape_to_noescape
|
|
// CHECK: apply
|
|
// CHECK: destroy_value [[CE]]
|
|
// CHECK: destroy_value [[PA2]]
|
|
// CHECK: destroy_value [[PA1]]
|
|
// CHECK: return
|
|
|
|
// CHECK-LABEL: sil [ossa] @reabstractionTest : $@convention(thin) (Int) -> ()
|
|
// CHECK: [[F:%.*]] = function_ref @$s25testClosureThunkNoEscape20aB14ConvertHelper2SiTf1nc_n
|
|
// CHECK: apply [[F]]
|
|
// CHECK: return
|
|
sil [ossa] @reabstractionTest : $(Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%48 = alloc_stack $Int
|
|
%49 = function_ref @testClosureConvertHelper2 : $@convention(thin) (Int) -> Int
|
|
%50 = partial_apply [callee_guaranteed] %49(%0) : $@convention(thin) (Int) -> Int
|
|
%51 = convert_escape_to_noescape %50 : $@callee_guaranteed () -> Int to $@noescape @callee_guaranteed () -> Int
|
|
%52 = function_ref @reabstractionThunk : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
|
|
%53 = partial_apply [callee_guaranteed] %52(%51) : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
|
|
%54 = convert_escape_to_noescape %53 : $@callee_guaranteed () -> @out Int to $@noescape @callee_guaranteed () -> @out Int
|
|
%55 = function_ref @testClosureThunkNoEscape2 : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> @out Int) -> @out Int
|
|
apply %55(%48, %54) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> @out Int) -> @out Int
|
|
destroy_value %50
|
|
destroy_value %53
|
|
destroy_value %54
|
|
dealloc_stack %48 : $*Int
|
|
%empty = tuple ()
|
|
return %empty : $()
|
|
}
|
|
|
|
sil [ossa] @testClosureConvertHelper3 : $@convention(thin) (Int) -> Int
|
|
sil [reabstraction_thunk] @reabstractionThunk3 : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
|
|
|
|
sil [ossa] @testClosureThunkNoEscape3 : $@convention(thin) (@owned @noescape @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Int>) -> @out () {
|
|
entry(%empty : $*(), %closure : @owned $@noescape @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Int>):
|
|
%out = alloc_stack $Int
|
|
%ret = apply %closure(%out) : $@noescape @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Int>
|
|
dealloc_stack %out : $*Int
|
|
store %ret to [trivial] %empty : $*()
|
|
destroy_value %closure
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @reabstractionTest4 {{.*}} {
|
|
// CHECK: [[HELPER:%[^,]+]] = function_ref @testClosureConvertHelper3
|
|
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [[HELPER]]
|
|
// CHECK: [[NOESCAPE_CLOSURE:%[^,]+]] = convert_escape_to_noescape [[CLOSURE]]
|
|
// CHECK: [[SPECIALIZATION:%[^,]+]] = function_ref @$s25testClosureThunkNoEscape30aB14ConvertHelper3SiTf1nc_n
|
|
// CHECK: apply [[SPECIALIZATION]]{{.*}}
|
|
// CHECK: destroy_value [[CLOSURE]]
|
|
// CHECK: destroy_value [[NOESCAPE_CLOSURE]]
|
|
// CHECK-LABEL: } // end sil function 'reabstractionTest4'
|
|
sil [ossa] @reabstractionTest4 : $(Int) -> () {
|
|
bb0(%value : $Int):
|
|
%testThrowingClosureConvertHelper = function_ref @testClosureConvertHelper3 : $@convention(thin) (Int) -> Int
|
|
%closure = partial_apply [callee_guaranteed] %testThrowingClosureConvertHelper(%value) : $@convention(thin) (Int) -> Int
|
|
%noescapeClosure = convert_escape_to_noescape %closure : $@callee_guaranteed () -> Int to $@noescape @callee_guaranteed () -> Int
|
|
%thunk = function_ref @reabstractionThunk3 : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
|
|
%appliedThunk = partial_apply [callee_guaranteed] [on_stack] %thunk(%noescapeClosure) : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
|
|
|
|
%dependency = mark_dependence %appliedThunk : $@noescape @callee_guaranteed () -> @out Int on %noescapeClosure : $@noescape @callee_guaranteed () -> Int
|
|
%generified = convert_function %dependency : $@noescape @callee_guaranteed () -> @out Int to $@noescape @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Int>
|
|
%test = function_ref @testClosureThunkNoEscape3 : $@convention(thin) (@owned @noescape @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Int>) -> @out ()
|
|
%out = alloc_stack $()
|
|
%ret = apply %test(%out, %generified) : $@convention(thin) (@owned @noescape @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <Int>) -> @out ()
|
|
dealloc_stack %out : $*()
|
|
destroy_value %closure
|
|
destroy_value %noescapeClosure
|
|
%empty = tuple ()
|
|
return %empty : $()
|
|
}
|
|
|
|
sil [ossa] @testThrowingClosureConvertHelper : $@convention(thin) (Int) -> (Int, @error any Error)
|
|
sil [reabstraction_thunk] @reabstractionThunkThrowing : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (@out Int, @error any Error)
|
|
|
|
sil [ossa] @testClosureThunkNoEscapeThrowing : $@convention(thin) (@owned @noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>) -> (@out (), @error any Error) {
|
|
entry(%empty : $*(), %closure : @owned $@noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>):
|
|
%out = alloc_stack $Int
|
|
try_apply %closure(%out) : $@noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>, normal bb1, error bb2
|
|
|
|
bb1(%ret : $()):
|
|
destroy_value %closure
|
|
dealloc_stack %out : $*Int
|
|
store %ret to [trivial] %empty : $*()
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
|
|
bb2(%error : $any Error):
|
|
destroy_value %closure
|
|
dealloc_stack %out : $*Int
|
|
throw %error : $any Error
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @reabstractionThrowing : $@convention(thin) (Int) -> ((), @error any Error) {
|
|
// CHECK: [[HELPER:%[^,]+]] = function_ref @testThrowingClosureConvertHelper
|
|
// CHECK: [[CLOSURE:%[^,]+]] = partial_apply [callee_guaranteed] [[HELPER]]
|
|
// CHECK: [[NOESCAPE_CLOSURE:%[^,]+]] = convert_escape_to_noescape [[CLOSURE]]
|
|
// CHECK: [[SPECIALIZATION:%[^,]+]] = function_ref @$s32testClosureThunkNoEscapeThrowing0afB13ConvertHelperSiTf1nc_n
|
|
// CHECK: try_apply [[SPECIALIZATION]]{{.*}}normal [[NORMAL_BLOCK:bb[0-9]+]], error [[ERROR_BLOCK:bb[0-9]+]]
|
|
// CHECK: [[NORMAL_BLOCK]]
|
|
// CHECK: destroy_value [[NOESCAPE_CLOSURE]]
|
|
// CHECK: destroy_value [[CLOSURE]]
|
|
// CHECK: [[ERROR_BLOCK]]
|
|
// CHECK: destroy_value [[NOESCAPE_CLOSURE]]
|
|
// CHECK: destroy_value [[CLOSURE]]
|
|
// CHECK-LABEL: } // end sil function 'reabstractionThrowing'
|
|
sil [ossa] @reabstractionThrowing : $(Int) -> ((), @error any Error) {
|
|
bb0(%value : $Int):
|
|
%testThrowingClosureConvertHelper = function_ref @testThrowingClosureConvertHelper : $@convention(thin) (Int) -> (Int, @error any Error)
|
|
%closure = partial_apply [callee_guaranteed] %testThrowingClosureConvertHelper(%value) : $@convention(thin) (Int) -> (Int, @error any Error)
|
|
%noescapeClosure = convert_escape_to_noescape %closure : $@callee_guaranteed () -> (Int, @error any Error) to $@noescape @callee_guaranteed () -> (Int, @error any Error)
|
|
%thunk = function_ref @reabstractionThunkThrowing : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (@out Int, @error any Error)
|
|
%appliedThunk = partial_apply [callee_guaranteed] [on_stack] %thunk(%noescapeClosure) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error any Error)) -> (@out Int, @error any Error)
|
|
|
|
%dependency = mark_dependence %appliedThunk : $@noescape @callee_guaranteed () -> (@out Int, @error any Error) on %noescapeClosure : $@noescape @callee_guaranteed () -> (Int, @error any Error)
|
|
%generified = convert_function %dependency : $@noescape @callee_guaranteed () -> (@out Int, @error any Error) to $@noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>
|
|
%test = function_ref @testClosureThunkNoEscapeThrowing : $@convention(thin) (@owned @noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>) -> (@out (), @error any Error)
|
|
%out = alloc_stack $()
|
|
try_apply %test(%out, %generified) : $@convention(thin) (@owned @noescape @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <Int>) -> (@out (), @error any Error), normal bb1, error bb2
|
|
|
|
bb1(%ret : $()):
|
|
dealloc_stack %out : $*()
|
|
destroy_value %noescapeClosure
|
|
destroy_value %closure
|
|
%empty = tuple ()
|
|
return %empty : $()
|
|
|
|
bb2(%error : $any Error):
|
|
dealloc_stack %out : $*()
|
|
destroy_value %noescapeClosure
|
|
destroy_value %closure
|
|
throw %error : $any Error
|
|
}
|
|
|
|
// Currently not supported cases.
|
|
|
|
sil [ossa] @testClosureThunk4 : $@convention(thin) (@owned @callee_guaranteed () -> @out Int) -> @out Int {
|
|
bb0(%0 : $*Int, %1 : @owned $@callee_guaranteed () -> @out Int):
|
|
apply %1(%0) : $@callee_guaranteed () -> @out Int
|
|
destroy_value %1
|
|
%8 = tuple ()
|
|
return %8 : $()
|
|
}
|
|
// CHECK-LABEL: sil [ossa] @reabstractionTest2
|
|
// CHECK: bb0(%0 : $Int):
|
|
// CHECK: [[STK:%.*]] = alloc_stack $Int
|
|
// CHECK: [[F:%.*]] = function_ref @testClosureConvertHelper2
|
|
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[F]](%0)
|
|
// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA]]
|
|
// CHECK: [[F2:%.*]] = function_ref @reabstractionThunk
|
|
// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [[F2]]([[CVT]])
|
|
// CHECK: [[F3:%.*]] = function_ref @$s17testClosureThunk40aB14ConvertHelper2SiTf1nc_n : $@convention(thin) (Int) -> @out Int
|
|
// CHECK: apply [[F3]]([[STK]], %0)
|
|
// CHECK: destroy_value [[PA]]
|
|
// CHECK: dealloc_stack [[STK]]
|
|
// CHECK: return
|
|
|
|
sil [ossa] @reabstractionTest2 : $(Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%48 = alloc_stack $Int
|
|
%49 = function_ref @testClosureConvertHelper2 : $@convention(thin) (Int) -> Int
|
|
%50 = partial_apply [callee_guaranteed] %49(%0) : $@convention(thin) (Int) -> Int
|
|
%51 = convert_escape_to_noescape %50 : $@callee_guaranteed () -> Int to $@noescape @callee_guaranteed () -> Int
|
|
%52 = function_ref @reabstractionThunk : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
|
|
%53 = partial_apply [callee_guaranteed] %52(%51) : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
|
|
%55 = function_ref @testClosureThunk4 : $@convention(thin) (@owned @callee_guaranteed () -> @out Int) -> @out Int
|
|
apply %55(%48, %53) : $@convention(thin) (@owned @callee_guaranteed () -> @out Int) -> @out Int
|
|
destroy_value %50
|
|
dealloc_stack %48 : $*Int
|
|
%empty = tuple ()
|
|
return %empty : $()
|
|
}
|
|
|
|
// Only support the ultimate partial_apply.
|
|
sil [reabstraction_thunk] @reabstractionThunk2 : $@convention(thin) (@guaranteed @callee_guaranteed () -> Int) -> @out Int
|
|
|
|
// CHECK-LABEL: sil [ossa] @reabstractionTest3 : $@convention(thin) (Int) -> () {
|
|
// CHECK: bb0(%0 : $Int):
|
|
// CHECK: [[STK:%.*]] = alloc_stack $Int
|
|
// CHECK: [[SPEC:%.*]] = function_ref @$s25testClosureThunkNoEscape20aB14ConvertHelper2SiTf1nc_n : $@convention(thin) (Int) -> @out Int // user: %9
|
|
// CHECK: = apply [[SPEC]]([[STK]], %0) : $@convention(thin) (Int) -> @out Int
|
|
// CHECK: dealloc_stack [[STK]] : $*Int
|
|
// CHECK: return
|
|
|
|
sil [ossa] @reabstractionTest3 : $(Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%48 = alloc_stack $Int
|
|
%49 = function_ref @testClosureConvertHelper2 : $@convention(thin) (Int) -> Int
|
|
%50 = partial_apply [callee_guaranteed] %49(%0) : $@convention(thin) (Int) -> Int
|
|
%52 = function_ref @reabstractionThunk2 : $@convention(thin) (@guaranteed @callee_guaranteed () -> Int) -> @out Int
|
|
%53 = partial_apply [callee_guaranteed] %52(%50) : $@convention(thin) (@guaranteed @callee_guaranteed () -> Int) -> @out Int
|
|
%54 = convert_escape_to_noescape %53 : $@callee_guaranteed () -> @out Int to $@noescape @callee_guaranteed () -> @out Int
|
|
%55 = function_ref @testClosureThunkNoEscape2 : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> @out Int) -> @out Int
|
|
apply %55(%48, %54) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> @out Int) -> @out Int
|
|
destroy_value %54
|
|
destroy_value %53
|
|
dealloc_stack %48 : $*Int
|
|
%empty = tuple ()
|
|
return %empty : $()
|
|
}
|
|
|
|
//////////////////////
|
|
// Begin Apply Test //
|
|
//////////////////////
|
|
|
|
sil [ossa] @coroutine_user : $@yield_once @convention(thin) (@guaranteed @noescape @callee_guaranteed () -> Int) -> @yields Int {
|
|
bb0(%0 : @guaranteed $@noescape @callee_guaranteed () -> Int):
|
|
%1 = apply %0() : $@noescape @callee_guaranteed () -> Int
|
|
unreachable
|
|
}
|
|
|
|
// CHECK-LABEL: sil shared [ossa] @$s14coroutine_user25testClosureConvertHelper2SiTf1c_n : $@yield_once @convention(thin) (Int) -> @yields Int {
|
|
|
|
// CHECK-LABEL: sil [ossa] @test_coroutine_user : $@convention(thin) (Int) -> Int {
|
|
// CHECK: [[C:%.*]] = function_ref @$s14coroutine_user25testClosureConvertHelper2SiTf1c_n : $@yield_once @convention(thin) (Int) -> @yields Int
|
|
// CHECK: = begin_apply [[C]](%0)
|
|
// CHECK: } // end sil function 'test_coroutine_user'
|
|
sil [ossa] @test_coroutine_user : $@convention(thin) (Int) -> Int {
|
|
bb0(%0 : $Int):
|
|
%1 = function_ref @testClosureConvertHelper2 : $@convention(thin) (Int) -> Int
|
|
%2 = partial_apply [callee_guaranteed] %1(%0) : $@convention(thin) (Int) -> Int
|
|
%3 = convert_escape_to_noescape %2 : $@callee_guaranteed () -> Int to $@noescape @callee_guaranteed () -> Int
|
|
%4 = function_ref @coroutine_user : $@yield_once @convention(thin) (@guaranteed @noescape @callee_guaranteed () -> Int) -> @yields Int
|
|
(%value, %token) = begin_apply %4(%3) : $@yield_once @convention(thin) (@guaranteed @noescape @callee_guaranteed () -> Int) -> @yields Int
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
end_apply %token as $()
|
|
destroy_value %3
|
|
br bb3
|
|
|
|
bb2:
|
|
abort_apply %token
|
|
destroy_value %3
|
|
br bb3
|
|
|
|
bb3:
|
|
destroy_value %2
|
|
return %value : $Int
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @reabstractionTest_on_stack
|
|
// CHECK: bb0([[A:%.*]] : $Int):
|
|
// CHECK: [[R:%.*]] = alloc_stack $Int
|
|
// CHECK: [[F:%.*]] = function_ref @$s25testClosureThunkNoEscape20aB14ConvertHelper2SiTf1nc_n
|
|
// CHECK: apply [[F]]([[R]], [[A]])
|
|
sil [ossa] @reabstractionTest_on_stack : $(Int) -> () {
|
|
bb0(%0 : $Int):
|
|
%48 = alloc_stack $Int
|
|
%49 = function_ref @testClosureConvertHelper2 : $@convention(thin) (Int) -> Int
|
|
%50 = partial_apply [callee_guaranteed] [on_stack] %49(%0) : $@convention(thin) (Int) -> Int
|
|
%52 = function_ref @reabstractionThunk : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
|
|
%53 = partial_apply [callee_guaranteed] [on_stack] %52(%50) : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
|
|
%55 = function_ref @testClosureThunkNoEscape2 : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> @out Int) -> @out Int
|
|
apply %55(%48, %53) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> @out Int) -> @out Int
|
|
destroy_value %53 : $@noescape @callee_guaranteed () -> @out Int
|
|
destroy_value %50 : $@noescape @callee_guaranteed () -> Int
|
|
dealloc_stack %48 : $*Int
|
|
%empty = tuple ()
|
|
return %empty : $()
|
|
}
|
|
|
|
sil [ossa] @closure_with_string : $@convention(thin) (@guaranteed String) -> ()
|
|
|
|
sil [ossa] @use_non_escaping_closure : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> () {
|
|
bb0(%0 : @guaranteed $@noescape @callee_guaranteed () -> ()):
|
|
%2 = apply %0() : $@noescape @callee_guaranteed () -> ()
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @non_trivial_arg_capture : {{.*}} {
|
|
// CHECK-NOT: retain_value {{%.*}} : $String
|
|
// CHECK-LABEL: } // end sil function 'non_trivial_arg_capture'
|
|
sil [ossa] @non_trivial_arg_capture : $@convention(thin) (@guaranteed String) -> () {
|
|
bb0(%nc : @guaranteed $String):
|
|
%closure_fn = function_ref @closure_with_string : $@convention(thin) (@guaranteed String) -> ()
|
|
%closure = partial_apply [callee_guaranteed] [on_stack] %closure_fn(%nc) : $@convention(thin) (@guaranteed String) -> ()
|
|
%use = function_ref @use_non_escaping_closure : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
|
|
apply %use(%closure) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
|
|
destroy_value %closure
|
|
%11 = tuple ()
|
|
return %11 : $()
|
|
}
|
|
|
|
struct NC : ~Copyable {
|
|
deinit {}
|
|
}
|
|
|
|
sil hidden [ossa] [noinline] @noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> () {
|
|
bb0(%0 : @guaranteed $NC):
|
|
%retval = tuple ()
|
|
return %retval : $()
|
|
}
|
|
|
|
sil hidden [ossa] [noinline] @use_noncopyable_arg_closure : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> () {
|
|
bb0(%0 : @guaranteed $@noescape @callee_guaranteed () -> ()):
|
|
%2 = apply %0() : $@noescape @callee_guaranteed () -> ()
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @specialize_noncopyable_arg_closure : {{.*}} {
|
|
// CHECK: = function_ref @$s27use_noncopyable_arg_closure0b1_c1_D04main2NCVTf1c_n : $@convention(thin) (@guaranteed NC) -> ()
|
|
// CHECK-LABEL: } // end sil function 'specialize_noncopyable_arg_closure'
|
|
sil [ossa] @specialize_noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> () {
|
|
bb0(%nc : @guaranteed $NC):
|
|
%closure_fn = function_ref @noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> ()
|
|
%closure = partial_apply [callee_guaranteed] [on_stack] %closure_fn(%nc) : $@convention(thin) (@guaranteed NC) -> ()
|
|
%use = function_ref @use_noncopyable_arg_closure : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
|
|
apply %use(%closure) : $@convention(thin) (@guaranteed @noescape @callee_guaranteed () -> ()) -> ()
|
|
destroy_value %closure
|
|
%11 = tuple ()
|
|
return %11 : $()
|
|
}
|
|
|
|
sil hidden [ossa] [noinline] @use_escaping_noncopyable_arg_closure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
|
|
bb0(%0 : @guaranteed $@callee_guaranteed () -> ()):
|
|
%2 = apply %0() : $@callee_guaranteed () -> ()
|
|
%3 = tuple ()
|
|
return %3 : $()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @dont_specialize_noncopyable_arg_closure : {{.*}} {
|
|
// CHECK: [[C:%.*]] = partial_apply
|
|
// CHECK: apply {{%[0-9]+}}([[C]]) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
// CHECK-LABEL: } // end sil function 'dont_specialize_noncopyable_arg_closure'
|
|
sil [ossa] @dont_specialize_noncopyable_arg_closure : $@convention(thin) (@owned NC) -> () {
|
|
bb0(%nc : @owned $NC):
|
|
%closure_fn = function_ref @noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> ()
|
|
%closure = partial_apply [callee_guaranteed] %closure_fn(%nc) : $@convention(thin) (@guaranteed NC) -> ()
|
|
%use = function_ref @use_escaping_noncopyable_arg_closure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
apply %use(%closure) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
destroy_value %closure
|
|
%11 = tuple ()
|
|
return %11 : $()
|
|
}
|
|
|
|
sil @closure_with_closure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
|
|
// Just make sure the pass is not crashing.
|
|
sil [ossa] @test_recursion : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
|
|
bb0(%0 : @guaranteed $@callee_guaranteed () -> ()):
|
|
%2 = apply %0() : $@callee_guaranteed () -> ()
|
|
cond_br undef, bb1, bb2
|
|
|
|
bb1:
|
|
%5 = function_ref @closure_with_closure : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
%6 = copy_value %0
|
|
%7 = partial_apply [callee_guaranteed] %5(%6) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
%8 = function_ref @test_recursion : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
%9 = apply %8(%7) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> ()
|
|
destroy_value %7
|
|
br bb3
|
|
|
|
bb2:
|
|
br bb3
|
|
|
|
bb3:
|
|
%13 = tuple ()
|
|
return %13
|
|
}
|