Skip to content

Commit af8ae59

Browse files
authored
Merge pull request #59547 from hyp/eng/struct-init
[interop][SwiftToCxx] emit struct initializers
2 parents 8125a85 + 71065e9 commit af8ae59

File tree

6 files changed

+205
-21
lines changed

6 files changed

+205
-21
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "swift/AST/TypeCheckRequests.h"
3232
#include "swift/AST/TypeVisitor.h"
3333
#include "swift/IDE/CommentConversion.h"
34+
#include "swift/IRGen/Linking.h"
3435
#include "swift/Parse/Lexer.h"
3536
#include "swift/Parse/Parser.h"
3637

@@ -229,10 +230,6 @@ class DeclAndTypePrinter::Implementation
229230
protocolMembersOptional = !protocolMembersOptional;
230231
os << (protocolMembersOptional ? "@optional\n" : "@required\n");
231232
}
232-
// Limit C++ decls for now.
233-
if (outputLang == OutputLanguageMode::Cxx &&
234-
!(isa<VarDecl>(VD) || isa<FuncDecl>(VD)))
235-
continue;
236233
ASTVisitor::visit(const_cast<ValueDecl*>(VD));
237234
}
238235
}
@@ -855,11 +852,10 @@ class DeclAndTypePrinter::Implementation
855852
}
856853

