Skip to content

Commit 4e1a1b8

Browse files
authored
Merge pull request #60071 from hyp/eng/value-type-xmod-refs
[interop][SwiftToCxx] add support for passing/returning value types from other modules
2 parents 9a38146 + 42b2cd2 commit 4e1a1b8

File tree

9 files changed

+183
-51
lines changed

9 files changed

+183
-51
lines changed

lib/PrintAsClang/ClangSyntaxPrinter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ void ClangSyntaxPrinter::printModuleNameCPrefix(const ModuleDecl &mod) {
5757
os << mod.getName().str() << '_';
5858
}
5959

60+
void ClangSyntaxPrinter::printModuleNamespaceQualifiersIfNeeded(
61+
const ModuleDecl *referencedModule, const ModuleDecl *currentContext) {
62+
if (referencedModule == currentContext)
63+
return;
64+
printBaseName(referencedModule);
65+
os << "::";
66+
}
67+
6068
/// Print a C++ namespace declaration with the give name and body.
6169
void ClangSyntaxPrinter::printNamespace(
6270
llvm::function_ref<void(raw_ostream &OS)> namePrinter,

lib/PrintAsClang/ClangSyntaxPrinter.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ class ClangSyntaxPrinter {
5050
/// C type names inside the module.
5151
void printModuleNameCPrefix(const ModuleDecl &mod);
5252

53+
/// Print the optional namespace qualifiers for the given module reference if
54+
/// it's not the same as the current context.
55+
void
56+
printModuleNamespaceQualifiersIfNeeded(const ModuleDecl *referencedModule,
57+
const ModuleDecl *currentContext);
58+
5359
/// Print a C++ namespace declaration with the give name and body.
5460
void
5561
printNamespace(llvm::function_ref<void(raw_ostream &OS)> namePrinter,

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,9 +1059,9 @@ class DeclAndTypePrinter::Implementation
10591059
printFunctionClangAttributes(FD, funcTy);
10601060
printAvailability(FD);
10611061
os << " {\n";
1062-
funcPrinter.printCxxThunkBody(funcABI.getSymbolName(), resultTy,
1063-
FD->getParameters(), additionalParams,
1064-
funcTy->isThrowing());
1062+
funcPrinter.printCxxThunkBody(
1063+
funcABI.getSymbolName(), FD->getModuleContext(), resultTy,
1064+
FD->getParameters(), additionalParams, funcTy->isThrowing());
10651065
os << "}\n";
10661066
}
10671067

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,13 @@ class CFunctionSignatureTypePrinter
8585
PrimitiveTypeMapping &typeMapping, OutputLanguageMode languageMode,
8686
SwiftToClangInteropContext &interopContext,
8787
CFunctionSignatureTypePrinterModifierDelegate modifiersDelegate,
88+
const ModuleDecl *moduleContext,
8889
FunctionSignatureTypeUse typeUseKind =
8990
FunctionSignatureTypeUse::ParamType)
9091
: ClangSyntaxPrinter(os), cPrologueOS(cPrologueOS),
9192
typeMapping(typeMapping), interopContext(interopContext),
9293
languageMode(languageMode), modifiersDelegate(modifiersDelegate),
93-
typeUseKind(typeUseKind) {}
94+
moduleContext(moduleContext), typeUseKind(typeUseKind) {}
9495

9596
bool printIfKnownSimpleType(const TypeDecl *typeDecl,
9697
Optional<OptionalTypeKind> optionalKind,
@@ -168,11 +169,12 @@ class CFunctionSignatureTypePrinter
168169

169170
} else {
170171
ClangValueTypePrinter(os, cPrologueOS, typeMapping, interopContext)
171-
.printValueTypeParameterType(decl, languageMode, isInOutParam);
172+
.printValueTypeParameterType(decl, languageMode, moduleContext,
173+
isInOutParam);
172174
}
173175
} else
174176
ClangValueTypePrinter(os, cPrologueOS, typeMapping, interopContext)
175-
.printValueTypeReturnType(decl, languageMode);
177+
.printValueTypeReturnType(decl, languageMode, moduleContext);
176178
}
177179

