Skip to content

Commit 58e2b0d

Browse files
committed
IRGen: Use the static superclass for virtual dynamic dispatch
Following the self instance pointer to its class metadata isn't sound for chained super calls since it means the same metadata is pulled, resulting infinite recursion. NFC for actual IRGen. SILGen isn't using super_method for native dispatch yet. rdar://problem/22749732
1 parent 7dd3046 commit 58e2b0d

File tree

3 files changed

+23
-23
lines changed

3 files changed

+23
-23
lines changed

lib/IRGen/GenMeta.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4309,18 +4309,22 @@ llvm::Value *irgen::emitVirtualMethodValue(IRGenFunction &IGF,
43094309

43104310
// Find the metadata.
43114311
llvm::Value *metadata;
4312-
if ((isa<FuncDecl>(methodDecl) && cast<FuncDecl>(methodDecl)->isStatic()) ||
4313-
(isa<ConstructorDecl>(methodDecl) &&
4314-
method.kind == SILDeclRef::Kind::Allocator)) {
4315-
metadata = base;
4316-
} else {
4317-
metadata = emitHeapMetadataRefForHeapObject(IGF, base, baseType,
4318-
/*suppress cast*/ true);
4319-
}
4320-
43214312
if (useSuperVTable) {
4322-
auto superField = emitAddressOfSuperclassRefInClassMetadata(IGF, metadata);
4323-
metadata = IGF.Builder.CreateLoad(superField);
4313+
if (auto metaTy = dyn_cast<MetatypeType>(baseType.getSwiftRValueType()))
4314+
baseType = SILType::getPrimitiveObjectType(metaTy.getInstanceType());
4315+
4316+
auto superType = baseType.getSuperclass(/*resolver=*/nullptr);
4317+
metadata = emitClassHeapMetadataRef(IGF, superType.getSwiftRValueType(),
4318+
MetadataValueType::TypeMetadata);
4319+
} else {
4320+
if ((isa<FuncDecl>(methodDecl) && cast<FuncDecl>(methodDecl)->isStatic()) ||
4321+
(isa<ConstructorDecl>(methodDecl) &&
4322+
method.kind == SILDeclRef::Kind::Allocator)) {
4323+
metadata = base;
4324+
} else {
4325+
metadata = emitHeapMetadataRefForHeapObject(IGF, base, baseType,
4326+
/*suppress cast*/ true);
4327+
}
43244328
}
43254329

43264330
// Use the type of the method we were type-checked against, not the

test/IRGen/super_class_method.sil

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,9 @@ sil_vtable Grandchild {
4949
}
5050

5151
// CHECK-LABEL: define void @Grandchild_foo(%swift.type*) #0
52-
// CHECK: [[OPAQUE_GRANDCHILD:%[0-9]+]] = bitcast %swift.type* %0 to %swift.type**
53-
// CHECK: [[SUPER_METADATA_PTR:%[0-9]+]] = getelementptr inbounds %swift.type*, %swift.type** [[OPAQUE_GRANDCHILD]], i32 1
54-
// CHECK: [[SUPER_METADATA:%[0-9]+]] = load %swift.type*, %swift.type** [[SUPER_METADATA_PTR]]
55-
// CHECK: [[FOO_VTABLE_SLOT:%[0-9]+]] = getelementptr inbounds void (%swift.type*)*, void (%swift.type*)**
52+
// CHECK: [[CHILD_METADATA_PTR:%[0-9]+]] = call %swift.type* @_TMaC18super_class_method5Child()
53+
// CHECK: [[CASTED_CHILD_METADATA_PTR:%[0-9]+]] = bitcast %swift.type* [[CHILD_METADATA_PTR]] to void (%swift.type*)**
54+
// CHECK: [[FOO_VTABLE_SLOT:%[0-9]+]] = getelementptr inbounds void (%swift.type*)*, void (%swift.type*)** [[CASTED_CHILD_METADATA_PTR]]
5655
// CHECK: [[FOO_FNPTR:%[0-9]+]] = load void (%swift.type*)*, void (%swift.type*)** [[FOO_VTABLE_SLOT]]
5756
// CHECK: call void
5857

test/IRGen/super_instance_method.sil

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,10 @@ sil_vtable Grandchild {
4848
#Parent.foo!1: Grandchild_foo
4949
}
5050

51-
// CHECK: define void @Grandchild_foo(%C21super_instance_method10Grandchild*)
52-
// CHECK: [[OPAQUE_GRANDCHILD:%[0-9]+]] = bitcast %C21super_instance_method10Grandchild* %0 to %swift.type**
53-
// CHECK: [[GRANDCHILD_METADATA:%\..*]] = load %swift.type*, %swift.type** [[OPAQUE_GRANDCHILD]]
54-
// CHECK: [[OPAQUE_METADATA:%[0-9]+]] = bitcast %swift.type* [[GRANDCHILD_METADATA]] to %swift.type**
55-
// CHECK: [[SUPER_METADATA_PTR:%[0-9]+]] = getelementptr inbounds %swift.type*, %swift.type** [[OPAQUE_METADATA]], i32 1
56-
// CHECK: [[SUPER_METADATA:%[0-9]+]] = load %swift.type*, %swift.type** [[SUPER_METADATA_PTR]]
57-
// CHECK: [[FOO_VTABLE_SLOT:%[0-9]+]] = getelementptr inbounds void (%C21super_instance_method6Parent*)*, void (%C21super_instance_method6Parent*)**
58-
// CHECK: [[FOO_FNPTR:%[0-9]+]] = load void (%C21super_instance_method6Parent*)*, void (%C21super_instance_method6Parent*)** [[FOO_VTABLE_SLOT]]
51+
// CHECK-LABEL: define void @Grandchild_foo(%C21super_instance_method10Grandchild*)
52+
// CHECK: [[CHILD_METADATA_PTR:%[0-9]+]] = call %swift.type* @_TMaC21super_instance_method5Child()
53+
// CHECK: [[CASTED_CHILD_METADATA_PTR:%[0-9]+]] = bitcast %swift.type* [[CHILD_METADATA_PTR]] to void (%C21super_instance_method6Parent*)**
54+
// CHECK: [[FOO_VTABLE_SLOT:%[0-9]+]] = getelementptr inbounds void (%C21super_instance_method6Parent*)*, void (%C21super_instance_method6Parent*)** [[CASTED_CHILD_METADATA_PTR]]
55+
// CHECK: [[FOO_FN_PTR:%[0-9]+]] = load void (%C21super_instance_method6Parent*)*, void (%C21super_instance_method6Parent*)** [[FOO_VTABLE_SLOT]]
5956
// CHECK: call void
6057

0 commit comments

Comments
 (0)