Skip to content

Commit c0bda06

Browse files
committed
[interop][SwiftToCxx] emit class method bindings
1 parent 7c5b160 commit c0bda06

File tree

5 files changed

+132
-11
lines changed

5 files changed

+132
-11
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,10 @@ class DeclAndTypePrinter::Implementation
300300
if (outputLang == OutputLanguageMode::Cxx) {
301301
// FIXME: Non objc class.
302302
// FIXME: Print availability.
303-
ClangClassTypePrinter(os).printClassTypeDecl(CD, []() {
304-
// FIXME: print class body.
305-
});
303+
ClangClassTypePrinter(os).printClassTypeDecl(
304+
CD, [&]() { printMembers(CD->getMembers()); });
305+
os << outOfLineDefinitions;
306+
outOfLineDefinitions.clear();
306307
return;
307308
}
308309

lib/PrintAsClang/PrintClangClassType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void ClangClassTypePrinter::printClassTypeDecl(
5959

6060
os << " using " << baseClassName << "::" << baseClassName << ";\n";
6161
os << " using " << baseClassName << "::operator=;\n";
62-
62+
bodyPrinter();
6363
os << "protected:\n";
6464
os << " inline ";
6565
printer.printBaseName(typeDecl);

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ bool isKnownCType(Type t, PrimitiveTypeMapping &typeMapping) {
7878
}
7979

8080
struct CFunctionSignatureTypePrinterModifierDelegate {
81-
/// Prefix the indirect value type param being printed in C mode.
81+
/// Prefix the indirect value type / class type param being printed in C mode.
8282
Optional<llvm::function_ref<void(raw_ostream &)>>
83-
prefixIndirectParamValueTypeInC = None;
83+
prefixIndirectlyPassedParamTypeInC = None;
8484
};
8585

8686
// Prints types in the C function signature that corresponds to the
@@ -152,6 +152,8 @@ class CFunctionSignatureTypePrinter
152152
bool isInOutParam) {
153153
// FIXME: handle optionalKind.
154154
if (languageMode != OutputLanguageMode::Cxx) {
155+
if (modifiersDelegate.prefixIndirectlyPassedParamTypeInC)
156+
(*modifiersDelegate.prefixIndirectlyPassedParamTypeInC)(os);
155157
os << "void * _Nonnull";
156158
if (isInOutParam)
157159
os << " * _Nonnull";
@@ -188,8 +190,8 @@ class CFunctionSignatureTypePrinter
188190
if (languageMode != OutputLanguageMode::Cxx &&
189191
(decl->isResilient() ||
190192
interopContext.getIrABIDetails().shouldPassIndirectly(NT))) {
191-
if (modifiersDelegate.prefixIndirectParamValueTypeInC)
192-
(*modifiersDelegate.prefixIndirectParamValueTypeInC)(os);
193+
if (modifiersDelegate.prefixIndirectlyPassedParamTypeInC)
194+
(*modifiersDelegate.prefixIndirectlyPassedParamTypeInC)(os);
193195
// FIXME: it would be nice to print out the C struct type here.
194196
if (isInOutParam) {
195197
os << "void * _Nonnull";
@@ -407,13 +409,13 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
407409
interleaveComma(additionalParams, os, [&](const AdditionalParam &param) {
408410
if (param.role == AdditionalParam::Role::Self) {
409411
CFunctionSignatureTypePrinterModifierDelegate delegate;
410-
delegate.prefixIndirectParamValueTypeInC = [](raw_ostream &os) {
412+
delegate.prefixIndirectlyPassedParamTypeInC = [](raw_ostream &os) {
411413
os << "SWIFT_CONTEXT ";
412414
};
413415
if (FD->hasThrows())
414416
os << "SWIFT_CONTEXT ";
415417
if (param.isIndirect) {
416-
(*delegate.prefixIndirectParamValueTypeInC)(os);
418+
(*delegate.prefixIndirectlyPassedParamTypeInC)(os);
417419
os << "void * _Nonnull _self";
418420
} else {
419421
print(param.type, OptionalTypeKind::OTK_None, "_self",
@@ -649,7 +651,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
649651
modifiers.isInline = true;
650652
bool isMutating =
651653
isa<FuncDecl>(FD) ? cast<FuncDecl>(FD)->isMutating() : false;
652-
modifiers.isConst = !isMutating && !isConstructor;
654+
modifiers.isConst =
655+
!isa<ClassDecl>(typeDeclContext) && !isMutating && !isConstructor;
653656
printFunctionSignature(
654657
FD, isConstructor ? "init" : FD->getName().getBaseIdentifier().get(),
655658
resultTy, FunctionSignatureKind::CxxInlineThunk, {}, modifiers);

test/Interop/SwiftToCxx/methods/method-in-cxx-execution.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,37 @@ int main() {
3131
auto largeStructAdded = largeStructDoubled.added(largeStruct);
3232
largeStructAdded.dump();
3333
// CHECK-NEXT: -3, 6, -300, 126, 201, -30303
34+
35+
{
36+
auto classValue = createClassWithMethods(42);
37+
classValue.dump();
38+
// CHECK-NEXT: ClassWithMethods 42;
39+
auto classValueRef = classValue.sameRet();
40+
auto classValueOther = classValue.deepCopy(2);
41+
classValue.mutate();
42+
classValue.dump();
43+
classValueRef.dump();
44+
classValueOther.dump();
45+
}
46+
// CHECK-NEXT: ClassWithMethods -42;
47+
// CHECK-NEXT: ClassWithMethods -42;
48+
// CHECK-NEXT: ClassWithMethods 44;
49+
// CHECK-NEXT: ClassWithMethods 44 deinit
50+
// CHECK-NEXT: ClassWithMethods -42 deinit
51+
52+
auto classWithStruct = createPassStructInClassMethod();
53+
{
54+
auto largeStruct = classWithStruct.retStruct(-11);
55+
largeStruct.dump();
56+
// CHECK-NEXT: PassStructInClassMethod.retStruct -11;
57+
// CHECK-NEXT: 1, 2, 3, 4, 5, 6
58+
}
59+
classWithStruct.updateStruct(-578, largeStruct);
60+
{
61+
auto largeStruct = classWithStruct.retStruct(2);
62+
largeStruct.dump();
63+
// CHECK-NEXT: PassStructInClassMethod.retStruct 2;
64+
// CHECK-NEXT: -578, 2, -100, 42, 67, -10101
65+
}
3466
return 0;
3567
}

test/Interop/SwiftToCxx/methods/method-in-cxx.swift

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,78 @@ public struct LargeStruct {
2424
}
2525
}
2626

27+
public final class ClassWithMethods {
28+
var field: Int
29+
30+
init(_ x: Int) {
31+
field = x
32+
}
33+
34+
deinit {
35+
print("ClassWithMethods \(field) deinit")
36+
}
37+
38+
public func dump() {
39+
print("ClassWithMethods \(field);")
40+
}
41+
42+
public func sameRet() -> ClassWithMethods {
43+
return self
44+
}
45+
46+
public func mutate() {
47+
field = -field
48+
}
49+
50+
public func deepCopy(_ x: Int) -> ClassWithMethods {
51+
return ClassWithMethods(field + x)
52+
}
53+
}
54+
55+
public final class PassStructInClassMethod {
56+
var largeStruct: LargeStruct
57+
init() { largeStruct = LargeStruct(x1: 1, x2: 2, x3: 3, x4: 4, x5: 5, x6: 6) }
58+
59+
public func retStruct(_ x: Int) -> LargeStruct {
60+
print("PassStructInClassMethod.retStruct \(x);")
61+
return largeStruct
62+
}
63+
public func updateStruct(_ x: Int, _ y: LargeStruct) {
64+
largeStruct = LargeStruct(x1: x, x2: y.x2, x3: y.x3, x4: y.x4, x5: y.x5, x6: y.x6)
65+
}
66+
}
67+
68+
// CHECK: SWIFT_EXTERN void $s7Methods09ClassWithA0C4dumpyyF(SWIFT_CONTEXT void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // dump()
69+
// CHECK: SWIFT_EXTERN void * _Nonnull $s7Methods09ClassWithA0C7sameRetACyF(SWIFT_CONTEXT void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // sameRet()
70+
// CHECK: SWIFT_EXTERN void $s7Methods09ClassWithA0C6mutateyyF(SWIFT_CONTEXT void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // mutate()
71+
// CHECK: SWIFT_EXTERN void * _Nonnull $s7Methods09ClassWithA0C8deepCopyyACSiF(ptrdiff_t x, SWIFT_CONTEXT void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // deepCopy(_:)
2772
// CHECK: SWIFT_EXTERN void $s7Methods11LargeStructV7doubledACyF(SWIFT_INDIRECT_RESULT void * _Nonnull, SWIFT_CONTEXT const void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // doubled()
2873
// CHECK: SWIFT_EXTERN void $s7Methods11LargeStructV4dumpyyF(SWIFT_CONTEXT const void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // dump()
2974
// CHECK: SWIFT_EXTERN void $s7Methods11LargeStructV6scaledyACSi_SitF(SWIFT_INDIRECT_RESULT void * _Nonnull, ptrdiff_t x, ptrdiff_t y, SWIFT_CONTEXT const void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // scaled(_:_:)
3075
// CHECK: SWIFT_EXTERN void $s7Methods11LargeStructV5addedyA2CF(SWIFT_INDIRECT_RESULT void * _Nonnull, const void * _Nonnull x, SWIFT_CONTEXT const void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // added(_:)
76+
// CHECK: SWIFT_EXTERN void $s7Methods23PassStructInClassMethodC03retC0yAA05LargeC0VSiF(SWIFT_INDIRECT_RESULT void * _Nonnull, ptrdiff_t x, SWIFT_CONTEXT void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // retStruct(_:)
77+
// CHECK: SWIFT_EXTERN void $s7Methods23PassStructInClassMethodC06updateC0yySi_AA05LargeC0VtF(ptrdiff_t x, const void * _Nonnull y, SWIFT_CONTEXT void * _Nonnull _self) SWIFT_NOEXCEPT SWIFT_CALL; // updateStruct(_:_:)
78+
79+
// CHECK: class ClassWithMethods final : public swift::_impl::RefCountedClass {
80+
// CHECK: using RefCountedClass::RefCountedClass;
81+
// CHECK-NEXT: using RefCountedClass::operator=;
82+
// CHECK-NEXT: inline void dump();
83+
// CHECK-NEXT: inline ClassWithMethods sameRet();
84+
// CHECK-NEXT: inline void mutate();
85+
// CHECK-NEXT: inline ClassWithMethods deepCopy(swift::Int x);
86+
87+
// CHECK: inline void ClassWithMethods::dump() {
88+
// CHECK-NEXT: return _impl::$s7Methods09ClassWithA0C4dumpyyF(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
89+
// CHECK-NEXT: }
90+
// CHECK-NEXT: inline ClassWithMethods ClassWithMethods::sameRet() {
91+
// CHECK-NEXT: return _impl::_impl_ClassWithMethods::makeRetained(_impl::$s7Methods09ClassWithA0C7sameRetACyF(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)));
92+
// CHECK-NEXT: }
93+
// CHECK-NEXT: inline void ClassWithMethods::mutate() {
94+
// CHECK-NEXT: return _impl::$s7Methods09ClassWithA0C6mutateyyF(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
95+
// CHECK-NEXT: }
96+
// CHECK-NEXT: inline ClassWithMethods ClassWithMethods::deepCopy(swift::Int x) {
97+
// CHECK-NEXT: return _impl::_impl_ClassWithMethods::makeRetained(_impl::$s7Methods09ClassWithA0C8deepCopyyACSiF(x, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)));
98+
// CHECK-NEXT: }
3199

32100
// CHECK: class LargeStruct final {
33101
// CHECK: inline LargeStruct(LargeStruct &&) = default;
@@ -56,6 +124,23 @@ public struct LargeStruct {
56124
// CHECK-NEXT: });
57125
// CHECK-NEXT: }
58126

127+
// CHECK: inline LargeStruct PassStructInClassMethod::retStruct(swift::Int x) {
128+
// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) {
129+
// CHECK-NEXT: _impl::$s7Methods23PassStructInClassMethodC03retC0yAA05LargeC0VSiF(result, x, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
130+
// CHECK-NEXT: });
131+
// CHECK-NEXT: }
132+
// CHECK-NEXT: inline void PassStructInClassMethod::updateStruct(swift::Int x, const LargeStruct& y) {
133+
// CHECK-NEXT: return _impl::$s7Methods23PassStructInClassMethodC06updateC0yySi_AA05LargeC0VtF(x, _impl::_impl_LargeStruct::getOpaquePointer(y), ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
134+
// CHECK-NEXT: }
135+
136+
public func createClassWithMethods(_ x: Int) -> ClassWithMethods {
137+
return ClassWithMethods(x)
138+
}
139+
59140
public func createLargeStruct() -> LargeStruct {
60141
return LargeStruct(x1: -1, x2: 2, x3: -100, x4: 42, x5: 67, x6: -10101)
61142
}
143+
144+
public func createPassStructInClassMethod() -> PassStructInClassMethod {
145+
return PassStructInClassMethod()
146+
}

0 commit comments

Comments
 (0)