|
| 1 | +// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -generic-specializer -sil-partial-specialization-with-generic-substitutions %s | %FileCheck %s |
| 2 | + |
| 3 | +// Test different cases of partial specialization. |
| 4 | +// In particular, test the correctness of partial specializaitons where substitutions may be generic. |
| 5 | + |
| 6 | +sil_stage canonical |
| 7 | + |
| 8 | +import Builtin |
| 9 | +import Swift |
| 10 | +import SwiftShims |
| 11 | + |
| 12 | +@_silgen_name("use") |
| 13 | +public func use<T>(_ t: T) |
| 14 | + |
| 15 | +public protocol P { |
| 16 | +} |
| 17 | + |
| 18 | +public struct S<T> { |
| 19 | + @inline(never) public init(_ t: T) |
| 20 | +} |
| 21 | + |
| 22 | +@inline(never) public func simple_generic_callee<U, V>(_ u: U, _ v: V) |
| 23 | + |
| 24 | +public func simple_generic_caller1<U>(_ u: U) |
| 25 | + |
| 26 | +public func simple_generic_caller2<U>(_ u: U) |
| 27 | + |
| 28 | +// use |
| 29 | +sil @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> () |
| 30 | + |
| 31 | +// S.init(_:) |
| 32 | +sil [noinline] @_T022partial_specialization1SVACyxGxcfC : $@convention(method) <T> (@in T, @thin S<T>.Type) -> S<T> |
| 33 | + |
| 34 | +// simple_generic_callee<A, B>(_:_:) |
| 35 | +sil [noinline] @simple_generic_callee : $@convention(thin) <U, V> (@in U, @in V) -> () { |
| 36 | +bb0(%0 : $*U, %1 : $*V): |
| 37 | + // function_ref use |
| 38 | + %4 = function_ref @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> () |
| 39 | + %5 = alloc_stack $U |
| 40 | + copy_addr %0 to [initialization] %5 : $*U |
| 41 | + %7 = apply %4<U>(%5) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> () |
| 42 | + dealloc_stack %5 : $*U |
| 43 | + // function_ref use |
| 44 | + %9 = function_ref @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> () |
| 45 | + %10 = alloc_stack $V |
| 46 | + copy_addr %1 to [initialization] %10 : $*V |
| 47 | + %12 = apply %9<V>(%10) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> () |
| 48 | + dealloc_stack %10 : $*V |
| 49 | + destroy_addr %1 : $*V |
| 50 | + destroy_addr %0 : $*U |
| 51 | + %16 = tuple () |
| 52 | + return %16 : $() |
| 53 | +} // end sil function 'simple_generic_callee' |
| 54 | + |
| 55 | +// simple_generic_caller1<A>(_:) |
| 56 | +sil @simple_generic_caller1 : $@convention(thin) <U> (@in U) -> () { |
| 57 | +bb0(%0 : $*U): |
| 58 | + // function_ref simple_generic_callee<A, B>(_:_:) |
| 59 | + %2 = function_ref @simple_generic_callee : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> () |
| 60 | + %3 = alloc_stack $U |
| 61 | + copy_addr %0 to [initialization] %3 : $*U |
| 62 | + %5 = integer_literal $Builtin.Int32, 1 |
| 63 | + %6 = struct $Int32 (%5 : $Builtin.Int32) |
| 64 | + %7 = alloc_stack $Int32 |
| 65 | + store %6 to %7 : $*Int32 |
| 66 | + %9 = apply %2<U, Int32>(%3, %7) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> () |
| 67 | + dealloc_stack %7 : $*Int32 |
| 68 | + dealloc_stack %3 : $*U |
| 69 | + destroy_addr %0 : $*U |
| 70 | + %13 = tuple () |
| 71 | + return %13 : $() |
| 72 | +} // end sil function 'simple_generic_caller1' |
| 73 | + |
| 74 | +// simple_generic_caller2<A>(_:) |
| 75 | +sil @simple_generic_caller2 : $@convention(thin) <U> (@in U) -> () { |
| 76 | +bb0(%0 : $*U): |
| 77 | + // function_ref simple_generic_callee<A, B>(_:_:) |
| 78 | + %2 = function_ref @simple_generic_callee : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> () |
| 79 | + // function_ref S.init(_:) |
| 80 | + %3 = function_ref @_T022partial_specialization1SVACyxGxcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin S<τ_0_0>.Type) -> S<τ_0_0> |
| 81 | + %4 = metatype $@thin S<U>.Type |
| 82 | + %5 = alloc_stack $U |
| 83 | + copy_addr %0 to [initialization] %5 : $*U |
| 84 | + %7 = apply %3<U>(%5, %4) : $@convention(method) <τ_0_0> (@in τ_0_0, @thin S<τ_0_0>.Type) -> S<τ_0_0> |
| 85 | + dealloc_stack %5 : $*U |
| 86 | + %9 = alloc_stack $S<U> |
| 87 | + store %7 to %9 : $*S<U> |
| 88 | + %11 = integer_literal $Builtin.Int32, 1 |
| 89 | + %12 = struct $Int32 (%11 : $Builtin.Int32) |
| 90 | + %13 = alloc_stack $Int32 |
| 91 | + store %12 to %13 : $*Int32 |
| 92 | + %15 = apply %2<S<U>, Int32>(%9, %13) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> () |
| 93 | + dealloc_stack %13 : $*Int32 |
| 94 | + dealloc_stack %9 : $*S<U> |
| 95 | + destroy_addr %0 : $*U |
| 96 | + %19 = tuple () |
| 97 | + return %19 : $() |
| 98 | +} // end sil function 'simple_generic_caller2' |
| 99 | + |
| 100 | +// Check that a partial specialization for simple_generic_callee<U, Int32> was created. |
| 101 | +// CHECK-LABEL: sil shared [noinline] @_T021simple_generic_calleexs5Int32Vq_RszACRs0_r1_lItiy_Tp5 : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 == τ_0_1, τ_0_2 == Int32> (@in τ_0_0, Int32) -> () |
| 102 | + |
| 103 | + |
| 104 | +// Check that a partial specialization for simple_generic_callee<S<U>, Int32> was created. |
| 105 | +// CHECK-LABEL: sil shared [noinline] @_T021simple_generic_callee4main1SVyxGs5Int32VAERs_AGRs0_r1_lItyy_Tp5 : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_1 == S<τ_0_0>, τ_0_2 == Int32> (S<τ_0_0>, Int32) -> () |
| 106 | + |
| 107 | +// Check that no partial specializations are produced if all substitutions in the substitution list |
| 108 | +// are archetypes. |
| 109 | +// CHECK-LABEL: sil @simple_generic_caller3 : $@convention(thin) <U> (@in U) -> () |
| 110 | +// CHECK-NOT: specialized |
| 111 | +// CHECK: function_ref @simple_generic_callee : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> () |
| 112 | +// CHECK-NOT: specialized |
| 113 | +// CHECK: // end sil function 'simple_generic_caller3' |
| 114 | +// simple_generic_caller3<A>(_:) |
| 115 | +sil @simple_generic_caller3 : $@convention(thin) <U> (@in U) -> () { |
| 116 | +bb0(%0 : $*U): |
| 117 | + // function_ref simple_generic_callee<A, B>(_:_:) |
| 118 | + %2 = function_ref @simple_generic_callee : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> () |
| 119 | + %3 = alloc_stack $U |
| 120 | + copy_addr %0 to [initialization] %3 : $*U |
| 121 | + %5 = apply %2<U, U>(%3, %0) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> () |
| 122 | + dealloc_stack %3 : $*U |
| 123 | + %7 = tuple () |
| 124 | + return %7 : $() |
| 125 | +} // end sil function 'simple_generic_caller3' |
| 126 | + |
| 127 | +// Check that partial specialization is not peformed for generic type parameters where |
| 128 | +// the substitution contains an open existential. |
| 129 | +// CHECK-LABEL: sil @simple_generic_caller4 : $@convention(thin) (@in P, Builtin.Int1) -> () |
| 130 | +// CHECK: function_ref @_T021simple_generic_calleexBi1_Bi1_Rs_r0_lItiy_Tp5 : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 == Builtin.Int1> (@in τ_0_0, Builtin.Int1) -> () |
| 131 | +// CHECK: // end sil function 'simple_generic_caller4' |
| 132 | +sil @simple_generic_caller4 : $@convention(thin) (@in P, Builtin.Int1) -> () { |
| 133 | +bb0(%0 : $*P, %1: $Builtin.Int1): |
| 134 | + cond_br %1, bb1, bb2 |
| 135 | +bb1: |
| 136 | + %2 = open_existential_addr mutable_access %0 : $*P to $*@opened("1B6851A6-4796-11E6-B7DF-B8E856428C60") P |
| 137 | + %3 = alloc_stack $@opened("1B6851A6-4796-11E6-B7DF-B8E856428C60") P |
| 138 | + copy_addr [take] %2 to [initialization] %3 : $*@opened("1B6851A6-4796-11E6-B7DF-B8E856428C60") P |
| 139 | + %5 = alloc_stack $Builtin.Int1 |
| 140 | + store %1 to %5 : $*Builtin.Int1 |
| 141 | + // function_ref simple_generic_callee<A, B>(_:_:) |
| 142 | + %7 = function_ref @simple_generic_callee : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> () |
| 143 | + %8 = apply %7<@opened("1B6851A6-4796-11E6-B7DF-B8E856428C60") P, Builtin.Int1>(%3, %5) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> () |
| 144 | + dealloc_stack %5 : $*Builtin.Int1 |
| 145 | + destroy_addr %3 : $*@opened("1B6851A6-4796-11E6-B7DF-B8E856428C60") P |
| 146 | + dealloc_stack %3 : $*@opened("1B6851A6-4796-11E6-B7DF-B8E856428C60") P |
| 147 | + br bb3 |
| 148 | +bb2: |
| 149 | + destroy_addr %0 : $*P |
| 150 | + br bb3 |
| 151 | +bb3: |
| 152 | + %13 = tuple () |
| 153 | + return %13 : $() |
| 154 | +} // end sil function 'simple_generic_caller4' |
0 commit comments