Skip to content

Commit 6e31af6

Browse files
committed
IRGen: Simplify enumerateFulfillments()
1 parent c5ab104 commit 6e31af6

File tree

6 files changed

+65
-116
lines changed

6 files changed

+65
-116
lines changed

lib/IRGen/Fulfillment.cpp

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -279,38 +279,43 @@ bool FulfillmentMap::searchNominalTypeMetadata(IRGenModule &IGM,
279279

280280
bool hadFulfillment = false;
281281

282+
auto subs = type->getContextSubstitutionMap(IGM.getSwiftModule(), nominal);
283+
282284
GenericTypeRequirements requirements(IGM, nominal);
283-
requirements.enumerateFulfillments(
284-
IGM, type->getContextSubstitutionMap(IGM.getSwiftModule(), nominal),
285-
[&](unsigned reqtIndex, CanType arg, ProtocolConformanceRef conf) {
286-
// Skip uninteresting type arguments.
287-
if (!keys.hasInterestingType(arg))
288-
return;
289-
290-
// If the fulfilled value is type metadata, refine the path.
291-
if (conf.isInvalid()) {
292-
auto argState =
293-
getPresumedMetadataStateForTypeArgument(metadataState);
294-
MetadataPath argPath = path;
295-
argPath.addNominalTypeArgumentComponent(reqtIndex);
296-
hadFulfillment |= searchTypeMetadata(
297-
IGM, arg, IsExact, argState, source, std::move(argPath), keys);
298-
return;
299-
}
300-
301-
// Otherwise, it's a conformance.
302-
303-
// Ignore it unless the type itself is interesting.
304-
if (!keys.isInterestingType(arg))
305-
return;
306-
307-
// Refine the path.
308-
MetadataPath argPath = path;
309-
argPath.addNominalTypeArgumentConformanceComponent(reqtIndex);
310-
311-
hadFulfillment |= searchWitnessTable(IGM, arg, conf.getRequirement(),
312-
source, std::move(argPath), keys);
313-
});
285+
286+
for (unsigned reqtIndex : indices(requirements.getRequirements())) {
287+
auto requirement = requirements.getRequirements()[reqtIndex];
288+
auto arg = requirement.getTypeParameter().subst(subs)->getCanonicalType();
289+
290+
// Skip uninteresting type arguments.
291+
if (!keys.hasInterestingType(arg))
292+
continue;
293+
294+
// If the fulfilled value is type metadata, refine the path.
295+
if (requirement.isMetadata()) {
296+
auto argState =
297+
getPresumedMetadataStateForTypeArgument(metadataState);
298+
MetadataPath argPath = path;
299+
argPath.addNominalTypeArgumentComponent(reqtIndex);
300+
hadFulfillment |= searchTypeMetadata(
301+
IGM, arg, IsExact, argState, source, std::move(argPath), keys);
302+
continue;
303+
}
304+
305+
// Otherwise, it's a conformance.
306+
assert(requirement.isWitnessTable());
307+
308+
// Ignore it unless the type itself is interesting.
309+
if (!keys.isInterestingType(arg))
310+
continue;
311+
312+
// Refine the path.
313+
MetadataPath argPath = path;
314+
argPath.addNominalTypeArgumentConformanceComponent(reqtIndex);
315+
316+
hadFulfillment |= searchWitnessTable(IGM, arg, requirement.getProtocol(),
317+
source, std::move(argPath), keys);
318+
}
314319

315320
return hadFulfillment;
316321
}

