Skip to content

Commit 0dc7dd5

Browse files
committed
VTableSpecializer: make sure to specialize tables of superclasses
Fixes an IRGen crash if a superclass of a class is generic and not used otherwise. rdar://122405558
1 parent 6e8b80c commit 0dc7dd5

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

lib/SILOptimizer/Transforms/VTableSpecializer.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ namespace {
3838

3939
class VTableSpecializer : public SILModuleTransform {
4040
bool specializeVTables(SILModule &module);
41+
bool specializeVTablesOfSuperclasses(SILModule &module);
4142

4243
/// The entry point to the transformation.
4344
void run() override {
@@ -85,9 +86,11 @@ static bool specializeVTablesInFunction(SILFunction &func, SILModule &module,
8586
bool VTableSpecializer::specializeVTables(SILModule &module) {
8687
bool changed = false;
8788
for (SILFunction &func : module) {
88-
specializeVTablesInFunction(func, module, this);
89+
changed |= specializeVTablesInFunction(func, module, this);
8990
}
9091

92+
changed |= specializeVTablesOfSuperclasses(module);
93+
9194
for (SILVTable *vtable : module.getVTables()) {
9295
if (vtable->getClass()->isGenericContext()) continue;
9396

@@ -112,6 +115,28 @@ bool VTableSpecializer::specializeVTables(SILModule &module) {
112115
return changed;
113116
}
114117

118+
bool VTableSpecializer::specializeVTablesOfSuperclasses(SILModule &module) {
119+
bool changed = false;
120+
// The module's vtable table can grow while we are specializing superclass vtables.
121+
for (unsigned i = 0; i < module.getVTables().size(); ++i) {
122+
SILVTable *vtable = module.getVTables()[i];
123+
if (vtable->getClass()->isGenericContext() && !vtable->getClassType())
124+
continue;
125+
126+
SILType superClassTy;
127+
if (SILType classTy = vtable->getClassType()) {
128+
superClassTy = classTy.getSuperclass();
129+
} else {
130+
if (Type superTy = vtable->getClass()->getSuperclass())
131+
superClassTy = SILType::getPrimitiveObjectType(superTy->getCanonicalType());
132+
}
133+
if (superClassTy) {
134+
changed |= (specializeVTableForType(superClassTy, module, this) != nullptr);
135+
}
136+
}
137+
return changed;
138+
}
139+
115140
SILVTable *swift::specializeVTableForType(SILType classTy, SILModule &module,
116141
SILTransform *transform) {
117142
CanType astType = classTy.getASTType();

test/embedded/generic-classes.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,31 @@ func makeItFoo<F: Fooable>(f: F) {
2222
f.foo()
2323
}
2424

25+
class BaseClass<A> {
26+
func test() {}
27+
}
28+
29+
class SubClass1<B>: BaseClass<Int> {
30+
override func test() {}
31+
}
32+
33+
class SubClass2 : SubClass1<Int> {
34+
override func test() { print("SubClass2") }
35+
}
36+
2537
@main
2638
struct Main {
2739
static func main() {
2840
let f = GenericFooableClass<Int>()
2941
makeItFoo(f: f)
3042
let g: GenericFooableClass = GenericFooableSubClass<Int>()
3143
makeItFoo(f: g)
44+
let x = SubClass2()
45+
x.test()
3246
}
3347
}
3448

3549
// CHECK: GenericFooableClass<T>.foo
3650
// CHECK: GenericFooableSubClass<T>.foo
51+
// CHECK: SubClass2
3752

0 commit comments

Comments
 (0)