Files
swift-mirror/test/SILOptimizer/specialize.sil
Erik Eckstein 7839b54b8a GenericSpecializer: drop metatype arguments in specialized functions
And replace them with explicit `metatype` instruction in the entry block.
This allows such metatype instructions to be deleted if they are dead.

This was already done for performance-annotated functions. But now do this for all functions.

It is essential that performance-annotated functions are specialized in the same way as other functions.
Because otherwise it can happen that the same specialization has different performance characteristics in different modules.
And it's up to the linker to select one of those ODR functions when linking.

Also, dropping metatype arguments is good for performance and code size in general.

This change also contains a few bug fixes for dropping metatype arguments.

rdar://110509780
2023-06-15 21:42:01 +02:00

762 lines
41 KiB
Plaintext

// RUN: %target-sil-opt -parse-serialized-sil -enable-sil-verify-all -sil-partial-specialization -generic-specializer -save-optimization-record-path=%t.yaml %/s | %FileCheck %s
// RUN: %FileCheck -check-prefix=YAML %s < %t.yaml
sil_stage canonical
import Builtin
import Swift
// CHECK-LABEL: sil @exp1 : $@convention(thin) () -> () {
// CHECK-NOT: apply
// Call of specialized initializer: <Int32>
// CHECK: [[CTOR:%[0-9]+]] = function_ref @$s8XXX_inits5Int32V_Tgm5
// CHECK: apply [[CTOR]]
// CHECK: [[ACCEPTS_INT:%[0-9]+]] = function_ref @acceptsInt
// Call of specialized XXX_foo: <Int32>
// CHECK: [[FOO:%[0-9]+]] = function_ref @$s7XXX_foos5Int32V_Tg5
// CHECK: apply [[FOO]]
// CHECK: apply [[ACCEPTS_INT]]
// CHECK: return
// CHEcK: sil @exp2 : $@convention(thin) () -> () {
// YAML: --- !Passed
// YAML-NEXT: Pass: sil-generic-specializer
// YAML-NEXT: Name: sil.Specialized
// YAML-NEXT: DebugLoc:
// YAML: File: {{.*}}/specialize.sil
// YAML: Line: 132
// YAML: Column: 8
// YAML-NEXT: Function: exp1
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Specialized function '
// YAML-NEXT: - Function: '"XXX_init"'
// YAML-NEXT: DebugLoc:
// YAML: File: {{.*}}/specialize.sil
// YAML: Line: 73
// YAML: Column: 17
// YAML-NEXT: - String: ' with type '
// YAML-NEXT: - FuncType: '(Int32) -> XXX<Int32>'
// YAML-NEXT: ...
// YAML-NEXT: --- !Passed
// YAML-NEXT: Pass: sil-generic-specializer
// YAML-NEXT: Name: sil.Specialized
// YAML-NEXT: DebugLoc:
// YAML: File: {{.*}}/specialize.sil
// YAML: Line: 142
// YAML: Column: 9
// YAML-NEXT: Function: exp1
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Specialized function '
// YAML-NEXT: - Function: '"XXX_foo"'
// YAML-NEXT: DebugLoc:
// YAML: File: {{.*}}/specialize.sil
// YAML: Line: 90
// YAML: Column: 17
// YAML-NEXT: - String: ' with type '
// YAML-NEXT: - FuncType: '(Int32, @inout XXX<Int32>) -> Int32'
// YAML-NEXT: ...
struct XXX<T> {
init(t: T)
mutating func foo(t: T) -> Int32
var m_t: T
}
// top_level_code
sil private @top_level_code : $@convention(thin) () -> () {
bb0:
%0 = tuple () // user: %1
return %0 : $() // id: %1
}
// specialize.XXX.init <A>(specialize.XXX<A>.Type)(t : A) -> specialize.XXX<A>
sil [noinline] @XXX_init : $@convention(thin) <T> (@in T, @thin XXX<T>.Type) -> @out XXX<T> {
bb0(%0 : $*XXX<T>, %1 : $*T, %2 : $@thin XXX<T>.Type):
%3 = alloc_stack $XXX<T>, var, name "sf" // users: %7, %11, %13
debug_value %1 : $*T, let, name "t", expr op_deref // id: %4
%5 = alloc_stack $T // users: %6, %8, %9
copy_addr %1 to [init] %5 : $*T // id: %6
%7 = struct_element_addr %3 : $*XXX<T>, #XXX.m_t // user: %8
copy_addr [take] %5 to [init] %7 : $*T // id: %8
dealloc_stack %5 : $*T // id: %9
destroy_addr %1 : $*T // id: %10
copy_addr [take] %3 to [init] %0 : $*XXX<T> // id: %11
%12 = tuple () // user: %14
dealloc_stack %3 : $*XXX<T> // id: %13
return %12 : $() // id: %14
}
// specialize.XXX.foo <A>(@inout specialize.XXX<A>)(t : A) -> Swift.Int32
sil [noinline] @XXX_foo : $@convention(method) <T> (@in T, @inout XXX<T>) -> Int32 {
bb0(%0 : $*T, %1 : $*XXX<T>):
debug_value %0 : $*T, let, name "t", expr op_deref // id: %2
%3 = alloc_stack $T // users: %4, %6, %7
copy_addr %0 to [init] %3 : $*T // id: %4
%5 = struct_element_addr %1 : $*XXX<T>, #XXX.m_t // user: %6
copy_addr [take] %3 to %5 : $*T // id: %6
dealloc_stack %3 : $*T // id: %7
%8 = integer_literal $Builtin.Int32, 4 // user: %9
%9 = struct $Int32 (%8 : $Builtin.Int32) // user: %11
destroy_addr %0 : $*T // id: %10
return %9 : $Int32 // id: %11
}
// Swift.Int32._convertFromBuiltinIntegerLiteral (Swift.Int32.Type)(Builtin.IntLiteral) -> Swift.Int32
sil public_external [transparent] @$sSi33_convertFromBuiltinIntegerLiteralySiBI_cSimF : $@convention(thin) (Builtin.IntLiteral, @thin Int32.Type) -> Int32 {
bb0(%0 : $Builtin.IntLiteral, %1 : $@thin Int32.Type):
%3 = builtin "s_to_s_checked_trunc_IntLiteral_Int32"(%0 : $Builtin.IntLiteral) : $(Builtin.Int32, Builtin.Int1)
%4 = tuple_extract %3 : $(Builtin.Int32, Builtin.Int1), 0 // user: %5
%5 = struct $Int32 (%4 : $Builtin.Int32) // user: %6
return %5 : $Int32 // id: %6
}
// specialize.acceptsInt (Swift.Int32) -> ()
sil [noinline] @acceptsInt : $@convention(thin) (Int32) -> () {
bb0(%0 : $Int32):
debug_value %0 : $Int32, let, name "x" // id: %1
%2 = tuple () // user: %3
return %2 : $() // id: %3
}
// specialize.exp1 () -> ()
sil @exp1 : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $XXX<Int32>, var, name "II" // users: %7, %15, %19
// function_ref specialize.XXX.init <A>(specialize.XXX<A>.Type)(t : A) -> specialize.XXX<A>
%1 = function_ref @XXX_init : $@convention(thin) <τ_0_0> (@in τ_0_0, @thin XXX<τ_0_0>.Type) -> @out XXX<τ_0_0> // user: %7
%2 = metatype $@thin XXX<Int32>.Type // user: %7
%3 = alloc_stack $Int32 // users: %6, %7, %8
%4 = integer_literal $Builtin.Int32, 5 // user: %5
%5 = struct $Int32 (%4 : $Builtin.Int32) // user: %6
store %5 to %3 : $*Int32 // id: %6
%7 = apply %1<Int32>(%0, %3, %2) : $@convention(thin) <τ_0_0> (@in τ_0_0, @thin XXX<τ_0_0>.Type) -> @out XXX<τ_0_0>
dealloc_stack %3 : $*Int32 // id: %8
// function_ref specialize.acceptsInt (Swift.Int32) -> ()
%9 = function_ref @acceptsInt : $@convention(thin) (Int32) -> () // user: %16
// function_ref specialize.XXX.foo <A>(@inout specialize.XXX<A>)(t : A) -> Swift.Int32
%10 = function_ref @XXX_foo : $@convention(method) <τ_0_0> (@in τ_0_0, @inout XXX<τ_0_0>) -> Int32 // user: %15
%11 = alloc_stack $Int32 // users: %14, %15, %17
%12 = integer_literal $Builtin.Int32, 4 // user: %13
%13 = struct $Int32 (%12 : $Builtin.Int32) // user: %14
store %13 to %11 : $*Int32 // id: %14
%15 = apply %10<Int32>(%11, %0) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout XXX<τ_0_0>) -> Int32 // user: %16
%16 = apply %9(%15) : $@convention(thin) (Int32) -> ()
dealloc_stack %11 : $*Int32 // id: %17
%18 = tuple () // user: %20
dealloc_stack %0 : $*XXX<Int32> // id: %19
return %18 : $() // id: %20
}
// specialize.exp2 () -> ()
sil @exp2 : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $XXX<UInt8>, var, name "I8" // users: %7, %15, %19
// function_ref specialize.XXX.init <A>(specialize.XXX<A>.Type)(t : A) -> specialize.XXX<A>
%1 = function_ref @XXX_init : $@convention(thin) <τ_0_0> (@in τ_0_0, @thin XXX<τ_0_0>.Type) -> @out XXX<τ_0_0> // user: %7
%2 = metatype $@thin XXX<UInt8>.Type // user: %7
%3 = alloc_stack $UInt8 // users: %6, %7, %8
%4 = integer_literal $Builtin.Int8, 5 // user: %5
%5 = struct $UInt8 (%4 : $Builtin.Int8) // user: %6
store %5 to %3 : $*UInt8 // id: %6
%7 = apply %1<UInt8>(%0, %3, %2) : $@convention(thin) <τ_0_0> (@in τ_0_0, @thin XXX<τ_0_0>.Type) -> @out XXX<τ_0_0>
dealloc_stack %3 : $*UInt8 // id: %8
// function_ref specialize.acceptsInt (Swift.Int32) -> ()
%9 = function_ref @acceptsInt : $@convention(thin) (Int32) -> () // user: %16
// function_ref specialize.XXX.foo <A>(@inout specialize.XXX<A>)(t : A) -> Swift.Int32
%10 = function_ref @XXX_foo : $@convention(method) <τ_0_0> (@in τ_0_0, @inout XXX<τ_0_0>) -> Int32 // user: %15
%11 = alloc_stack $UInt8 // users: %14, %15, %17
%12 = integer_literal $Builtin.Int8, 4 // user: %13
%13 = struct $UInt8 (%12 : $Builtin.Int8) // user: %14
store %13 to %11 : $*UInt8 // id: %14
%15 = apply %10<UInt8>(%11, %0) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout XXX<τ_0_0>) -> Int32 // user: %16
%16 = apply %9(%15) : $@convention(thin) (Int32) -> ()
dealloc_stack %11 : $*UInt8 // id: %17
%18 = tuple () // user: %20
dealloc_stack %0 : $*XXX<UInt8> // id: %19
return %18 : $() // id: %20
}
// specialize.useClosure <A>(fun : () -> A) -> A
sil @useClosure : $@convention(thin) <T> (@owned @callee_owned () -> @out T) -> @out T {
bb0(%0 : $*T, %1 : $@callee_owned () -> @out T):
debug_value %1 : $@callee_owned () -> @out T, let, name "fun" // id: %2
strong_retain %1 : $@callee_owned () -> @out T // id: %3
%4 = apply %1(%0) : $@callee_owned () -> @out T
strong_release %1 : $@callee_owned () -> @out T // id: %5
%6 = tuple () // user: %7
return %6 : $() // id: %7
}
// specialize.getGenericClosure <A>(t : A) -> () -> A
sil @getGenericClosure : $@convention(thin) <T> (@in T) -> @owned @callee_owned () -> @out T {
bb0(%0 : $*T):
debug_value %0 : $*T, let, name "t", expr op_deref // id: %1
// function_ref specialize.(getGenericClosure <A>(t : A) -> () -> A).(tmp #1) (())A
%2 = function_ref @getGenericClosure_closure : $@convention(thin) <τ_0_0> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 // user: %5
%3 = alloc_box $<τ_0_0> { var τ_0_0 } <T> // users: %4, %5, %5
%3a = project_box %3 : $<τ_0_0> { var τ_0_0 } <T>, 0
copy_addr %0 to [init] %3a : $*T // id: %4
%5 = partial_apply %2<T>(%3) : $@convention(thin) <τ_0_0> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0 // user: %7
destroy_addr %0 : $*T // id: %6
return %5 : $@callee_owned () -> @out T // id: %7
}
// specialize.(getGenericClosure <A>(t : A) -> () -> A).(tmp #1) (())
sil shared @getGenericClosure_closure : $@convention(thin) <T> (@owned <τ_0_0> { var τ_0_0 } <T>) -> @out T {
bb0(%0 : $*T, %1 : $<τ_0_0> { var τ_0_0 } <T>):
%2 = project_box %1 : $<τ_0_0> { var τ_0_0 } <T>, 0
copy_addr %2 to [init] %0 : $*T // id: %3
strong_release %1 : $<τ_0_0> { var τ_0_0 } <T> // id: %4
%5 = tuple () // user: %6
return %5 : $() // id: %6
}
// specialize.specializePartialApplies () -> Swift.UInt8
sil @specializePartialApplies : $@convention(thin) () -> UInt8 {
bb0:
%0 = alloc_stack $UInt8, var, name "i" // users: %3, %18
%1 = integer_literal $Builtin.Int8, 5 // user: %2
%2 = struct $UInt8 (%1 : $Builtin.Int8) // users: %3, %7
store %2 to %0 : $*UInt8 // id: %3
// function_ref specialize.useClosure <A>(fun : () -> A) -> A
%4 = function_ref @useClosure : $@convention(thin) <τ_0_0> (@owned @callee_owned () -> @out τ_0_0) -> @out τ_0_0 // user: %14
// function_ref specialize.getGenericClosure <A>(t : A) -> () -> A
%5 = function_ref @getGenericClosure : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @owned @callee_owned () -> @out τ_0_0 // user: %8
%6 = alloc_stack $UInt8 // users: %7, %8, %17
store %2 to %6 : $*UInt8 // id: %7
%8 = apply %5<UInt8>(%6) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> @owned @callee_owned () -> @out τ_0_0 // user: %10
// function_ref reabstraction thunk helper from @callee_owned () -> (@out Swift.UInt8) to @callee_owned () -> (@unowned Swift.UInt8)
%9 = function_ref @$ss5UInt8VIxr_ABIxd_TR : $@convention(thin) (@owned @callee_owned () -> @out UInt8) -> UInt8 // user: %10
%10 = partial_apply %9(%8) : $@convention(thin) (@owned @callee_owned () -> @out UInt8) -> UInt8 // user: %12
// function_ref reabstraction thunk helper from @callee_owned () -> (@unowned Swift.UInt8) to @callee_owned () -> (@out Swift.UInt8)
%11 = function_ref @$ss5UInt8VIxd_ABIxr_TR : $@convention(thin) (@owned @callee_owned () -> UInt8) -> @out UInt8 // user: %12
%12 = partial_apply %11(%10) : $@convention(thin) (@owned @callee_owned () -> UInt8) -> @out UInt8 // user: %14
%13 = alloc_stack $UInt8 // users: %14, %15, %16
%14 = apply %4<UInt8>(%13, %12) : $@convention(thin) <τ_0_0> (@owned @callee_owned () -> @out τ_0_0) -> @out τ_0_0
%15 = load %13 : $*UInt8 // user: %19
dealloc_stack %13 : $*UInt8 // id: %16
dealloc_stack %6 : $*UInt8 // id: %17
dealloc_stack %0 : $*UInt8 // id: %18
return %15 : $UInt8 // id: %19
}
// reabstraction thunk helper from @callee_owned () -> (@out Swift.UInt8) to @callee_owned () -> (@unowned Swift.UInt8)
sil shared [transparent] @$ss5UInt8VIxr_ABIxd_TR : $@convention(thin) (@owned @callee_owned () -> @out UInt8) -> UInt8 {
bb0(%0 : $@callee_owned () -> @out UInt8):
%1 = alloc_stack $UInt8 // users: %2, %3, %4
%2 = apply %0(%1) : $@callee_owned () -> @out UInt8
%3 = load %1 : $*UInt8 // user: %5
dealloc_stack %1 : $*UInt8 // id: %4
return %3 : $UInt8 // id: %5
}
// reabstraction thunk helper from @callee_owned () -> (@unowned Swift.UInt8) to @callee_owned () -> (@out Swift.UInt8)
sil shared [transparent] @$ss5UInt8VIxd_ABIxr_TR : $@convention(thin) (@owned @callee_owned () -> UInt8) -> @out UInt8 {
bb0(%0 : $*UInt8, %1 : $@callee_owned () -> UInt8):
%2 = apply %1() : $@callee_owned () -> UInt8 // user: %3
store %2 to %0 : $*UInt8 // id: %3
%4 = tuple () // user: %5
return %4 : $() // id: %5
}
class Base {
}
sil_vtable Base {
}
sil @generic_upcast : $@convention(thin) <T where T : Base> (@owned T) -> @owned Base {
bb0(%0 : $T):
%2 = upcast %0 : $T to $Base
return %2 : $Base
}
sil @specialize_generic_upcast : $@convention(thin)(@owned Base) -> @owned Base {
bb0(%0 : $Base):
%1 = function_ref @generic_upcast : $@convention(thin)<T where T : Base> (@owned T) -> @owned Base
%2 = apply %1<Base>(%0) : $@convention(thin)<T where T : Base> (@owned T) -> @owned Base
return %2 : $Base
}
// CHECK-LABEL: sil shared @{{.*}}generic_upcast{{.*}}Tg5 : $@convention(thin) (@owned Base) -> @owned Base {
// CHECK: bb0(%0 : $Base):
// CHECK: return %0 : $Base
// YAML: Line: 277
// YAML: Column: 8
// YAML-NEXT: Function: specialize_generic_upcast
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Specialized function '
// YAML-NEXT: - Function: '"generic_upcast"'
// YAML-NEXT: DebugLoc:
// YAML: File: {{.*}}/specialize.sil
// YAML: Line: 268
// YAML: Column: 6
// YAML-NEXT: - String: ' with type '
// YAML-NEXT: - FuncType: '(@owned Base) -> @owned Base'
// YAML-NEXT: ...
// Check generic specialization of partial_apply
protocol P { func get() -> Int32 }
struct C : P { func get() -> Int32 }
// test4.C.get (test4.C)() -> Swift.Int32
sil hidden @C_get : $@convention(method) (C) -> Int32 {
bb0(%0 : $C):
debug_value %0 : $C, let, name "self" // id: %1
%2 = integer_literal $Builtin.Int32, 1 // user: %3
%3 = struct $Int32 (%2 : $Builtin.Int32) // user: %4
return %3 : $Int32 // id: %4
}
// test4.C.init (test4.C.Type)() -> test4.C
sil hidden [noinline] @C_init : $@convention(thin) (@thin C.Type) -> C {
bb0(%0 : $@thin C.Type):
%1 = alloc_stack $C, var, name "sf" // user: %3
%2 = struct $C () // user: %4
dealloc_stack %1 : $*C // id: %3
return %2 : $C // id: %4
}
// protocol witness for test4.P.get <A : test4.P>(test4.P.Self)() -> Swift.Int32 in conformance test4.C : test4.P in test4
sil hidden [transparent] [thunk] @test4_P_get_witness_C : $@convention(witness_method: P) (@in_guaranteed C) -> Int32 {
bb0(%0 : $*C):
%1 = load %0 : $*C // user: %3
// function_ref test4.C.get (test4.C)() -> Swift.Int32
%2 = function_ref @C_get : $@convention(method) (C) -> Int32 // user: %3
%3 = apply %2(%1) : $@convention(method) (C) -> Int32 // user: %4
return %3 : $Int32 // id: %4
}
// test4.boo <A : test4.P, B>(A) -> (Swift.Int32, B) -> Swift.Int32
sil hidden [noinline] @boo : $@convention(thin) <U, T where U : P> (@in U) -> @owned @callee_owned (Int32, @in T) -> Int32 {
bb0(%0 : $*U):
debug_value %0 : $*U, let, name "y", expr op_deref // id: %1
// function_ref test4.(boo <A : test4.P, B>(A) -> (Swift.Int32, B) -> Swift.Int32).(closure #1)
%2 = function_ref @boo_closure : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : P> (Int32, @in τ_0_1, @owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> Int32 // user: %5
%3 = alloc_box $<τ_0_0> { var τ_0_0 } <U> // users: %4, %5, %5
%3a = project_box %3 : $<τ_0_0> { var τ_0_0 } <U>, 0
copy_addr %0 to [init] %3a : $*U // id: %4
%5 = partial_apply %2<U, T>(%3) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : P> (Int32, @in τ_0_1, @owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> Int32 // user: %7
destroy_addr %0 : $*U // id: %6
return %5 : $@callee_owned (Int32, @in T) -> Int32 // id: %7
}
// test4.(boo <A : test4.P, B>(A) -> (Swift.Int32, B) -> Swift.Int32).(closure #1)
sil shared [noinline] @boo_closure : $@convention(thin) <U, T where U : P> (Int32, @in T, @owned <τ_0_0> { var τ_0_0 } <U>) -> Int32 {
bb0(%0 : $Int32, %1 : $*T, %2 : $<τ_0_0> { var τ_0_0 } <U>):
%3 = project_box %2 : $<τ_0_0> { var τ_0_0 } <U>, 0
debug_value %0 : $Int32, let, name "x" // id: %4
debug_value %1 : $*T, let, name "z", expr op_deref // id: %5
%6 = witness_method $U, #P.get : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32 // user: %7
%7 = apply %6<U>(%3) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32 // user: %8
%8 = struct_extract %7 : $Int32, #Int32._value // user: %11
%9 = struct_extract %0 : $Int32, #Int32._value // user: %11
%10 = integer_literal $Builtin.Int1, -1 // user: %11
%11 = builtin "sadd_with_overflow_Int32"(%8 : $Builtin.Int32, %9 : $Builtin.Int32, %10 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // users: %12, %13
%12 = tuple_extract %11 : $(Builtin.Int32, Builtin.Int1), 0 // user: %15
%13 = tuple_extract %11 : $(Builtin.Int32, Builtin.Int1), 1 // user: %14
cond_fail %13 : $Builtin.Int1 // id: %14
%15 = struct $Int32 (%12 : $Builtin.Int32) // user: %18
strong_release %2 : $<τ_0_0> { var τ_0_0 } <U> // id: %16
destroy_addr %1 : $*T // id: %17
return %15 : $Int32 // id: %18
}
// static Swift.+ infix (Swift.Int32, Swift.Int32) -> Swift.Int32
sil public_external [transparent] @$ss1poiys5Int32VAC_ACtFZ : $@convention(thin) (Int32, Int32) -> Int32 {
bb0(%0 : $Int32, %1 : $Int32):
%2 = struct_extract %0 : $Int32, #Int32._value // user: %5
%3 = struct_extract %1 : $Int32, #Int32._value // user: %5
%4 = integer_literal $Builtin.Int1, -1 // user: %5
%5 = builtin "sadd_with_overflow_Int32"(%2 : $Builtin.Int32, %3 : $Builtin.Int32, %4 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // users: %6, %7
%6 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 0 // user: %9
%7 = tuple_extract %5 : $(Builtin.Int32, Builtin.Int1), 1 // user: %8
cond_fail %7 : $Builtin.Int1 // id: %8
%9 = struct $Int32 (%6 : $Builtin.Int32) // user: %10
return %9 : $Int32 // id: %10
}
// test4.foo <A : test4.P, B : test4.P>(A, B) -> (Swift.Int32, Swift.Float) -> Swift.Int32
sil hidden [noinline] @foo : $@convention(thin) <T, U where T : P, U : P> (@in T, @in U) -> @owned @callee_owned (Int32, Float) -> Int32 {
bb0(%0 : $*T, %1 : $*U):
debug_value %0 : $*T, let, name "x", expr op_deref // id: %2
debug_value %1 : $*U, let, name "y", expr op_deref // id: %3
// function_ref test4.boo <A : test4.P, B>(A) -> (Swift.Int32, B) -> Swift.Int32
%4 = function_ref @boo : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : P> (@in τ_0_0) -> @owned @callee_owned (Int32, @in τ_0_1) -> Int32 // user: %7
%5 = alloc_stack $U // users: %6, %7, %10
copy_addr %1 to [init] %5 : $*U // id: %6
%7 = apply %4<U, Float>(%5) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : P> (@in τ_0_0) -> @owned @callee_owned (Int32, @in τ_0_1) -> Int32 // user: %9
// function_ref reabstraction thunk helper <T_0_0, T_0_1 where T_0_0: test4.P, T_0_1: test4.P> from @callee_owned (@unowned Swift.Int32, @in Swift.Float) -> (@unowned Swift.Int32) to @callee_owned (@unowned Swift.Int32, @unowned Swift.Float) -> (@unowned Swift.Int32)
%8 = function_ref @_TTRG1_RPq_P5test41P_Pq0_PS0___XFo_dVs5Int32iSf_dS1__XFo_dS1_dSf_dS1__ : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : P, τ_0_1 : P> (Int32, Float, @owned @callee_owned (Int32, @in Float) -> Int32) -> Int32 // user: %9
%9 = partial_apply %8<T, U>(%7) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : P, τ_0_1 : P> (Int32, Float, @owned @callee_owned (Int32, @in Float) -> Int32) -> Int32 // user: %13
dealloc_stack %5 : $*U // id: %10
destroy_addr %1 : $*U // id: %11
destroy_addr %0 : $*T // id: %12
return %9 : $@callee_owned (Int32, Float) -> Int32 // id: %13
}
// reabstraction thunk helper <T_0_0, T_0_1 where T_0_0: test4.P, T_0_1: test4.P> from @callee_owned (@unowned Swift.Int32, @in Swift.Float) -> (@unowned Swift.Int32) to @callee_owned (@unowned Swift.Int32, @unowned Swift.Float) -> (@unowned Swift.Int32)
sil shared [transparent] [thunk] @_TTRG1_RPq_P5test41P_Pq0_PS0___XFo_dVs5Int32iSf_dS1__XFo_dS1_dSf_dS1__ : $@convention(thin) <T, U where T : P, U : P> (Int32, Float, @owned @callee_owned (Int32, @in Float) -> Int32) -> Int32 {
bb0(%0 : $Int32, %1 : $Float, %2 : $@callee_owned (Int32, @in Float) -> Int32):
%3 = alloc_stack $Float // users: %4, %5, %6
store %1 to %3 : $*Float // id: %4
%5 = apply %2(%0, %3) : $@callee_owned (Int32, @in Float) -> Int32 // user: %7
dealloc_stack %3 : $*Float // id: %6
return %5 : $Int32 // id: %7
}
// test4.gen1 <A : test4.P>(A) -> (Swift.Int32) -> Swift.Int32
sil hidden [noinline] @gen1 : $@convention(thin) <T where T : P> (@in T) -> @owned @callee_owned (Int32) -> Int32 {
bb0(%0 : $*T):
debug_value %0 : $*T, let, name "x", expr op_deref // id: %1
// function_ref test4.(gen1 <A : test4.P>(A) -> (Swift.Int32) -> Swift.Int32).(closure #1)
%2 = function_ref @gen1_closure : $@convention(thin) <τ_0_0 where τ_0_0 : P> (Int32, @owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> Int32 // user: %5
%3 = alloc_box $<τ_0_0> { var τ_0_0 } <T> // users: %4, %5, %5
%3a = project_box %3 : $<τ_0_0> { var τ_0_0 } <T>, 0
copy_addr %0 to [init] %3a : $*T // id: %4
%5 = partial_apply %2<T>(%3) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (Int32, @owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> Int32 // user: %7
destroy_addr %0 : $*T // id: %6
return %5 : $@callee_owned (Int32) -> Int32 // id: %7
}
// test4.(gen1 <A : test4.P>(A) -> (Swift.Int32) -> Swift.Int32).(closure #1)
sil shared [noinline] @gen1_closure : $@convention(thin) <T where T : P> (Int32, @owned <τ_0_0> { var τ_0_0 } <T>) -> Int32 {
bb0(%0 : $Int32, %1 : $<τ_0_0> { var τ_0_0 } <T>):
%2 = project_box %1 : $<τ_0_0> { var τ_0_0 } <T>, 0
debug_value %0 : $Int32 , let, name "$0" // id: %3
%4 = witness_method $T, #P.get : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32 // user: %5
%5 = apply %4<T>(%2) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32 // user: %6
%6 = struct_extract %5 : $Int32, #Int32._value // user: %9
%7 = struct_extract %0 : $Int32, #Int32._value // user: %9
%8 = integer_literal $Builtin.Int1, -1 // user: %9
%9 = builtin "sadd_with_overflow_Int32"(%6 : $Builtin.Int32, %7 : $Builtin.Int32, %8 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) // users: %10, %11
%10 = tuple_extract %9 : $(Builtin.Int32, Builtin.Int1), 0 // user: %13
%11 = tuple_extract %9 : $(Builtin.Int32, Builtin.Int1), 1 // user: %12
cond_fail %11 : $Builtin.Int1 // id: %12
%13 = struct $Int32 (%10 : $Builtin.Int32) // user: %15
strong_release %1 : $<τ_0_0> { var τ_0_0 } <T> // id: %14
return %13 : $Int32 // id: %15
}
// check that there is a generic specialization of boo
// CHECK-LABEL: sil shared [noinline] @$s3booxs5Int32VSfACIexyid_4main1PRzSfRs_r0_lIetio_Tp5AD1CV_Tg5 : $@convention(thin) (C) -> @owned @callee_owned (Int32, @in Float) -> Int32
// CHECK: [[CLOSURE_SPECIALIZATION:%[0-9]+]] = function_ref @$s11boo_closures5Int32VSfxz_x_lXXAC4main1PRzSfRs_r0_lIetyyxd_TP5AD1CV_TG5
// CHECK: partial_apply [[CLOSURE_SPECIALIZATION:%[0-9]+]]
// CHECK: return
// Check that there is a generic specialization of a closure from boo
// CHECK-LABEL: sil shared [noinline] @$s11boo_closures5Int32VSfxz_x_lXXAC4main1PRzSfRs_r0_lIetyyxd_Tp5AD1CV_Tg5
// CHECK: return
// Check that there is a generic specialization of foo
// CHECK-LABEL: sil shared [noinline] @$s3foo4main1CV_ADTg5 : $@convention(thin) (C, C) -> @owned @callee_owned (Int32, Float) -> Int32
// CHECK: function_ref @$s3booxs5Int32VSfACIexyid_4main1PRzSfRs_r0_lIetio_Tp5AD1CV_Tg5
// check that it invokes a generic specialization of the reabstraction thunk helper which invokes a specialization boo
// CHECK: [[THUNK_SPECIALIZATION:%[0-9]+]] = function_ref @$s053_TTRG1_RPq_P5test41P_Pq0_PS0___XFo_dVs5Int32iSf_dS1__f2_dj2_di2_dJ2__4main1CV_ADTg5
// CHECK-NOT: apply
// CHECK: partial_apply [[THUNK_SPECIALIZATION]]
// CHECK-NOT: apply
// CHECK: return
// Check that there is a generic specialization of gen1
// CHECK-LABEL: sil shared [noinline] @$s4gen14main1CV_Tg5 : $@convention(thin) (C) -> @owned @callee_owned (Int32) -> Int32
// check that it invokes a generic specialization of the closure by mean of partial_apply
// CHECK: [[CLOSURE_SPECIALIZATION:%[0-9]+]] = function_ref @$s12gen1_closure4main1CV_Tg5
// CHECK-NOT: apply
// CHECK: partial_apply [[CLOSURE_SPECIALIZATION]]
// CHECK-NOT: apply
// CHECK: return
// Check that there is a generic specialization of a closure from gen1
// CHECK-LABEL: sil shared [noinline] @$s12gen1_closure4main1CV_Tg5 : $@convention(thin) (Int32, @owned <τ_0_0> { var τ_0_0 } <C>) -> Int32
// CHECK: return
// test4.bar () -> Swift.Int32
// CHECK-LABEL: sil hidden @bar
// check that it does not invoke a generic specialization of foo
// CHECK-NOT: function_ref @foo
// check that it invokes a generic specialization of foo
// CHECK: function_ref @$s3foo4main1CV_ADTg5
sil hidden @bar : $@convention(thin) () -> Int32 {
bb0:
%0 = alloc_stack $@callee_owned (Int32, Float) -> Int32, var, name "f" // users: %11, %22
// function_ref test4.C.init (test4.C.Type)() -> test4.C
%1 = function_ref @C_init : $@convention(thin) (@thin C.Type) -> C // user: %3
%2 = metatype $@thin C.Type // user: %3
%3 = apply %1(%2) : $@convention(thin) (@thin C.Type) -> C // users: %4, %7, %9
debug_value %3 : $C, let, name "c" // id: %4
// function_ref test4.foo <A : test4.P, B : test4.P>(A, B) -> (Swift.Int32, Swift.Float) -> Swift.Int32
%5 = function_ref @foo : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : P, τ_0_1 : P> (@in τ_0_0, @in τ_0_1) -> @owned @callee_owned (Int32, Float) -> Int32 // user: %10
%6 = alloc_stack $C // users: %7, %10, %13
store %3 to %6 : $*C // id: %7
%8 = alloc_stack $C // users: %9, %10, %12
store %3 to %8 : $*C // id: %9
%10 = apply %5<C, C>(%6, %8) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : P, τ_0_1 : P> (@in τ_0_0, @in τ_0_1) -> @owned @callee_owned (Int32, Float) -> Int32 // users: %11, %14, %20, %21
store %10 to %0 : $*@callee_owned (Int32, Float) -> Int32 // id: %11
dealloc_stack %8 : $*C // id: %12
dealloc_stack %6 : $*C // id: %13
strong_retain %10 : $@callee_owned (Int32, Float) -> Int32 // id: %14
%15 = integer_literal $Builtin.Int32, 3 // user: %16
%16 = struct $Int32 (%15 : $Builtin.Int32) // user: %20
%17 = float_literal $Builtin.FPIEEE80, 0x4000C8F5C28F5C28F5C3 // 3.1400000000000000001 // user: %18
%18 = builtin "fptrunc_FPIEEE80_FPIEEE32"(%17 : $Builtin.FPIEEE80) : $Builtin.FPIEEE32 // user: %19
%19 = struct $Float (%18 : $Builtin.FPIEEE32) // user: %20
%20 = apply %10(%16, %19) : $@callee_owned (Int32, Float) -> Int32 // user: %23
strong_release %10 : $@callee_owned (Int32, Float) -> Int32 // id: %21
dealloc_stack %0 : $*@callee_owned (Int32, Float) -> Int32 // id: %22
return %20 : $Int32 // id: %23
}
// test4.testBar () -> Swift.Int32
sil @testBar : $@convention(thin) () -> Int32 {
bb0:
// function_ref test4.bar () -> Swift.Int32
%0 = function_ref @bar : $@convention(thin) () -> Int32 // user: %1
%1 = apply %0() : $@convention(thin) () -> Int32 // user: %2
return %1 : $Int32 // id: %2
}
// CHECK-LABEL: sil @testGen1
// Call of C_init
// CHECK: function_ref @C_init
// CHECK: apply
// Reference to the generic specialization of gen1
// CHECK-NOT: function_ref @gen1
// CHECK: function_ref @$s4gen14main1CV_Tg5 : $@convention(thin) (C) -> @owned @callee_owned (Int32) -> Int32
sil @testGen1 : $@convention(thin) () -> Int32 {
bb0:
%0 = alloc_stack $@callee_owned (Int32) -> Int32, var, name "f" // users: %9, %16
// function_ref test4.C.init (test4.C.Type)() -> test4.C
%1 = function_ref @C_init : $@convention(thin) (@thin C.Type) -> C // user: %3
%2 = metatype $@thin C.Type // user: %3
%3 = apply %1(%2) : $@convention(thin) (@thin C.Type) -> C // users: %4, %7
debug_value %3 : $C, let, name "c" // id: %4
// function_ref test4.gen1 <A : test4.P>(A) -> (Swift.Int32) -> Swift.Int32
%5 = function_ref @gen1 : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in τ_0_0) -> @owned @callee_owned (Int32) -> Int32 // user: %8
%6 = alloc_stack $C // users: %7, %8, %10
store %3 to %6 : $*C // id: %7
%8 = apply %5<C>(%6) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in τ_0_0) -> @owned @callee_owned (Int32) -> Int32 // users: %9, %11, %14, %15
store %8 to %0 : $*@callee_owned (Int32) -> Int32 // id: %9
dealloc_stack %6 : $*C // id: %10
strong_retain %8 : $@callee_owned (Int32) -> Int32 // id: %11
%12 = integer_literal $Builtin.Int32, 3 // user: %13
%13 = struct $Int32 (%12 : $Builtin.Int32) // user: %14
%14 = apply %8(%13) : $@callee_owned (Int32) -> Int32 // user: %17
strong_release %8 : $@callee_owned (Int32) -> Int32 // id: %15
dealloc_stack %0 : $*@callee_owned (Int32) -> Int32 // id: %16
return %14 : $Int32 // id: %17
}
// test_bind<A> (Builtin.RawPointer, A.Type) -> ()
// Check that this is specialized as T=Int.
// CHECK-LABEL: sil shared @$s9test_bindSi_Tgm5 : $@convention(thin) (Builtin.RawPointer) -> ()
// CHECK: bind_memory %0 : $Builtin.RawPointer, {{%.*}} : $Builtin.Word to $*Int
// CHECK: return
sil hidden @test_bind : $@convention(thin) <T> (Builtin.RawPointer, @thick T.Type) -> () {
bb0(%0 : $Builtin.RawPointer, %1 : $@thick T.Type):
%4 = integer_literal $Builtin.Word, 1
%5 = metatype $@thick T.Type
%6 = bind_memory %0 : $Builtin.RawPointer, %4 : $Builtin.Word to $*T
%7 = tuple ()
%8 = tuple ()
return %8 : $()
}
// Invoke test_bind with T=Int.
sil @call_bind : $@convention(thin) (Builtin.RawPointer) -> () {
bb0(%0 : $Builtin.RawPointer):
// function_ref test_bind<A> (Builtin.RawPointer, A.Type) -> ()
%2 = function_ref @test_bind : $@convention(thin) <τ_0_0> (Builtin.RawPointer, @thick τ_0_0.Type) -> ()
%3 = metatype $@thick Int.Type
%4 = apply %2<Int>(%0, %3) : $@convention(thin) <τ_0_0> (Builtin.RawPointer, @thick τ_0_0.Type) -> ()
%5 = tuple ()
return %5 : $()
}
// invokeGenericClosure<A>(todo:)
sil [noinline] @invokeGenericClosure : $@convention(thin) <R> (@owned @callee_owned () -> (@out R, @error Error)) -> (@out R, @error Error) {
bb0(%0 : $*R, %1 : $@callee_owned () -> (@out R, @error Error)):
debug_value %1 : $@callee_owned () -> (@out R, @error Error), let, name "todo", argno 1 // id: %2
debug_value undef : $Error, var, name "$error", argno 2 // id: %3
strong_retain %1 : $@callee_owned () -> (@out R, @error Error) // id: %4
try_apply %1(%0) : $@callee_owned () -> (@out R, @error Error), normal bb1, error bb2 // id: %5
bb1(%6 : $()): // Preds: bb0
strong_release %1 : $@callee_owned () -> (@out R, @error Error) // id: %7
%8 = tuple () // user: %9
return %8 : $() // id: %9
// %10 // user: %12
bb2(%10 : $Error): // Preds: bb0
strong_release %1 : $@callee_owned () -> (@out R, @error Error) // id: %11
throw %10 : $Error // id: %12
} // end sil function 'invokeGenericClosure'
sil public_external @error : $@convention(thin) () -> Never
// action()
sil @action : $@convention(thin) () -> Never
// thunk for @callee_owned () -> (@unowned Never, @error @owned Error)
sil @action_thunk : $@convention(thin) (@owned @callee_owned () -> (Never, @error Error)) -> (@out Never, @error Error)
// Check that in a case where a generic specialization is a non-return function,
// the return value is not stored after the call and an unreachable instruction
// is inserted as a terminator of a basic block.
//
// CHECK-LABEL: sil @testGenericClosureSpecialization
// Call of the generic specialization of invokeGenericClosure<Never>
// CHECK: function_ref @$s20invokeGenericClosures5NeverO_Tg5 : $@convention(thin) (@owned @callee_owned () -> (@out Never, @error any Error)) -> (Never, @error any Error)
// CHECK: apply [nothrow]
// CHECK: unreachable
// CHECK: end sil function 'testGenericClosureSpecialization'
sil @testGenericClosureSpecialization : $@convention(thin) () -> @error Error {
bb0:
// function_ref invokeGenericClosure<A>(todo:)
%1 = function_ref @invokeGenericClosure : $@convention(thin) <τ_0_0> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
%2 = alloc_stack $Never
// function_ref action()
%3 = function_ref @action : $@convention(thin) () -> Never
%4 = thin_to_thick_function %3 : $@convention(thin) () -> Never to $@callee_owned () -> Never
%5 = convert_function %4 : $@callee_owned () -> Never to $@callee_owned () -> (Never, @error Error)
// function_ref thunk for @callee_owned () -> (@unowned Never, @error @owned Error)
%6 = function_ref @action_thunk : $@convention(thin) (@owned @callee_owned () -> (Never, @error Error)) -> (@out Never, @error Error)
%7 = partial_apply %6(%5) : $@convention(thin) (@owned @callee_owned () -> (Never, @error Error)) -> (@out Never, @error Error)
%8 = apply [nothrow] %1<Never>(%2, %7) : $@convention(thin) <τ_0_0> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
unreachable
} // end sil function 'testGenericClosureSpecialization'
// Test a specialization of a self-recursive generic closure.
// CHECK-LABEL: sil shared @$s27selfReferringGenericClosurexBi64_Bi64_Bi64_Rs_r0_lIetnyy_Tp5 : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 == Builtin.Int64> (@in_guaranteed τ_0_0, Builtin.Int64, Builtin.Int64) -> () {
// CHECK: [[SPECIALIZED_FN:%[0-9]+]] = function_ref @$s27selfReferringGenericClosurexBi64_Bi64_Bi64_Rs_r0_lIetnyy_Tp5
// CHECK: partial_apply [[SPECIALIZED_FN]]{{.*}}({{.*}}) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 == Builtin.Int64> (@in_guaranteed τ_0_0, Builtin.Int64, Builtin.Int64) -> ()
// CHECK-LABEL: sil @selfReferringGenericClosure : $@convention(thin) <R, S> (@in_guaranteed R, @in_guaranteed S, Builtin.Int64) -> ()
// Refer to the specialized version of the function
// CHECK: [[SPECIALIZED_FN:%[0-9]+]] = function_ref @$s27selfReferringGenericClosurexBi64_Bi64_Bi64_Rs_r0_lIetnyy_Tp5
// CHECK: partial_apply [[SPECIALIZED_FN]]<R, Builtin.Int64>({{.*}}) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 == Builtin.Int64> (@in_guaranteed τ_0_0, Builtin.Int64, Builtin.Int64) -> ()
sil @selfReferringGenericClosure : $@convention(thin) <R, S> (@in_guaranteed R, @in_guaranteed S, Builtin.Int64) -> () {
bb0(%0 : $*R, %1 : $*S, %2 : $Builtin.Int64):
%4 = integer_literal $Builtin.Int64, 100
%5 = builtin "cmp_eq_Int64"(%2 : $Builtin.Int64, %4 : $Builtin.Int64) : $Builtin.Int1
cond_br %5, bb2, bb1
bb1:
%val_storage = alloc_stack $Builtin.Int64
%val = integer_literal $Builtin.Int64, 4
store %val to %val_storage : $*Builtin.Int64
%fn = function_ref @selfReferringGenericClosure : $@convention(thin) <U, V> (@in_guaranteed U, @in_guaranteed V, Builtin.Int64) -> ()
%7 = partial_apply %fn<R, Builtin.Int64>(%0, %val_storage, %4) : $@convention(thin) <U, V> (@in_guaranteed U, @in_guaranteed V, Builtin.Int64) -> ()
dealloc_stack %val_storage : $*Builtin.Int64
br bb3
bb2:
br bb3
bb3:
%8 = tuple ()
return %8 : $()
}
struct YYY<T> {
}
enum MyOptional<T> {
case none
case some(T)
}
// Check that a specialization of a self-recursive function is produced
// and it is not crashing the compiler.
// CHECK-LABEL: sil shared @$s25testSelfRecursiveFunction4main10MyOptionalOyAB3YYYVyypGG_Tg5 : $@convention(thin) (MyOptional<YYY<Any>>) -> ()
sil @testSelfRecursiveFunction : $@convention(thin) <T> (@in T) -> () {
bb0(%0 : $*T):
%2 = function_ref @testSelfRecursiveFunction : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
%3 = alloc_stack $MyOptional<YYY<Any>>
inject_enum_addr %3 : $*MyOptional<YYY<Any>>, #MyOptional.none!enumelt
%5 = tuple ()
%6 = load %3 : $*MyOptional<YYY<Any>>
%7 = alloc_stack $MyOptional<YYY<Any>>
store %6 to %7 : $*MyOptional<YYY<Any>>
%9 = apply %2<MyOptional<YYY<Any>>>(%7) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
dealloc_stack %7 : $*MyOptional<YYY<Any>>
dealloc_stack %3 : $*MyOptional<YYY<Any>>
destroy_addr %0 : $*T
%13 = tuple ()
return %13 : $()
} // end sil function 'testSelfRecursiveFunction'
sil @id : $@convention(thin) <T> (@in T) -> @out T {
bb0(%0 : $*T, %1 :$*T):
copy_addr [take] %1 to [init] %0 : $*T
%t = tuple ()
return %t : $()
}
// This should not assert.
// CHECK-LABEL: sil shared @$s26specialize_no_return_applys5NeverO_Tgm5
// CHECK: apply
// CHECK-NEXT: unreachable
sil @specialize_no_return_apply: $@convention(thin) <T> (@thick T.Type) -> () {
bb0(%0 : $@thick T.Type):
%in = alloc_stack $T
%out = alloc_stack $T
%f = function_ref @id : $@convention(thin) <T> (@in T) -> @out T
%r = apply %f<T>(%out, %in) : $@convention(thin) <T> (@in T) -> @out T
dealloc_stack %out : $*T
dealloc_stack %in : $*T
%t = tuple ()
return %t : $()
}
sil @test_specialize_noreturn_apply : $@convention(thin) () -> () {
bb0:
%f = function_ref @specialize_no_return_apply : $@convention(thin) <T> (@thick T.Type) -> ()
%m = metatype $@thick Never.Type
%r = apply %f<Never>(%m) : $@convention(thin) <T> (@thick T.Type) -> ()
%t = tuple ()
return %t : $()
}
sil shared @closure : $@convention(thin) <T> (@in_guaranteed T) -> () {
bb0(%0 : $*T):
%5 = tuple ()
return %5 : $()
}
sil @getExistingExternalSpecialization : $@convention(thin) <T> (@in_guaranteed T) -> @owned @callee_owned () -> () {
bb0(%0 : $*T):
%2 = function_ref @closure : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
%5 = partial_apply %2<T>(%0) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
return %5 : $@callee_owned () -> ()
}
// Make sure we don't crash here
// CHECK-LABEL: sil @testExistingExternalSpecialization :
// CHECK: function_ref @$s33getExistingExternalSpecializations5UInt8V_Tg5
// CHECK: } // end sil function 'testExistingExternalSpecialization'
sil @testExistingExternalSpecialization : $@convention(thin) () -> () {
bb0:
%0 = alloc_stack $UInt8
%1 = integer_literal $Builtin.Int8, 5
%2 = struct $UInt8 (%1 : $Builtin.Int8)
store %2 to %0 : $*UInt8
%5 = function_ref @getExistingExternalSpecialization : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @owned @callee_owned () -> ()
%8 = apply %5<UInt8>(%0) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @owned @callee_owned () -> ()
dealloc_stack %0 : $*UInt8
%r = tuple ()
return %r : $()
}
sil @$s7closures5UInt8V_Tg5 : $@convention(thin) (UInt8) -> ()