blob: 0d085d0d979b9b0d4733dc08920736a5df4c941b [file] [log] [blame]
// RUN: %target-sil-opt -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_Tg5
// 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-NEXT: File: {{.*}}/specialize.sil
// YAML-NEXT: Line: 132
// YAML-NEXT: Column: 8
// YAML-NEXT: Function: exp1
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Specialized function '
// YAML-NEXT: - Function: '"XXX_init"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/specialize.sil
// YAML-NEXT: Line: 73
// YAML-NEXT: Column: 17
// YAML-NEXT: - String: ' with type '
// YAML-NEXT: - FuncType: '(Int32, @thin XXX<Int32>.Type) -> XXX<Int32>'
// YAML-NEXT: ...
// YAML-NEXT: --- !Passed
// YAML-NEXT: Pass: sil-generic-specializer
// YAML-NEXT: Name: sil.Specialized
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/specialize.sil
// YAML-NEXT: Line: 142
// YAML-NEXT: Column: 9
// YAML-NEXT: Function: exp1
// YAML-NEXT: Args:
// YAML-NEXT: - String: 'Specialized function '
// YAML-NEXT: - Function: '"XXX_foo"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}/specialize.sil
// YAML-NEXT: Line: 90
// YAML-NEXT: 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_addr %1 : $*T, let, name "t" // id: %4
%5 = alloc_stack $T // users: %6, %8, %9
copy_addr %1 to [initialization] %5 : $*T // id: %6
%7 = struct_element_addr %3 : $*XXX<T>, #XXX.m_t // user: %8
copy_addr [take] %5 to [initialization] %7 : $*T // id: %8
dealloc_stack %5 : $*T // id: %9
destroy_addr %1 : $*T // id: %10
copy_addr [take] %3 to [initialization] %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_addr %0 : $*T, let, name "t" // id: %2
%3 = alloc_stack $T // users: %4, %6, %7
copy_addr %0 to [initialization] %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_addr %0 : $*T, let, name "t" // 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 [initialization] %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 [initialization] %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-NEXT: 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-NEXT: File: {{.*}}/specialize.sil
// YAML-NEXT: Line: 268
// YAML-NEXT: 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_addr %0 : $*U, let, name "y" // 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 [initialization] %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_addr %1 : $*T, let, name "z" // id: %5
%6 = witness_method $U, #P.get!1 : $@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] [serialized] @$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_addr %0 : $*T, let, name "x" // id: %2
debug_value_addr %1 : $*U, let, name "y" // 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 [initialization] %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_addr %0 : $*T, let, name "x" // 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 [initialization] %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!1 : $@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_Tg5 : $@convention(thin) (Builtin.RawPointer, @thick Int.Type) -> ()
// 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
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 Error)) -> (Never, @error 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'