857854
struct FuncionSwiftABIInformation {
858-
FuncionSwiftABIInformation(AbstractFunctionDecl *FD,
859-
Mangle::ASTMangler &mangler) {
855+
FuncionSwiftABIInformation(AbstractFunctionDecl *FD) {
860856
isCDecl = FD->getAttrs().hasAttribute<CDeclAttr>();
861857
if (!isCDecl) {
862-
auto mangledName = mangler.mangleAnyDecl(FD, /*prefix=*/true);
858+
auto mangledName = SILDeclRef(FD).mangle();
863859
symbolName = FD->getASTContext().AllocateCopy(mangledName);
864860
} else {
865861
symbolName = FD->getAttrs().getAttribute<CDeclAttr>()->Name;
@@ -895,8 +891,7 @@ class DeclAndTypePrinter::Implementation
895891
auto resultTy =
896892
getForeignResultType(FD, funcTy, asyncConvention, errorConvention);
897893

898-
Mangle::ASTMangler mangler;
899-
FuncionSwiftABIInformation funcABI(FD, mangler);
894+
FuncionSwiftABIInformation funcABI(FD);
900895

901896
os << "SWIFT_EXTERN ";
902897

@@ -905,7 +900,7 @@ class DeclAndTypePrinter::Implementation
905900
owningPrinter.interopContext);
906901
llvm::SmallVector<DeclAndTypeClangFunctionPrinter::AdditionalParam, 1>
907902
additionalParams;
908-
if (selfTypeDeclContext) {
903+
if (selfTypeDeclContext && !isa<ConstructorDecl>(FD)) {
909904
additionalParams.push_back(
910905
{DeclAndTypeClangFunctionPrinter::AdditionalParam::Role::Self,
911906
(*selfTypeDeclContext)->getDeclaredType(),

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -397,17 +397,22 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
397397
void DeclAndTypeClangFunctionPrinter::printCxxMethod(
398398
const NominalTypeDecl *typeDeclContext, const AbstractFunctionDecl *FD,
399399
StringRef swiftSymbolName, Type resultTy, bool isDefinition) {
400-
os << " inline ";
400+
bool isConstructor = isa<ConstructorDecl>(FD);
401+
os << " ";
402+
if (isConstructor && !isDefinition)
403+
os << "static ";
404+
os << "inline ";
401405
// FIXME: Full qualifier.
402406
FunctionSignatureModifiers modifiers;
403407
if (isDefinition)
404408
modifiers.qualifierContext = typeDeclContext;
405-
printFunctionSignature(FD, FD->getName().getBaseIdentifier().get(), resultTy,
406-
FunctionSignatureKind::CxxInlineThunk, {}, modifiers);
409+
printFunctionSignature(
410+
FD, isConstructor ? "init" : FD->getName().getBaseIdentifier().get(),
411+
resultTy, FunctionSignatureKind::CxxInlineThunk, {}, modifiers);
407412
bool isMutating = false;
408413
if (auto *funcDecl = dyn_cast<FuncDecl>(FD))
409414
isMutating = funcDecl->isMutating();
410-
if (!isMutating)
415+
if (!isMutating && !isConstructor)
411416
os << " const";
412417
if (!isDefinition) {
413418
os << ";\n";
@@ -416,12 +421,15 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
416421

417422
os << " {\n";
418423
// FIXME: should it be objTy for resultTy?
424+
SmallVector<AdditionalParam, 2> additionalParams;
425+
if (!isConstructor)
426+
additionalParams.push_back(AdditionalParam{
427+
AdditionalParam::Role::Self,
428+
typeDeclContext->getDeclaredType(),
429+
/*isIndirect=*/isMutating,
430+
});
419431
printCxxThunkBody(swiftSymbolName, resultTy, FD->getParameters(),
420-
{AdditionalParam{
421-
AdditionalParam::Role::Self,
422-
typeDeclContext->getDeclaredType(),
423-
/*isIndirect=*/isMutating,
424-
}});
432+
additionalParams);
425433
os << " }\n";
426434
}
427435

lib/PrintAsClang/PrintClangFunction.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ class DeclAndTypeClangFunctionPrinter {
8585
const ParameterList *params,
8686
ArrayRef<AdditionalParam> additionalParams = {});
8787

88-
/// Print the Swift method as C++ method declaration/definition.
88+
/// Print the Swift method as C++ method declaration/definition, including
89+
/// constructors.
8990
void printCxxMethod(const NominalTypeDecl *typeDeclContext,
9091
const AbstractFunctionDecl *FD, StringRef swiftSymbolName,
9192
Type resultTy, bool isDefinition);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend %S/init-in-cxx.swift -typecheck -module-name Init -clang-header-expose-public-decls -emit-clang-header-path %t/inits.h
4+
5+
// RUN: %target-interop-build-clangxx -c %s -I %t -o %t/swift-init-execution.o
6+
// RUN: %target-interop-build-swift %S/init-in-cxx.swift -o %t/swift-init-execution -Xlinker %t/swift-init-execution.o -module-name Init -Xfrontend -entry-point-function-name -Xfrontend swiftMain
7+
8+
// RUN: %target-codesign %t/swift-init-execution
9+
// RUN: %target-run %t/swift-init-execution | %FileCheck %s
10+
11+
// REQUIRES: executable_test
12+
13+
#include <assert.h>
14+
#include "inits.h"
15+
16+
int main() {
17+
using namespace Init;
18+
19+
auto smallStruct = FirstSmallStruct::init();
20+
assert(smallStruct.getX() == 42);
21+
auto smallStruct2 = FirstSmallStruct::init(24);
22+
assert(smallStruct2.getX() == 24);
23+
24+
auto largeStruct = LargeStruct::init();
25+
assert(largeStruct.getX1() == 0);
26+
assert(largeStruct.getX2() == 0);
27+
assert(largeStruct.getX3() == 0);
28+
assert(largeStruct.getX4() == 0);
29+
assert(largeStruct.getX5() == 0);
30+
assert(largeStruct.getX6() == 0);
31+
auto largeStruct2 = LargeStruct::init(99, smallStruct2);
32+
assert(largeStruct2.getX1() == 99);
33+
assert(largeStruct2.getX2() == 24);
34+
assert(largeStruct2.getX3() == -99);
35+
assert(largeStruct2.getX4() == 0);
36+
assert(largeStruct2.getX5() == 11);
37+
assert(largeStruct2.getX6() == 99 * 24);
38+
39+
{
40+
StructWithRefCountStoredProp structWithRefCountStoredProp =
41+
StructWithRefCountStoredProp::init();
42+
(void)structWithRefCountStoredProp;
43+
(void)StructWithRefCountStoredProp::init(22);
44+
}
45+
// CHECK: create RefCountedClass -1
46+
// CHECK-NEXT: create RefCountedClass 22
47+
// CHECK-NEXT: destroy RefCountedClass 22
48+
// CHECK-NEXT: destroy RefCountedClass -1
49+
return 0;
50+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %s -typecheck -module-name Init -clang-header-expose-public-decls -emit-clang-header-path %t/inits.h
3+
// RUN: %FileCheck %s < %t/inits.h
4+
5+
// RUN: %check-interop-cxx-header-in-clang(%t/inits.h -Wno-unused-function)
6+
7+
8+
// CHECK: SWIFT_EXTERN struct swift_interop_stub_Init_FirstSmallStruct $s4Init16FirstSmallStructVACycfC(void) SWIFT_NOEXCEPT SWIFT_CALL; // init()
9+
// CHECK-NEXT: SWIFT_EXTERN struct swift_interop_stub_Init_FirstSmallStruct $s4Init16FirstSmallStructVyACSicfC(ptrdiff_t x) SWIFT_NOEXCEPT SWIFT_CALL; // init(_:)
10+
11+
// CHECK: SWIFT_EXTERN void $s4Init11LargeStructVACycfC(SWIFT_INDIRECT_RESULT void * _Nonnull) SWIFT_NOEXCEPT SWIFT_CALL; // init()
12+
// CHECK-NEXT: SWIFT_EXTERN void $s4Init11LargeStructV1x1yACSi_AA010FirstSmallC0VtcfC(SWIFT_INDIRECT_RESULT void * _Nonnull, ptrdiff_t x, struct swift_interop_stub_Init_FirstSmallStruct y) SWIFT_NOEXCEPT SWIFT_CALL; // init(x:y:)
13+
14+
// CHECK: SWIFT_EXTERN struct swift_interop_stub_Init_StructWithRefCountStoredProp $s4Init28StructWithRefCountStoredPropVACycfC(void) SWIFT_NOEXCEPT SWIFT_CALL; // init()
15+
// CHECK-NEXT: SWIFT_EXTERN struct swift_interop_stub_Init_StructWithRefCountStoredProp $s4Init28StructWithRefCountStoredPropV1xACSi_tcfC(ptrdiff_t x) SWIFT_NOEXCEPT SWIFT_CALL; // init(x:)
16+
17+
public struct FirstSmallStruct {
18+
public let x: UInt32
19+
20+
public init() {
21+
x = 42
22+
}
23+
24+
public init(_ x: Int) {
25+
self.x = UInt32(x)
26+
}
27+
28+
private init(_ y: Float) {
29+
fatalError("nope")
30+
}
31+
}
32+
33+
// CHECK: class FirstSmallStruct final {
34+
// CHECK-NEXT: public:
35+
// CHECK: inline FirstSmallStruct(FirstSmallStruct &&) = default;
36+
// CHECK-NEXT: inline uint32_t getX() const;
37+
// CHECK-NEXT: static inline FirstSmallStruct init();
38+
// CHECK-NEXT: static inline FirstSmallStruct init(swift::Int x);
39+
// CHECK-NEXT: private:
40+
41+
// CHECK: inline uint32_t FirstSmallStruct::getX() const {
42+
// CHECK-NEXT: return _impl::$s4Init16FirstSmallStructV1xs6UInt32Vvg(_impl::swift_interop_passDirect_Init_FirstSmallStruct(_getOpaquePointer()));
43+
// CHECK-NEXT: }
44+
// CHECK-NEXT: inline FirstSmallStruct FirstSmallStruct::init() {
45+
// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) {
46+
// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_FirstSmallStruct(result, _impl::$s4Init16FirstSmallStructVACycfC());
47+
// CHECK-NEXT: });
48+
// CHECK-NEXT: }
49+
// CHECK-NEXT: inline FirstSmallStruct FirstSmallStruct::init(swift::Int x) {
50+
// CHECK-NEXT: return _impl::_impl_FirstSmallStruct::returnNewValue([&](char * _Nonnull result) {
51+
// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_FirstSmallStruct(result, _impl::$s4Init16FirstSmallStructVyACSicfC(x));
52+
// CHECK-NEXT: });
53+
// CHECK-NEXT: }
54+
55+
public struct LargeStruct {
56+
public let x1, x2, x3, x4, x5, x6: Int
57+
58+
public init () {
59+
x1 = 0
60+
x2 = 0
61+
x3 = 0
62+
x4 = 0
63+
x5 = 0
64+
x6 = 0
65+
}
66+
67+
public init(x: Int, y: FirstSmallStruct) {
68+
x1 = x
69+
x2 = Int(y.x)
70+
x3 = -x
71+
x4 = 0
72+
x5 = 11
73+
x6 = x * Int(y.x)
74+
}
75+
}
76+
77+
// CHECK: class LargeStruct final {
78+
// CHECK: inline swift::Int getX6() const;
79+
// CHECK-NEXT: static inline LargeStruct init();
80+
// CHECK-NEXT: static inline LargeStruct init(swift::Int x, const FirstSmallStruct& y);
81+
// CHECK-NEXT: private:
82+
83+
// CHECK: inline LargeStruct LargeStruct::init() {
84+
// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) {
85+
// CHECK-NEXT: _impl::$s4Init11LargeStructVACycfC(result);
86+
// CHECK-NEXT: });
87+
// CHECK-NEXT: }
88+
// CHECK-NEXT: inline LargeStruct LargeStruct::init(swift::Int x, const FirstSmallStruct& y) {
89+
// CHECK-NEXT: return _impl::_impl_LargeStruct::returnNewValue([&](void * _Nonnull result) {
90+
// CHECK-NEXT: _impl::$s4Init11LargeStructV1x1yACSi_AA010FirstSmallC0VtcfC(result, x, _impl::swift_interop_passDirect_Init_FirstSmallStruct(_impl::_impl_FirstSmallStruct::getOpaquePointer(y)));
91+
// CHECK-NEXT: });
92+
// CHECK-NEXT: }
93+
94+
private class RefCountedClass {
95+
let x: Int
96+
97+
init(x: Int) {
98+
self.x = x
99+
print("create RefCountedClass \(x)")
100+
}
101+
deinit {
102+
print("destroy RefCountedClass \(x)")
103+
}
104+
}
105+
106+
public struct StructWithRefCountStoredProp {
107+
private let storedRef: RefCountedClass
108+
109+
public init() {
110+
storedRef = RefCountedClass(x: -1)
111+
}
112+
113+
public init(x: Int) {
114+
storedRef = RefCountedClass(x: x)
115+
}
116+
}
117+
118+
// CHECK: static inline StructWithRefCountStoredProp init();
119+
// CHECK-NEXT: static inline StructWithRefCountStoredProp init(swift::Int x);
120+
121+
// CHECK: inline StructWithRefCountStoredProp StructWithRefCountStoredProp::init() {
122+
// CHECK-NEXT: return _impl::_impl_StructWithRefCountStoredProp::returnNewValue([&](char * _Nonnull result) {
123+
// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_StructWithRefCountStoredProp(result, _impl::$s4Init28StructWithRefCountStoredPropVACycfC());
124+
// CHECK-NEXT: });
125+
// CHECK-NEXT: }
126+
// CHECK-NEXT: inline StructWithRefCountStoredProp StructWithRefCountStoredProp::init(swift::Int x) {
127+
// CHECK-NEXT: return _impl::_impl_StructWithRefCountStoredProp::returnNewValue([&](char * _Nonnull result) {
128+
// CHECK-NEXT: _impl::swift_interop_returnDirect_Init_StructWithRefCountStoredProp(result, _impl::$s4Init28StructWithRefCountStoredPropV1xACSi_tcfC(x));
129+
// CHECK-NEXT: });
130+
// CHECK-NEXT: }

test/Interop/SwiftToCxx/properties/getter-in-cxx.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ private class RefCountedClass {
132132
public struct StructWithRefCountStoredProp {
133133
private let storedRef: RefCountedClass
134134

135-
public init(x: Int) {
135+
internal init(x: Int) {
136136
storedRef = RefCountedClass(x: x)
137137
}
138138

0 commit comments

Comments
 (0)