Skip to content

Commit 5e8dc12

Browse files
authored
Merge pull request #61107 from hyp/eng/generic-enum
[interop][SwiftToCxx] initial generic enum support
2 parents ad5fdf7 + 7925701 commit 5e8dc12

File tree

6 files changed

+534
-146
lines changed

6 files changed

+534
-146
lines changed

lib/IRGen/IRABIDetailsProvider.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ class IRABIDetailsProviderImpl {
111111
getEnumTagMapping(const EnumDecl *ED) {
112112
llvm::MapVector<EnumElementDecl *, IRABIDetailsProvider::EnumElementInfo>
113113
elements;
114-
auto &enumImplStrat =
115-
getEnumImplStrategy(IGM, ED->getDeclaredType()->getCanonicalType());
114+
auto &enumImplStrat = getEnumImplStrategy(
115+
IGM, ED->DeclContext::getDeclaredTypeInContext()->getCanonicalType());
116116

117117
for (auto *element : ED->getAllElements()) {
118118
auto tagIdx = enumImplStrat.getTagIndex(element);

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 131 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -434,12 +434,15 @@ class DeclAndTypePrinter::Implementation
434434

435435
os << " inline bool is" << name << "() const;\n";
436436

437+
outOfLineSyntaxPrinter
438+
.printNominalTypeOutsideMemberDeclTemplateSpecifiers(ED);
437439
outOfLineOS << " inline bool ";
438-
outOfLineSyntaxPrinter.printBaseName(ED);
439-
outOfLineOS << "::is" << name << "() const {\n";
440+
outOfLineSyntaxPrinter.printNominalTypeQualifier(
441+
ED, /*moduleContext=*/ED->getModuleContext());
442+
outOfLineOS << "is" << name << "() const {\n";
440443
outOfLineOS << " return *this == ";
441-
outOfLineSyntaxPrinter.printBaseName(ED);
442-
outOfLineOS << "::";
444+
outOfLineSyntaxPrinter.printNominalTypeQualifier(
445+
ED, /*moduleContext=*/ED->getModuleContext());
443446
outOfLineSyntaxPrinter.printIdentifier(caseName);
444447
outOfLineOS << ";\n";
445448
outOfLineOS << " }\n";
@@ -452,12 +455,7 @@ class DeclAndTypePrinter::Implementation
452455
associatedValueList->size() > 1) {
453456
return;
454457
}
455-
auto paramType = associatedValueList->front()->getType();
456-
Type objectType;
457-
OptionalTypeKind optKind;
458-
std::tie(objectType, optKind) = getObjectTypeAndOptionality(
459-
paramType->getNominalOrBoundGenericNominal(), paramType);
460-
auto objectTypeDecl = objectType->getNominalOrBoundGenericNominal();
458+
auto paramType = associatedValueList->front()->getInterfaceType();
461459

462460
std::string declName, defName, name;
463461
llvm::raw_string_ostream declOS(declName), defOS(defName), nameOS(name);
@@ -469,9 +467,12 @@ class DeclAndTypePrinter::Implementation
469467
[&](auto &types) {
470468
// Printing function name and return type
471469
os << " inline " << types[paramType] << " get" << name;
470+
outOfLineSyntaxPrinter
471+
.printNominalTypeOutsideMemberDeclTemplateSpecifiers(ED);
472472
outOfLineOS << " inline " << types[paramType] << ' ';
473-
outOfLineSyntaxPrinter.printBaseName(ED);
474-
outOfLineOS << "::get" << name;
473+
outOfLineSyntaxPrinter.printNominalTypeQualifier(
474+
ED, /*moduleContext=*/ED->getModuleContext());
475+
outOfLineOS << "get" << name;
475476
},
476477
[&](auto &types) {}, true,
477478
[&](auto &types) {
@@ -487,6 +488,20 @@ class DeclAndTypePrinter::Implementation
487488
outOfLineOS << "(*this);\n";
488489
outOfLineOS << " char * _Nonnull payloadFromDestruction = "
489490
"thisCopy->_destructiveProjectEnumData();\n";
491+
if (const auto *gtpt = paramType->getAs<GenericTypeParamType>()) {
492+
DeclAndTypeClangFunctionPrinter::printGenericReturnSequence(
493+
outOfLineOS, gtpt, [](StringRef) {},
494+
/*initializeWithTake=*/StringRef("payloadFromDestruction"));
495+
return;
496+
}
497+
// FIXME: unify non-generic return with regular function emission
498+
// return path.
499+
Type objectType;
500+
OptionalTypeKind optKind;
501+
std::tie(objectType, optKind) = getObjectTypeAndOptionality(
502+
paramType->getNominalOrBoundGenericNominal(), paramType);
503+
auto objectTypeDecl = objectType->getNominalOrBoundGenericNominal();
504+
490505
if (auto knownCxxType =
491506
owningPrinter.typeMapping.getKnownCxxTypeInfo(
492507
objectTypeDecl)) {
@@ -553,107 +568,115 @@ class DeclAndTypePrinter::Implementation
553568
neededTypes.push_back(paramType);
554569
}
555570

556-
clangFuncPrinter.printCustomCxxFunction(
557-
neededTypes,
558-
[&](auto &types) {
559-
// Printing function name and return type
560-
os << " inline ";
561-
syntaxPrinter.printBaseName(elementDecl->getParentEnum());
562-
os << " operator()";
563-
564-
outOfLineOS << " inline ";
565-
outOfLineSyntaxPrinter.printBaseName(
566-
elementDecl->getParentEnum());
567-
outOfLineOS << ' ';
568-
outOfLineSyntaxPrinter.printBaseName(
569-
elementDecl->getParentEnum());
570-
outOfLineOS << "::_impl_" << elementDecl->getNameStr()
571-
<< "::operator()";
572-
},
573-
[&](auto &types) {
574-
// Printing parameters
575-
if (!paramType) {
576-
return;
577-
}
578-
assert(objectTypeDecl != nullptr);
579-
if (owningPrinter.typeMapping.getKnownCxxTypeInfo(
580-
objectTypeDecl)) {
581-
os << types[paramType] << " val";
582-
outOfLineOS << types[paramType] << " val";
583-
} else {
584-
os << "const " << types[paramType] << " &val";
585-
outOfLineOS << "const " << types[paramType] << " &val";
586-
}
587-
},
588-
true,
589-
[&](auto &types) {
590-
// Printing function body
591-
outOfLineOS << " auto result = ";
592-
outOfLineSyntaxPrinter.printBaseName(
593-
elementDecl->getParentEnum());
594-
outOfLineOS << "::_make();\n";
595-
596-
if (paramType) {
571+
// FIXME: support generic constructor.
572+
if (!ED->isGeneric())
573+
clangFuncPrinter.printCustomCxxFunction(
574+
neededTypes,
575+
[&](auto &types) {
576+
// Printing function name and return type
577+
os << " inline ";
578+
syntaxPrinter.printBaseName(elementDecl->getParentEnum());
579+
os << " operator()";
580+
581+
outOfLineOS << " inline ";
582+
outOfLineSyntaxPrinter.printBaseName(
583+
elementDecl->getParentEnum());
584+
outOfLineOS << ' ';
585+
outOfLineSyntaxPrinter.printBaseName(
586+
elementDecl->getParentEnum());
587+
outOfLineOS << "::_impl_" << elementDecl->getNameStr()
588+
<< "::operator()";
589+
},
590+
[&](auto &types) {
591+
// Printing parameters
592+
if (!paramType) {
593+
return;
594+
}
597595
assert(objectTypeDecl != nullptr);
598-
599596
if (owningPrinter.typeMapping.getKnownCxxTypeInfo(
600597
objectTypeDecl)) {
601-
outOfLineOS << " memcpy(result._getOpaquePointer(), &val, "
602-
"sizeof(val));\n";
598+
os << types[paramType] << " val";
599+
outOfLineOS << types[paramType] << " val";
600+
} else {
601+
os << "const " << types[paramType] << " &val";
602+
outOfLineOS << "const " << types[paramType] << " &val";
603+
}
604+
},
605+
true,
606+
[&](auto &types) {
607+
// Printing function body
608+
outOfLineOS << " auto result = ";
609+
outOfLineSyntaxPrinter.printBaseName(
610+
elementDecl->getParentEnum());
611+
outOfLineOS << "::_make();\n";
612+
613+
if (paramType) {
614+
assert(objectTypeDecl != nullptr);
615+
616+
if (owningPrinter.typeMapping.getKnownCxxTypeInfo(
617+
objectTypeDecl)) {
618+
outOfLineOS
619+
<< " memcpy(result._getOpaquePointer(), &val, "
620+
"sizeof(val));\n";
621+
} else {
622+
outOfLineOS << " alignas(";
623+
outOfLineSyntaxPrinter
624+
.printModuleNamespaceQualifiersIfNeeded(
625+
objectTypeDecl->getModuleContext(),
626+
ED->getModuleContext());
627+
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
628+
outOfLineOS << ") unsigned char buffer[sizeof(";
629+
outOfLineSyntaxPrinter
630+
.printModuleNamespaceQualifiersIfNeeded(
631+
objectTypeDecl->getModuleContext(),
632+
ED->getModuleContext());
633+
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
634+
outOfLineOS << ")];\n";
635+
outOfLineOS << " auto *valCopy = new(buffer) ";
636+
outOfLineSyntaxPrinter
637+
.printModuleNamespaceQualifiersIfNeeded(
638+
objectTypeDecl->getModuleContext(),
639+
ED->getModuleContext());
640+
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
641+
outOfLineOS << "(val);\n";
642+
outOfLineOS << " ";
643+
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
644+
<< "::";
645+
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
646+
outOfLineOS << "::implClassFor<";
647+
outOfLineSyntaxPrinter
648+
.printModuleNamespaceQualifiersIfNeeded(
649+
objectTypeDecl->getModuleContext(),
650+
ED->getModuleContext());
651+
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
652+
outOfLineOS << ">::type::initializeWithTake(result._"
653+
"getOpaquePointer(), ";
654+
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
655+
<< "::";
656+
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
657+
outOfLineOS << "::implClassFor<";
658+
outOfLineSyntaxPrinter
659+
.printModuleNamespaceQualifiersIfNeeded(
660+
objectTypeDecl->getModuleContext(),
661+
ED->getModuleContext());
662+
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
663+
outOfLineOS << ">::type::getOpaquePointer(*valCopy)";
664+
outOfLineOS << ");\n";
665+
}
666+
}
667+
668+
outOfLineOS << " result._destructiveInjectEnumTag(";
669+
if (ED->isResilient()) {
670+
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName()
671+
<< "::" << elementInfo->globalVariableName;
603672
} else {
604-
outOfLineOS << " alignas(";
605-
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
606-
objectTypeDecl->getModuleContext(),
607-
ED->getModuleContext());
608-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
609-
outOfLineOS << ") unsigned char buffer[sizeof(";
610-
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
611-
objectTypeDecl->getModuleContext(),
612-
ED->getModuleContext());
613-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
614-
outOfLineOS << ")];\n";
615-
outOfLineOS << " auto *valCopy = new(buffer) ";
616-
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
617-
objectTypeDecl->getModuleContext(),
618-
ED->getModuleContext());
619-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
620-
outOfLineOS << "(val);\n";
621-
outOfLineOS << " ";
622-
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
623-
<< "::";
624-
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
625-
outOfLineOS << "::implClassFor<";
626-
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
627-
objectTypeDecl->getModuleContext(),
628-
ED->getModuleContext());
629-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
630-
outOfLineOS << ">::type::initializeWithTake(result._"
631-
"getOpaquePointer(), ";
632-
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
633-
<< "::";
634-
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
635-
outOfLineOS << "::implClassFor<";
636-
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
637-
objectTypeDecl->getModuleContext(),
638-
ED->getModuleContext());
639-
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
640-
outOfLineOS << ">::type::getOpaquePointer(*valCopy)";
641-
outOfLineOS << ");\n";
673+
outOfLineOS << elementInfo->tag;
642674
}
643-
}
644-
645-
outOfLineOS << " result._destructiveInjectEnumTag(";
646-
if (ED->isResilient()) {
647-
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName()
648-
<< "::" << elementInfo->globalVariableName;
649-
} else {
650-
outOfLineOS << elementInfo->tag;
651-
}
652-
outOfLineOS << ");\n";
653-
outOfLineOS << " return result;\n";
654-
outOfLineOS << " ";
655-
},
656-
ED->getModuleContext(), outOfLineOS);
675+
outOfLineOS << ");\n";
676+
outOfLineOS << " return result;\n";
677+
outOfLineOS << " ";
678+
},
679+
ED->getModuleContext(), outOfLineOS);
657680
}
658681
os << " } ";
659682
syntaxPrinter.printIdentifier(caseName);

0 commit comments

Comments
 (0)