Skip to content

Commit 983e2f3

Browse files
authored
Merge pull request #60848 from hyp/eng/generic-type-1
[interop][SwiftToCxx] initial generic struct support
2 parents 6ce4bea + 9835888 commit 983e2f3

15 files changed

+646
-169
lines changed

include/swift/IRGen/IRABIDetailsProvider.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ class IRABIDetailsProvider {
105105
/// access function.
106106
FunctionABISignature getTypeMetadataAccessFunctionSignature();
107107

108+
/// Returns additional generic requirement parameters that are required to
109+
/// call the type metadata access function for the given type.
110+
SmallVector<GenericRequirement, 2>
111+
getTypeMetadataAccessFunctionGenericRequirementParameters(
112+
NominalTypeDecl *nominal);
113+
108114
struct EnumElementInfo {
109115
unsigned tag;
110116
StringRef globalVariableName;

lib/IRGen/IRABIDetailsProvider.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "FixedTypeInfo.h"
1616
#include "GenEnum.h"
1717
#include "GenType.h"
18+
#include "GenericRequirement.h"
1819
#include "IRGen.h"
1920
#include "IRGenModule.h"
2021
#include "NativeConventionSchema.h"
@@ -126,6 +127,16 @@ class IRABIDetailsProviderImpl {
126127
return {returnTy, {paramTy}};
127128
}
128129

130+
SmallVector<GenericRequirement, 2>
131+
getTypeMetadataAccessFunctionGenericRequirementParameters(
132+
NominalTypeDecl *nominal) {
133+
GenericTypeRequirements requirements(IGM, nominal);
134+
SmallVector<GenericRequirement, 2> result;
135+
for (const auto &req : requirements.getRequirements())
136+
result.push_back(req);
137+
return result;
138+
}
139+
129140
llvm::MapVector<EnumElementDecl *, IRABIDetailsProvider::EnumElementInfo>
130141
getEnumTagMapping(const EnumDecl *ED) {
131142
llvm::MapVector<EnumElementDecl *, IRABIDetailsProvider::EnumElementInfo>
@@ -221,6 +232,13 @@ IRABIDetailsProvider::getTypeMetadataAccessFunctionSignature() {
221232
return impl->getTypeMetadataAccessFunctionSignature();
222233
}
223234

235+
SmallVector<GenericRequirement, 2>
236+
IRABIDetailsProvider::getTypeMetadataAccessFunctionGenericRequirementParameters(
237+
NominalTypeDecl *nominal) {
238+
return impl->getTypeMetadataAccessFunctionGenericRequirementParameters(
239+
nominal);
240+
}
241+
224242
llvm::MapVector<EnumElementDecl *, IRABIDetailsProvider::EnumElementInfo>
225243
IRABIDetailsProvider::getEnumTagMapping(const EnumDecl *ED) {
226244
return impl->getEnumTagMapping(ED);

lib/PrintAsClang/ClangSyntaxPrinter.cpp

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,10 @@ void ClangSyntaxPrinter::printNullability(
159159
}
160160

161161
void ClangSyntaxPrinter::printSwiftTypeMetadataAccessFunctionCall(
162-
StringRef name) {
163-
os << name << "(0)";
162+
StringRef name, ArrayRef<GenericRequirement> requirements) {
163+
os << name << "(0";
164+
printGenericRequirementsInstantiantions(requirements, LeadingTrivia::Comma);
165+
os << ')';
164166
}
165167

166168
void ClangSyntaxPrinter::printValueWitnessTableAccessSequenceFromTypeMetadata(
@@ -187,12 +189,92 @@ void ClangSyntaxPrinter::printValueWitnessTableAccessSequenceFromTypeMetadata(
187189
}
188190

189191
void ClangSyntaxPrinter::printCTypeMetadataTypeFunction(
190-
const NominalTypeDecl *typeDecl, StringRef typeMetadataFuncName) {
192+
const NominalTypeDecl *typeDecl, StringRef typeMetadataFuncName,
193+
llvm::ArrayRef<GenericRequirement> genericRequirements) {
194+
// FIXME: Support generic requirements > 3.
195+
if (!genericRequirements.empty())
196+
os << "static_assert(" << genericRequirements.size()
197+
<< " <= " << NumDirectGenericTypeMetadataAccessFunctionArgs
198+
<< ", \"unsupported generic requirement list for metadata func\");\n";
191199
os << "// Type metadata accessor for " << typeDecl->getNameStr() << "\n";
192200
os << "SWIFT_EXTERN ";
193201
printSwiftImplQualifier();
194202
os << "MetadataResponseTy " << typeMetadataFuncName << '(';
195203
printSwiftImplQualifier();
196-
os << "MetadataRequestTy)";
204+
os << "MetadataRequestTy";
205+
if (!genericRequirements.empty())
206+
os << ", ";
207+
llvm::interleaveComma(genericRequirements, os,
208+
[&](const GenericRequirement &) {
209+
// FIXME: Print parameter name.
210+
os << "void * _Nonnull";
211+
});
212+
os << ')';
197213
os << " SWIFT_NOEXCEPT SWIFT_CALL;\n\n";
198214
}
215+
216+
void ClangSyntaxPrinter::printGenericTypeParamTypeName(
217+
const GenericTypeParamType *gtpt) {
218+
os << "T_" << gtpt->getDepth() << '_' << gtpt->getIndex();
219+
}
220+
221+
void ClangSyntaxPrinter::printGenericSignature(
222+
const CanGenericSignature &signature) {
223+
os << "template<";
224+
llvm::interleaveComma(
225+
signature.getGenericParams(), os,
226+
[&](const CanTypeWrapper<GenericTypeParamType> &genericParamType) {
227+
os << "class ";
228+
printGenericTypeParamTypeName(genericParamType);
229+
});
230+
os << ">\n";
231+
os << "requires ";
232+
llvm::interleave(
233+
signature.getGenericParams(), os,
234+
[&](const CanTypeWrapper<GenericTypeParamType> &genericParamType) {
235+
os << "swift::isUsableInGenericContext<";
236+
printGenericTypeParamTypeName(genericParamType);
237+
os << ">";
238+
},
239+
" && ");
240+
os << "\n";
241+
}
242+
243+
void ClangSyntaxPrinter::printGenericSignatureParams(
244+
const CanGenericSignature &signature) {
245+
os << '<';
246+
llvm::interleaveComma(
247+
signature.getGenericParams(), os,
248+
[&](const CanTypeWrapper<GenericTypeParamType> &genericParamType) {
249+
printGenericTypeParamTypeName(genericParamType);
250+
});
251+
os << '>';
252+
}
253+
254+
void ClangSyntaxPrinter::printGenericRequirementInstantiantion(
255+
const GenericRequirement &requirement) {
256+
assert(!requirement.Protocol && "protocol requirements not supported yet!");
257+
auto *gtpt = requirement.TypeParameter->getAs<GenericTypeParamType>();
258+
assert(gtpt && "unexpected generic param type");
259+
os << "swift::getTypeMetadata<";
260+
printGenericTypeParamTypeName(gtpt);
261+
os << ">()";
262+
}
263+
264+
void ClangSyntaxPrinter::printGenericRequirementsInstantiantions(
265+
ArrayRef<GenericRequirement> requirements, LeadingTrivia leadingTrivia) {
266+
if (leadingTrivia == LeadingTrivia::Comma && !requirements.empty())
267+
os << ", ";
268+
llvm::interleaveComma(requirements, os,
269+
[&](const GenericRequirement &requirement) {
270+
printGenericRequirementInstantiantion(requirement);
271+
});
272+
}
273+
274+
void ClangSyntaxPrinter::printPrimaryCxxTypeName(
275+
const NominalTypeDecl *type, const ModuleDecl *moduleContext) {
276+
printModuleNamespaceQualifiersIfNeeded(type->getModuleContext(),
277+
moduleContext);
278+
// FIXME: Print class qualifiers for nested class references.
279+
printBaseName(type);
280+
}

lib/PrintAsClang/ClangSyntaxPrinter.h

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313
#ifndef SWIFT_PRINTASCLANG_CLANGSYNTAXPRINTER_H
1414
#define SWIFT_PRINTASCLANG_CLANGSYNTAXPRINTER_H
1515

16+
#include "swift/AST/GenericRequirement.h"
1617
#include "swift/Basic/LLVM.h"
1718
#include "swift/ClangImporter/ClangImporter.h"
1819
#include "llvm/ADT/StringRef.h"
1920
#include "llvm/Support/raw_ostream.h"
2021

2122
namespace swift {
2223

24+
class CanGenericSignature;
25+
class GenericTypeParamType;
2326
class ModuleDecl;
2427
class NominalTypeDecl;
2528

@@ -41,6 +44,8 @@ StringRef getCxxOpaqueStorageClassName();
4144

4245
class ClangSyntaxPrinter {
4346
public:
47+
enum class LeadingTrivia { None, Comma };
48+
4449
ClangSyntaxPrinter(raw_ostream &os) : os(os) {}
4550

4651
/// Print a given identifier. If the identifer conflicts with a keyword, add a
@@ -98,16 +103,46 @@ class ClangSyntaxPrinter {
98103
static bool isClangKeyword(Identifier name);
99104

100105
/// Print the call expression to the Swift type metadata access function.
101-
void printSwiftTypeMetadataAccessFunctionCall(StringRef name);
106+
void printSwiftTypeMetadataAccessFunctionCall(
107+
StringRef name, ArrayRef<GenericRequirement> requirements);
102108

103109
/// Print the set of statements to access the value witness table pointer
104110
/// ('vwTable') from the given type metadata variable.
105111
void printValueWitnessTableAccessSequenceFromTypeMetadata(
106112
StringRef metadataVariable, StringRef vwTableVariable, int indent);
107113

108114
/// Print the metadata accessor function for the given type declaration.
109-
void printCTypeMetadataTypeFunction(const NominalTypeDecl *typeDecl,
110-
StringRef typeMetadataFuncName);
115+
void printCTypeMetadataTypeFunction(
116+
const NominalTypeDecl *typeDecl, StringRef typeMetadataFuncName,
117+
llvm::ArrayRef<GenericRequirement> genericRequirements);
118+
119+
/// Print the name of the generic type param type in C++.
120+
void printGenericTypeParamTypeName(const GenericTypeParamType *gtpt);
121+
122+
/// Print the Swift generic signature as C++ template declaration alongside
123+
/// its requirements.
124+
void printGenericSignature(const CanGenericSignature &signature);
125+
126+
/// Print the C++ template parameters that should be passed for a given
127+
/// generic signature.
128+
void printGenericSignatureParams(const CanGenericSignature &signature);
129+
130+
/// Print the call to the C++ type traits that computes the underlying type /
131+
/// witness table pointer value that are passed to Swift for the given generic
132+
/// requirement.
133+
void
134+
printGenericRequirementInstantiantion(const GenericRequirement &requirement);
135+
136+
/// Print the list of calls to C++ type traits that compute the generic
137+
/// pointer values to pass to Swift.
138+
void printGenericRequirementsInstantiantions(
139+
ArrayRef<GenericRequirement> requirements,
140+
LeadingTrivia leadingTrivia = LeadingTrivia::None);
141+
142+
// Print the C++ type name that corresponds to the primary user facing C++
143+
// class for the given nominal type.
144+
void printPrimaryCxxTypeName(const NominalTypeDecl *type,
145+
const ModuleDecl *moduleContext);
111146

112147
protected:
113148
raw_ostream &os;

lib/PrintAsClang/PrintClangClassType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ void ClangClassTypePrinter::printClassTypeDecl(
3737
// Print out special functions, like functions that
3838
// access type metadata.
3939
printer.printCTypeMetadataTypeFunction(
40-
typeDecl, typeMetadataFuncName);
40+
typeDecl, typeMetadataFuncName, {});
4141
});
4242

4343
std::string baseClassName;

0 commit comments

Comments
 (0)