Skip to content

[interop][SwiftToCxx] initial generic enum support #61107

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/IRGen/IRABIDetailsProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ class IRABIDetailsProviderImpl {
getEnumTagMapping(const EnumDecl *ED) {
llvm::MapVector<EnumElementDecl *, IRABIDetailsProvider::EnumElementInfo>
elements;
auto &enumImplStrat =
getEnumImplStrategy(IGM, ED->getDeclaredType()->getCanonicalType());
auto &enumImplStrat = getEnumImplStrategy(
IGM, ED->DeclContext::getDeclaredTypeInContext()->getCanonicalType());

for (auto *element : ED->getAllElements()) {
auto tagIdx = enumImplStrat.getTagIndex(element);
Expand Down
239 changes: 131 additions & 108 deletions lib/PrintAsClang/DeclAndTypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,12 +434,15 @@ class DeclAndTypePrinter::Implementation

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

outOfLineSyntaxPrinter
.printNominalTypeOutsideMemberDeclTemplateSpecifiers(ED);
outOfLineOS << " inline bool ";
outOfLineSyntaxPrinter.printBaseName(ED);
outOfLineOS << "::is" << name << "() const {\n";
outOfLineSyntaxPrinter.printNominalTypeQualifier(
ED, /*moduleContext=*/ED->getModuleContext());
outOfLineOS << "is" << name << "() const {\n";
outOfLineOS << " return *this == ";
outOfLineSyntaxPrinter.printBaseName(ED);
outOfLineOS << "::";
outOfLineSyntaxPrinter.printNominalTypeQualifier(
ED, /*moduleContext=*/ED->getModuleContext());
outOfLineSyntaxPrinter.printIdentifier(caseName);
outOfLineOS << ";\n";
outOfLineOS << " }\n";
Expand All @@ -452,12 +455,7 @@ class DeclAndTypePrinter::Implementation
associatedValueList->size() > 1) {
return;
}
auto paramType = associatedValueList->front()->getType();
Type objectType;
OptionalTypeKind optKind;
std::tie(objectType, optKind) = getObjectTypeAndOptionality(
paramType->getNominalOrBoundGenericNominal(), paramType);
auto objectTypeDecl = objectType->getNominalOrBoundGenericNominal();
auto paramType = associatedValueList->front()->getInterfaceType();

std::string declName, defName, name;
llvm::raw_string_ostream declOS(declName), defOS(defName), nameOS(name);
Expand All @@ -469,9 +467,12 @@ class DeclAndTypePrinter::Implementation
[&](auto &types) {
// Printing function name and return type
os << " inline " << types[paramType] << " get" << name;
outOfLineSyntaxPrinter
.printNominalTypeOutsideMemberDeclTemplateSpecifiers(ED);
outOfLineOS << " inline " << types[paramType] << ' ';
outOfLineSyntaxPrinter.printBaseName(ED);
outOfLineOS << "::get" << name;
outOfLineSyntaxPrinter.printNominalTypeQualifier(
ED, /*moduleContext=*/ED->getModuleContext());
outOfLineOS << "get" << name;
},
[&](auto &types) {}, true,
[&](auto &types) {
Expand All @@ -487,6 +488,20 @@ class DeclAndTypePrinter::Implementation
outOfLineOS << "(*this);\n";
outOfLineOS << " char * _Nonnull payloadFromDestruction = "
"thisCopy->_destructiveProjectEnumData();\n";
if (const auto *gtpt = paramType->getAs<GenericTypeParamType>()) {
DeclAndTypeClangFunctionPrinter::printGenericReturnSequence(
outOfLineOS, gtpt, [](StringRef) {},
/*initializeWithTake=*/StringRef("payloadFromDestruction"));
return;
}
// FIXME: unify non-generic return with regular function emission
// return path.
Type objectType;
OptionalTypeKind optKind;
std::tie(objectType, optKind) = getObjectTypeAndOptionality(
paramType->getNominalOrBoundGenericNominal(), paramType);
auto objectTypeDecl = objectType->getNominalOrBoundGenericNominal();

if (auto knownCxxType =
owningPrinter.typeMapping.getKnownCxxTypeInfo(
objectTypeDecl)) {
Expand Down Expand Up @@ -553,107 +568,115 @@ class DeclAndTypePrinter::Implementation
neededTypes.push_back(paramType);
}

clangFuncPrinter.printCustomCxxFunction(
neededTypes,
[&](auto &types) {
// Printing function name and return type
os << " inline ";
syntaxPrinter.printBaseName(elementDecl->getParentEnum());
os << " operator()";

outOfLineOS << " inline ";
outOfLineSyntaxPrinter.printBaseName(
elementDecl->getParentEnum());
outOfLineOS << ' ';
outOfLineSyntaxPrinter.printBaseName(
elementDecl->getParentEnum());
outOfLineOS << "::_impl_" << elementDecl->getNameStr()
<< "::operator()";
},
[&](auto &types) {
// Printing parameters
if (!paramType) {
return;
}
assert(objectTypeDecl != nullptr);
if (owningPrinter.typeMapping.getKnownCxxTypeInfo(
objectTypeDecl)) {
os << types[paramType] << " val";
outOfLineOS << types[paramType] << " val";
} else {
os << "const " << types[paramType] << " &val";
outOfLineOS << "const " << types[paramType] << " &val";
}
},
true,
[&](auto &types) {
// Printing function body
outOfLineOS << " auto result = ";
outOfLineSyntaxPrinter.printBaseName(
elementDecl->getParentEnum());
outOfLineOS << "::_make();\n";

if (paramType) {
// FIXME: support generic constructor.
if (!ED->isGeneric())
clangFuncPrinter.printCustomCxxFunction(
neededTypes,
[&](auto &types) {
// Printing function name and return type
os << " inline ";
syntaxPrinter.printBaseName(elementDecl->getParentEnum());
os << " operator()";

outOfLineOS << " inline ";
outOfLineSyntaxPrinter.printBaseName(
elementDecl->getParentEnum());
outOfLineOS << ' ';
outOfLineSyntaxPrinter.printBaseName(
elementDecl->getParentEnum());
outOfLineOS << "::_impl_" << elementDecl->getNameStr()
<< "::operator()";
},
[&](auto &types) {
// Printing parameters
if (!paramType) {
return;
}
assert(objectTypeDecl != nullptr);

if (owningPrinter.typeMapping.getKnownCxxTypeInfo(
objectTypeDecl)) {
outOfLineOS << " memcpy(result._getOpaquePointer(), &val, "
"sizeof(val));\n";
os << types[paramType] << " val";
outOfLineOS << types[paramType] << " val";
} else {
os << "const " << types[paramType] << " &val";
outOfLineOS << "const " << types[paramType] << " &val";
}
},
true,
[&](auto &types) {
// Printing function body
outOfLineOS << " auto result = ";
outOfLineSyntaxPrinter.printBaseName(
elementDecl->getParentEnum());
outOfLineOS << "::_make();\n";

if (paramType) {
assert(objectTypeDecl != nullptr);

if (owningPrinter.typeMapping.getKnownCxxTypeInfo(
objectTypeDecl)) {
outOfLineOS
<< " memcpy(result._getOpaquePointer(), &val, "
"sizeof(val));\n";
} else {
outOfLineOS << " alignas(";
outOfLineSyntaxPrinter
.printModuleNamespaceQualifiersIfNeeded(
objectTypeDecl->getModuleContext(),
ED->getModuleContext());
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
outOfLineOS << ") unsigned char buffer[sizeof(";
outOfLineSyntaxPrinter
.printModuleNamespaceQualifiersIfNeeded(
objectTypeDecl->getModuleContext(),
ED->getModuleContext());
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
outOfLineOS << ")];\n";
outOfLineOS << " auto *valCopy = new(buffer) ";
outOfLineSyntaxPrinter
.printModuleNamespaceQualifiersIfNeeded(
objectTypeDecl->getModuleContext(),
ED->getModuleContext());
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
outOfLineOS << "(val);\n";
outOfLineOS << " ";
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
<< "::";
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
outOfLineOS << "::implClassFor<";
outOfLineSyntaxPrinter
.printModuleNamespaceQualifiersIfNeeded(
objectTypeDecl->getModuleContext(),
ED->getModuleContext());
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
outOfLineOS << ">::type::initializeWithTake(result._"
"getOpaquePointer(), ";
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
<< "::";
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
outOfLineOS << "::implClassFor<";
outOfLineSyntaxPrinter
.printModuleNamespaceQualifiersIfNeeded(
objectTypeDecl->getModuleContext(),
ED->getModuleContext());
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
outOfLineOS << ">::type::getOpaquePointer(*valCopy)";
outOfLineOS << ");\n";
}
}

outOfLineOS << " result._destructiveInjectEnumTag(";
if (ED->isResilient()) {
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName()
<< "::" << elementInfo->globalVariableName;
} else {
outOfLineOS << " alignas(";
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
objectTypeDecl->getModuleContext(),
ED->getModuleContext());
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
outOfLineOS << ") unsigned char buffer[sizeof(";
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
objectTypeDecl->getModuleContext(),
ED->getModuleContext());
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
outOfLineOS << ")];\n";
outOfLineOS << " auto *valCopy = new(buffer) ";
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
objectTypeDecl->getModuleContext(),
ED->getModuleContext());
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
outOfLineOS << "(val);\n";
outOfLineOS << " ";
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
<< "::";
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
outOfLineOS << "::implClassFor<";
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
objectTypeDecl->getModuleContext(),
ED->getModuleContext());
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
outOfLineOS << ">::type::initializeWithTake(result._"
"getOpaquePointer(), ";
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
<< "::";
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
outOfLineOS << "::implClassFor<";
outOfLineSyntaxPrinter.printModuleNamespaceQualifiersIfNeeded(
objectTypeDecl->getModuleContext(),
ED->getModuleContext());
outOfLineSyntaxPrinter.printBaseName(objectTypeDecl);
outOfLineOS << ">::type::getOpaquePointer(*valCopy)";
outOfLineOS << ");\n";
outOfLineOS << elementInfo->tag;
}
}

outOfLineOS << " result._destructiveInjectEnumTag(";
if (ED->isResilient()) {
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName()
<< "::" << elementInfo->globalVariableName;
} else {
outOfLineOS << elementInfo->tag;
}
outOfLineOS << ");\n";
outOfLineOS << " return result;\n";
outOfLineOS << " ";
},
ED->getModuleContext(), outOfLineOS);
outOfLineOS << ");\n";
outOfLineOS << " return result;\n";
outOfLineOS << " ";
},
ED->getModuleContext(), outOfLineOS);
}
os << " } ";
syntaxPrinter.printIdentifier(caseName);
Expand Down
Loading