Skip to content

Commit 910ca17

Browse files
authored
Merge pull request swiftlang#63583 from hyp/eng/vtable3
[interop][SwiftToCxx] use vtable offset/thunk to dispatch class property and subscript accessors
2 parents babaa4b + b63577d commit 910ca17

File tree

6 files changed

+278
-17
lines changed

6 files changed

+278
-17
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,13 +1013,13 @@ class DeclAndTypePrinter::Implementation
10131013
declPrinter.printCxxSubscriptAccessorMethod(
10141014
typeDeclContext, accessor, funcABI->getSignature(),
10151015
funcABI->getSymbolName(), resultTy,
1016-
/*isDefinition=*/false);
1016+
/*isDefinition=*/false, dispatchInfo);
10171017
else
10181018
declPrinter.printCxxPropertyAccessorMethod(
10191019
typeDeclContext, accessor, funcABI->getSignature(),
10201020
funcABI->getSymbolName(), resultTy,
10211021
/*isStatic=*/isClassMethod,
1022-
/*isDefinition=*/false);
1022+
/*isDefinition=*/false, dispatchInfo);
10231023
} else {
10241024
declPrinter.printCxxMethod(typeDeclContext, AFD,
10251025
funcABI->getSignature(),
@@ -1037,13 +1037,14 @@ class DeclAndTypePrinter::Implementation
10371037
if (SD)
10381038
defPrinter.printCxxSubscriptAccessorMethod(
10391039
typeDeclContext, accessor, funcABI->getSignature(),
1040-
funcABI->getSymbolName(), resultTy, /*isDefinition=*/true);
1040+
funcABI->getSymbolName(), resultTy, /*isDefinition=*/true,
1041+
dispatchInfo);
10411042
else
10421043
defPrinter.printCxxPropertyAccessorMethod(
10431044
typeDeclContext, accessor, funcABI->getSignature(),
10441045
funcABI->getSymbolName(), resultTy,
10451046
/*isStatic=*/isClassMethod,
1046-
/*isDefinition=*/true);
1047+
/*isDefinition=*/true, dispatchInfo);
10471048
} else {
10481049
defPrinter.printCxxMethod(typeDeclContext, AFD, funcABI->getSignature(),
10491050
funcABI->getSymbolName(), resultTy,

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,7 +1425,8 @@ static std::string remapPropertyName(const AccessorDecl *accessor,
14251425
void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
14261426
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
14271427
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
1428-
Type resultTy, bool isStatic, bool isDefinition) {
1428+
Type resultTy, bool isStatic, bool isDefinition,
1429+
Optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo) {
14291430
assert(accessor->isSetter() || accessor->getParameters()->size() == 0);
14301431
os << " ";
14311432

@@ -1450,14 +1451,16 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
14501451
// FIXME: should it be objTy for resultTy?
14511452
printCxxThunkBody(accessor, signature, swiftSymbolName, typeDeclContext,
14521453
accessor->getModuleContext(), resultTy,
1453-
accessor->getParameters());
1454+
accessor->getParameters(),
1455+
/*hasThrows=*/false, nullptr, isStatic, dispatchInfo);
14541456
os << " }\n";
14551457
}
14561458

14571459
void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
14581460
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
14591461
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
1460-
Type resultTy, bool isDefinition) {
1462+
Type resultTy, bool isDefinition,
1463+
Optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo) {
14611464
assert(accessor->isGetter());
14621465
FunctionSignatureModifiers modifiers;
14631466
if (isDefinition)
@@ -1474,9 +1477,10 @@ void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
14741477
}
14751478
os << " {\n";
14761479
// FIXME: should it be objTy for resultTy?
1477-
printCxxThunkBody(accessor, signature, swiftSymbolName, typeDeclContext,
1478-
accessor->getModuleContext(), resultTy,
1479-
accessor->getParameters());
1480+
printCxxThunkBody(
1481+
accessor, signature, swiftSymbolName, typeDeclContext,
1482+
accessor->getModuleContext(), resultTy, accessor->getParameters(),
1483+
/*hasThrows=*/false, nullptr, /*isStatic=*/false, dispatchInfo);
14801484
os << " }\n";
14811485
}
14821486

