Skip to content

Commit 09c6210

Browse files
committed
SILGen: Use vtable thunk abstraction for super_method instructions
The constant provided to the callee for super methods reference the backing implementation, but the vtable entry may point to a thunk with different abstraction when using mixed concrete and generic classes in the hierarchy. The SIL devirtualizer expects super method references to match what's in the vtable. Also update the verifier for SuperMethodInst types - before it required that the types be the same, but they may not be for the same reasons noted above. Instead, do a similar check as for ClassMethodInst. https://bugs.swift.org/browse/SR-134
1 parent 1f8397b commit 09c6210

File tree

4 files changed

+75
-10
lines changed

4 files changed

+75
-10
lines changed

lib/SIL/Verifier.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,8 +1686,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
16861686
}
16871687

16881688
void checkSuperMethodInst(SuperMethodInst *CMI) {
1689-
require(CMI->getType() == TC.getConstantType(CMI->getMember()),
1690-
"result type of super_method must match type of method");
1689+
auto overrideTy = TC.getConstantOverrideType(CMI->getMember());
1690+
requireSameType(CMI->getType(), SILType::getPrimitiveObjectType(overrideTy),
1691+
"result type of super_method must match abstracted type of method");
16911692
auto methodType = requireObjectType(SILFunctionType, CMI,
16921693
"result of super_method");
16931694
require(!methodType->getExtInfo().hasContext(),

lib/SILGen/SILGenApply.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -593,13 +593,15 @@ class Callee {
593593
constant = Constant.atUncurryLevel(level);
594594
constantInfo = gen.getConstantInfo(*constant);
595595

596-
SILValue methodVal = gen.B.createSuperMethod(Loc,
597-
SelfValue,
598-
*constant,
599-
constantInfo.getSILType(),
600-
/*volatile*/
601-
constant->isForeign);
602-
596+
if (SILDeclRef baseConstant = Constant.getOverriddenVTableEntry())
597+
constantInfo = gen.SGM.Types.getConstantOverrideInfo(Constant,
598+
baseConstant);
599+
auto methodVal = gen.B.createSuperMethod(Loc,
600+
SelfValue,
601+
*constant,
602+
constantInfo.getSILType(),
603+
/*volatile*/
604+
constant->isForeign);
603605
mv = ManagedValue::forUnmanaged(methodVal);
604606
break;
605607
}

test/IRGen/concrete_inherits_generic_base.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -module-name foo -emit-ir %s | FileCheck %s
1+
// RUN: %target-swift-frontend -use-native-super-method -module-name foo -emit-ir %s | FileCheck %s
22

33
// -- Classes with generic bases can't go in the @objc_classes list, since
44
// they need runtime initialization before they're valid.

test/SILPasses/super_method.swift

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,65 @@ class Grandchild : Child {
2828
super.foo()
2929
}
3030
}
31+
32+
class GenericParent<A> {
33+
let a: A
34+
init(a: A) {
35+
self.a = a
36+
}
37+
38+
func onlyInParent() {}
39+
40+
@inline(never)
41+
final func finalOnlyInParent() {}
42+
43+
@inline(never)
44+
func method() {}
45+
46+
@inline(never)
47+
class func classMethod() {}
48+
}
49+
50+
class GenericChild<A> : GenericParent<A> {}
51+
52+
class GenericGrandchild<A> : GenericChild<A> {
53+
// CHECK-LABEL: sil hidden @_TFC12super_method17GenericGrandchild16onlyInGrandchildfT_T_ : $@convention(method) <A> (@guaranteed GenericGrandchild<A>) -> ()
54+
func onlyInGrandchild() {
55+
// CHECK: super_method {{%[0-9+]}} : $GenericGrandchild<A>, #GenericParent.onlyInParent!1 : <A> GenericParent<A> -> () -> () , $@convention(method) <τ_0_0> (@guaranteed GenericParent<τ_0_0>) -> ()
56+
super.onlyInParent()
57+
// CHECK: function_ref @_TFC12super_method13GenericParent17finalOnlyInParentfT_T_ : $@convention(method) <τ_0_0> (@guaranteed GenericParent<τ_0_0>) -> ()
58+
super.finalOnlyInParent()
59+
}
60+
// CHECK-LABEL: sil hidden @_TFC12super_method17GenericGrandchild6methodfT_T_ : $@convention(method) <A> (@guaranteed GenericGrandchild<A>) -> ()
61+
override func method() {
62+
// CHECK: super_method {{%[0-9]+}} : $GenericGrandchild<A>, #GenericParent.method!1 : <A> GenericParent<A> -> () -> () , $@convention(method) <τ_0_0> (@guaranteed GenericParent<τ_0_0>) -> ()
63+
super.method()
64+
}
65+
}
66+
67+
class ConcreteChild : GenericParent<String> {
68+
// CHECK-LABEL: sil hidden @_TFC12super_method13ConcreteChildcfT1aSS_S0_ : $@convention(method) (@owned String, @owned ConcreteChild) -> @owned ConcreteChild
69+
override init(a: String) {
70+
// CHECK-NOT: super_method {{%[0-9]+}} : $ConcreteChild, #GenericParent.init!initializer.1
71+
// CHECK: [[INIT_FN_REF:%[0-9]+]] = function_ref @_TFC12super_method13GenericParentcfT1ax_GS0_x_ : $@convention(method) <τ_0_0> (@in τ_0_0, @owned GenericParent<τ_0_0>) -> @owned GenericParent<τ_0_0> // user: %10
72+
// CHECK-NEXT: apply [[INIT_FN_REF]]
73+
super.init(a: a)
74+
}
75+
}
76+
77+
class ConcreteGrandchild : ConcreteChild {
78+
// CHECK-LABEL: sil hidden @_TFC12super_method18ConcreteGrandchild16onlyInGrandchildfT_T_ : $@convention(method) (@guaranteed ConcreteGrandchild) -> ()
79+
func onlyInGrandchild() {
80+
// CHECK-NOT: super_method {{%[0-9]+}} : $ConcreteGrandchild, #GenericParent.onlyInParent!1
81+
// CHECK: function_ref @_TFC12super_method13GenericParent12onlyInParentfT_T_ : $@convention(method) <τ_0_0> (@guaranteed GenericParent<τ_0_0>) -> ()
82+
super.onlyInParent()
83+
// CHECK: function_ref @_TFC12super_method13GenericParent17finalOnlyInParentfT_T_ : $@convention(method) <τ_0_0> (@guaranteed GenericParent<τ_0_0>) -> ()
84+
super.finalOnlyInParent()
85+
}
86+
// CHECK-LABEL: sil hidden @_TFC12super_method18ConcreteGrandchild6methodfT_T_ : $@convention(method) (@guaranteed ConcreteGrandchild) -> ()
87+
override func method() {
88+
// CHECK-NOT: super_method {{%[0-9]+}} : $ConcreteGrandchild, #GenericParent.method!1
89+
// CHECK: function_ref @_TFC12super_method13GenericParent6methodfT_T_ : $@convention(method) <τ_0_0> (@guaranteed GenericParent<τ_0_0>) -> ()
90+
super.method()
91+
}
92+
}

0 commit comments

Comments
 (0)