Skip to content

Commit 07337cd

Browse files
committed
[interop][SwiftToCxx] initial generic enum support
1 parent 789e695 commit 07337cd

File tree

5 files changed

+359
-102
lines changed

5 files changed

+359
-102
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: 113 additions & 100 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";
@@ -464,6 +467,8 @@ class DeclAndTypePrinter::Implementation
464467
ClangSyntaxPrinter(nameOS).printIdentifier(elementDecl->getNameStr());
465468
name[0] = std::toupper(name[0]);
466469

470+
if (ED->isGeneric())
471+
return;
467472
clangFuncPrinter.printCustomCxxFunction(
468473
{paramType},
469474
[&](auto &types) {
@@ -553,107 +558,115 @@ class DeclAndTypePrinter::Implementation
553558
neededTypes.push_back(paramType);
554559
}
555560

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

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,14 @@ class CFunctionSignatureTypePrinter
381381
BGT->getGenericArgs());
382382
}
383383

384+
ClangRepresentation
385+
visitBoundGenericEnumType(BoundGenericEnumType *BGT,
386+
Optional<OptionalTypeKind> optionalKind,
387+
bool isInOutParam) {
388+
return visitValueType(BGT, BGT->getDecl(), optionalKind, isInOutParam,
389+
BGT->getGenericArgs());
390+
}
391+
384392
ClangRepresentation
385393
visitGenericTypeParamType(GenericTypeParamType *genericTpt,
386394
Optional<OptionalTypeKind> optionalKind,
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend %S/generic-enum-in-cxx.swift -typecheck -module-name Generics -clang-header-expose-public-decls -emit-clang-header-path %t/generics.h
4+
5+
// RUN: %target-interop-build-clangxx -std=gnu++20 -c %s -I %t -o %t/swift-generics-execution.o
6+
// RUN: %target-interop-build-swift %S/generic-enum-in-cxx.swift -o %t/swift-generics-execution -Xlinker %t/swift-generics-execution.o -module-name Generics -Xfrontend -entry-point-function-name -Xfrontend swiftMain
7+
8+
// RUN: %target-codesign %t/swift-generics-execution
9+
// RUN: %target-run %t/swift-generics-execution | %FileCheck %s
10+
11+
// REQUIRES: executable_test
12+
13+
#include "generics.h"
14+
#include <cassert>
15+
16+
int main() {
17+
using namespace Generics;
18+
19+
{
20+
auto x = makeGenericOpt<int>(42);
21+
takeGenericOpt(x);
22+
// CHECK: some(42)
23+
inoutGenericOpt(x, -11);
24+
takeGenericOpt(x);
25+
// CHECK-NEXT: none
26+
inoutGenericOpt(x, -11);
27+
takeGenericOpt(x);
28+
// CHECK-NEXT: some(-11)
29+
x.method();
30+
// CHECK-NEXT: GenericOpt<T>::testme::some(-11);
31+
assert(x.getComputedProp() == 42);
32+
x.reset();
33+
assert(x.genericMethod<double>(5.25) == 5.25);
34+
// CHECK-NEXT: GenericOpt<T>::genericMethod<T>::none,5.25;
35+
}
36+
{
37+
auto x = makeConcreteOpt(0xFA);
38+
takeConcreteOpt(x);
39+
// CHECK-NEXT: CONCRETE opt: some(250) ;
40+
inoutConcreteOpt(x);
41+
takeConcreteOpt(x);
42+
// CHECK-NEXT: CONCRETE opt: some(750) ;
43+
inoutConcreteOpt(x);
44+
takeConcreteOpt(x);
45+
// CHECK-NEXT: CONCRETE opt: some(2250) ;
46+
x.method();
47+
// CHECK-NEXT: GenericOpt<T>::testme::some(2250);
48+
assert(x.getComputedProp() == 42);
49+
x.reset();
50+
assert(x.genericMethod<double>(-1.25) == -1.25);
51+
// CHECK-NEXT: GenericOpt<T>::genericMethod<T>::none,-1.25;
52+
}
53+
return 0;
54+
}

0 commit comments

Comments
 (0)