lib/PrintAsClang/PrintClangFunction.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,17 +125,18 @@ class DeclAndTypeClangFunctionPrinter {
125125
Optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo);
126126

127127
/// Print the C++ getter/setter method signature.
128-
void printCxxPropertyAccessorMethod(const NominalTypeDecl *typeDeclContext,
129-
const AccessorDecl *accessor,
130-
const LoweredFunctionSignature &signature,
131-
StringRef swiftSymbolName, Type resultTy,
132-
bool isStatic, bool isDefinition);
128+
void printCxxPropertyAccessorMethod(
129+
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
130+
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
131+
Type resultTy, bool isStatic, bool isDefinition,
132+
Optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo);
133133

134134
/// Print the C++ subscript method.
135135
void printCxxSubscriptAccessorMethod(
136136
const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
137137
const LoweredFunctionSignature &signature, StringRef swiftSymbolName,
138-
Type resultTy, bool isDefinition);
138+
Type resultTy, bool isDefinition,
139+
Optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo);
139140

140141
/// Print Swift type as C/C++ type, as the return type of a C/C++ function.
141142
ClangRepresentation

test/Interop/SwiftToCxx/class/swift-class-virtual-method-dispatch-execution.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,75 @@ int main() {
9292
derivedDerived.methodInDerivedDerived();
9393
// CHECK-NEXT: DerivedDerivedClass.methodInDerivedDerived
9494
}
95+
96+
{
97+
swift::Int x;
98+
x = base.getVirtualComputedProp();
99+
assert(x == 21);
100+
101+
x = derived.getVirtualComputedProp();
102+
assert(x == -75);
103+
x = derivedAsBase.getVirtualComputedProp();
104+
assert(x == -75);
105+
106+
x = derivedDerived.getVirtualComputedProp();
107+
assert(x == -75);
108+
x = derivedDerivedAsBase.getVirtualComputedProp();
109+
assert(x == -75);
110+
}
111+
112+
{
113+
int64_t x;
114+
x = base.getVirtualComputedGetSet();
115+
assert(x == 0);
116+
base.setVirtualComputedGetSet(45);
117+
x = base.getVirtualComputedGetSet();
118+
assert(x == 45);
119+
120+
x = derived.getVirtualComputedGetSet();
121+
assert(x == 0);
122+
derivedAsBase.setVirtualComputedGetSet(9);
123+
x = derivedAsBase.getVirtualComputedGetSet();
124+
assert(x == 18);
125+
derived.setVirtualComputedGetSet(-1);
126+
x = derived.getVirtualComputedGetSet();
127+
assert(x == -2);
128+
129+
x = derivedDerived.getVirtualComputedGetSet();
130+
assert(x == 0);
131+
derivedDerivedAsBase.setVirtualComputedGetSet(3);
132+
x = derivedDerivedAsBase.getVirtualComputedGetSet();
133+
assert(x == 6);
134+
}
135+
136+
{
137+
swift::Int x;
138+
x = base.getStoredProp();
139+
assert(x == 0);
140+
141+
derivedAsBase.setStoredProp(39);
142+
x = derivedAsBase.getStoredProp();
143+
assert(x == -39);
144+
145+
x = derivedDerivedAsBase.getStoredProp();
146+
assert(x == 0);
147+
derivedDerivedAsBase.setStoredProp(843);
148+
x = derivedDerivedAsBase.getStoredProp();
149+
assert(x == 844);
150+
151+
x = derivedDerived.getComputedPropInDerivedDerived();
152+
assert(x == 11);
153+
}
154+
155+
{
156+
swift::Int x;
157+
x = base[23];
158+
assert(x == 23);
159+
160+
x = derivedAsBase[23];
161+
assert(x == 46);
162+
x = derivedDerivedAsBase[-11];
163+
assert(x == -22);
164+
}
95165
return 0;
96166
}

