1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
// RUN: %target-swift-frontend -Xllvm -sil-inline-generics -emit-sorted-sil -emit-sil -enable-spec-devirt -O %s | %FileCheck %s
// We used to crash on this when trying to devirtualize t.boo(a, 1),
// because it is an "apply" with replacement types that contain
// archetypes, and the devirtualizer was not able to handle that
// case correctly.
//
// rdar://19912272
protocol P {
associatedtype Node
}
class C<T:P> {
typealias Node = T.Node
func foo(_ n:Node) {
}
func boo<S>(_ n:Node, s:S) {
}
}
func test1<T>(_ t:C<T>, a: T.Node) {
t.boo(a, s:1)
}
class Base<T> {
func foo() {
}
class func boo() {
}
}
class Derived<T> : Base<T> {
override func foo() {
}
override class func boo() {
}
}
// Check that testDevirt is specialized and uses speculative devirtualization.
// CHECK-LABEL: sil shared [noinline] @{{.*}}testDevirt
// CHECK: checked_cast_br [exact] CC<Int32> in %{{.*}} : $CC<Int32> to CC<Int32>
// CHECK: class_method
// CHECK: }
@inline(never)
public func testDevirt<T>(_ c: CC<T>) -> T? {
return c.next()
}
// Check that the instance method Derived<T>.foo can be devirtualized, because Derived.foo is an internal function,
// Derived has no subclasses and it is a WMO compilation.
// CHECK-LABEL: sil shared [noinline] @$s22devirt_unbound_generic5test2yyAA7DerivedCyxGlFTf4d_n
// CHECK-NOT: class_method
// CHECK-NOT: witness_method
// CHECK-NOT: apply
// CHECK: return
// CHECK: end sil function '$s22devirt_unbound_generic5test2yyAA7DerivedCyxGlFTf4d_n'
@inline(never)
func test2<T>(_ d: Derived<T>) {
d.foo()
}
public func doTest2<T>(_ t:T) {
test2(Derived<T>())
}
// Check that the class method Derived<T>.boo can be devirtualized, because Derived.boo is an internal function,
// Derived has no subclasses and it is a WMO compilation.
// CHECK: sil shared [noinline] @$s22devirt_unbound_generic5test3yyAA7DerivedCyxGlFTf4d_n
// CHECK-NOT: class_method
// CHECK-NOT: witness_method
// CHECK-NOT: apply
// CHECK: return
// CHECK: end sil function '$s22devirt_unbound_generic5test3yyAA7DerivedCyxGlFTf4d_n'
@inline(never)
func test3<T>(_ d: Derived<T>) {
type(of: d).boo()
}
public func doTest3<T>(_ t:T) {
test3(Derived<T>())
}
public protocol ProtocolWithAssocType {
associatedtype Element
}
private class CP<Base: ProtocolWithAssocType> {
var value: Base.Element
init(_ v: Base.Element) {
value = v
}
func getCount() -> Int32 {
return 1
}
}
private class Base1: ProtocolWithAssocType {
typealias Element = Int32
}
private class Base2<T>: ProtocolWithAssocType {
typealias Element = Int32
}
private class CP2: CP<Base2<Int>> {
init() {
super.init(1)
}
override func getCount() -> Int32 {
return 2
}
}
private class CP3: CP<Base2<Int>> {
init() {
super.init(1)
}
override func getCount() -> Int32 {
return 3
}
}
public class CC<CT> {
func next() -> CT? {
return nil
}
}
public protocol QQ {
associatedtype Base: PP
}
public protocol PP {
associatedtype Element
}
internal class D<DT: QQ> : CC<DT.Base.Element> {
override func next() -> DT.Base.Element? {
return nil
}
}
public struct S: PP {
public typealias Element = Int32
}
final public class E: QQ {
public typealias Base = S
}
// Check that c.next() inside test4 gets completely devirtualized.
// CHECK-LABEL: sil @{{.*}}test4{{.*}}
// CHECK-NOT: class_method
// CHECK: return
public func test4() -> Int32? {
let c: CC<Int32> = D<E>();
return c.next()
}
public func test5() -> Int32? {
return testDevirt(D<E>())
}
// The compiler used to crash on this code, because of
// generic types involved in the devirtualization.
//
// rdar://25891588
//
// CHECK-LABEL: sil private [noinline] {{.*}}@{{.*}}test6
// CHECK-NOT: class_method
// CHECK-NOT: checked_cast_br
// CHECK-NOT: class_method
// CHECK: }
@inline(never)
private func test6<T: ProtocolWithAssocType>(_ c: CP<T>) -> T.Element {
return c.value
}
public func doTest6() {
test6(CP<Base1>(1))
}
// CHECK-LABEL: sil private [noinline] @{{.*}}test7
// CHECK-NOT: class_method
// CHECK: checked_cast_br
// CHECK-NOT: class_method
// CHECK: }
@inline(never)
private func test7<T: ProtocolWithAssocType>(_ c: CP<T>) -> Int32 {
return c.getCount()
}
public func doTest7() {
test7(CP2())
}
|