Skip to content

Commit a00c0b4

Browse files
authored
Merge pull request #59445 from hyp/eng/emit-struct-instance-getters
[interop][SwiftToCxx] emit instance property getters for structs
2 parents 40cee8a + d7fd123 commit a00c0b4

13 files changed

+456
-59
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 77 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,10 @@ class DeclAndTypePrinter::Implementation
336342
ClangValueTypePrinter printer(os, owningPrinter.prologueOS,
337343
owningPrinter.typeMapping,
338344
owningPrinter.interopContext);
339-
printer.printValueTypeDecl(SD);
345+
printer.printValueTypeDecl(
346+
SD, /*bodyPrinter=*/[&]() { printMembers(SD->getMembers()); });
347+
os << outOfLineDefinitions;
348+
outOfLineDefinitions.clear();
340349
}
341350

342351
void visitExtensionDecl(ExtensionDecl *ED) {
@@ -514,6 +523,45 @@ class DeclAndTypePrinter::Implementation
514523
bool isClassMethod,
515524
bool isNSUIntegerSubscript = false) {
516525
printDocumentationComment(AFD);
526+
527+
Optional<ForeignAsyncConvention> asyncConvention =
528+
AFD->getForeignAsyncConvention();
529+
Optional<ForeignErrorConvention> errorConvention =
530+
AFD->getForeignErrorConvention();
531+
Type rawMethodTy = AFD->getMethodInterfaceType();
532+
auto methodTy = rawMethodTy->castTo<FunctionType>();
533+
auto resultTy =
534+
getForeignResultType(AFD, methodTy, asyncConvention, errorConvention);
535+
536+
if (outputLang == OutputLanguageMode::Cxx) {
537+
auto *typeDeclContext = cast<NominalTypeDecl>(AFD->getParent());
538+
539+
std::string cFuncDecl;
540+
llvm::raw_string_ostream cFuncPrologueOS(cFuncDecl);
541+
auto funcABI = Implementation(cFuncPrologueOS, owningPrinter, outputLang)
542+
.printSwiftABIFunctionSignatureAsCxxFunction(
543+
AFD, methodTy,
544+
/*selfTypeDeclContext=*/typeDeclContext);
545+
owningPrinter.prologueOS << cFuncPrologueOS.str();
546+
547+
DeclAndTypeClangFunctionPrinter declPrinter(os, owningPrinter.prologueOS,
548+
owningPrinter.typeMapping,
549+
owningPrinter.interopContext);
550+
declPrinter.printCxxPropertyAccessorMethod(
551+
typeDeclContext, AFD, funcABI.getSymbolName(), resultTy,
552+
/*isDefinition=*/false);
553+
554+
llvm::raw_string_ostream defOS(outOfLineDefinitions);
555+
DeclAndTypeClangFunctionPrinter defPrinter(
556+
defOS, owningPrinter.prologueOS, owningPrinter.typeMapping,
557+
owningPrinter.interopContext);
558+
defPrinter.printCxxPropertyAccessorMethod(
559+
typeDeclContext, AFD, funcABI.getSymbolName(), resultTy,
560+
/*isDefinition=*/true);
561+
562+
return;
563+
}
564+
517565
if (isClassMethod)
518566
os << "+ (";
519567
else
@@ -527,15 +575,6 @@ class DeclAndTypePrinter::Implementation
527575
}
528576
}
529577

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-
539578
// Constructors and methods returning DynamicSelf return
540579
// instancetype.
541580
if (isa<ConstructorDecl>(AFD) ||
@@ -796,7 +835,8 @@ class DeclAndTypePrinter::Implementation
796835
}
797836

798837
struct FuncionSwiftABIInformation {
799-
FuncionSwiftABIInformation(FuncDecl *FD, Mangle::ASTMangler &mangler) {
838+
FuncionSwiftABIInformation(AbstractFunctionDecl *FD,
839+
Mangle::ASTMangler &mangler) {
800840
isCDecl = FD->getAttrs().hasAttribute<CDeclAttr>();
801841
if (!isCDecl) {
802842
auto mangledName = mangler.mangleAnyDecl(FD, /*prefix=*/true);
@@ -818,8 +858,9 @@ class DeclAndTypePrinter::Implementation
818858
};
819859

820860
// Print out the extern C Swift ABI function signature.
821-
FuncionSwiftABIInformation
822-
printSwiftABIFunctionSignatureAsCxxFunction(FuncDecl *FD) {
861+
FuncionSwiftABIInformation printSwiftABIFunctionSignatureAsCxxFunction(
862+
AbstractFunctionDecl *FD, Optional<FunctionType *> givenFuncType = None,
863+
Optional<NominalTypeDecl *> selfTypeDeclContext = None) {
823864
assert(outputLang == OutputLanguageMode::Cxx);
824865
Optional<ForeignAsyncConvention> asyncConvention =
825866
FD->getForeignAsyncConvention();
@@ -828,7 +869,9 @@ class DeclAndTypePrinter::Implementation
828869
assert(!FD->getGenericSignature() &&
829870
"top-level generic functions not supported here");
830871
// FIXME (Alex): Make type adjustments for C++.
831-
auto funcTy = FD->getInterfaceType()->castTo<FunctionType>();
872+
auto funcTy = givenFuncType
873+
? *givenFuncType
874+
: FD->getInterfaceType()->castTo<FunctionType>();
832875
auto resultTy =
833876
getForeignResultType(FD, funcTy, asyncConvention, errorConvention);
834877

@@ -840,9 +883,17 @@ class DeclAndTypePrinter::Implementation
840883
DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.prologueOS,
841884
owningPrinter.typeMapping,
842885
owningPrinter.interopContext);
886+
llvm::SmallVector<DeclAndTypeClangFunctionPrinter::AdditionalParam, 1>
887+
additionalParams;
888+
if (selfTypeDeclContext) {
889+
additionalParams.push_back(
890+
{DeclAndTypeClangFunctionPrinter::AdditionalParam::Role::Self,
891+
(*selfTypeDeclContext)->getDeclaredType()});
892+
}
843893
funcPrinter.printFunctionSignature(
844894
FD, funcABI.getSymbolName(), resultTy,
845-
DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CFunctionProto);
895+
DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CFunctionProto,
896+
additionalParams);
846897
// Swift functions can't throw exceptions, we can only
847898
// throw them from C++ when emitting C++ inline thunks for the Swift
848899
// functions.
@@ -1186,6 +1237,17 @@ class DeclAndTypePrinter::Implementation
11861237
assert(VD->getDeclContext()->isTypeContext() &&
11871238
"cannot handle global variables right now");
11881239

1240+
if (outputLang == OutputLanguageMode::Cxx) {
1241+
// FIXME: Documentation.
1242+
// FIXME: availability.
1243+
// FIXME: support static properties.
1244+
if (VD->isStatic())
1245+
return;
1246+
auto *getter = VD->getOpaqueAccessor(AccessorKind::Get);
1247+
printAbstractFunctionAsMethod(getter, /*isStatic=*/false);
1248+
return;
1249+
}
1250+
11891251
printDocumentationComment(VD);
11901252

11911253
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)