3
3
sil_stage canonical
4
4
5
5
import Builtin
6
+ import Swift
6
7
7
8
@objc class MyNSObject {}
8
9
private class Base : MyNSObject {
9
10
override init()
10
11
@inline(never) func foo()
12
+ @inline(never) func exit() -> Never
11
13
}
12
14
13
15
private class Sub : Base {
14
16
override init()
15
17
@inline(never) override func foo()
18
+ @inline(never) override func exit() -> Never
16
19
}
17
20
18
21
sil private [noinline] @_TBaseFooFun : $@convention(method) (@guaranteed Base) -> () {
@@ -27,12 +30,19 @@ bb0(%0 : $Sub):
27
30
return %1 : $()
28
31
}
29
32
33
+
34
+ sil @Base_exit : $@convention(method) (@guaranteed Base) -> Never
35
+
36
+ sil @Sub_exit : $@convention(method) (@guaranteed Sub) -> Never
37
+
30
38
sil_vtable Base {
31
39
#Base.foo!1: _TBaseFooFun
40
+ #Base.exit!1: Base_exit
32
41
}
33
42
34
43
sil_vtable Sub {
35
44
#Base.foo!1: _TSubFooFun
45
+ #Base.exit!1: Sub_exit
36
46
}
37
47
38
48
sil @test_objc_ancestry : $@convention(thin) (@guaranteed Base) -> () {
@@ -124,3 +134,23 @@ bb0(%0: $Base2):
124
134
%3 = tuple()
125
135
return %3 : $()
126
136
}
137
+
138
+ // Check that NoReturn functions are devirtualized properly.
139
+ // The new apply should be followed by an unreachable instruction
140
+ // instead of a branch instruction.
141
+ // CHECK-LABEL: sil{{.*}}test_devirt_of_noreturn_function
142
+ // CHECK: checked_cast_br
143
+ // CHECK: function_ref @Base_exit
144
+ // CHECK-NEXT: apply
145
+ // CHECK-NEXT: unreachable
146
+ // CHECK: checked_cast_br
147
+ // CHECK: function_ref @Sub_exit
148
+ // CHECK-NEXT: apply
149
+ // CHECK-NEXT: unreachable
150
+ sil hidden [noinline] @test_devirt_of_noreturn_function : $@convention(thin) (@owned Base) -> () {
151
+ bb0(%0 : $Base):
152
+ %2 = class_method %0 : $Base, #Base.exit!1 : (Base) -> () -> Never, $@convention(method) (@guaranteed Base) -> Never
153
+ %3 = apply %2(%0) : $@convention(method) (@guaranteed Base) -> Never
154
+ unreachable
155
+ }
156
+
0 commit comments