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.
@@ -402,29 +414,19 @@ void ClangValueTypePrinter::printValueTypeDecl(
402
414
printTypeGenericTraits (os, typeDecl, typeMetadataFuncName);
403
415
}
404
416
405
- // / Print the name of the C stub struct for passing/returning a value type
406
- // / directly to/from swiftcc function.
407
- static void printStubCTypeName (raw_ostream &os, const NominalTypeDecl *type) {
408
- os << " swift_interop_stub_" ;
409
- printCTypeName (os, type);
410
- }
411
-
412
417
// / Print out the C stub struct that's used to pass/return a value type directly
413
418
// / to/from swiftcc function.
414
419
static void
415
- printCStructStubForDirectPassing (raw_ostream &os, const NominalTypeDecl *SD ,
420
+ printCStructStubForDirectPassing (raw_ostream &os, StringRef stubName, Type type ,
416
421
PrimitiveTypeMapping &typeMapping,
417
422
SwiftToClangInteropContext &interopContext) {
418
423
// Print out a C stub for this value type.
419
424
os << " // Stub struct to be used to pass/return values to/from Swift "
420
425
" functions.\n " ;
421
- os << " struct " ;
422
- printStubCTypeName (os, SD);
423
- os << " {\n " ;
426
+ os << " struct " << stubName << " {\n " ;
424
427
llvm::SmallVector<std::pair<clang::CharUnits, clang::CharUnits>, 8 > fields;
425
428
interopContext.getIrABIDetails ().enumerateDirectPassingRecordMembers (
426
- SD->getDeclaredType (),
427
- [&](clang::CharUnits offset, clang::CharUnits end, Type t) {
429
+ type, [&](clang::CharUnits offset, clang::CharUnits end, Type t) {
428
430
auto info =
429
431
typeMapping.getKnownCTypeInfo (t->getNominalOrBoundGenericNominal ());
430
432
if (!info)
@@ -436,13 +438,12 @@ printCStructStubForDirectPassing(raw_ostream &os, const NominalTypeDecl *SD,
436
438
fields.push_back (std::make_pair (offset, end));
437
439
});
438
440
os << " };\n\n " ;
441
+ auto minimalStubName = stubName;
442
+ minimalStubName.consume_front (" swift_interop_stub_" );
439
443
440
444
// Emit a stub that returns a value directly from swiftcc function.
441
- os << " static inline void swift_interop_returnDirect_" ;
442
- printCTypeName (os, SD);
443
- os << " (char * _Nonnull result, struct " ;
444
- printStubCTypeName (os, SD);
445
- os << " value" ;
445
+ os << " static inline void swift_interop_returnDirect_" << minimalStubName;
446
+ os << " (char * _Nonnull result, struct " << stubName << " value" ;
446
447
os << " ) __attribute__((always_inline)) {\n " ;
447
448
for (size_t i = 0 ; i < fields.size (); ++i) {
448
449
os << " memcpy(result + " << fields[i].first .getQuantity () << " , "
@@ -452,14 +453,10 @@ printCStructStubForDirectPassing(raw_ostream &os, const NominalTypeDecl *SD,
452
453
os << " }\n\n " ;
453
454
454
455
// Emit a stub that is used to pass value type directly to swiftcc function.
455
- os << " static inline struct " ;
456
- printStubCTypeName (os, SD);
457
- os << " swift_interop_passDirect_" ;
458
- printCTypeName (os, SD);
456
+ os << " static inline struct " << stubName << " swift_interop_passDirect_"
457
+ << minimalStubName;
459
458
os << " (const char * _Nonnull value) __attribute__((always_inline)) {\n " ;
460
- os << " struct " ;
461
- printStubCTypeName (os, SD);
462
- os << " result;\n " ;
459
+ os << " struct " << stubName << " result;\n " ;
463
460
for (size_t i = 0 ; i < fields.size (); ++i) {
464
461
os << " memcpy(&result._" << (i + 1 ) << " , value + "
465
462
<< fields[i].first .getQuantity () << " , "
@@ -469,38 +466,6 @@ printCStructStubForDirectPassing(raw_ostream &os, const NominalTypeDecl *SD,
469
466
os << " }\n\n " ;
470
467
}
471
468
472
- void ClangValueTypePrinter::printCStubTypeName (const NominalTypeDecl *type) {
473
- printStubCTypeName (os, type);
474
- // Ensure the stub is declared in the header.
475
- interopContext.runIfStubForDeclNotEmitted (type, [&]() {
476
- printCStructStubForDirectPassing (cPrologueOS, type, typeMapping,
477
- interopContext);
478
- });
479
- }
480
-
481
- void ClangValueTypePrinter::printValueTypeParameterType (
482
- const NominalTypeDecl *type, OutputLanguageMode outputLang,
483
- const ModuleDecl *moduleContext, bool isInOutParam) {
484
- assert (isa<StructDecl>(type) || isa<EnumDecl>(type));
485
- if (outputLang != OutputLanguageMode::Cxx) {
486
- if (!isInOutParam) {
487
- // C functions only take stub values directly as parameters.
488
- os << " struct " ;
489
- printCStubTypeName (type);
490
- } else {
491
- // Directly pass the pointer (from getOpaquePointer) to C interface
492
- // when in inout mode
493
- os << " char * _Nonnull" ;
494
- }
495
- return ;
496
- }
497
- if (!isInOutParam) {
498
- os << " const " ;
499
- }
500
- printCxxTypeName (os, type, moduleContext);
501
- os << ' &' ;
502
- }
503
-
504
469
void ClangValueTypePrinter::printParameterCxxToCUseScaffold (
505
470
bool isIndirect, const NominalTypeDecl *type,
506
471
const ModuleDecl *moduleContext, llvm::function_ref<void ()> typePrinter,
@@ -531,6 +496,7 @@ void ClangValueTypePrinter::printValueTypeReturnType(
531
496
const NominalTypeDecl *type, OutputLanguageMode outputLang,
532
497
TypeUseKind typeUse, const ModuleDecl *moduleContext) {
533
498
assert (isa<StructDecl>(type) || isa<EnumDecl>(type));
499
+ assert (outputLang == OutputLanguageMode::Cxx);
534
500
// FIXME: make a type use.
535
501
if (outputLang == OutputLanguageMode::Cxx) {
536
502
if (typeUse == TypeUseKind::CxxTypeName)
@@ -542,12 +508,27 @@ void ClangValueTypePrinter::printValueTypeReturnType(
542
508
os << cxx_synthesis::getCxxImplNamespaceName () << " ::" ;
543
509
printCxxImplClassName (os, type);
544
510
}
545
- } else {
546
- os << " struct " ;
547
- printCStubTypeName (type);
548
511
}
549
512
}
550
513
514
+ void ClangValueTypePrinter::printCStubType (Type type,
515
+ const NominalTypeDecl *typeDecl,
516
+ ArrayRef<Type> genericArgs) {
517
+ os << " struct " ;
518
+ std::string stubName;
519
+ {
520
+ llvm::raw_string_ostream stubNameOS (stubName);
521
+ stubNameOS << " swift_interop_stub_" ;
522
+ printCTypeName (stubNameOS, typeDecl, genericArgs);
523
+ }
524
+ os << stubName;
525
+ // Ensure the stub is declared in the header.
526
+ interopContext.runIfStubForDeclNotEmitted (stubName, [&]() {
527
+ printCStructStubForDirectPassing (cPrologueOS, stubName, type, typeMapping,
528
+ interopContext);
529
+ });
530
+ }
531
+
551
532
void ClangValueTypePrinter::printValueTypeIndirectReturnScaffold (
552
533
const NominalTypeDecl *type, const ModuleDecl *moduleContext,
553
534
llvm::function_ref<void ()> typePrinter,
@@ -562,19 +543,17 @@ void ClangValueTypePrinter::printValueTypeIndirectReturnScaffold(
562
543
}
563
544
564
545
void ClangValueTypePrinter::printValueTypeDirectReturnScaffold (
565
- const NominalTypeDecl *type, const ModuleDecl *moduleContext,
546
+ const NominalTypeDecl *type, ArrayRef<Type> genericArgs,
547
+ const ModuleDecl *moduleContext, llvm::function_ref<void ()> typePrinter,
566
548
llvm::function_ref<void()> bodyPrinter) {
567
549
assert (isa<StructDecl>(type) || isa<EnumDecl>(type));
568
550
os << " return " ;
569
- ClangSyntaxPrinter (os).printModuleNamespaceQualifiersIfNeeded (
570
- type->getModuleContext (), moduleContext);
571
- os << cxx_synthesis::getCxxImplNamespaceName () << " ::" ;
572
- printCxxImplClassName (os, type);
551
+ typePrinter ();
573
552
os << " ::returnNewValue([&](char * _Nonnull result) {\n " ;
574
553
os << " " ;
575
554
os << cxx_synthesis::getCxxImplNamespaceName () << " ::"
576
555
<< " swift_interop_returnDirect_" ;
577
- printCTypeName (os, type);
556
+ printCTypeName (os, type, genericArgs );
578
557
os << " (result, " ;
579
558
bodyPrinter ();
580
559
os << " );\n " ;
0 commit comments