Skip to content

Commit d4a7f86

Browse files
committed
[interop][SwiftToCxx] do not emit unsupported function signatures yet
1 parent dcf87a2 commit d4a7f86

File tree

4 files changed

+160
-73
lines changed

4 files changed

+160
-73
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -685,18 +685,20 @@ class DeclAndTypePrinter::Implementation
685685
.printSwiftABIFunctionSignatureAsCxxFunction(
686686
AFD, methodTy,
687687
/*selfTypeDeclContext=*/typeDeclContext);
688+
if (!funcABI)
689+
return;
688690
owningPrinter.prologueOS << cFuncPrologueOS.str();
689691

690692
DeclAndTypeClangFunctionPrinter declPrinter(os, owningPrinter.prologueOS,
691693
owningPrinter.typeMapping,
692694
owningPrinter.interopContext);
693695
if (auto *accessor = dyn_cast<AccessorDecl>(AFD)) {
694696
declPrinter.printCxxPropertyAccessorMethod(
695-
typeDeclContext, accessor, funcABI.getSymbolName(), resultTy,
697+
typeDeclContext, accessor, funcABI->getSymbolName(), resultTy,
696698
/*isDefinition=*/false);
697699
} else {
698700
declPrinter.printCxxMethod(typeDeclContext, AFD,
699-
funcABI.getSymbolName(), resultTy,
701+
funcABI->getSymbolName(), resultTy,
700702
/*isDefinition=*/false);
701703
}
702704

@@ -708,11 +710,12 @@ class DeclAndTypePrinter::Implementation
708710
if (auto *accessor = dyn_cast<AccessorDecl>(AFD)) {
709711

710712
defPrinter.printCxxPropertyAccessorMethod(
711-
typeDeclContext, accessor, funcABI.getSymbolName(), resultTy,
713+
typeDeclContext, accessor, funcABI->getSymbolName(), resultTy,
712714
/*isDefinition=*/true);
713715
} else {
714-
defPrinter.printCxxMethod(typeDeclContext, AFD, funcABI.getSymbolName(),
715-
resultTy, /*isDefinition=*/true);
716+
defPrinter.printCxxMethod(typeDeclContext, AFD,
717+
funcABI->getSymbolName(), resultTy,
718+
/*isDefinition=*/true);
716719
}
717720

718721
// FIXME: SWIFT_WARN_UNUSED_RESULT
@@ -1043,7 +1046,8 @@ class DeclAndTypePrinter::Implementation
10431046
}
10441047

