Skip to content

Commit 45d209f

Browse files
committed
[interop][SwiftToCxx] initial generic struct support
1 parent 8214b85 commit 45d209f

File tree

9 files changed

+260
-26
lines changed

9 files changed

+260
-26
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: 73 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,79 @@ 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) {
191194
os << "// Type metadata accessor for " << typeDecl->getNameStr() << "\n";
192195
os << "SWIFT_EXTERN ";
193196
printSwiftImplQualifier();
194197
os << "MetadataResponseTy " << typeMetadataFuncName << '(';
195198
printSwiftImplQualifier();
196-
os << "MetadataRequestTy)";
199+
os << "MetadataRequestTy";
200+
if (!genericRequirements.empty())
201+
os << ", ";
202+
llvm::interleaveComma(genericRequirements, os,
203+
[&](const GenericRequirement &) {
204+
// FIXME: Print parameter name.
205+
os << "void * _Nonnull";
206+
});
207+
os << ')';
197208
os << " SWIFT_NOEXCEPT SWIFT_CALL;\n\n";
198209
}
210+
211+
void ClangSyntaxPrinter::printGenericTypeParamTypeName(
212+
const GenericTypeParamType *gtpt) {
213+
os << "T_" << gtpt->getDepth() << '_' << gtpt->getIndex();
214+
}
215+
216+
void ClangSyntaxPrinter::printGenericSignature(
217+
const CanGenericSignature &signature) {
218+
os << "template<";
219+
llvm::interleaveComma(
220+
signature.getGenericParams(), os,
221+
[&](const CanTypeWrapper<GenericTypeParamType> &genericParamType) {
222+
os << "class ";
223+
printGenericTypeParamTypeName(genericParamType);
224+
});
225+
os << ">\n";
226+
os << "requires ";
227+
llvm::interleave(
228+
signature.getGenericParams(), os,
229+
[&](const CanTypeWrapper<GenericTypeParamType> &genericParamType) {
230+
os << "swift::isUsableInGenericContext<";
231+
printGenericTypeParamTypeName(genericParamType);
232+
os << ">";
233+
},
234+
" && ");
235+
os << "\n";
236+
}
237+
238+
void ClangSyntaxPrinter::printGenericSignatureParams(
239+
const CanGenericSignature &signature) {
240+
os << '<';
241+
llvm::interleaveComma(
242+
signature.getGenericParams(), os,
243+
[&](const CanTypeWrapper<GenericTypeParamType> &genericParamType) {
244+
printGenericTypeParamTypeName(genericParamType);
245+
});
246+
os << '>';
247+
}
248+
249+
void ClangSyntaxPrinter::printGenericRequirementInstantiantion(
250+
const GenericRequirement &requirement) {
251+
assert(!requirement.Protocol && "protocol requirements not supported yet!");
252+
auto *gtpt = requirement.TypeParameter->getAs<GenericTypeParamType>();
253+
assert(gtpt && "unexpected generic param type");
254+
os << "swift::getTypeMetadata<";
255+
printGenericTypeParamTypeName(gtpt);
256+
os << ">()";
257+
}
258+
259+
void ClangSyntaxPrinter::printGenericRequirementsInstantiantions(
260+
ArrayRef<GenericRequirement> requirements, LeadingTrivia leadingTrivia) {
261+
if (leadingTrivia == LeadingTrivia::Comma && !requirements.empty())
262+
os << ", ";
263+
llvm::interleaveComma(requirements, os,
264+
[&](const GenericRequirement &requirement) {
265+
printGenericRequirementInstantiantion(requirement);
266+
});
267+
}

lib/PrintAsClang/ClangSyntaxPrinter.h

Lines changed: 33 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,41 @@ 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);
111141

112142
protected:
113143
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)