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
}

0 commit comments

Comments
 (0)