Skip to content

Commit f611dfb

Browse files
committed
[interop][SwiftToCxx] emit instance property getters for structs
1 parent b17b4d5 commit f611dfb

13 files changed

+462
-61
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ class DeclAndTypePrinter::Implementation
109109

110110
SmallVector<const FunctionType *, 4> openFunctionTypes;
111111

112+
std::string outOfLineDefinitions;
113+
112114
ASTContext &getASTContext() const {
113115
return owningPrinter.M.getASTContext();
114116
}
@@ -211,6 +213,7 @@ class DeclAndTypePrinter::Implementation
211213
template <bool AllowDelayed = false, typename R>
212214
void printMembers(R &&members) {
213215
bool protocolMembersOptional = false;
216+
assert(outOfLineDefinitions.empty());
214217
for (const Decl *member : members) {
215218
auto VD = dyn_cast<ValueDecl>(member);
216219
if (!VD || !shouldInclude(VD) || isa<TypeDecl>(VD))
@@ -226,6 +229,9 @@ class DeclAndTypePrinter::Implementation
226229
protocolMembersOptional = !protocolMembersOptional;
227230
os << (protocolMembersOptional ? "@optional\n" : "@required\n");
228231
}
232+
// Limit C++ decls for now.
233+
if (outputLang == OutputLanguageMode::Cxx && !isa<VarDecl>(VD))
234+
continue;
229235
ASTVisitor::visit(const_cast<ValueDecl*>(VD));
230236
}
231237
}
@@ -336,7 +342,12 @@ class DeclAndTypePrinter::Implementation
336342
ClangValueTypePrinter printer(os, owningPrinter.prologueOS,
337343
owningPrinter.typeMapping,
338344
owningPrinter.interopContext);
339-
printer.printValueTypeDecl(SD);
345+
std::string outOfLineMemberDefinition;
346+
347+
printer.printValueTypeDecl(
348+
SD, /*bodyPrinter=*/[&]() { printMembers(SD->getMembers()); });
349+
os << outOfLineDefinitions;
350+
outOfLineDefinitions.clear();
340351
}
341352

342353
void visitExtensionDecl(ExtensionDecl *ED) {
@@ -514,6 +525,46 @@ class DeclAndTypePrinter::Implementation
514525
bool isClassMethod,
515526
bool isNSUIntegerSubscript = false) {
516527
printDocumentationComment(AFD);
528+
529+
Optional<ForeignAsyncConvention> asyncConvention =
530+
AFD->getForeignAsyncConvention();
531+
Optional<ForeignErrorConvention> errorConvention =
532+
AFD->getForeignErrorConvention();
533+
Type rawMethodTy = AFD->getMethodInterfaceType();
534+
auto methodTy = rawMethodTy->castTo<FunctionType>();
535+
auto resultTy =
536+
getForeignResultType(AFD, methodTy, asyncConvention, errorConvention);
537+
538+
if (outputLang == OutputLanguageMode::Cxx) {
539+
// FIXME: can this ever fail?
540+
auto *typeDeclContext = cast<NominalTypeDecl>(AFD->getParent());
541+
542+
std::string cFuncDecl;
543+
llvm::raw_string_ostream cFuncPrologueOS(cFuncDecl);
544+
auto funcABI = Implementation(cFuncPrologueOS, owningPrinter, outputLang)
545+
.printSwiftABIFunctionSignatureAsCxxFunction(
546+
AFD, methodTy,
547+
/*selfTypeDeclContext=*/typeDeclContext);
548+
owningPrinter.prologueOS << cFuncPrologueOS.str();
549+
550+
DeclAndTypeClangFunctionPrinter declPrinter(os, owningPrinter.prologueOS,
551+
owningPrinter.typeMapping,
552+
owningPrinter.interopContext);
553+
declPrinter.printCxxPropertyAccessorMethod(
554+
typeDeclContext, AFD, funcABI.getSymbolName(), resultTy,
555+
/*isDefinition=*/false);
556+
557+
llvm::raw_string_ostream defOS(outOfLineDefinitions);
558+
DeclAndTypeClangFunctionPrinter defPrinter(
559+
defOS, owningPrinter.prologueOS, owningPrinter.typeMapping,
560+
owningPrinter.interopContext);
561+
defPrinter.printCxxPropertyAccessorMethod(
562+
typeDeclContext, AFD, funcABI.getSymbolName(), resultTy,
563+
/*isDefinition=*/true);
564+
565+
return;
566+
}
567+
517568
if (isClassMethod)
518569
os << "+ (";
519570
else
@@ -527,15 +578,6 @@ class DeclAndTypePrinter::Implementation
527578
}
528579
}
529580

530-
Optional<ForeignAsyncConvention> asyncConvention
531-
= AFD->getForeignAsyncConvention();
532-
Optional<ForeignErrorConvention> errorConvention
533-
= AFD->getForeignErrorConvention();
534-
Type rawMethodTy = AFD->getMethodInterfaceType();
535-
auto methodTy = rawMethodTy->castTo<FunctionType>();
536-
auto resultTy = getForeignResultType(
537-
AFD, methodTy, asyncConvention, errorConvention);
538-
539581
// Constructors and methods returning DynamicSelf return
540582
// instancetype.
541583
if (isa<ConstructorDecl>(AFD) ||
@@ -796,7 +838,8 @@ class DeclAndTypePrinter::Implementation
796838
}
797839