test/Interop/SwiftToCxx/class/swift-class-virtual-method-dispatch.swift

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@ public class BaseClass {
1919
public final func finalMethodInBase(_ x: Int) -> Int {
2020
return x * 2
2121
}
22+
23+
public var virtualComputedProp: Int {
24+
return 21
25+
}
26+
public var virtualComputedGetSet: Int64 {
27+
get {
28+
return field
29+
}
30+
set {
31+
field = newValue
32+
}
33+
}
34+
public var storedProp: Int = 0
35+
36+
public subscript(_ i: Int) -> Int {
37+
return i
38+
}
2239
}
2340

2441
public class DerivedClass: BaseClass {
@@ -34,6 +51,30 @@ public class DerivedClass: BaseClass {
3451
public func virtualMethodInDerived(_ x: BaseClass) -> BaseClass {
3552
return x
3653
}
54+
55+
override public var virtualComputedProp: Int {
56+
return -75
57+
}
58+
override public var virtualComputedGetSet: Int64 {
59+
get {
60+
super.virtualComputedGetSet
61+
}
62+
set {
63+
super.virtualComputedGetSet = newValue * 2
64+
}
65+
}
66+
override public var storedProp: Int {
67+
get {
68+
return -super.storedProp
69+
}
70+
set {
71+
super.storedProp = newValue
72+
}
73+
}
74+
75+
override public subscript(_ i: Int) -> Int {
76+
return i * 2
77+
}
3778
}
3879

3980
public final class DerivedDerivedClass: DerivedClass {
@@ -49,6 +90,16 @@ public final class DerivedDerivedClass: DerivedClass {
4990
public func methodInDerivedDerived() {
5091
print("DerivedDerivedClass.methodInDerivedDerived")
5192
}
93+
override public var storedProp: Int {
94+
get {
95+
return -super.storedProp
96+
}
97+
set {
98+
super.storedProp = newValue + 1
99+
}
100+
}
101+
public var storedPropInDerivedDerived: Int = 0
102+
public var computedPropInDerivedDerived: Int { return 11 }
52103
}
53104

54105
public func returnBaseClass() -> BaseClass {
@@ -83,6 +134,53 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
83134
// CHECK-NEXT: return _impl::$s5Class04BaseA0C013finalMethodInB0yS2iF(x, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
84135
// CHECK-NEXT: }
85136

137+
// CHECK: swift::Int BaseClass::getVirtualComputedProp() {
138+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
139+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
140+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class04BaseA0C19virtualComputedPropSivg);
141+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 2]]));
142+
// CHECK-NEXT: return (* fptr_)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
143+
// CHECK-NEXT: }
144+
145+
// CHECK: int64_t BaseClass::getVirtualComputedGetSet() {
146+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
147+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
148+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class04BaseA0C21virtualComputedGetSets5Int64Vvg);
149+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 3]]));
150+
// CHECK-NEXT: return (* fptr_)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
151+
// CHECK-NEXT: }
152+
153+
// CHECK: void BaseClass::setVirtualComputedGetSet(int64_t newValue) {
154+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
155+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
156+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class04BaseA0C21virtualComputedGetSets5Int64Vvs);
157+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 4]]));
158+
// CHECK-NEXT: return (* fptr_)(newValue, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
159+
// CHECK-NEXT: }
160+
161+
// CHECK: swift::Int BaseClass::getStoredProp() {
162+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
163+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
164+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class04BaseA0C10storedPropSivg);
165+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 6]]));
166+
// CHECK-NEXT: return (* fptr_)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
167+
// CHECK-NEXT: }
168+
169+
// CHECK: void BaseClass::setStoredProp(swift::Int value) {
170+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
171+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
172+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class04BaseA0C10storedPropSivs);
173+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 7]]));
174+
// CHECK-NEXT: return (* fptr_)(value, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
175+
// CHECK-NEXT: }
176+
177+
// CHECK: swift::Int BaseClass::operator [](swift::Int i) const
178+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
179+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
180+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class04BaseA0CyS2icig);
181+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 9]]));
182+
// CHECK-NEXT: return (* fptr_)(i, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
183+
86184
// CHECK: void DerivedClass::virtualMethod() {
87185
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
88186
// CHECK-NEXT: void **vtable_ = *selfPtr_;
@@ -103,10 +201,57 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
103201
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
104202
// CHECK-NEXT: void **vtable_ = *selfPtr_;
105203
// CHECK-NEXT: using FType = decltype(_impl::$s5Class07DerivedA0C015virtualMethodInB0yAA04BaseA0CAFF);
106-
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 2]]));
204+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 10]]));
107205
// CHECK-NEXT: return _impl::_impl_BaseClass::makeRetained((* fptr_)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(x), ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)));
108206
// CHECK-NEXT: }
109207