178180
void visitPart(Type Ty, Optional<OptionalTypeKind> optionalKind,
@@ -186,6 +188,7 @@ class CFunctionSignatureTypePrinter
186188
SwiftToClangInteropContext &interopContext;
187189
OutputLanguageMode languageMode;
188190
CFunctionSignatureTypePrinterModifierDelegate modifiersDelegate;
191+
const ModuleDecl *moduleContext;
189192
FunctionSignatureTypeUse typeUseKind;
190193
};
191194

@@ -195,6 +198,7 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
195198
const AbstractFunctionDecl *FD, StringRef name, Type resultTy,
196199
FunctionSignatureKind kind, ArrayRef<AdditionalParam> additionalParams,
197200
FunctionSignatureModifiers modifiers) {
201+
auto emittedModule = FD->getModuleContext();
198202
OutputLanguageMode outputLang = kind == FunctionSignatureKind::CFunctionProto
199203
? OutputLanguageMode::ObjC
200204
: OutputLanguageMode::Cxx;
@@ -205,8 +209,9 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
205209
CFunctionSignatureTypePrinterModifierDelegate delegate = {}) {
206210
// FIXME: add support for noescape and PrintMultiPartType,
207211
// see DeclAndTypePrinter::print.
208-
CFunctionSignatureTypePrinter typePrinter(
209-
os, cPrologueOS, typeMapping, outputLang, interopContext, delegate);
212+
CFunctionSignatureTypePrinter typePrinter(os, cPrologueOS, typeMapping,
213+
outputLang, interopContext,
214+
delegate, emittedModule);
210215
typePrinter.visit(ty, optionalKind, isInOutParam);
211216

212217
if (!name.empty()) {
@@ -228,7 +233,7 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
228233
DeclAndTypePrinter::getObjectTypeAndOptionality(FD, resultTy);
229234
CFunctionSignatureTypePrinter typePrinter(
230235
os, cPrologueOS, typeMapping, outputLang, interopContext,
231-
CFunctionSignatureTypePrinterModifierDelegate(),
236+
CFunctionSignatureTypePrinterModifierDelegate(), emittedModule,
232237
FunctionSignatureTypeUse::ReturnType);
233238
// Param for indirect return cannot be marked as inout
234239
typePrinter.visit(objTy, retKind, /*isInOutParam=*/false);
@@ -312,8 +317,8 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
312317
}
313318

314319
void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
315-
Type type, StringRef name, bool isInOut, bool isIndirect,
316-
llvm::Optional<AdditionalParam::Role> paramRole) {
320+
Type type, StringRef name, const ModuleDecl *moduleContext, bool isInOut,
321+
bool isIndirect, llvm::Optional<AdditionalParam::Role> paramRole) {
317322
auto namePrinter = [&]() { ClangSyntaxPrinter(os).printIdentifier(name); };
318323
if (!isKnownCxxType(type, typeMapping) &&
319324
!hasKnownOptionalNullableCxxMapping(type)) {
@@ -323,7 +328,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
323328
.printParameterCxxToCUseScaffold(
324329
isIndirect || decl->isResilient() ||
325330
interopContext.getIrABIDetails().shouldPassIndirectly(type),
326-
decl, namePrinter, isInOut,
331+
decl, moduleContext, namePrinter, isInOut,
327332
/*isSelf=*/paramRole &&
328333
*paramRole == AdditionalParam::Role::Self);
329334
return;
@@ -339,12 +344,14 @@ void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
339344

340345
void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
341346
const ParamDecl *param, StringRef name) {
342-
printCxxToCFunctionParameterUse(param->getType(), name, param->isInOut());
347+
printCxxToCFunctionParameterUse(param->getType(), name,
348+
param->getModuleContext(), param->isInOut());
343349
}
344350

345351
void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
346-
StringRef swiftSymbolName, Type resultTy, const ParameterList *params,
347-
ArrayRef<AdditionalParam> additionalParams, bool hasThrows) {
352+
StringRef swiftSymbolName, const ModuleDecl *moduleContext, Type resultTy,
353+
const ParameterList *params, ArrayRef<AdditionalParam> additionalParams,
354+
bool hasThrows) {
348355
if (hasThrows) {
349356
os << " void* opaqueError = nullptr;\n";
350357
os << " void* self = nullptr;\n";
@@ -382,17 +389,17 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
382389
os << ", ";
383390
interleaveComma(additionalParams, os, [&](const AdditionalParam &param) {
384391
if (param.role == AdditionalParam::Role::Self && !hasThrows)
385-
printCxxToCFunctionParameterUse(param.type, "*this", /*isInOut=*/false,
386-
/*isIndirect=*/param.isIndirect,
387-
param.role);
392+
printCxxToCFunctionParameterUse(
393+
param.type, "*this", moduleContext, /*isInOut=*/false,
394+
/*isIndirect=*/param.isIndirect, param.role);
388395
else if(param.role == AdditionalParam::Role::Self && hasThrows)
389-
printCxxToCFunctionParameterUse(param.type, "self", /*isInOut=*/false,
390-
/*isIndirect=*/param.isIndirect,
391-
param.role);
396+
printCxxToCFunctionParameterUse(
397+
param.type, "self", moduleContext, /*isInOut=*/false,
398+
/*isIndirect=*/param.isIndirect, param.role);
392399
else if(param.role == AdditionalParam::Role::Error && hasThrows)
393-
printCxxToCFunctionParameterUse(param.type, "&opaqueError", /*isInOut=*/false,
394-
/*isIndirect=*/param.isIndirect,
395-
param.role);
400+
printCxxToCFunctionParameterUse(
401+
param.type, "&opaqueError", moduleContext, /*isInOut=*/false,
402+
/*isIndirect=*/param.isIndirect, param.role);
396403
});
397404
}
398405

@@ -412,12 +419,13 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
412419
interopContext);
413420
if (isIndirect) {
414421
valueTypePrinter.printValueTypeIndirectReturnScaffold(
415-
decl, [&](StringRef returnParam) {
422+
decl, moduleContext, [&](StringRef returnParam) {
416423
printCallToCFunc(/*additionalParam=*/returnParam);
417424
});
418425
} else {
419426
valueTypePrinter.printValueTypeDirectReturnScaffold(
420-
decl, [&]() { printCallToCFunc(/*additionalParam=*/None); });
427+
decl, moduleContext,
428+
[&]() { printCallToCFunc(/*additionalParam=*/None); });
421429
}
422430
return;
423431
}
@@ -464,8 +472,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
464472
typeDeclContext->getDeclaredType(),
465473
/*isIndirect=*/isMutating,
466474
});
467-
printCxxThunkBody(swiftSymbolName, resultTy, FD->getParameters(),
468-
additionalParams, FD->hasThrows());
475+
printCxxThunkBody(swiftSymbolName, FD->getModuleContext(), resultTy,
476+
FD->getParameters(), additionalParams, FD->hasThrows());
469477
os << " }\n";
470478
}
471479

