Skip to content

Commit 9a61985

Browse files
authored
Merge pull request #32171 from jckarter/vtable-kind-validation
SIL: Verify kinds of vtable entries.
2 parents a813610 + 8538a2a commit 9a61985

24 files changed

+178
-92
lines changed

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,12 @@ bool SILDeclRef::requiresNewVTableEntry() const {
814814
if (derivativeFunctionIdentifier)
815815
if (derivativeFunctionRequiresNewVTableEntry(*this))
816816
return true;
817-
if (cast<AbstractFunctionDecl>(getDecl())->needsNewVTableEntry())
817+
if (!hasDecl())
818+
return false;
819+
auto fnDecl = dyn_cast<AbstractFunctionDecl>(getDecl());
820+
if (!fnDecl)
821+
return false;
822+
if (fnDecl->needsNewVTableEntry())
818823
return true;
819824
return false;
820825
}

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5360,8 +5360,22 @@ void SILProperty::verify(const SILModule &M) const {
53605360
void SILVTable::verify(const SILModule &M) const {
53615361
if (!verificationEnabled(M))
53625362
return;
5363-
5364-
for (auto &entry : getEntries()) {
5363+
5364+
// Compare against the base class vtable if there is one.
5365+
const SILVTable *superVTable = nullptr;
5366+
auto superclass = getClass()->getSuperclassDecl();
5367+
if (superclass) {
5368+
for (auto &vt : M.getVTables()) {
5369+
if (vt.getClass() == superclass) {
5370+
superVTable = &vt;
5371+
break;
5372+
}
5373+
}
5374+
}
5375+
5376+
for (unsigned i : indices(getEntries())) {
5377+
auto &entry = getEntries()[i];
5378+
53655379
// All vtable entries must be decls in a class context.
53665380
assert(entry.Method.hasDecl() && "vtable entry is not a decl");
53675381
auto baseInfo =
@@ -5403,6 +5417,55 @@ void SILVTable::verify(const SILModule &M) const {
54035417
"vtable entry for " + baseName + " must be ABI-compatible",
54045418
*entry.Implementation);
54055419
}
5420+
5421+
// Validate the entry against its superclass vtable.
5422+
if (!superclass) {
5423+
// Root methods should not have inherited or overridden entries.
5424+
bool validKind;
5425+
switch (entry.TheKind) {
5426+
case Entry::Normal:
5427+
case Entry::NormalNonOverridden:
5428+
validKind = true;
5429+
break;
5430+
5431+
case Entry::Inherited:
5432+
case Entry::Override:
5433+
validKind = false;
5434+
break;
5435+
}
5436+
assert(validKind && "vtable entry in root class must not be inherited or override");
5437+
} else if (superVTable) {
5438+
// Validate the entry against the matching entry from the superclass
5439+
// vtable.
5440+
5441+
const Entry *superEntry = nullptr;
5442+
for (auto &se : superVTable->getEntries()) {
5443+
if (se.Method.getOverriddenVTableEntry() == entry.Method.getOverriddenVTableEntry()) {
5444+
superEntry = &se;
5445+
break;
5446+
}
5447+
}
5448+
5449+
switch (entry.TheKind) {
5450+
case Entry::Normal:
5451+
case Entry::NormalNonOverridden:
5452+
assert(!superEntry && "non-root vtable entry must be inherited or override");
5453+
break;
5454+
5455+
case Entry::Inherited:
5456+
break;
5457+
5458+
case Entry::Override:
5459+
if (!superEntry)
5460+
break;
5461+
5462+
// The superclass entry must not prohibit overrides.
5463+
assert(superEntry->TheKind != Entry::NormalNonOverridden
5464+
&& "vtable entry overrides an entry that claims to have no overrides");
5465+
// TODO: Check the root vtable entry for the method too.
5466+
break;
5467+
}
5468+
}
54065469
}
54075470
}
54085471

lib/Sema/TypeCheckDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,10 @@ NeedsNewVTableEntryRequest::evaluate(Evaluator &evaluator,
830830
if (!isa<ClassDecl>(dc))
831831
return true;
832832

833+
// Destructors always use a fixed vtable entry.
834+
if (isa<DestructorDecl>(decl))
835+
return false;
836+
833837
assert(isa<FuncDecl>(decl) || isa<ConstructorDecl>(decl));
834838

835839
// Final members are always be called directly.

test/SIL/Parser/basic.sil

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,11 +1688,22 @@ bb0:
16881688
return %1 : $()
16891689
}
16901690

1691+
class Foo2: Foo {}
1692+
16911693
// CHECK-LABEL: sil_vtable Foo {
1692-
// CHECK: #Foo.subscript!getter: {{.*}} : @Foo_subscript_getter
1693-
// CHECK: #Foo.subscript!setter: {{.*}} : @Foo_subscript_setter [override]
1694+
// CHECK: #Foo.subscript!getter: {{.*}} : @Foo_subscript_getter [nonoverridden]
1695+
// CHECK: #Foo.subscript!setter: {{.*}} : @Foo_subscript_setter
16941696
// CHECK: }
16951697
sil_vtable Foo {
1696-
#Foo.subscript!getter: @Foo_subscript_getter
1698+
#Foo.subscript!getter: @Foo_subscript_getter [nonoverridden]
1699+
#Foo.subscript!setter: @Foo_subscript_setter
1700+
}
1701+
1702+
// CHECK-LABEL: sil_vtable Foo2 {
1703+
// CHECK: #Foo.subscript!getter: {{.*}} : @Foo_subscript_getter [inherited]
1704+
// CHECK: #Foo.subscript!setter: {{.*}} : @Foo_subscript_setter [override]
1705+
// CHECK: }
1706+
sil_vtable Foo2 {
1707+
#Foo.subscript!getter: @Foo_subscript_getter [inherited]
16971708
#Foo.subscript!setter: @Foo_subscript_setter [override]
16981709
}

test/SILOptimizer/basic-callee-printer.sil

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ sil_vtable private_base {
340340
}
341341

342342
sil_vtable private_derived {
343-
#private_base.foo: @private_derived_foo
343+
#private_base.foo: @private_derived_foo [override]
344344
}
345345

346346
sil_vtable internal_base {
@@ -349,8 +349,8 @@ sil_vtable internal_base {
349349
}
350350

351351
sil_vtable internal_derived {
352-
#internal_base.foo: @internal_derived_foo
353-
#internal_base.bar: @internal_derived_bar
352+
#internal_base.foo: @internal_derived_foo [override]
353+
#internal_base.bar: @internal_derived_bar [override]
354354
}
355355

356356
sil_vtable public_base {
@@ -360,9 +360,9 @@ sil_vtable public_base {
360360
}
361361

362362
sil_vtable public_derived {
363-
#public_base.foo: @public_derived_foo
364-
#public_base.bar: @public_derived_bar
365-
#public_base.baz: @public_derived_baz
363+
#public_base.foo: @public_derived_foo [override]
364+
#public_base.bar: @public_derived_bar [override]
365+
#public_base.baz: @public_derived_baz [override]
366366
}
367367

368368
private protocol private_proto_1 {
@@ -659,8 +659,8 @@ sil_vtable SomeItem {
659659
}
660660

661661
sil_vtable SomeChildItem {
662-
#SomeItem.init!allocator: @SomeChildItem_allocator
663-
#SomeItem.init!initializer: @SomeChildItem_initializer
662+
#SomeItem.init!allocator: @SomeChildItem_allocator [override]
663+
#SomeItem.init!initializer: @SomeChildItem_initializer [override]
664664
#SomeChildItem.deinit!deallocator: @SomeChildItem_destructor
665665
}
666666

test/SILOptimizer/dead_func_init_method.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ sil_vtable Base {
3636
}
3737

3838
sil_vtable Derived {
39-
#Base.init!allocator: @DerivedInit
39+
#Base.init!allocator: @DerivedInit [override]
4040
}
4141

4242

test/SILOptimizer/devirt_access.sil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@ sil_vtable X {
151151
}
152152

153153
sil_vtable Y {
154-
#X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si // devirt_access2.X.ping (devirt_access2.X)() -> Swift.Int
155-
#X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ // devirt_access2.Y.init (devirt_access2.Y.Type)() -> devirt_access2.Y
154+
#X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si [inherited]
155+
#X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ [override]
156156
}
157157

158158
sil_vtable A {
@@ -161,6 +161,6 @@ sil_vtable A {
161161
}
162162

163163
sil_vtable B {
164-
#A.ping: @_TFC14devirt_access21B4pingfS0_FT_Si // devirt_access2.B.ping (devirt_access2.B)() -> Swift.Int
165-
#A.init!initializer: @_TFC14devirt_access21BcfMS0_FT_S0_ // devirt_access2.B.init (devirt_access2.B.Type)() -> devirt_access2.B
164+
#A.ping: @_TFC14devirt_access21B4pingfS0_FT_Si [override]
165+
#A.init!initializer: @_TFC14devirt_access21BcfMS0_FT_S0_ [override]
166166
}

test/SILOptimizer/devirt_access_ownership.sil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ sil_vtable X {
147147
}
148148

149149
sil_vtable Y {
150-
#X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si // devirt_access2.X.ping (devirt_access2.X)() -> Swift.Int
151-
#X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ // devirt_access2.Y.init (devirt_access2.Y.Type)() -> devirt_access2.Y
150+
#X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si [inherited]
151+
#X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ [override]
152152
}
153153

154154
sil_vtable A {
@@ -157,6 +157,6 @@ sil_vtable A {
157157
}
158158

159159
sil_vtable B {
160-
#A.ping: @_TFC14devirt_access21B4pingfS0_FT_Si // devirt_access2.B.ping (devirt_access2.B)() -> Swift.Int
161-
#A.init!initializer: @_TFC14devirt_access21BcfMS0_FT_S0_ // devirt_access2.B.init (devirt_access2.B.Type)() -> devirt_access2.B
160+
#A.ping: @_TFC14devirt_access21B4pingfS0_FT_Si [override]
161+
#A.init!initializer: @_TFC14devirt_access21BcfMS0_FT_S0_ [override]
162162
}

test/SILOptimizer/devirt_access_serialized.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,6 @@ sil_vtable X {
5252
}
5353

5454
sil_vtable Y {
55-
#X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si // devirt_access2.X.ping (devirt_access2.X)() -> Swift.Int
56-
#X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ // devirt_access2.Y.init (devirt_access2.Y.Type)() -> devirt_access2.Y
55+
#X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si [inherited]
56+
#X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ [inherited]
5757
}

test/SILOptimizer/devirt_access_serialized_ownership.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,6 @@ sil_vtable X {
5050
}
5151

5252
sil_vtable Y {
53-
#X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si // devirt_access2.X.ping (devirt_access2.X)() -> Swift.Int
54-
#X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ // devirt_access2.Y.init (devirt_access2.Y.Type)() -> devirt_access2.Y
53+
#X.ping: @_TFC14devirt_access21X4pingfS0_FT_Si [inherited]
54+
#X.init!initializer: @_TFC14devirt_access21YcfMS0_FT_S0_ [override]
5555
}

test/SILOptimizer/devirt_override.sil

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class MD5 : Hash {
1616
}
1717

1818

19+
sil @_TFC4test4HashcfMS0_FT_S0_ : $@convention(method) (@owned Hash) -> @owned Hash
20+
1921
sil @_TFC4test3MD5cfMS0_FT_S0_ : $@convention(method) (@owned MD5) -> @owned MD5 {
2022
bb0(%0 : $MD5):
2123
release_value %0 : $MD5
@@ -64,14 +66,15 @@ bb0:
6466
sil_vtable Hash {
6567
#Hash.update: @_TFC9hash2_new4Hash6updatefS0_FT3MsgVs5UInt83CntSi_T_
6668
#Hash.hash: @_TFC4test4Hash4hashfS0_FT3MsgVs5UInt8_T_
69+
#Hash.init!initializer: @_TFC4test4HashcfMS0_FT_S0_
6770
}
6871

6972
sil_vtable MD5 {
7073
// vtable should be keyed with the least-derived method, otherwise
7174
// devirtualizer will choose the wrong function ref.
72-
#Hash.hash: @_TFC4test3MD54hashfS0_FT3MsgVs5UInt8_T_
73-
#MD5.init!initializer: @_TFC4test3MD5cfMS0_FT_S0_
74-
#Hash.update: @_TFC9hash2_new4Hash6updatefS0_FT3MsgVs5UInt83CntSi_T_
75+
#Hash.hash: @_TFC4test3MD54hashfS0_FT3MsgVs5UInt8_T_ [override]
76+
#Hash.init!initializer: @_TFC4test3MD5cfMS0_FT_S0_ [override]
77+
#Hash.update: @_TFC9hash2_new4Hash6updatefS0_FT3MsgVs5UInt83CntSi_T_ [override]
7578
}
7679

7780
class C {
@@ -127,9 +130,9 @@ sil_vtable C {
127130
}
128131

129132
sil_vtable D {
130-
#C.doIt: @_TFC1b1D4doItfS0_FT_T_
133+
#C.doIt: @_TFC1b1D4doItfS0_FT_T_ [override]
131134
}
132135

133136
sil_vtable E {
134-
#C.doIt: @_TFC1b1E4doItfS0_FT_T_
137+
#C.doIt: @_TFC1b1E4doItfS0_FT_T_ [override]
135138
}

test/SILOptimizer/devirt_override_ownership.sil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ sil_vtable Hash {
7070
sil_vtable MD5 {
7171
// vtable should be keyed with the least-derived method, otherwise
7272
// devirtualizer will choose the wrong function ref.
73-
#Hash.hash: @_TFC4test3MD54hashfS0_FT3MsgVs5UInt8_T_
73+
#Hash.hash: @_TFC4test3MD54hashfS0_FT3MsgVs5UInt8_T_ [override]
7474
#MD5.init!initializer: @_TFC4test3MD5cfMS0_FT_S0_
75-
#Hash.update: @_TFC9hash2_new4Hash6updatefS0_FT3MsgVs5UInt83CntSi_T_
75+
#Hash.update: @_TFC9hash2_new4Hash6updatefS0_FT3MsgVs5UInt83CntSi_T_ [override]
7676
}
7777

7878
class C {
@@ -129,9 +129,9 @@ sil_vtable C {
129129
}
130130

131131
sil_vtable D {
132-
#C.doIt: @_TFC1b1D4doItfS0_FT_T_
132+
#C.doIt: @_TFC1b1D4doItfS0_FT_T_ [override]
133133
}
134134

135135
sil_vtable E {
136-
#C.doIt: @_TFC1b1E4doItfS0_FT_T_
136+
#C.doIt: @_TFC1b1E4doItfS0_FT_T_ [override]
137137
}

test/SILOptimizer/devirt_speculative.sil

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ sil_vtable Base {
4141
}
4242

4343
sil_vtable Sub {
44-
#Base.foo: @_TSubFooFun
45-
#Base.exit: @Sub_exit
44+
#Base.foo: @_TSubFooFun [override]
45+
#Base.exit: @Sub_exit [override]
4646
}
4747

4848
sil @test_objc_ancestry : $@convention(thin) (@guaranteed Base) -> () {
@@ -97,7 +97,7 @@ sil_vtable Base2 {
9797
}
9898

9999
sil_vtable Sub2 {
100-
#Base2.foo: @_TSub2FooFun
100+
#Base2.foo: @_TSub2FooFun [override]
101101
}
102102

103103
sil @test_objc_ancestry2 : $@convention(thin) (@guaranteed Base2) -> () {

test/SILOptimizer/devirt_try_apply.sil

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -848,43 +848,43 @@ sil_vtable D1 {
848848
}
849849

850850
sil_vtable D3 {
851-
#D1.f1: @_TFC16devirt_try_apply2D32f1fzT_CS_1A// devirt_try_apply.D3.f1 () throws -> devirt_try_apply.A
851+
#D1.f1: @_TFC16devirt_try_apply2D32f1fzT_CS_1A [override] // devirt_try_apply.D3.f1 () throws -> devirt_try_apply.A
852852
}
853853

854854

855855
sil_vtable Base {
856856
#Base.foo: @_TFC16devirt_try_apply4Base3foofS0_FzT_GSqVs5Int32_
857857
#Base.boo1: @_TFC16devirt_try_apply4Base4boo1fS0_FzT_S0_
858858
#Base.boo2: @_TFC16devirt_try_apply4Base4boo2fS0_FzT_GSqS0__
859-
#Base.deinit!deallocator: @_TFC16devirt_try_apply4BaseD
860859
#Base.init!initializer: @_TFC16devirt_try_apply4BasecfMS0_FT_S0_
860+
#Base.deinit!deallocator: @_TFC16devirt_try_apply4BaseD
861861
}
862862

863863
sil_vtable Derived1 {
864-
#Base.foo: @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_
865-
#Base.boo1: @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_
866-
#Base.boo2: @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__
867-
#Base.init!initializer: @_TFC16devirt_try_apply8Derived1cfMS0_FT_S0_
864+
#Base.foo: @_TFC16devirt_try_apply8Derived13foofS0_FzT_GSqVs5Int32_ [override]
865+
#Base.boo1: @_TFC16devirt_try_apply8Derived14boo1fS0_FzT_S0_ [override]
866+
#Base.boo2: @_TFC16devirt_try_apply8Derived14boo2fS0_FzT_GSqS0__ [override]
867+
#Base.init!initializer: @_TFC16devirt_try_apply8Derived1cfMS0_FT_S0_ [override]
868868
#Derived1.deinit!deallocator: @_TFC16devirt_try_apply8Derived1D
869869
}
870870

871871
sil_vtable Derived2 {
872-
#Base.foo: @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32
873-
#Base.boo1: @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_
874-
#Base.boo2: @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_
875-
#Base.init!initializer: @_TFC16devirt_try_apply8Derived2cfMS0_FT_S0_
872+
#Base.foo: @_TTVFC16devirt_try_apply8Derived23foofS0_FzT_Vs5Int32 [override]
873+
#Base.boo1: @_TFC16devirt_try_apply8Derived24boo1fS0_FzT_S0_ [override]
874+
#Base.boo2: @_TFC16devirt_try_apply8Derived24boo2fS0_FzT_S0_ [override]
875+
#Base.init!initializer: @_TFC16devirt_try_apply8Derived2cfMS0_FT_S0_ [override]
876876
#Derived2.deinit!deallocator: @_TFC16devirt_try_apply8Derived2D
877877
}
878878

879879
sil_vtable CP1 {
880880
#CP1.foo: @_TFC16devirt_try_apply3CP13foofS0_FzT_Vs5Int32
881-
#CP1.deinit!deallocator: @_TFC16devirt_try_apply3CP1D
882881
#CP1.init!initializer: @_TFC16devirt_try_apply3CP1cfMS0_FT_S0_
882+
#CP1.deinit!deallocator: @_TFC16devirt_try_apply3CP1D
883883
}
884884

885885
sil_vtable CP2 {
886-
#CP1.foo: @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32
887-
#CP1.init!initializer: @_TFC16devirt_try_apply3CP2cfMS0_FT_S0_
886+
#CP1.foo: @_TFC16devirt_try_apply3CP23foofS0_FzT_Vs5Int32 [override]
887+
#CP1.init!initializer: @_TFC16devirt_try_apply3CP2cfMS0_FT_S0_ [override]
888888
#CP2.deinit!deallocator: @_TFC16devirt_try_apply3CP2D
889889
}
890890

0 commit comments

Comments
 (0)