15
15
#include " OutputLanguageMode.h"
16
16
#include " PrimitiveTypeMapping.h"
17
17
#include " SwiftToClangInteropContext.h"
18
+ #include " swift/AST/ASTMangler.h"
18
19
#include " swift/AST/Decl.h"
19
20
#include " swift/AST/ParameterList.h"
20
21
#include " swift/AST/Type.h"
27
28
using namespace swift ;
28
29
29
30
// / Print out the C type name of a struct/enum declaration.
30
- static void printCTypeName (raw_ostream &os, const NominalTypeDecl *type) {
31
+ static void printCTypeName (raw_ostream &os, const NominalTypeDecl *type,
32
+ ArrayRef<Type> genericArgs = {}) {
31
33
ClangSyntaxPrinter printer (os);
32
34
printer.printModuleNameCPrefix (*type->getParentModule ());
33
35
// FIXME: add nested type qualifiers to fully disambiguate the name.
34
36
printer.printBaseName (type);
37
+ if (!genericArgs.empty ()) {
38
+ os << ' _' ;
39
+ llvm::interleave (
40
+ genericArgs, os,
41
+ [&](Type t) {
42
+ swift::Mangle::ASTMangler mangler;
43
+ os << mangler.mangleTypeWithoutPrefix (t);
44
+ },
45
+ " _" );
46
+ }
35
47
}
36
48
37
49
// / Print out the C++ type name of a struct/enum declaration.
@@ -385,29 +397,19 @@ void ClangValueTypePrinter::printValueTypeDecl(
385
397
printTypeGenericTraits (os, typeDecl, typeMetadataFuncName);
386
398
}
387
399
388
- // / Print the name of the C stub struct for passing/returning a value type
389
- // / directly to/from swiftcc function.
390
- static void printStubCTypeName (raw_ostream &os, const NominalTypeDecl *type) {
391
- os << " swift_interop_stub_" ;
392
- printCTypeName (os, type);
393
- }
394
-
395
400
// / Print out the C stub struct that's used to pass/return a value type directly
396
401
// / to/from swiftcc function.
397
402
static void
398
- printCStructStubForDirectPassing (raw_ostream &os, const NominalTypeDecl *SD ,
403
+ printCStructStubForDirectPassing (raw_ostream &os, StringRef stubName, Type type ,
399
404
PrimitiveTypeMapping &typeMapping,
400
405
SwiftToClangInteropContext &interopContext) {
401
406
// Print out a C stub for this value type.
402
407
os << " // Stub struct to be used to pass/return values to/from Swift "
403
408
" functions.\n " ;
404
- os << " struct " ;
405
- printStubCTypeName (os, SD);
406
- os << " {\n " ;
409
+ os << " struct " << stubName << " {\n " ;
407
410
llvm::SmallVector<std::pair<clang::CharUnits, clang::CharUnits>, 8 > fields;
408
411
interopContext.getIrABIDetails ().enumerateDirectPassingRecordMembers (
409
- SD->getDeclaredType (),
410
- [&](clang::CharUnits offset, clang::CharUnits end, Type t) {
412
+ type, [&](clang::CharUnits offset, clang::CharUnits end, Type t) {
411
413
auto info =
412
414
typeMapping.getKnownCTypeInfo (t->getNominalOrBoundGenericNominal ());
413
415
if (!info)
@@ -419,13 +421,12 @@ printCStructStubForDirectPassing(raw_ostream &os, const NominalTypeDecl *SD,
419
421
fields.push_back (std::make_pair (offset, end));
420
422
});
421
423
os << " };\n\n " ;
424
+ auto minimalStubName = stubName;
425
+ minimalStubName.consume_front (" swift_interop_stub_" );
422
426
423
427
// Emit a stub that returns a value directly from swiftcc function.
424
- os << " static inline void swift_interop_returnDirect_" ;
425
- printCTypeName (os, SD);
426
- os << " (char * _Nonnull result, struct " ;
427
- printStubCTypeName (os, SD);
428
- os << " value" ;
428
+ os << " static inline void swift_interop_returnDirect_" << minimalStubName;
429
+ os << " (char * _Nonnull result, struct " << stubName << " value" ;
429
430
os << " ) __attribute__((always_inline)) {\n " ;
430
431
for (size_t i = 0 ; i < fields.size (); ++i) {
431
432
os << " memcpy(result + " << fields[i].first .getQuantity () << " , "
@@ -435,14 +436,10 @@ printCStructStubForDirectPassing(raw_ostream &os, const NominalTypeDecl *SD,
435
436
os << " }\n\n " ;
436
437
437
438
// Emit a stub that is used to pass value type directly to swiftcc function.
438
- os << " static inline struct " ;
439
- printStubCTypeName (os, SD);
440
- os << " swift_interop_passDirect_" ;
441
- printCTypeName (os, SD);
439
+ os << " static inline struct " << stubName << " swift_interop_passDirect_"
440
+ << minimalStubName;
442
441
os << " (const char * _Nonnull value) __attribute__((always_inline)) {\n " ;
443
- os << " struct " ;
444
- printStubCTypeName (os, SD);
445
- os << " result;\n " ;
442
+ os << " struct " << stubName << " result;\n " ;
446
443
for (size_t i = 0 ; i < fields.size (); ++i) {
447
444
os << " memcpy(&result._" << (i + 1 ) << " , value + "
448
445
<< fields[i].first .getQuantity () << " , "
@@ -452,38 +449,6 @@ printCStructStubForDirectPassing(raw_ostream &os, const NominalTypeDecl *SD,
452
449
os << " }\n\n " ;
453
450
}
454
451
455
- void ClangValueTypePrinter::printCStubTypeName (const NominalTypeDecl *type) {
456
- printStubCTypeName (os, type);
457
- // Ensure the stub is declared in the header.
458
- interopContext.runIfStubForDeclNotEmitted (type, [&]() {
459
- printCStructStubForDirectPassing (cPrologueOS, type, typeMapping,
460
- interopContext);
461
- });
462
- }
463
-
464
- void ClangValueTypePrinter::printValueTypeParameterType (
465
- const NominalTypeDecl *type, OutputLanguageMode outputLang,
466
- const ModuleDecl *moduleContext, bool isInOutParam) {
467
- assert (isa<StructDecl>(type) || isa<EnumDecl>(type));
468
- if (outputLang != OutputLanguageMode::Cxx) {
469
- if (!isInOutParam) {
470
- // C functions only take stub values directly as parameters.
471
- os << " struct " ;
472
- printCStubTypeName (type);
473
- } else {
474
- // Directly pass the pointer (from getOpaquePointer) to C interface
475
- // when in inout mode
476
- os << " char * _Nonnull" ;
477
- }
478
- return ;
479
- }
480
- if (!isInOutParam) {
481
- os << " const " ;
482
- }
483
- printCxxTypeName (os, type, moduleContext);
484
- os << ' &' ;
485
- }
486
-
487
452
void ClangValueTypePrinter::printParameterCxxToCUseScaffold (
488
453
bool isIndirect, const NominalTypeDecl *type,
489
454
const ModuleDecl *moduleContext, llvm::function_ref<void ()> typePrinter,
@@ -514,6 +479,7 @@ void ClangValueTypePrinter::printValueTypeReturnType(
514
479
const NominalTypeDecl *type, OutputLanguageMode outputLang,
515
480
TypeUseKind typeUse, const ModuleDecl *moduleContext) {
516
481
assert (isa<StructDecl>(type) || isa<EnumDecl>(type));
482
+ assert (outputLang == OutputLanguageMode::Cxx);
517
483
// FIXME: make a type use.
518
484
if (outputLang == OutputLanguageMode::Cxx) {
519
485
if (typeUse == TypeUseKind::CxxTypeName)
@@ -525,12 +491,27 @@ void ClangValueTypePrinter::printValueTypeReturnType(
525
491
os << cxx_synthesis::getCxxImplNamespaceName () << " ::" ;
526
492
printCxxImplClassName (os, type);
527
493
}
528
- } else {
529
- os << " struct " ;
530
- printCStubTypeName (type);
531
494
}
532
495
}
533
496
497
+ void ClangValueTypePrinter::printCStubType (Type type,
498
+ const NominalTypeDecl *typeDecl,
499
+ ArrayRef<Type> genericArgs) {
500
+ os << " struct " ;
501
+ std::string stubName;
502
+ {
503
+ llvm::raw_string_ostream stubNameOS (stubName);
504
+ stubNameOS << " swift_interop_stub_" ;
505
+ printCTypeName (stubNameOS, typeDecl, genericArgs);
506
+ }
507
+ os << stubName;
508
+ // Ensure the stub is declared in the header.
509
+ interopContext.runIfStubForDeclNotEmitted (stubName, [&]() {
510
+ printCStructStubForDirectPassing (cPrologueOS, stubName, type, typeMapping,
511
+ interopContext);
512
+ });
513
+ }
514
+
534
515
void ClangValueTypePrinter::printValueTypeIndirectReturnScaffold (
535
516
const NominalTypeDecl *type, const ModuleDecl *moduleContext,
536
517
llvm::function_ref<void ()> typePrinter,
@@ -545,19 +526,17 @@ void ClangValueTypePrinter::printValueTypeIndirectReturnScaffold(
545
526
}
546
527
547
528
void ClangValueTypePrinter::printValueTypeDirectReturnScaffold (
548
- const NominalTypeDecl *type, const ModuleDecl *moduleContext,
529
+ const NominalTypeDecl *type, ArrayRef<Type> genericArgs,
530
+ const ModuleDecl *moduleContext, llvm::function_ref<void ()> typePrinter,
549
531
llvm::function_ref<void()> bodyPrinter) {
550
532
assert (isa<StructDecl>(type) || isa<EnumDecl>(type));
551
533
os << " return " ;
552
- ClangSyntaxPrinter (os).printModuleNamespaceQualifiersIfNeeded (
553
- type->getModuleContext (), moduleContext);
554
- os << cxx_synthesis::getCxxImplNamespaceName () << " ::" ;
555
- printCxxImplClassName (os, type);
534
+ typePrinter ();
556
535
os << " ::returnNewValue([&](char * _Nonnull result) {\n " ;
557
536
os << " " ;
558
537
os << cxx_synthesis::getCxxImplNamespaceName () << " ::"
559
538
<< " swift_interop_returnDirect_" ;
560
- printCTypeName (os, type);
539
+ printCTypeName (os, type, genericArgs );
561
540
os << " (result, " ;
562
541
bodyPrinter ();
563
542
os << " );\n " ;
0 commit comments