Skip to content

Commit 270fde9

Browse files
authored
Merge pull request swiftlang#60892 from hyp/eng/generic-struct-method
[interop][SwiftToCxx] add support for invoking methods in generic structs & unify function and struct generics
2 parents 50d6d6a + a5043c3 commit 270fde9

24 files changed

+621
-343
lines changed

include/swift/IRGen/IRABIDetailsProvider.h

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,45 @@ class IRABIDetailsProvider {
4949
};
5050

5151
/// Information about any ABI additional parameters.
52-
struct ABIAdditionalParam {
53-
enum class ABIParameterRole { GenericRequirementRole, Self, Error };
52+
class ABIAdditionalParam {
53+
public:
54+
enum class ABIParameterRole {
55+
/// A parameter that corresponds to a generic requirement that must be
56+
/// fullfilled by a call to this function.
57+
GenericRequirement,
58+
/// A parameter that corresponds to a Swift type pointer sourced from a
59+
/// valid metadata source, like the type of another argument.
60+
GenericTypeMetadataSource,
61+
/// A parameter that corresponds to the 'self' parameter.
62+
Self,
63+
/// The Swift error parameter.
64+
Error
65+
};
66+
67+
inline ABIParameterRole getRole() const { return role; }
68+
69+
inline GenericRequirement getGenericRequirement() {
70+
assert(role == ABIParameterRole::GenericRequirement);
71+
return *genericRequirement;
72+
}
73+
74+
inline CanType getMetadataSourceType() {
75+
assert(role == ABIParameterRole::GenericTypeMetadataSource);
76+
return canType;
77+
}
78+
79+
private:
80+
inline ABIAdditionalParam(
81+
ABIParameterRole role,
82+
llvm::Optional<GenericRequirement> genericRequirement, CanType canType)
83+
: role(role), genericRequirement(genericRequirement), canType(canType) {
84+
}
5485

5586
ABIParameterRole role;
5687
llvm::Optional<GenericRequirement> genericRequirement;
57-
TypeDecl *type;
88+
CanType canType;
89+
90+
friend class IRABIDetailsProviderImpl;
5891
};
5992

6093
/// Returns the size and alignment for the given type, or \c None if the type

lib/IRGen/GenCall.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,8 @@ namespace {
397397
unsigned AsyncResumeFunctionSwiftSelfIdx = 0;
398398
FunctionPointerKind FnKind;
399399
bool ShouldComputeABIDetails;
400-
SmallVector<GenericRequirement, 4> GenericRequirements;
400+
SmallVector<PolymorphicSignatureExpandedTypeSource, 4>
401+
polymorphicSignatureTypeSources;
401402

402403
SignatureExpansion(IRGenModule &IGM, CanSILFunctionType fnType,
403404
FunctionPointerKind fnKind,
@@ -1631,9 +1632,9 @@ void SignatureExpansion::expandParameters() {
16311632
// Next, the generic signature.
16321633
if (hasPolymorphicParameters(FnType) &&
16331634
!FnKind.shouldSuppressPolymorphicArguments())
1634-
expandPolymorphicSignature(IGM, FnType, ParamIRTypes,
1635-
ShouldComputeABIDetails ? &GenericRequirements
1636-
: nullptr);
1635+
expandPolymorphicSignature(
1636+
IGM, FnType, ParamIRTypes,
1637+
ShouldComputeABIDetails ? &polymorphicSignatureTypeSources : nullptr);
16371638

16381639
// Certain special functions are passed the continuation directly.
16391640
if (FnKind.shouldPassContinuationDirectly()) {
@@ -1931,8 +1932,8 @@ Signature SignatureExpansion::getSignature() {
19311932
result.ExtraDataKind = ExtraData::kindForMember<void>();
19321933
}
19331934
if (ShouldComputeABIDetails)
1934-
result.ABIDetails =
1935-
SignatureExpansionABIDetails{std::move(GenericRequirements)};
1935+
result.ABIDetails = SignatureExpansionABIDetails{
1936+
std::move(polymorphicSignatureTypeSources)};
19361937
return result;
19371938
}
19381939

lib/IRGen/GenProto.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3462,26 +3462,33 @@ namespace {
34623462
: PolymorphicConvention(IGM, fn) {}
34633463

34643464
void expand(SmallVectorImpl<llvm::Type *> &out,
3465-
SmallVectorImpl<GenericRequirement> *reqs) {
3465+
SmallVectorImpl<PolymorphicSignatureExpandedTypeSource> *reqs) {
3466+
auto outStartSize = out.size();
3467+
(void)outStartSize;
34663468
for (auto &source : getSources())
3467-
addEarlySource(source, out);
3469+
addEarlySource(source, out, reqs);
34683470

34693471
enumerateUnfulfilledRequirements([&](GenericRequirement reqt) {
34703472
if (reqs)
34713473
reqs->push_back(reqt);
34723474
out.push_back(reqt.Protocol ? IGM.WitnessTablePtrTy
34733475
: IGM.TypeMetadataPtrTy);
34743476
});
3477+
assert((!reqs || reqs->size() == (out.size() - outStartSize)) &&
3478+
"missing type source for type");
34753479
}
34763480

34773481
private:
34783482
/// Add signature elements for the source metadata.
3479-
void addEarlySource(const MetadataSource &source,
3480-
SmallVectorImpl<llvm::Type*> &out) {
3483+
void addEarlySource(
3484+
const MetadataSource &source, SmallVectorImpl<llvm::Type *> &out,
3485+
SmallVectorImpl<PolymorphicSignatureExpandedTypeSource> *reqs) {
34813486
switch (source.getKind()) {
34823487
case MetadataSource::Kind::ClassPointer: return; // already accounted for
34833488
case MetadataSource::Kind::Metadata: return; // already accounted for
34843489
case MetadataSource::Kind::GenericLValueMetadata:
3490+
if (reqs)
3491+
reqs->push_back(source);
34853492
return out.push_back(IGM.TypeMetadataPtrTy);
34863493
case MetadataSource::Kind::SelfMetadata:
34873494
case MetadataSource::Kind::SelfWitnessTable:
@@ -3498,7 +3505,7 @@ namespace {
34983505
void irgen::expandPolymorphicSignature(
34993506
IRGenModule &IGM, CanSILFunctionType polyFn,
35003507
SmallVectorImpl<llvm::Type *> &out,
3501-
SmallVectorImpl<GenericRequirement> *outReqs) {
3508+
SmallVectorImpl<PolymorphicSignatureExpandedTypeSource> *outReqs) {
35023509
ExpandPolymorphicSignature(IGM, polyFn).expand(out, outReqs);
35033510
}
35043511

lib/IRGen/GenProto.h

Lines changed: 4 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "Fulfillment.h"
2323
#include "GenericRequirement.h"
24+
#include "MetadataSource.h"
2425

2526
namespace llvm {
2627
class Type;
@@ -48,6 +49,7 @@ namespace irgen {
4849
class MetadataPath;
4950
class MetadataResponse;
5051
class NativeCCEntryPointArgumentEmission;
52+
class PolymorphicSignatureExpandedTypeSource;
5153
class ProtocolInfo;
5254
class TypeInfo;
5355

@@ -102,7 +104,8 @@ namespace irgen {
102104
void expandPolymorphicSignature(
103105
IRGenModule &IGM, CanSILFunctionType type,
104106
SmallVectorImpl<llvm::Type *> &types,
105-
SmallVectorImpl<GenericRequirement> *outReqs = nullptr);
107+
SmallVectorImpl<PolymorphicSignatureExpandedTypeSource> *outReqs =
108+
nullptr);
106109

107110
/// Return the number of trailing arguments necessary for calling a
108111
/// witness method.
@@ -179,90 +182,6 @@ namespace irgen {
179182
CanType srcType,
180183
ProtocolConformanceRef conformance);
181184

182-
class MetadataSource {
183-
public:
184-
enum class Kind {
185-
/// Metadata is derived from a source class pointer.
186-
ClassPointer,
187-
188-
/// Metadata is derived from a type metadata pointer.
189-
Metadata,
190-
191-
/// Metadata is derived from the origin type parameter.
192-
GenericLValueMetadata,
193-
194-
/// Metadata is obtained directly from the from a Self metadata
195-
/// parameter passed via the WitnessMethod convention.
196-
SelfMetadata,
197-
198-
/// Metadata is derived from the Self witness table parameter
199-
/// passed via the WitnessMethod convention.
200-
SelfWitnessTable,
201-
202-
/// Metadata is obtained directly from the FixedType indicated. Used with
203-
/// Objective-C generics, where the actual argument is erased at runtime
204-
/// and its existential bound is used instead.
205-
ErasedTypeMetadata,
206-
};
207-
208-
static bool requiresSourceIndex(Kind kind) {
209-
return (kind == Kind::ClassPointer ||
210-
kind == Kind::Metadata ||
211-
kind == Kind::GenericLValueMetadata);
212-
}
213-
214-
static bool requiresFixedType(Kind kind) {
215-
return (kind == Kind::ErasedTypeMetadata);
216-
}
217-
218-
enum : unsigned { InvalidSourceIndex = ~0U };
219-
220-
private:
221-
/// The kind of source this is.
222-
Kind TheKind;
223-
224-
/// For ClassPointer, Metadata, and GenericLValueMetadata, the source index;
225-
/// for ErasedTypeMetadata, the type; for others, Index should be set to
226-
/// InvalidSourceIndex.
227-
union {
228-
unsigned Index;
229-
CanType FixedType;
230-
};
231-
232-
public:
233-
CanType Type;
234-
235-
MetadataSource(Kind kind, CanType type)
236-
: TheKind(kind), Index(InvalidSourceIndex), Type(type)
237-
{
238-
assert(!requiresSourceIndex(kind) && !requiresFixedType(kind));
239-
}
240-
241-
242-
MetadataSource(Kind kind, CanType type, unsigned index)
243-
: TheKind(kind), Index(index), Type(type) {
244-
assert(requiresSourceIndex(kind));
245-
assert(index != InvalidSourceIndex);
246-
}
247-
248-
MetadataSource(Kind kind, CanType type, CanType fixedType)
249-
: TheKind(kind), FixedType(fixedType), Type(type) {
250-
assert(requiresFixedType(kind));
251-
}
252-
253-
Kind getKind() const { return TheKind; }
254-
255-
unsigned getParamIndex() const {
256-
assert(requiresSourceIndex(getKind()));
257-
return Index;
258-
}
259-
260-
CanType getFixedType() const {
261-
assert(requiresFixedType(getKind()));
262-
return FixedType;
263-
}
264-
};
265-
266185
using GenericParamFulfillmentCallback =
267186
llvm::function_ref<void(CanType genericParamType,
268187
const MetadataSource &source,

lib/IRGen/IRABIDetailsProvider.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,20 +167,30 @@ class IRABIDetailsProviderImpl {
167167
auto signature = Signature::getUncached(IGM, silFuncType, funcPointerKind,
168168
/*shouldComputeABIDetail=*/true);
169169

170-
for (const auto &reqt : signature.getABIDetails().GenericRequirements) {
171-
params.push_back({IRABIDetailsProvider::ABIAdditionalParam::
172-
ABIParameterRole::GenericRequirementRole,
173-
reqt, typeConverter.Context.getOpaquePointerDecl()});
170+
using ABIAdditionalParam = IRABIDetailsProvider::ABIAdditionalParam;
171+
using ParamRole = ABIAdditionalParam::ABIParameterRole;
172+
for (const auto &typeSource :
173+
signature.getABIDetails().polymorphicSignatureExpandedTypeSources) {
174+
typeSource.visit(
175+
[&](const GenericRequirement &reqt) {
176+
params.push_back(ABIAdditionalParam(ParamRole::GenericRequirement,
177+
reqt, CanType()));
178+
},
179+
[&](const MetadataSource &metadataSource) {
180+
auto index = metadataSource.getParamIndex();
181+
auto canType =
182+
silFuncType->getParameters()[index].getInterfaceType();
183+
params.push_back(ABIAdditionalParam(
184+
ParamRole::GenericTypeMetadataSource, llvm::None, canType));
185+
});
174186
}
175187
for (auto attrSet : signature.getAttributes()) {
176188
if (attrSet.hasAttribute(llvm::Attribute::AttrKind::SwiftSelf))
177189
params.push_back(
178-
{IRABIDetailsProvider::ABIAdditionalParam::ABIParameterRole::Self,
179-
llvm::None, typeConverter.Context.getOpaquePointerDecl()});
190+
ABIAdditionalParam(ParamRole::Self, llvm::None, CanType()));
180191
if (attrSet.hasAttribute(llvm::Attribute::AttrKind::SwiftError))
181192
params.push_back(
182-
{IRABIDetailsProvider::ABIAdditionalParam::ABIParameterRole::Error,
183-
llvm::None, typeConverter.Context.getOpaquePointerDecl()});
193+
ABIAdditionalParam(ParamRole::Error, llvm::None, CanType()));
184194
}
185195
return params;
186196
}

lib/IRGen/MetadataSource.h

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//===--- MetadataSource.h - structure for the source of metadata *- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_IRGEN_METADATA_SOURCE_H
14+
#define SWIFT_IRGEN_METADATA_SOURCE_H
15+
16+
#include "swift/AST/Types.h"
17+
18+
namespace swift {
19+
namespace irgen {
20+
21+
class MetadataSource {
22+
public:
23+
enum class Kind {
24+
/// Metadata is derived from a source class pointer.
25+
ClassPointer,
26+
27+
/// Metadata is derived from a type metadata pointer.
28+
Metadata,
29+
30+
/// Metadata is derived from the origin type parameter.
31+
GenericLValueMetadata,
32+
33+
/// Metadata is obtained directly from the from a Self metadata
34+
/// parameter passed via the WitnessMethod convention.
35+
SelfMetadata,
36+
37+
/// Metadata is derived from the Self witness table parameter
38+
/// passed via the WitnessMethod convention.
39+
SelfWitnessTable,
40+
41+
/// Metadata is obtained directly from the FixedType indicated. Used with
42+
/// Objective-C generics, where the actual argument is erased at runtime
43+
/// and its existential bound is used instead.
44+
ErasedTypeMetadata,
45+
};
46+
47+
static bool requiresSourceIndex(Kind kind) {
48+
return (kind == Kind::ClassPointer ||
49+
kind == Kind::Metadata ||
50+
kind == Kind::GenericLValueMetadata);
51+
}
52+
53+
static bool requiresFixedType(Kind kind) {
54+
return (kind == Kind::ErasedTypeMetadata);
55+
}
56+
57+
enum : unsigned { InvalidSourceIndex = ~0U };
58+
59+
private:
60+
/// The kind of source this is.
61+
Kind TheKind;
62+
63+
/// For ClassPointer, Metadata, and GenericLValueMetadata, the source index;
64+
/// for ErasedTypeMetadata, the type; for others, Index should be set to
65+
/// InvalidSourceIndex.
66+
union {
67+
unsigned Index;
68+
CanType FixedType;
69+
};
70+
71+
public:
72+
CanType Type;
73+
74+
MetadataSource(Kind kind, CanType type)
75+
: TheKind(kind), Index(InvalidSourceIndex), Type(type)
76+
{
77+
assert(!requiresSourceIndex(kind) && !requiresFixedType(kind));
78+
}
79+
80+
81+
MetadataSource(Kind kind, CanType type, unsigned index)
82+
: TheKind(kind), Index(index), Type(type) {
83+
assert(requiresSourceIndex(kind));
84+
assert(index != InvalidSourceIndex);
85+
}
86+
87+
MetadataSource(Kind kind, CanType type, CanType fixedType)
88+
: TheKind(kind), FixedType(fixedType), Type(type) {
89+
assert(requiresFixedType(kind));
90+
}
91+
92+
Kind getKind() const { return TheKind; }
93+
94+
unsigned getParamIndex() const {
95+
assert(requiresSourceIndex(getKind()));
96+
return Index;
97+
}
98+
99+
CanType getFixedType() const {
100+
assert(requiresFixedType(getKind()));
101+
return FixedType;
102+
}
103+
};
104+
105+
} // end namespace irgen
106+
} // end namespace swift
107+
108+
#endif

0 commit comments

Comments
 (0)