798840
struct FuncionSwiftABIInformation {
799-
FuncionSwiftABIInformation(FuncDecl *FD, Mangle::ASTMangler &mangler) {
841+
FuncionSwiftABIInformation(AbstractFunctionDecl *FD,
842+
Mangle::ASTMangler &mangler) {
800843
isCDecl = FD->getAttrs().hasAttribute<CDeclAttr>();
801844
if (!isCDecl) {
802845
auto mangledName = mangler.mangleAnyDecl(FD, /*prefix=*/true);
@@ -818,8 +861,9 @@ class DeclAndTypePrinter::Implementation
818861
};
819862

820863
// Print out the extern C Swift ABI function signature.
821-
FuncionSwiftABIInformation
822-
printSwiftABIFunctionSignatureAsCxxFunction(FuncDecl *FD) {
864+
FuncionSwiftABIInformation printSwiftABIFunctionSignatureAsCxxFunction(
865+
AbstractFunctionDecl *FD, Optional<FunctionType *> givenFuncType = None,
866+
Optional<NominalTypeDecl *> selfTypeDeclContext = None) {
823867
assert(outputLang == OutputLanguageMode::Cxx);
824868
Optional<ForeignAsyncConvention> asyncConvention =
825869
FD->getForeignAsyncConvention();
@@ -828,7 +872,9 @@ class DeclAndTypePrinter::Implementation
828872
assert(!FD->getGenericSignature() &&
829873
"top-level generic functions not supported here");
830874
// FIXME (Alex): Make type adjustments for C++.
831-
auto funcTy = FD->getInterfaceType()->castTo<FunctionType>();
875+
auto funcTy = givenFuncType
876+
? *givenFuncType
877+
: FD->getInterfaceType()->castTo<FunctionType>();
832878
auto resultTy =
833879
getForeignResultType(FD, funcTy, asyncConvention, errorConvention);
834880

@@ -840,9 +886,17 @@ class DeclAndTypePrinter::Implementation
840886
DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.prologueOS,
841887
owningPrinter.typeMapping,
842888
owningPrinter.interopContext);
889+
llvm::SmallVector<DeclAndTypeClangFunctionPrinter::AdditionalParam, 1>
890+
additionalParams;
891+
if (selfTypeDeclContext) {
892+
additionalParams.push_back(
893+
{DeclAndTypeClangFunctionPrinter::AdditionalParam::Role::Self,
894+
(*selfTypeDeclContext)->getDeclaredType()});
895+
}
843896
funcPrinter.printFunctionSignature(
844897
FD, funcABI.getSymbolName(), resultTy,
845-
DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CFunctionProto);
898+
DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CFunctionProto,
899+
additionalParams);
846900
// Swift functions can't throw exceptions, we can only
847901
// throw them from C++ when emitting C++ inline thunks for the Swift
848902
// functions.
@@ -1179,6 +1233,18 @@ class DeclAndTypePrinter::Implementation
11791233
assert(VD->getDeclContext()->isTypeContext() &&
11801234
"cannot handle global variables right now");
11811235

1236+
if (outputLang == OutputLanguageMode::Cxx) {
1237+
// FIXME: Documentation.
1238+
// FIXME: availability.
1239+
// FIXME: support static properties.
1240+
if (VD->isStatic())
1241+
return;
1242+
// Explicitly look at each accessor here: see visitAccessorDecl.
1243+
auto *getter = VD->getOpaqueAccessor(AccessorKind::Get);
1244+
printAbstractFunctionAsMethod(getter, /*isStatic=*/false);
1245+
return;
1246+
}
1247+
11821248
printDocumentationComment(VD);
11831249

11841250
if (VD->isStatic()) {

lib/PrintAsClang/ModuleContentsWriter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,8 +662,9 @@ void swift::printModuleContentsAsCxx(
662662
std::string modulePrologueBuf;
663663
llvm::raw_string_ostream prologueOS{modulePrologueBuf};
664664

665+
// FIXME: Use getRequiredAccess once @expose is supported.
665666
ModuleWriter writer(moduleOS, prologueOS, imports, M, interopContext,
666-
getRequiredAccess(M), OutputLanguageMode::Cxx);
667+
AccessLevel::Public, OutputLanguageMode::Cxx);
667668
writer.write();
668669

669670
os << "#ifndef SWIFT_PRINTED_CORE\n";

lib/PrintAsClang/PrintAsClang.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
317317
};
318318
emitMacro("SWIFT_CALL", "__attribute__((swiftcall))");
319319
emitMacro("SWIFT_INDIRECT_RESULT", "__attribute__((swift_indirect_result))");
320+
emitMacro("SWIFT_CONTEXT", "__attribute__((swift_context))");
320321
// SWIFT_NOEXCEPT applies 'noexcept' in C++ mode only.
321322
emitCxxConditional(
322323
out, [&] { emitMacro("SWIFT_NOEXCEPT", "noexcept"); },

0 commit comments

Comments
 (0)