@@ -32,7 +32,8 @@ using namespace swift;
32
32
33
33
namespace {
34
34
35
- enum class FunctionSignatureTypeUse { ParamType, ReturnType };
35
+ // FIXME: RENAME.
36
+ enum class FunctionSignatureTypeUse { TypeReference, ParamType, ReturnType };
36
37
37
38
Optional<PrimitiveTypeMapping::ClangTypeInfo>
38
39
getKnownTypeInfo (const TypeDecl *typeDecl, PrimitiveTypeMapping &typeMapping,
@@ -68,7 +69,7 @@ bool isResilientType(Type t) {
68
69
return false ;
69
70
}
70
71
71
- bool isGenericType (Type t) { return t->is <GenericTypeParamType> (); }
72
+ bool isGenericType (Type t) { return t->hasTypeParameter (); }
72
73
73
74
bool isKnownCxxType (Type t, PrimitiveTypeMapping &typeMapping) {
74
75
return isKnownType (t, typeMapping, OutputLanguageMode::Cxx);
@@ -79,6 +80,10 @@ bool isKnownCType(Type t, PrimitiveTypeMapping &typeMapping) {
79
80
}
80
81
81
82
struct CFunctionSignatureTypePrinterModifierDelegate {
83
+ // / Prefix the initially printed value type.
84
+ Optional<llvm::function_ref<ClangValueTypePrinter::TypeUseKind(
85
+ ClangValueTypePrinter::TypeUseKind)>>
86
+ mapValueTypeUseKind = None;
82
87
// / Prefix the indirect value type / class type param being printed in C mode.
83
88
Optional<llvm::function_ref<void (raw_ostream &)>>
84
89
prefixIndirectlyPassedParamTypeInC = None;
@@ -185,20 +190,24 @@ class CFunctionSignatureTypePrinter
185
190
ClangRepresentation visitEnumType (EnumType *ET,
186
191
Optional<OptionalTypeKind> optionalKind,
187
192
bool isInOutParam) {
188
- return visitValueType (ET, optionalKind, isInOutParam);
193
+ return visitValueType (ET->getNominalOrBoundGenericNominal (), ET,
194
+ optionalKind, isInOutParam);
189
195
}
190
196
191
197
ClangRepresentation visitStructType (StructType *ST,
192
198
Optional<OptionalTypeKind> optionalKind,
193
199
bool isInOutParam) {
194
- return visitValueType (ST, optionalKind, isInOutParam);
200
+ return visitValueType (ST->getNominalOrBoundGenericNominal (), ST,
201
+ optionalKind, isInOutParam);
195
202
}
196
203
197
- ClangRepresentation visitValueType (NominalType *NT,
204
+ ClangRepresentation visitValueType (const NominalTypeDecl *decl,
205
+ NominalType *NT,
198
206
Optional<OptionalTypeKind> optionalKind,
199
- bool isInOutParam) {
200
- assert (isa<StructType>(NT) || isa<EnumType>(NT));
201
- const auto *decl = NT->getNominalOrBoundGenericNominal ();
207
+ bool isInOutParam,
208
+ ArrayRef<Type> genericArgs = {}) {
209
+ if (NT)
210
+ assert (isa<StructType>(NT) || isa<EnumType>(NT));
202
211
assert (isa<StructDecl>(decl) || isa<EnumDecl>(decl));
203
212
204
213
// Handle known type names.
@@ -211,7 +220,7 @@ class CFunctionSignatureTypePrinter
211
220
if (typeUseKind == FunctionSignatureTypeUse::ParamType) {
212
221
if (languageMode != OutputLanguageMode::Cxx &&
213
222
(decl->isResilient () ||
214
- interopContext.getIrABIDetails ().shouldPassIndirectly (NT))) {
223
+ (NT && interopContext.getIrABIDetails ().shouldPassIndirectly (NT) ))) {
215
224
if (modifiersDelegate.prefixIndirectlyPassedParamTypeInC )
216
225
(*modifiersDelegate.prefixIndirectlyPassedParamTypeInC )(os);
217
226
// FIXME: it would be nice to print out the C struct type here.
@@ -226,9 +235,30 @@ class CFunctionSignatureTypePrinter
226
235
.printValueTypeParameterType (decl, languageMode, moduleContext,
227
236
isInOutParam);
228
237
}
229
- } else
238
+ } else {
230
239
ClangValueTypePrinter (os, cPrologueOS, typeMapping, interopContext)
231
- .printValueTypeReturnType (decl, languageMode, moduleContext);
240
+ .printValueTypeReturnType (
241
+ decl, languageMode,
242
+ modifiersDelegate.mapValueTypeUseKind
243
+ ? (*modifiersDelegate.mapValueTypeUseKind )(
244
+ ClangValueTypePrinter::TypeUseKind::CxxTypeName)
245
+ : ClangValueTypePrinter::TypeUseKind::CxxTypeName,
246
+ moduleContext);
247
+ if (!genericArgs.empty ()) {
248
+ os << ' <' ;
249
+ llvm::SaveAndRestore<FunctionSignatureTypeUse> typeUseNormal (
250
+ typeUseKind, FunctionSignatureTypeUse::TypeReference);
251
+ decltype (modifiersDelegate) emptyModifiersDelegate;
252
+ llvm::SaveAndRestore<decltype (modifiersDelegate)> modReset (
253
+ modifiersDelegate, emptyModifiersDelegate);
254
+ ClangRepresentation result = ClangRepresentation::representable;
255
+ llvm::interleaveComma (genericArgs, os, [&](Type t) {
256
+ result.merge (visitPart (t, None, false ));
257
+ });
258
+ os << ' >' ;
259
+ return result;
260
+ }
261
+ }
232
262
return ClangRepresentation::representable;
233
263
}
234
264
@@ -262,15 +292,17 @@ class CFunctionSignatureTypePrinter
262
292
bool isInOutParam) {
263
293
if (printIfKnownGenericStruct (BGT, optionalKind, isInOutParam))
264
294
return ClangRepresentation::representable;
265
- return ClangRepresentation::unsupported;
295
+ return visitValueType (BGT->getDecl (), nullptr , optionalKind, isInOutParam,
296
+ BGT->getGenericArgs ());
266
297
}
267
298
268
299
ClangRepresentation
269
300
visitGenericTypeParamType (GenericTypeParamType *genericTpt,
270
301
Optional<OptionalTypeKind> optionalKind,
271
302
bool isInOutParam) {
272
303
// FIXME: handle optionalKind.
273
- if (typeUseKind == FunctionSignatureTypeUse::ReturnType) {
304
+ if (typeUseKind == FunctionSignatureTypeUse::ReturnType ||
305
+ typeUseKind == FunctionSignatureTypeUse::TypeReference) {
274
306
// generic is always returned indirectly in C signature.
275
307
assert (languageMode == OutputLanguageMode::Cxx);
276
308
os << genericTpt->getName ();
@@ -628,7 +660,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
628
660
// indirectly by a pointer.
629
661
if (!isKnownCxxType (resultTy, typeMapping) &&
630
662
!hasKnownOptionalNullableCxxMapping (resultTy)) {
631
- if (isGenericType ( resultTy)) {
663
+ if (resultTy-> is <GenericTypeParamType>( )) {
632
664
std::string returnAddress;
633
665
llvm::raw_string_ostream ros (returnAddress);
634
666
ros << " reinterpret_cast<void *>(&returnValue)" ;
@@ -666,13 +698,29 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
666
698
if (auto *decl = resultTy->getNominalOrBoundGenericNominal ()) {
667
699
if ((isa<StructDecl>(decl) || isa<EnumDecl>(decl))) {
668
700
bool isIndirect =
669
- decl->isResilient () ||
701
+ decl->isResilient () || isGenericType (resultTy) ||
670
702
interopContext.getIrABIDetails ().shouldReturnIndirectly (resultTy);
671
703
ClangValueTypePrinter valueTypePrinter (os, cPrologueOS, typeMapping,
672
704
interopContext);
673
705
if (isIndirect) {
674
706
valueTypePrinter.printValueTypeIndirectReturnScaffold (
675
- decl, moduleContext, [&](StringRef returnParam) {
707
+ decl, moduleContext,
708
+ [&]() {
709
+ CFunctionSignatureTypePrinterModifierDelegate delegate;
710
+ delegate
711
+ .mapValueTypeUseKind = [](ClangValueTypePrinter::TypeUseKind
712
+ kind) {
713
+ return ClangValueTypePrinter::TypeUseKind::CxxImplTypeName;
714
+ };
715
+ CFunctionSignatureTypePrinter typePrinter (
716
+ os, cPrologueOS, typeMapping, OutputLanguageMode::Cxx,
717
+ interopContext, delegate, moduleContext, declPrinter,
718
+ FunctionSignatureTypeUse::TypeReference);
719
+ auto result =
720
+ typePrinter.visit (resultTy, None, /* isInOut=*/ false );
721
+ assert (!result.isUnsupported ());
722
+ },
723
+ [&](StringRef returnParam) {
676
724
printCallToCFunc (/* additionalParam=*/ returnParam);
677
725
});
678
726
} else {
0 commit comments