10451048
// Print out the extern C Swift ABI function signature.
1046-
FuncionSwiftABIInformation printSwiftABIFunctionSignatureAsCxxFunction(
1049+
Optional<FuncionSwiftABIInformation>
1050+
printSwiftABIFunctionSignatureAsCxxFunction(
10471051
AbstractFunctionDecl *FD, Optional<FunctionType *> givenFuncType = None,
10481052
Optional<NominalTypeDecl *> selfTypeDeclContext = None) {
10491053
assert(outputLang == OutputLanguageMode::Cxx);
@@ -1063,13 +1067,16 @@ class DeclAndTypePrinter::Implementation
10631067
auto resultTy =
10641068
getForeignResultType(FD, funcTy, asyncConvention, errorConvention);
10651069

1070+
std::string cRepresentationString;
1071+
llvm::raw_string_ostream cRepresentationOS(cRepresentationString);
1072+
10661073
FuncionSwiftABIInformation funcABI(FD);
10671074

1068-
os << "SWIFT_EXTERN ";
1075+
cRepresentationOS << "SWIFT_EXTERN ";
10691076

1070-
DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.prologueOS,
1071-
owningPrinter.typeMapping,
1072-
owningPrinter.interopContext);
1077+
DeclAndTypeClangFunctionPrinter funcPrinter(
1078+
cRepresentationOS, owningPrinter.prologueOS, owningPrinter.typeMapping,
1079+
owningPrinter.interopContext);
10731080
auto ABIparams = owningPrinter.interopContext.getIrABIDetails()
10741081
.getFunctionABIAdditionalParams(FD);
10751082
llvm::SmallVector<DeclAndTypeClangFunctionPrinter::AdditionalParam, 2>
@@ -1085,10 +1092,16 @@ class DeclAndTypePrinter::Implementation
10851092
if (!selfTypeDeclContext && !ABIparams.empty())
10861093
convertABIAdditionalParams(FD, resultTy, ABIparams, additionalParams);
10871094

1088-
funcPrinter.printFunctionSignature(
1095+
auto representation = funcPrinter.printFunctionSignature(
10891096
FD, funcABI.getSymbolName(), resultTy,
10901097
DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CFunctionProto,
10911098
additionalParams);
1099+
if (representation.isUnsupported()) {
1100+
// FIXME: Emit remark about unemitted declaration.
1101+
return None;
1102+
}
1103+
1104+
os << cRepresentationOS.str();
10921105
// Swift functions can't throw exceptions, we can only
10931106
// throw them from C++ when emitting C++ inline thunks for the Swift
10941107
// functions.
@@ -1371,8 +1384,10 @@ class DeclAndTypePrinter::Implementation
13711384
llvm::raw_string_ostream cFuncPrologueOS(cFuncDecl);
13721385
auto funcABI = Implementation(cFuncPrologueOS, owningPrinter, outputLang)
13731386
.printSwiftABIFunctionSignatureAsCxxFunction(FD);
1387+
if (!funcABI)
1388+
return;
13741389
owningPrinter.prologueOS << cFuncPrologueOS.str();
1375-
printAbstractFunctionAsCxxFunctionThunk(FD, funcABI);
1390+
printAbstractFunctionAsCxxFunctionThunk(FD, *funcABI);
13761391
return;
13771392
}
13781393
if (FD->getDeclContext()->isTypeContext())

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 86 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ struct CFunctionSignatureTypePrinterModifierDelegate {
8686
// Prints types in the C function signature that corresponds to the
8787
// native Swift function/method.
8888
class CFunctionSignatureTypePrinter
89-
: public TypeVisitor<CFunctionSignatureTypePrinter, void,
89+
: public TypeVisitor<CFunctionSignatureTypePrinter, ClangRepresentation,
9090
Optional<OptionalTypeKind>, bool>,
9191
private ClangSyntaxPrinter {
9292
public:
@@ -123,68 +123,79 @@ class CFunctionSignatureTypePrinter
123123
return true;
124124
}
125125

126-
void visitType(TypeBase *Ty, Optional<OptionalTypeKind> optionalKind,
127-
bool isInOutParam) {
126+
ClangRepresentation visitType(TypeBase *Ty,
127+
Optional<OptionalTypeKind> optionalKind,
128+
bool isInOutParam) {
128129
assert(Ty->getDesugaredType() == Ty && "unhandled sugared type");
129130
os << "/* ";
130131
Ty->print(os);
131132
os << " */";
133+
return ClangRepresentation::unsupported;
132134
}
133135

134-
void visitTupleType(TupleType *TT, Optional<OptionalTypeKind> optionalKind,
135-
bool isInOutParam) {
136+
ClangRepresentation visitTupleType(TupleType *TT,
137+
Optional<OptionalTypeKind> optionalKind,
138+
bool isInOutParam) {
136139
assert(TT->getNumElements() == 0);
137140
// FIXME: Handle non-void type.
138141
os << "void";
142+
return ClangRepresentation::representable;
139143
}
140144

141-
void visitTypeAliasType(TypeAliasType *aliasTy,
142-
Optional<OptionalTypeKind> optionalKind,
143-
bool isInOutParam) {
145+
ClangRepresentation
146+
visitTypeAliasType(TypeAliasType *aliasTy,
147+
Optional<OptionalTypeKind> optionalKind,
148+
bool isInOutParam) {
144149
const TypeAliasDecl *alias = aliasTy->getDecl();
145150
if (printIfKnownSimpleType(alias, optionalKind, isInOutParam))
146-
return;
151+
return ClangRepresentation::representable;
147152

148-
visitPart(aliasTy->getSinglyDesugaredType(), optionalKind, isInOutParam);
153+
return visitPart(aliasTy->getSinglyDesugaredType(), optionalKind,
154+
isInOutParam);
149155
}
150156

151-
void visitClassType(ClassType *CT, Optional<OptionalTypeKind> optionalKind,
152-
bool isInOutParam) {
157+
ClangRepresentation visitClassType(ClassType *CT,
158+
Optional<OptionalTypeKind> optionalKind,
159+
bool isInOutParam) {
153160
// FIXME: handle optionalKind.
154161
if (languageMode != OutputLanguageMode::Cxx) {
155162
if (modifiersDelegate.prefixIndirectlyPassedParamTypeInC)
156163
(*modifiersDelegate.prefixIndirectlyPassedParamTypeInC)(os);
157164
os << "void * _Nonnull";
158165
if (isInOutParam)
159166
os << " * _Nonnull";
160-
return;
167+
return ClangRepresentation::representable;
161168
}
162169
if (typeUseKind == FunctionSignatureTypeUse::ParamType && !isInOutParam)
163170
os << "const ";
164171
ClangSyntaxPrinter(os).printBaseName(CT->getDecl());
165172
if (typeUseKind == FunctionSignatureTypeUse::ParamType)
166173
os << "&";
174+
return ClangRepresentation::representable;
167175
}
168176

169-
void visitEnumType(EnumType *ET, Optional<OptionalTypeKind> optionalKind,
170-
bool isInOutParam) {
171-
visitValueType(ET, optionalKind, isInOutParam);
177+
ClangRepresentation visitEnumType(EnumType *ET,
178+
Optional<OptionalTypeKind> optionalKind,
179+
bool isInOutParam) {
180+
return visitValueType(ET, optionalKind, isInOutParam);
172181
}
173182

174-
void visitStructType(StructType *ST, Optional<OptionalTypeKind> optionalKind,
175-
bool isInOutParam) {
176-
visitValueType(ST, optionalKind, isInOutParam);
183+
ClangRepresentation visitStructType(StructType *ST,
184+
Optional<OptionalTypeKind> optionalKind,
185+
bool isInOutParam) {
186+
return visitValueType(ST, optionalKind, isInOutParam);
177187
}
178188

179-
void visitValueType(NominalType *NT, Optional<OptionalTypeKind> optionalKind,
180-
bool isInOutParam) {
189+
ClangRepresentation visitValueType(NominalType *NT,
190+
Optional<OptionalTypeKind> optionalKind,
191+
bool isInOutParam) {
181192
assert(isa<StructType>(NT) || isa<EnumType>(NT));
182193
const auto *decl = NT->getNominalOrBoundGenericNominal();
183194
assert(isa<StructDecl>(decl) || isa<EnumDecl>(decl));
184195

185196
// Handle known type names.
186197
if (printIfKnownSimpleType(decl, optionalKind, isInOutParam))
187-
return;
198+
return ClangRepresentation::representable;
188199
// FIXME: Handle optional structures.
189200
if (typeUseKind == FunctionSignatureTypeUse::ParamType) {
190201
if (languageMode != OutputLanguageMode::Cxx &&
@@ -207,6 +218,7 @@ class CFunctionSignatureTypePrinter
207218
} else
208219
ClangValueTypePrinter(os, cPrologueOS, typeMapping, interopContext)
209220
.printValueTypeReturnType(decl, languageMode, moduleContext);
221+
return ClangRepresentation::representable;
210222
}
211223

212224
bool printIfKnownGenericStruct(const BoundGenericStructType *BGT,
@@ -233,38 +245,43 @@ class CFunctionSignatureTypePrinter
233245
return true;
234246
}
235247

236-
void visitBoundGenericStructType(BoundGenericStructType *BGT,
237-
Optional<OptionalTypeKind> optionalKind,
238-
bool isInOutParam) {
248+
ClangRepresentation
249+
visitBoundGenericStructType(BoundGenericStructType *BGT,
250+
Optional<OptionalTypeKind> optionalKind,
251+
bool isInOutParam) {
239252
if (printIfKnownGenericStruct(BGT, optionalKind, isInOutParam))
240-
return;
253+
return ClangRepresentation::representable;
254+
return ClangRepresentation::unsupported;
241255
}
242256

243-
void visitGenericTypeParamType(GenericTypeParamType *genericTpt,
244-
Optional<OptionalTypeKind> optionalKind,
245-
bool isInOutParam) {
257+
ClangRepresentation
258+
visitGenericTypeParamType(GenericTypeParamType *genericTpt,
259+
Optional<OptionalTypeKind> optionalKind,
260+
bool isInOutParam) {
246261
// FIXME: handle optionalKind.
247262
if (typeUseKind == FunctionSignatureTypeUse::ReturnType) {
248263
// generic is always returned indirectly in C signature.
249264
assert(languageMode == OutputLanguageMode::Cxx);
250265
os << genericTpt->getName();
251-
return;
266+
return ClangRepresentation::representable;
252267
}
253268
if (!isInOutParam)
254269
os << "const ";
255270
if (languageMode == OutputLanguageMode::Cxx) {
256271
// Pass a reference to a template type.
257272
os << genericTpt->getName();
258273
os << " &";
259-
return;
274+
return ClangRepresentation::representable;
260275
}
261276
// Pass an opaque param in C mode.
262277
os << "void * _Nonnull";
278+
return ClangRepresentation::representable;
263279
}
264280

265-
void visitPart(Type Ty, Optional<OptionalTypeKind> optionalKind,
266-
bool isInOutParam) {
267-
TypeVisitor::visit(Ty, optionalKind, isInOutParam);
281+
ClangRepresentation visitPart(Type Ty,
282+
Optional<OptionalTypeKind> optionalKind,
283+
bool isInOutParam) {
284+
return TypeVisitor::visit(Ty, optionalKind, isInOutParam);
268285
}
269286

270287
private:
@@ -279,18 +296,19 @@ class CFunctionSignatureTypePrinter
279296

280297
} // end namespace
281298

282-
void DeclAndTypeClangFunctionPrinter::printClangFunctionReturnType(
299+
ClangRepresentation
300+
DeclAndTypeClangFunctionPrinter::printClangFunctionReturnType(
283301
Type ty, OptionalTypeKind optKind, ModuleDecl *moduleContext,
284302
OutputLanguageMode outputLang) {
285303
CFunctionSignatureTypePrinter typePrinter(
286304
os, cPrologueOS, typeMapping, outputLang, interopContext,
287305
CFunctionSignatureTypePrinterModifierDelegate(), moduleContext,
288306
FunctionSignatureTypeUse::ReturnType);
289307
// Param for indirect return cannot be marked as inout
290-
typePrinter.visit(ty, optKind, /*isInOutParam=*/false);
308+
return typePrinter.visit(ty, optKind, /*isInOutParam=*/false);
291309
}
292310

293-
void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
311+
ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
294312
const AbstractFunctionDecl *FD, StringRef name, Type resultTy,
295313
FunctionSignatureKind kind, ArrayRef<AdditionalParam> additionalParams,
296314
FunctionSignatureModifiers modifiers) {
@@ -321,19 +339,21 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
321339
auto print =
322340
[&, this](Type ty, Optional<OptionalTypeKind> optionalKind,
323341
StringRef name, bool isInOutParam,
324-
CFunctionSignatureTypePrinterModifierDelegate delegate = {}) {
325-
// FIXME: add support for noescape and PrintMultiPartType,
326-
// see DeclAndTypePrinter::print.
327-
CFunctionSignatureTypePrinter typePrinter(os, cPrologueOS, typeMapping,
328-
outputLang, interopContext,
329-
delegate, emittedModule);
330-
typePrinter.visit(ty, optionalKind, isInOutParam);
331-
332-
if (!name.empty()) {
333-
os << ' ';
334-
ClangSyntaxPrinter(os).printIdentifier(name);
335-
}
336-
};
342+
CFunctionSignatureTypePrinterModifierDelegate delegate = {})
343+
-> ClangRepresentation {
344+
// FIXME: add support for noescape and PrintMultiPartType,
345+
// see DeclAndTypePrinter::print.
346+
CFunctionSignatureTypePrinter typePrinter(os, cPrologueOS, typeMapping,
347+
outputLang, interopContext,
348+
delegate, emittedModule);
349+
auto result = typePrinter.visit(ty, optionalKind, isInOutParam);
350+
351+
if (!name.empty()) {
352+
os << ' ';
353+
ClangSyntaxPrinter(os).printIdentifier(name);
354+
}
355+
return result;
356+
};
337357

338358
// Print any modifiers before the signature.
339359
if (modifiers.isStatic) {
@@ -343,6 +363,9 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
343363
if (modifiers.isInline)
344364
os << "inline ";
345365

366+
ClangRepresentation resultingRepresentation =
367+
ClangRepresentation::representable;
368+
346369
// Print out the return type.
347370
bool isIndirectReturnType =
348371
kind == FunctionSignatureKind::CFunctionProto &&
@@ -355,7 +378,11 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
355378
Type objTy;
356379
std::tie(objTy, retKind) =
357380
DeclAndTypePrinter::getObjectTypeAndOptionality(FD, resultTy);
358-
printClangFunctionReturnType(objTy, retKind, emittedModule, outputLang);
381+
if (resultingRepresentation
382+
.merge(printClangFunctionReturnType(objTy, retKind, emittedModule,
383+
outputLang))
384+
.isUnsupported())
385+
return resultingRepresentation;
359386
} else {
360387
os << "void";
361388
}
@@ -398,9 +425,12 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
398425
llvm::raw_string_ostream os(paramName);
399426
os << "_" << paramIndex;
400427
}
401-
print(objTy, argKind, paramName, param->isInOut());
428+
resultingRepresentation.merge(
429+
print(objTy, argKind, paramName, param->isInOut()));
402430
++paramIndex;
403431
});
432+
if (resultingRepresentation.isUnsupported())
433+
return resultingRepresentation;
404434
}
405435
if (additionalParams.size()) {
406436
assert(kind == FunctionSignatureKind::CFunctionProto);
@@ -419,8 +449,9 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
419449
(*delegate.prefixIndirectlyPassedParamTypeInC)(os);
420450
os << "void * _Nonnull _self";
421451
} else {
422-
print(param.type, OptionalTypeKind::OTK_None, "_self",
423-
/*isInOut*/ false, delegate);
452+
resultingRepresentation.merge(
453+
print(param.type, OptionalTypeKind::OTK_None, "_self",
454+
/*isInOut*/ false, delegate));
424455
}
425456
} else if (param.role == AdditionalParam::Role::Error) {
426457
os << "SWIFT_ERROR_RESULT ";
@@ -440,6 +471,7 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
440471
os << ')';
441472
if (modifiers.isConst)
442473
os << " const";
474+
return resultingRepresentation;
443475
}
444476

445477
void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(

0 commit comments

Comments
 (0)