Skip to content

Commit b33bb38

Browse files
committed
IRGen: fix the superclass pointer for generic classes in embedded swift
fixes in IRGen crash
1 parent d6e86a8 commit b33bb38

File tree

3 files changed

+59
-1
lines changed

3 files changed

+59
-1
lines changed

lib/IRGen/ClassMetadataVisitor.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@ template <class Impl> class ClassMetadataVisitor
6767
: super(IGM), Target(target), VTable(vtable) {}
6868

6969
public:
70+
71+
// Layout in embedded mode while considering the class type.
72+
// This is important for adding the right superclass pointer.
73+
// The regular `layout` method can be used for layout tasks for which the
74+
// actual superclass pointer is not relevant.
75+
void layoutEmbedded(CanType classTy) {
76+
asImpl().noteAddressPoint();
77+
asImpl().addEmbeddedSuperclass(classTy);
78+
asImpl().addDestructorFunction();
79+
addEmbeddedClassMembers(Target);
80+
}
81+
7082
void layout() {
7183
static_assert(MetadataAdjustmentIndex::Class == 3,
7284
"Adjustment index must be synchronized with this layout");

lib/IRGen/GenMeta.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3903,6 +3903,16 @@ namespace {
39033903
llvm_unreachable("covered switch");
39043904
}
39053905

3906+
void addEmbeddedSuperclass(CanType classTy) {
3907+
CanType superclass = asImpl().getSuperclassTypeForMetadata();
3908+
if (!superclass) {
3909+
B.addNullPointer(IGM.TypeMetadataPtrTy);
3910+
return;
3911+
}
3912+
CanType superTy = classTy->getSuperclass()->getCanonicalType();
3913+
B.add(IGM.getAddrOfTypeMetadata(superTy));
3914+
}
3915+
39063916
void addSuperclass() {
39073917
if (asImpl().shouldAddNullSuperclass()) {
39083918
B.addNullPointer(IGM.TypeMetadataPtrTy);
@@ -5025,7 +5035,7 @@ static void emitEmbeddedVTable(IRGenModule &IGM, CanType classTy,
50255035

50265036
FixedClassMetadataBuilder builder(IGM, classDecl, init, fragileLayout,
50275037
vtable);
5028-
builder.layout();
5038+
builder.layoutEmbedded(classTy);
50295039
bool canBeConstant = builder.canBeConstant();
50305040

50315041
StringRef section{};

test/embedded/generic-classes.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %target-run-simple-swift(%S/Inputs/print.swift -enable-experimental-feature Embedded -parse-as-library -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s
2+
3+
// REQUIRES: executable_test
4+
// REQUIRES: optimized_stdlib
5+
// REQUIRES: VENDOR=apple
6+
// REQUIRES: OS=macosx
7+
8+
protocol Fooable {
9+
func foo()
10+
}
11+
12+
class GenericFooableClass<T>: Fooable {
13+
func foo() { print("GenericFooableClass<T>.foo") }
14+
}
15+
16+
class GenericFooableSubClass<T>: GenericFooableClass<T> {
17+
override func foo() { print("GenericFooableSubClass<T>.foo") }
18+
}
19+
20+
func makeItFoo<F: Fooable>(f: F) {
21+
f.foo()
22+
}
23+
24+
@main
25+
struct Main {
26+
static func main() {
27+
let f = GenericFooableClass<Int>()
28+
makeItFoo(f: f)
29+
let g: GenericFooableClass = GenericFooableSubClass<Int>()
30+
makeItFoo(f: g)
31+
}
32+
}
33+
34+
// CHECK: GenericFooableClass<T>.foo
35+
// CHECK: GenericFooableSubClass<T>.foo
36+

0 commit comments

Comments
 (0)