@@ -482,7 +490,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
482490
CFunctionSignatureTypePrinter typePrinter(
483491
os, cPrologueOS, typeMapping, OutputLanguageMode::Cxx, interopContext,
484492
CFunctionSignatureTypePrinterModifierDelegate(),
485-
FunctionSignatureTypeUse::ReturnType);
493+
accessor->getModuleContext(), FunctionSignatureTypeUse::ReturnType);
486494
typePrinter.visit(objTy, retKind, /*isInOut=*/false);
487495

488496
ClangSyntaxPrinter printer(os);
@@ -506,7 +514,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
506514
}
507515
os << " {\n";
508516
// FIXME: should it be objTy for resultTy?
509-
printCxxThunkBody(swiftSymbolName, resultTy, accessor->getParameters(),
517+
printCxxThunkBody(swiftSymbolName, accessor->getModuleContext(), resultTy,
518+
accessor->getParameters(),
510519
{AdditionalParam{AdditionalParam::Role::Self,
511520
typeDeclContext->getDeclaredType(),
512521
/*isIndirect=*/false}});

lib/PrintAsClang/PrintClangFunction.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
#include "swift/AST/Type.h"
1717
#include "swift/Basic/LLVM.h"
18-
#include "swift/IRGen/IRABIDetailsProvider.h"
1918
#include "llvm/ADT/ArrayRef.h"
2019
#include "llvm/ADT/Optional.h"
2120
#include "llvm/ADT/StringRef.h"
@@ -26,6 +25,7 @@ namespace swift {
2625
class AbstractFunctionDecl;
2726
class AccessorDecl;
2827
class FuncDecl;
28+
class ModuleDecl;
2929
class NominalTypeDecl;
3030
class ParamDecl;
3131
class ParameterList;
@@ -82,7 +82,8 @@ class DeclAndTypeClangFunctionPrinter {
8282

8383
/// Print the body of the inline C++ function thunk that calls the underlying
8484
/// Swift function.
85-
void printCxxThunkBody(StringRef swiftSymbolName, Type resultTy,
85+
void printCxxThunkBody(StringRef swiftSymbolName,
86+
const ModuleDecl *moduleContext, Type resultTy,
8687
const ParameterList *params,
8788
ArrayRef<AdditionalParam> additionalParams = {},
8889
bool hasThrows = false);
@@ -101,7 +102,8 @@ class DeclAndTypeClangFunctionPrinter {
101102

102103
private:
103104
void printCxxToCFunctionParameterUse(
104-
Type type, StringRef name, bool isInOut, bool isIndirect = false,
105+
Type type, StringRef name, const ModuleDecl *moduleContext, bool isInOut,
106+
bool isIndirect = false,
105107
llvm::Optional<AdditionalParam::Role> paramRole = None);
106108

107109
bool hasKnownOptionalNullableCxxMapping(Type type);

lib/PrintAsClang/PrintClangValueType.cpp

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,13 @@ static void printCTypeName(raw_ostream &os, const NominalTypeDecl *type) {
3535
}
3636

3737
/// Print out the C++ type name of a struct/enum declaration.
38-
static void printCxxTypeName(raw_ostream &os, const NominalTypeDecl *type) {
39-
// FIXME: Print namespace qualifiers for references from other modules.
38+
static void printCxxTypeName(raw_ostream &os, const NominalTypeDecl *type,
39+
const ModuleDecl *moduleContext) {
4040
// FIXME: Print class qualifiers for nested class references.
41-
ClangSyntaxPrinter(os).printBaseName(type);
41+
ClangSyntaxPrinter printer(os);
42+
printer.printModuleNamespaceQualifiersIfNeeded(type->getModuleContext(),
43+
moduleContext);
44+
printer.printBaseName(type);
4245
}
4346

4447
/// Print out the C++ type name of the implementation class that provides hidden
@@ -236,6 +239,7 @@ void ClangValueTypePrinter::printValueTypeDecl(
236239
os << ";\n";
237240
os << "};\n\n";
238241

242+
const auto *moduleContext = typeDecl->getModuleContext();
239243
// Print out the "hidden" _impl class.
240244
printer.printNamespace(
241245
cxx_synthesis::getCxxImplNamespaceName(), [&](raw_ostream &os) {
@@ -245,19 +249,19 @@ void ClangValueTypePrinter::printValueTypeDecl(
245249
os << "public:\n";
246250

247251
os << " static inline char * _Nonnull getOpaquePointer(";
248-
printCxxTypeName(os, typeDecl);
252+
printCxxTypeName(os, typeDecl, moduleContext);
249253
os << " &object) { return object._getOpaquePointer(); }\n";
250254

251255
os << " static inline const char * _Nonnull getOpaquePointer(const ";
252-
printCxxTypeName(os, typeDecl);
256+
printCxxTypeName(os, typeDecl, moduleContext);
253257
os << " &object) { return object._getOpaquePointer(); }\n";
254258

255259
os << " template<class T>\n";
256260
os << " static inline ";
257-
printCxxTypeName(os, typeDecl);
261+
printCxxTypeName(os, typeDecl, moduleContext);
258262
os << " returnNewValue(T callable) {\n";
259263
os << " auto result = ";
260-
printCxxTypeName(os, typeDecl);
264+
printCxxTypeName(os, typeDecl, moduleContext);
261265
os << "::_make();\n";
262266
os << " callable(result._getOpaquePointer());\n";
263267
os << " return result;\n";
@@ -348,7 +352,7 @@ void ClangValueTypePrinter::printCStubTypeName(const NominalTypeDecl *type) {
348352

349353
void ClangValueTypePrinter::printValueTypeParameterType(
350354
const NominalTypeDecl *type, OutputLanguageMode outputLang,
351-
bool isInOutParam) {
355+
const ModuleDecl *moduleContext, bool isInOutParam) {
352356
assert(isa<StructDecl>(type) || isa<EnumDecl>(type));
353357
if (outputLang != OutputLanguageMode::Cxx) {
354358
if (!isInOutParam) {
@@ -365,13 +369,14 @@ void ClangValueTypePrinter::printValueTypeParameterType(
365369
if (!isInOutParam) {
366370
os << "const ";
367371
}
368-
printCxxTypeName(os, type);
372+
printCxxTypeName(os, type, moduleContext);
369373
os << '&';
370374
}
371375

372376
void ClangValueTypePrinter::printParameterCxxToCUseScaffold(
373377
bool isIndirect, const NominalTypeDecl *type,
374-
llvm::function_ref<void()> cxxParamPrinter, bool isInOut, bool isSelf) {
378+
const ModuleDecl *moduleContext, llvm::function_ref<void()> cxxParamPrinter,
379+
bool isInOut, bool isSelf) {
375380
// A Swift value type is passed to its underlying Swift function
376381
assert(isa<StructDecl>(type) || isa<EnumDecl>(type));
377382
if (!isIndirect && !isInOut) {
@@ -383,6 +388,8 @@ void ClangValueTypePrinter::printParameterCxxToCUseScaffold(
383388
if (isSelf) {
384389
os << "_getOpaquePointer()";
385390
} else {
391+
ClangSyntaxPrinter(os).printModuleNamespaceQualifiersIfNeeded(
392+
type->getModuleContext(), moduleContext);
386393
os << cxx_synthesis::getCxxImplNamespaceName() << "::";
387394
printCxxImplClassName(os, type);
388395
os << "::getOpaquePointer(";
@@ -395,21 +402,25 @@ void ClangValueTypePrinter::printParameterCxxToCUseScaffold(
395402
}
396403

397404
void ClangValueTypePrinter::printValueTypeReturnType(
398-
const NominalTypeDecl *type, OutputLanguageMode outputLang) {
405+
const NominalTypeDecl *type, OutputLanguageMode outputLang,
406+
const ModuleDecl *moduleContext) {
399407
assert(isa<StructDecl>(type) || isa<EnumDecl>(type));
400408
if (outputLang == OutputLanguageMode::Cxx) {
401-
printCxxTypeName(os, type);
409+
printCxxTypeName(os, type, moduleContext);
402410
} else {
403411
os << "struct ";
404412
printCStubTypeName(type);
405413
}
406414
}
407415

408416
void ClangValueTypePrinter::printValueTypeIndirectReturnScaffold(
409-
const NominalTypeDecl *type,
417+
const NominalTypeDecl *type, const ModuleDecl *moduleContext,
410418
llvm::function_ref<void(StringRef)> bodyPrinter) {
411419
assert(isa<StructDecl>(type) || isa<EnumDecl>(type));
412-
os << " return " << cxx_synthesis::getCxxImplNamespaceName() << "::";
420+
os << " return ";
421+
ClangSyntaxPrinter(os).printModuleNamespaceQualifiersIfNeeded(
422+
type->getModuleContext(), moduleContext);
423+
os << cxx_synthesis::getCxxImplNamespaceName() << "::";
413424
printCxxImplClassName(os, type);
414425
os << "::returnNewValue([&](void * _Nonnull result) {\n ";
415426
bodyPrinter("result");
@@ -418,9 +429,13 @@ void ClangValueTypePrinter::printValueTypeIndirectReturnScaffold(
418429
}
419430

420431
void ClangValueTypePrinter::printValueTypeDirectReturnScaffold(
421-
const NominalTypeDecl *type, llvm::function_ref<void()> bodyPrinter) {
432+
const NominalTypeDecl *type, const ModuleDecl *moduleContext,
433+
llvm::function_ref<void()> bodyPrinter) {
422434
assert(isa<StructDecl>(type) || isa<EnumDecl>(type));
423-
os << " return " << cxx_synthesis::getCxxImplNamespaceName() << "::";
435+
os << " return ";
436+
ClangSyntaxPrinter(os).printModuleNamespaceQualifiersIfNeeded(
437+
type->getModuleContext(), moduleContext);
438+
os << cxx_synthesis::getCxxImplNamespaceName() << "::";
424439
printCxxImplClassName(os, type);
425440
os << "::returnNewValue([&](char * _Nonnull result) {\n";
426441
os << " ";

0 commit comments

Comments
 (0)