208+
// CHECK: swift::Int DerivedClass::getVirtualComputedProp() {
209+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
210+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
211+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class07DerivedA0C19virtualComputedPropSivg);
212+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 2]]));
213+
// CHECK-NEXT: return (* fptr_)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
214+
// CHECK-NEXT: }
215+
216+
// CHECK: int64_t DerivedClass::getVirtualComputedGetSet() {
217+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
218+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
219+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class07DerivedA0C21virtualComputedGetSets5Int64Vvg);
220+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 3]]));
221+
// CHECK-NEXT: return (* fptr_)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
222+
// CHECK-NEXT: }
223+
224+
// CHECK: void DerivedClass::setVirtualComputedGetSet(int64_t newValue) {
225+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
226+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
227+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class07DerivedA0C21virtualComputedGetSets5Int64Vvs);
228+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 4]]));
229+
// CHECK-NEXT: return (* fptr_)(newValue, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
230+
// CHECK-NEXT: }
231+
232+
// CHECK: swift::Int DerivedClass::getStoredProp() {
233+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
234+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
235+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class07DerivedA0C10storedPropSivg);
236+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 6]]));
237+
// CHECK-NEXT: return (* fptr_)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
238+
// CHECK-NEXT: }
239+
240+
// CHECK: void DerivedClass::setStoredProp(swift::Int newValue) {
241+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
242+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
243+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class07DerivedA0C10storedPropSivs);
244+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 7]]));
245+
// CHECK-NEXT: return (* fptr_)(newValue, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
246+
// CHECK-NEXT: }
247+
248+
// CHECK: swift::Int DerivedClass::operator [](swift::Int i) const
249+
// CHECK-NEXT: void ***selfPtr_ = reinterpret_cast<void ***>( ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
250+
// CHECK-NEXT: void **vtable_ = *selfPtr_;
251+
// CHECK-NEXT: using FType = decltype(_impl::$s5Class07DerivedA0CyS2icig);
252+
// CHECK-NEXT: FType *fptr_ = reinterpret_cast<FType *>(*(vtable_ + [[#VM1 + 9]]));
253+
// CHECK-NEXT: return (* fptr_)(i, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
254+
110255
// CHECK: void DerivedDerivedClass::virtualMethod() {
111256
// CHECK-NEXT: return _impl::$s5Class07DerivedbA0C13virtualMethodyyF(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
112257
// CHECK-NEXT: }
@@ -119,3 +264,10 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
119264
// CHECK-NEXT: return _impl::$s5Class07DerivedbA0C08methodInbB0yyF(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
120265
// CHECK-NEXT: }
121266

267+
// CHECK: swift::Int DerivedDerivedClass::getStoredProp() {
268+
// CHECK-NEXT: return _impl::$s5Class07DerivedbA0C10storedPropSivg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
269+
// CHECK-NEXT: }
270+
271+
// CHECK: swift::Int DerivedDerivedClass::getComputedPropInDerivedDerived() {
272+
// CHECK-NEXT: return _impl::$s5Class07DerivedbA0C014computedPropInbB0Sivg(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
273+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)