Skip to content

Commit 32723f7

Browse files
committed
[interop][SwiftToCxx] initial generic function support: pass generic parameters
Only primitive types are supported at the moment from C++ as the type traits aren't emitted for all types yet
1 parent 32f2b71 commit 32723f7

18 files changed

+568
-59
lines changed

include/swift/IRGen/IRABIDetailsProvider.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_IRGEN_IRABIDETAILSPROVIDER_H
1515

1616
#include "swift/AST/Decl.h"
17+
#include "swift/AST/GenericRequirement.h"
1718
#include "swift/AST/Type.h"
1819
#include "clang/AST/CharUnits.h"
1920
#include "llvm/ADT/MapVector.h"
@@ -49,14 +50,13 @@ class IRABIDetailsProvider {
4950

5051
/// Information about any ABI additional parameters.
5152
struct ABIAdditionalParam {
52-
enum class ABIParameterRole { Self, Error };
53+
enum class ABIParameterRole { GenericRequirementRole, Self, Error };
5354

5455
ABIParameterRole role;
56+
llvm::Optional<GenericRequirement> genericRequirement;
5557
TypeDecl *type;
5658
};
5759

58-
SmallVector<ABIAdditionalParam, 1> ABIAdditionalParams;
59-
6060
/// Returns the size and alignment for the given type, or \c None if the type
6161
/// is not a fixed layout type.
6262
llvm::Optional<SizeAndAlignment>

lib/IRGen/GenCall.cpp

+16-6
Original file line numberDiff line numberDiff line change
@@ -396,11 +396,14 @@ namespace {
396396
unsigned AsyncContextIdx;
397397
unsigned AsyncResumeFunctionSwiftSelfIdx = 0;
398398
FunctionPointerKind FnKind;
399+
bool ShouldComputeABIDetails;
400+
SmallVector<GenericRequirement, 4> GenericRequirements;
399401

400402
SignatureExpansion(IRGenModule &IGM, CanSILFunctionType fnType,
401-
FunctionPointerKind fnKind)
402-
: IGM(IGM), FnType(fnType), FnKind(fnKind) {
403-
}
403+
FunctionPointerKind fnKind,
404+
bool ShouldComputeABIDetails = false)
405+
: IGM(IGM), FnType(fnType), FnKind(fnKind),
406+
ShouldComputeABIDetails(ShouldComputeABIDetails) {}
404407

405408
/// Expand the components of the primary entrypoint of the function type.
406409
void expandFunctionType();
@@ -1628,7 +1631,9 @@ void SignatureExpansion::expandParameters() {
16281631
// Next, the generic signature.
16291632
if (hasPolymorphicParameters(FnType) &&
16301633
!FnKind.shouldSuppressPolymorphicArguments())
1631-
expandPolymorphicSignature(IGM, FnType, ParamIRTypes);
1634+
expandPolymorphicSignature(IGM, FnType, ParamIRTypes,
1635+
ShouldComputeABIDetails ? &GenericRequirements
1636+
: nullptr);
16321637

16331638
// Certain special functions are passed the continuation directly.
16341639
if (FnKind.shouldPassContinuationDirectly()) {
@@ -1925,14 +1930,19 @@ Signature SignatureExpansion::getSignature() {
19251930
} else {
19261931
result.ExtraDataKind = ExtraData::kindForMember<void>();
19271932
}
1933+
if (ShouldComputeABIDetails)
1934+
result.ABIDetails =
1935+
SignatureExpansionABIDetails{std::move(GenericRequirements)};
19281936
return result;
19291937
}
19301938

19311939
Signature Signature::getUncached(IRGenModule &IGM,
19321940
CanSILFunctionType formalType,
1933-
FunctionPointerKind fpKind) {
1941+
FunctionPointerKind fpKind,
1942+
bool shouldComputeABIDetails) {
19341943
GenericContextScope scope(IGM, formalType->getInvocationGenericSignature());
1935-
SignatureExpansion expansion(IGM, formalType, fpKind);
1944+
SignatureExpansion expansion(IGM, formalType, fpKind,
1945+
shouldComputeABIDetails);
19361946
expansion.expandFunctionType();
19371947
return expansion.getSignature();
19381948
}

lib/IRGen/GenProto.cpp

+9-5
Original file line numberDiff line numberDiff line change
@@ -3459,11 +3459,14 @@ namespace {
34593459
ExpandPolymorphicSignature(IRGenModule &IGM, CanSILFunctionType fn)
34603460
: PolymorphicConvention(IGM, fn) {}
34613461

3462-
void expand(SmallVectorImpl<llvm::Type*> &out) {
3462+
void expand(SmallVectorImpl<llvm::Type *> &out,
3463+
SmallVectorImpl<GenericRequirement> *reqs) {
34633464
for (auto &source : getSources())
34643465
addEarlySource(source, out);
34653466

34663467
enumerateUnfulfilledRequirements([&](GenericRequirement reqt) {
3468+
if (reqs)
3469+
reqs->push_back(reqt);
34673470
out.push_back(reqt.Protocol ? IGM.WitnessTablePtrTy
34683471
: IGM.TypeMetadataPtrTy);
34693472
});
@@ -3490,10 +3493,11 @@ namespace {
34903493
} // end anonymous namespace
34913494

34923495
/// Given a generic signature, add the argument types required in order to call it.
3493-
void irgen::expandPolymorphicSignature(IRGenModule &IGM,
3494-
CanSILFunctionType polyFn,
3495-
SmallVectorImpl<llvm::Type*> &out) {
3496-
ExpandPolymorphicSignature(IGM, polyFn).expand(out);
3496+
void irgen::expandPolymorphicSignature(
3497+
IRGenModule &IGM, CanSILFunctionType polyFn,
3498+
SmallVectorImpl<llvm::Type *> &out,
3499+
SmallVectorImpl<GenericRequirement> *outReqs) {
3500+
ExpandPolymorphicSignature(IGM, polyFn).expand(out, outReqs);
34973501
}
34983502

34993503
void irgen::expandTrailingWitnessSignature(IRGenModule &IGM,

lib/IRGen/GenProto.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,10 @@ namespace irgen {
9999

100100
/// Add the witness parameters necessary for calling a function with
101101
/// the given generics clause.
102-
void expandPolymorphicSignature(IRGenModule &IGM,
103-
CanSILFunctionType type,
104-
SmallVectorImpl<llvm::Type*> &types);
102+
void expandPolymorphicSignature(
103+
IRGenModule &IGM, CanSILFunctionType type,
104+
SmallVectorImpl<llvm::Type *> &types,
105+
SmallVectorImpl<GenericRequirement> *outReqs = nullptr);
105106

106107
/// Return the number of trailing arguments necessary for calling a
107108
/// witness method.

lib/IRGen/IRABIDetailsProvider.cpp

+10-3
Original file line numberDiff line numberDiff line change
@@ -148,17 +148,24 @@ class IRABIDetailsProviderImpl {
148148
auto silFuncType = function->getLoweredFunctionType();
149149
auto funcPointerKind =
150150
FunctionPointerKind(FunctionPointerKind::BasicKind::Function);
151-
auto signature = Signature::getUncached(IGM, silFuncType, funcPointerKind);
152151

152+
auto signature = Signature::getUncached(IGM, silFuncType, funcPointerKind,
153+
/*shouldComputeABIDetail=*/true);
154+
155+
for (const auto &reqt : signature.getABIDetails().GenericRequirements) {
156+
params.push_back({IRABIDetailsProvider::ABIAdditionalParam::
157+
ABIParameterRole::GenericRequirementRole,
158+
reqt, typeConverter.Context.getOpaquePointerDecl()});
159+
}
153160
for (auto attrSet : signature.getAttributes()) {
154161
if (attrSet.hasAttribute(llvm::Attribute::AttrKind::SwiftSelf))
155162
params.push_back(
156163
{IRABIDetailsProvider::ABIAdditionalParam::ABIParameterRole::Self,
157-
typeConverter.Context.getOpaquePointerDecl()});
164+
llvm::None, typeConverter.Context.getOpaquePointerDecl()});
158165
if (attrSet.hasAttribute(llvm::Attribute::AttrKind::SwiftError))
159166
params.push_back(
160167
{IRABIDetailsProvider::ABIAdditionalParam::ABIParameterRole::Error,
161-
typeConverter.Context.getOpaquePointerDecl()});
168+
llvm::None, typeConverter.Context.getOpaquePointerDecl()});
162169
}
163170
return params;
164171
}

lib/IRGen/Signature.h

+18-3
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818
#ifndef SWIFT_IRGEN_SIGNATURE_H
1919
#define SWIFT_IRGEN_SIGNATURE_H
2020

21-
#include "llvm/IR/Attributes.h"
22-
#include "llvm/IR/CallingConv.h"
21+
#include "swift/AST/GenericRequirement.h"
2322
#include "swift/AST/Types.h"
2423
#include "swift/Basic/ExternalUnion.h"
24+
#include "llvm/ADT/SmallVector.h"
25+
#include "llvm/IR/Attributes.h"
26+
#include "llvm/IR/CallingConv.h"
2527

2628
namespace llvm {
2729
class FunctionType;
@@ -94,6 +96,12 @@ class AsyncInfo {
9496
uint32_t AsyncResumeFunctionSwiftSelfIdx = 0;
9597
};
9698

99+
/// Recorded information about the specific ABI details.
100+
struct SignatureExpansionABIDetails {
101+
/// Generic requirements added to the signature during expansion.
102+
llvm::SmallVector<GenericRequirement, 2> GenericRequirements;
103+
};
104+
97105
/// A signature represents something which can actually be called.
98106
class Signature {
99107
using ExtraData =
@@ -104,6 +112,7 @@ class Signature {
104112
llvm::CallingConv::ID CallingConv;
105113
ExtraData::Kind ExtraDataKind; // packed with above
106114
ExtraData ExtraDataStorage;
115+
llvm::Optional<SignatureExpansionABIDetails> ABIDetails;
107116
static_assert(ExtraData::union_is_trivially_copyable,
108117
"not trivially copyable");
109118

@@ -126,7 +135,8 @@ class Signature {
126135
/// IRGenModule::getSignature(CanSILFunctionType), which is what
127136
/// clients should generally be using.
128137
static Signature getUncached(IRGenModule &IGM, CanSILFunctionType formalType,
129-
FunctionPointerKind kind);
138+
FunctionPointerKind kind,
139+
bool shouldComputeABIDetails = false);
130140

131141
/// Compute the signature of a coroutine's continuation function.
132142
static Signature forCoroutineContinuation(IRGenModule &IGM,
@@ -194,6 +204,11 @@ class Signature {
194204
assert(isValid());
195205
return Attributes;
196206
}
207+
208+
const SignatureExpansionABIDetails &getABIDetails() {
209+
assert(ABIDetails.hasValue());
210+
return *ABIDetails;
211+
}
197212
};
198213

199214
} // end namespace irgen

lib/PrintAsClang/DeclAndTypePrinter.cpp

+29-20
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ class DeclAndTypePrinter::Implementation
608608
}
609609

610610
Type getForeignResultType(AbstractFunctionDecl *AFD,
611-
FunctionType *methodTy,
611+
AnyFunctionType *methodTy,
612612
Optional<ForeignAsyncConvention> asyncConvention,
613613
Optional<ForeignErrorConvention> errorConvention) {
614614
// A foreign error convention can affect the result type as seen in
@@ -950,7 +950,7 @@ class DeclAndTypePrinter::Implementation
950950
}
951951

952952
/// Print C or C++ trailing attributes for a function declaration.
953-
void printFunctionClangAttributes(FuncDecl *FD, FunctionType *funcTy) {
953+
void printFunctionClangAttributes(FuncDecl *FD, AnyFunctionType *funcTy) {
954954
if (funcTy->getResult()->isUninhabited()) {
955955
os << " SWIFT_NORETURN";
956956
} else if (!funcTy->getResult()->isVoid() &&
@@ -1010,15 +1010,21 @@ class DeclAndTypePrinter::Implementation
10101010
llvm::SmallVector<DeclAndTypeClangFunctionPrinter::AdditionalParam, 2>
10111011
&params) {
10121012
for (auto param : ABIparams) {
1013-
if (param.role ==
1014-
IRABIDetailsProvider::ABIAdditionalParam::ABIParameterRole::Self)
1013+
if (param.role == IRABIDetailsProvider::ABIAdditionalParam::
1014+
ABIParameterRole::GenericRequirementRole)
1015+
params.push_back({DeclAndTypeClangFunctionPrinter::AdditionalParam::
1016+
Role::GenericRequirement,
1017+
resultTy->getASTContext().getOpaquePointerType(),
1018+
/*isIndirect=*/false, param.genericRequirement});
1019+
else if (param.role ==
1020+
IRABIDetailsProvider::ABIAdditionalParam::ABIParameterRole::Self)
10151021
params.push_back(
10161022
{DeclAndTypeClangFunctionPrinter::AdditionalParam::Role::Self,
10171023
resultTy->getASTContext().getOpaquePointerType(),
10181024
/*isIndirect=*/
10191025
isa<FuncDecl>(FD) ? cast<FuncDecl>(FD)->isMutating() : false});
1020-
if (param.role ==
1021-
IRABIDetailsProvider::ABIAdditionalParam::ABIParameterRole::Error)
1026+
else if (param.role == IRABIDetailsProvider::ABIAdditionalParam::
1027+
ABIParameterRole::Error)
10221028
params.push_back(
10231029
{DeclAndTypeClangFunctionPrinter::AdditionalParam::Role::Error,
10241030
resultTy->getASTContext().getOpaquePointerType()});
@@ -1034,12 +1040,15 @@ class DeclAndTypePrinter::Implementation
10341040
FD->getForeignAsyncConvention();
10351041
Optional<ForeignErrorConvention> errorConvention =
10361042
FD->getForeignErrorConvention();
1037-
assert(!FD->getGenericSignature() &&
1038-
"top-level generic functions not supported here");
10391043
// FIXME (Alex): Make type adjustments for C++.
1040-
auto funcTy = givenFuncType
1041-
? *givenFuncType
1042-
: FD->getInterfaceType()->castTo<FunctionType>();
1044+
AnyFunctionType *funcTy;
1045+
if (givenFuncType || FD->getInterfaceType()->is<FunctionType>()) {
1046+
funcTy = givenFuncType ? *givenFuncType
1047+
: FD->getInterfaceType()->castTo<FunctionType>();
1048+
} else {
1049+
funcTy = FD->getInterfaceType()->castTo<GenericFunctionType>();
1050+
}
1051+
10431052
auto resultTy =
10441053
getForeignResultType(FD, funcTy, asyncConvention, errorConvention);
10451054

@@ -1061,7 +1070,8 @@ class DeclAndTypePrinter::Implementation
10611070
/*isIndirect=*/
10621071
isa<FuncDecl>(FD) ? cast<FuncDecl>(FD)->isMutating() : false});
10631072
}
1064-
if (funcTy->isThrowing() && !ABIparams.empty())
1073+
// FIXME: Fix the method 'self' parameter.
1074+
if (!selfTypeDeclContext && !ABIparams.empty())
10651075
convertABIAdditionalParams(FD, resultTy, ABIparams, additionalParams);
10661076

10671077
funcPrinter.printFunctionSignature(
@@ -1098,26 +1108,25 @@ class DeclAndTypePrinter::Implementation
10981108
FD->getForeignAsyncConvention();
10991109
Optional<ForeignErrorConvention> errorConvention =
11001110
FD->getForeignErrorConvention();
1101-
assert(!FD->getGenericSignature() &&
1102-
"top-level generic functions not supported here");
1103-
auto funcTy = FD->getInterfaceType()->castTo<FunctionType>();
1111+
auto funcTy = FD->getInterfaceType()->castTo<AnyFunctionType>();
11041112
auto resultTy =
11051113
getForeignResultType(FD, funcTy, asyncConvention, errorConvention);
11061114

1107-
os << "inline ";
11081115
DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.prologueOS,
11091116
owningPrinter.typeMapping,
11101117
owningPrinter.interopContext);
11111118
llvm::SmallVector<DeclAndTypeClangFunctionPrinter::AdditionalParam, 2>
11121119
additionalParams;
11131120
auto ABIparams = owningPrinter.interopContext.getIrABIDetails()
11141121
.getFunctionABIAdditionalParams(FD);
1115-
if (funcTy->isThrowing() && !ABIparams.empty())
1122+
if (!ABIparams.empty())
11161123
convertABIAdditionalParams(FD, resultTy, ABIparams, additionalParams);
1117-
1124+
DeclAndTypeClangFunctionPrinter::FunctionSignatureModifiers modifiers;
1125+
modifiers.isInline = true;
11181126
funcPrinter.printFunctionSignature(
11191127
FD, FD->getName().getBaseIdentifier().get(), resultTy,
1120-
DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CxxInlineThunk);
1128+
DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CxxInlineThunk,
1129+
{}, modifiers);
11211130
// FIXME: Support throwing exceptions for Swift errors.
11221131
if (!funcTy->isThrowing())
11231132
os << " noexcept";
@@ -1126,7 +1135,7 @@ class DeclAndTypePrinter::Implementation
11261135
os << " {\n";
11271136
funcPrinter.printCxxThunkBody(
11281137
funcABI.getSymbolName(), FD->getModuleContext(), resultTy,
1129-
FD->getParameters(), additionalParams, funcTy->isThrowing());
1138+
FD->getParameters(), additionalParams, funcTy->isThrowing(), funcTy);
11301139
os << "}\n";
11311140
}
11321141

lib/PrintAsClang/ModuleContentsWriter.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,8 @@ void swift::printModuleContentsAsCxx(
677677

678678
os << "#ifndef SWIFT_PRINTED_CORE\n";
679679
os << "#define SWIFT_PRINTED_CORE\n";
680-
printSwiftToClangCoreScaffold(interopContext, writer.getTypeMapping(), os);
680+
printSwiftToClangCoreScaffold(interopContext, M.getASTContext(),
681+
writer.getTypeMapping(), os);
681682
os << "#endif\n";
682683

683684
// FIXME: refactor.

lib/PrintAsClang/PrintAsClang.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,15 @@ static void writePrologue(raw_ostream &out, ASTContext &ctx,
322322
emitMacro("SWIFT_INDIRECT_RESULT", "__attribute__((swift_indirect_result))");
323323
emitMacro("SWIFT_CONTEXT", "__attribute__((swift_context))");
324324
emitMacro("SWIFT_ERROR_RESULT", "__attribute__((swift_error_result))");
325+
if (ctx.getStdlibModule()->isStaticLibrary()) {
326+
emitMacro("SWIFT_IMPORT_STDLIB_SYMBOL");
327+
} else {
328+
out << "#if defined(_WIN32)\n";
329+
emitMacro("SWIFT_IMPORT_STDLIB_SYMBOL", "__declspec(dllimport)");
330+
out << "#else\n";
331+
emitMacro("SWIFT_IMPORT_STDLIB_SYMBOL");
332+
out << "#endif\n";
333+
}
325334
// SWIFT_NOEXCEPT applies 'noexcept' in C++ mode only.
326335
emitCxxConditional(
327336
out, [&] { emitMacro("SWIFT_NOEXCEPT", "noexcept"); },

0 commit comments

Comments
 (0)