lib/IRGen/GenProto.cpp

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3154,8 +3154,8 @@ void EmitPolymorphicArguments::emit(SubstitutionMap subs,
31543154
// For now, treat all archetypes independently.
31553155
enumerateUnfulfilledRequirements([&](GenericRequirement requirement) {
31563156
llvm::Value *requiredValue =
3157-
emitGenericRequirementFromSubstitutions(IGF, Generics,
3158-
requirement, subs);
3157+
emitGenericRequirementFromSubstitutions(IGF, requirement, subs,
3158+
MetadataState::Complete);
31593159
out.add(requiredValue);
31603160
});
31613161

@@ -3277,7 +3277,6 @@ GenericTypeRequirements::GenericTypeRequirements(IRGenModule &IGM,
32773277

32783278
// Construct a representative function type.
32793279
auto generics = ncGenerics.getCanonicalSignature();
3280-
Generics = generics;
32813280
auto fnType = SILFunctionType::get(generics, SILFunctionType::ExtInfo(),
32823281
SILCoroutineKind::None,
32833282
/*callee*/ ParameterConvention::Direct_Unowned,
@@ -3297,35 +3296,15 @@ GenericTypeRequirements::GenericTypeRequirements(IRGenModule &IGM,
32973296
// We do not need to consider extra sources.
32983297
}
32993298

3300-
void
3301-
GenericTypeRequirements::enumerateFulfillments(IRGenModule &IGM,
3302-
SubstitutionMap subs,
3303-
FulfillmentCallback callback) {
3304-
if (empty()) return;
3305-
3306-
for (auto reqtIndex : indices(getRequirements())) {
3307-
auto &reqt = getRequirements()[reqtIndex];
3308-
CanType type = reqt.getTypeParameter().subst(subs)->getCanonicalType();
3309-
if (reqt.isWitnessTable()) {
3310-
auto conformance =
3311-
subs.lookupConformance(reqt.getTypeParameter(), reqt.getProtocol());
3312-
callback(reqtIndex, type, conformance);
3313-
} else {
3314-
assert(reqt.isMetadata());
3315-
callback(reqtIndex, type, ProtocolConformanceRef::forInvalid());
3316-
}
3317-
}
3318-
}
3319-
33203299
void GenericTypeRequirements::emitInitOfBuffer(IRGenFunction &IGF,
33213300
SubstitutionMap subs,
33223301
Address buffer) {
33233302
if (Requirements.empty()) return;
33243303

33253304
emitInitOfGenericRequirementsBuffer(IGF, Requirements, buffer,
33263305
[&](GenericRequirement requirement) {
3327-
return emitGenericRequirementFromSubstitutions(IGF, Generics,
3328-
requirement, subs);
3306+
return emitGenericRequirementFromSubstitutions(IGF, requirement, subs,
3307+
MetadataState::Complete);
33293308
});
33303309
}
33313310

@@ -3358,9 +3337,9 @@ void irgen::emitInitOfGenericRequirementsBuffer(IRGenFunction &IGF,
33583337

33593338
llvm::Value *
33603339
irgen::emitGenericRequirementFromSubstitutions(IRGenFunction &IGF,
3361-
CanGenericSignature generics,
33623340
GenericRequirement requirement,
3363-
SubstitutionMap subs) {
3341+
SubstitutionMap subs,
3342+
DynamicMetadataRequest request) {
33643343
CanType depTy = requirement.getTypeParameter();
33653344
CanType argType = depTy.subst(subs)->getCanonicalType();
33663345

@@ -3369,7 +3348,7 @@ irgen::emitGenericRequirementFromSubstitutions(IRGenFunction &IGF,
33693348
return IGF.emitPackShapeExpression(argType);
33703349

33713350
case GenericRequirement::Kind::Metadata:
3372-
return IGF.emitTypeMetadataRef(argType);
3351+
return IGF.emitTypeMetadataRef(argType, request).getMetadata();
33733352

33743353
case GenericRequirement::Kind::WitnessTable: {
33753354
auto proto = requirement.getProtocol();

lib/IRGen/GenericArguments.h

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "IRGenFunction.h"
3030
#include "IRGenMangler.h"
3131
#include "IRGenModule.h"
32+
#include "MetadataRequest.h"
3233
#include "swift/AST/ASTContext.h"
3334
#include "swift/AST/ExistentialLayout.h"
3435
#include "swift/AST/GenericEnvironment.h"
@@ -50,13 +51,7 @@ struct GenericArguments {
5051
SmallVector<llvm::Value *, 8> Values;
5152
SmallVector<llvm::Type *, 8> Types;
5253

53-
static unsigned getNumGenericArguments(IRGenModule &IGM,
54-
NominalTypeDecl *nominal) {
55-
GenericTypeRequirements requirements(IGM, nominal);
56-
return requirements.getNumTypeRequirements();
57-
}
58-
59-
void collectTypes(IRGenModule &IGM, NominalTypeDecl *nominal) {
54+
void collectTypes(IRGenModule &IGM, NominalTypeDecl *nominal) {
6055
GenericTypeRequirements requirements(IGM, nominal);
6156
collectTypes(IGM, requirements);
6257
}
@@ -87,15 +82,10 @@ struct GenericArguments {
8782
void collect(IRGenFunction &IGF, SubstitutionMap subs) {
8883
GenericTypeRequirements requirements(IGF.IGM, subs.getGenericSignature());
8984

90-
requirements.enumerateFulfillments(
91-
IGF.IGM, subs,
92-
[&](unsigned reqtIndex, CanType type, ProtocolConformanceRef conf) {
93-
if (conf) {
94-
Values.push_back(emitWitnessTableRef(IGF, type, conf));
95-
} else {
96-
Values.push_back(IGF.emitAbstractTypeMetadataRef(type));
97-
}
98-
});
85+
for (auto requirement : requirements.getRequirements()) {
86+
Values.push_back(emitGenericRequirementFromSubstitutions(
87+
IGF, requirement, subs, MetadataState::Abstract));
88+
}
9989

10090
collectTypes(IGF.IGM, requirements);
10191
assert(Types.size() == Values.size());

lib/IRGen/GenericRequirement.h

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ namespace irgen {
4141
class Address;
4242
class IRGenFunction;
4343
class IRGenModule;
44+
class DynamicMetadataRequest;
4445

4546
using RequirementCallback =
4647
llvm::function_ref<void(GenericRequirement requirement)>;
@@ -54,9 +55,9 @@ void enumerateGenericSignatureRequirements(CanGenericSignature signature,
5455
/// value.
5556
llvm::Value *
5657
emitGenericRequirementFromSubstitutions(IRGenFunction &IGF,
57-
CanGenericSignature signature,
5858
GenericRequirement requirement,
59-
SubstitutionMap subs);
59+
SubstitutionMap subs,
60+
DynamicMetadataRequest request);
6061

6162
using EmitGenericRequirementFn =
6263
llvm::function_ref<llvm::Value*(GenericRequirement reqt)>;
@@ -86,15 +87,10 @@ void bindFromGenericRequirementsBuffer(IRGenFunction &IGF,
8687
/// A class describing the layout of the generic requirements of a
8788
/// nominal type metadata.
8889
///
89-
/// The generic requirements are always laid out as a sequence of type
90-
/// metadata (corresponding to the type parameters of the context established
91-
/// by the type, minus anything fulfillable from its parent type metadata)
92-
/// followed by a sequence of protocol witness tables (corresponding to the
93-
/// root conformances of the context established by the type, again minus
94-
/// anything fulfillable from its parent type metadata).
90+
/// The generic requirements are always laid out as a sequence of shape
91+
/// parameters, followed by type metadata and witness tables.
9592
class GenericTypeRequirements {
9693
llvm::SmallVector<GenericRequirement, 4> Requirements;
97-
CanGenericSignature Generics;
9894

9995
public:
10096
GenericTypeRequirements(IRGenModule &IGM, NominalTypeDecl *decl);
@@ -105,38 +101,8 @@ class GenericTypeRequirements {
105101
return Requirements;
106102
}
107103

108-
/// Return the number of entries required in order to store this data.
109-
unsigned getStorageSizeInWords() const {
110-
return Requirements.size();
111-
}
112-
113-
/// Return the number of type metadata requirements.
114-
unsigned getNumTypeRequirements() const {
115-
unsigned count = 0;
116-
for (auto i = Requirements.begin(), e = Requirements.end(); i != e; ++i) {
117-
if (i->isMetadata()) {
118-
count++;
119-
} else {
120-
#ifndef NDEBUG
121-
// Assert that the rest of the requirements are conformance
122-
// requirements.
123-
for (++i; i != e; ++i) {
124-
assert(i->isWitnessTable() && "type requirement followed conformance!");
125-
}
126-
#endif
127-
break;
128-
}
129-
}
130-
return count;
131-
}
132-
133104
bool empty() const { return Requirements.empty(); }
134105

135-
using FulfillmentCallback = llvm::function_ref<void(
136-
unsigned requirementIndex, CanType type, ProtocolConformanceRef conf)>;
137-
void enumerateFulfillments(IRGenModule &IGM, SubstitutionMap subs,
138-
FulfillmentCallback callback);
139-
140106
void emitInitOfBuffer(IRGenFunction &IGF, SubstitutionMap subs,
141107
Address buffer);
142108

lib/IRGen/IRGenSIL.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6543,8 +6543,8 @@ void IRGenSILFunction::visitKeyPathInst(swift::KeyPathInst *I) {
65436543
if (!I->getSubstitutions().empty()) {
65446544
emitInitOfGenericRequirementsBuffer(*this, requirements, argsBuf,
65456545
[&](GenericRequirement reqt) -> llvm::Value * {
6546-
return emitGenericRequirementFromSubstitutions(*this, sig,
6547-
reqt, subs);
6546+
return emitGenericRequirementFromSubstitutions(*this, reqt, subs,
6547+
MetadataState::Complete);
65486548
});
65496549
}
65506550

test/IRGen/variadic_generic_types.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,12 @@ struct G<T...> {
1717
callee()
1818
}
1919
}
20+
21+
func blackHole<T>(_: T) {}
22+
23+
blackHole(G< >.self)
24+
blackHole(G<Int, String>.self)
25+
26+
func genericMetadata<T...>(_: T...) {
27+
blackHole(G<T... >.self)
28+
}

0 commit comments

Comments
 (0)