Skip to content

Commit 266fa15

Browse files
committed
Bring PolymorphicConvention back into GenProto.cpp and expose
just the targeted operation that GenReflection actually needs. NFC.
1 parent 1419fc9 commit 266fa15

File tree

3 files changed

+227
-191
lines changed

3 files changed

+227
-191
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 166 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,74 @@
7070
using namespace swift;
7171
using namespace irgen;
7272

73+
namespace {
74+
75+
/// A class for computing how to pass arguments to a polymorphic
76+
/// function. The subclasses of this are the places which need to
77+
/// be updated if the convention changes.
78+
class PolymorphicConvention {
79+
protected:
80+
IRGenModule &IGM;
81+
ModuleDecl &M;
82+
CanSILFunctionType FnType;
83+
84+
CanGenericSignature Generics;
85+
86+
std::vector<MetadataSource> Sources;
87+
88+
FulfillmentMap Fulfillments;
89+
90+
GenericSignature::ConformsToArray getConformsTo(Type t) {
91+
return Generics->getConformsTo(t, M);
92+
}
93+
94+
public:
95+
PolymorphicConvention(IRGenModule &IGM, CanSILFunctionType fnType);
96+
97+
ArrayRef<MetadataSource> getSources() const { return Sources; }
98+
99+
using RequirementCallback =
100+
llvm::function_ref<void(GenericRequirement requirement)>;
101+
102+
void enumerateRequirements(const RequirementCallback &callback);
103+
104+
void enumerateUnfulfilledRequirements(const RequirementCallback &callback);
105+
106+
/// Returns a Fulfillment for a type parameter requirement, or
107+
/// nullptr if it's unfulfilled.
108+
const Fulfillment *getFulfillmentForTypeMetadata(CanType type) const;
109+
110+
/// Return the source of type metadata at a particular source index.
111+
const MetadataSource &getSource(size_t SourceIndex) const {
112+
return Sources[SourceIndex];
113+
}
114+
115+
private:
116+
void initGenerics();
117+
void considerNewTypeSource(MetadataSource::Kind kind, unsigned paramIndex,
118+
CanType type, IsExact_t isExact);
119+
bool considerType(CanType type, IsExact_t isExact,
120+
unsigned sourceIndex, MetadataPath &&path);
121+
122+
/// Testify to generic parameters in the Self type of a protocol
123+
/// witness method.
124+
void considerWitnessSelf(CanSILFunctionType fnType);
125+
126+
/// Testify to generic parameters in the Self type of an @objc
127+
/// generic or protocol method.
128+
void considerObjCGenericSelf(CanSILFunctionType fnType);
129+
130+
void considerParameter(SILParameterInfo param, unsigned paramIndex,
131+
bool isSelfParameter);
132+
133+
void addSelfMetadataFulfillment(CanType arg);
134+
void addSelfWitnessTableFulfillment(CanType arg, ProtocolDecl *proto);
135+
136+
void addPseudogenericFulfillments();
137+
};
138+
139+
} // end anonymous namespace
140+
73141
PolymorphicConvention::PolymorphicConvention(IRGenModule &IGM,
74142
CanSILFunctionType fnType)
75143
: IGM(IGM), M(*IGM.getSwiftModule()), FnType(fnType) {
@@ -196,7 +264,7 @@ void PolymorphicConvention::initGenerics() {
196264
Generics = FnType->getGenericSignature();
197265
}
198266

199-
void PolymorphicConvention::considerNewTypeSource(SourceKind kind,
267+
void PolymorphicConvention::considerNewTypeSource(MetadataSource::Kind kind,
200268
unsigned paramIndex,
201269
CanType type,
202270
IsExact_t isExact) {
@@ -241,15 +309,17 @@ void PolymorphicConvention::considerWitnessSelf(CanSILFunctionType fnType) {
241309
CanType selfTy = fnType->getSelfInstanceType();
242310

243311
// First, bind type metadata for Self.
244-
Sources.emplace_back(SourceKind::SelfMetadata, InvalidSourceIndex,
312+
Sources.emplace_back(MetadataSource::Kind::SelfMetadata,
313+
MetadataSource::InvalidSourceIndex,
245314
selfTy);
246315

247316
if (auto *proto = fnType->getDefaultWitnessMethodProtocol(M)) {
248317
// The Self type is abstract, so we must pass in a witness table.
249318
addSelfMetadataFulfillment(selfTy);
250319

251320
// Look at the witness table for the conformance.
252-
Sources.emplace_back(SourceKind::SelfWitnessTable, InvalidSourceIndex,
321+
Sources.emplace_back(MetadataSource::Kind::SelfWitnessTable,
322+
MetadataSource::InvalidSourceIndex,
253323
selfTy);
254324
addSelfWitnessTableFulfillment(selfTy, proto);
255325
} else {
@@ -266,7 +336,7 @@ void PolymorphicConvention::considerObjCGenericSelf(CanSILFunctionType fnType) {
266336
unsigned paramIndex = fnType->getParameters().size() - 1;
267337

268338
// Bind type metadata for Self.
269-
Sources.emplace_back(SourceKind::ClassPointer, paramIndex,
339+
Sources.emplace_back(MetadataSource::Kind::ClassPointer, paramIndex,
270340
selfTy);
271341

272342
if (isa<GenericTypeParamType>(selfTy))
@@ -290,7 +360,7 @@ void PolymorphicConvention::considerParameter(SILParameterInfo param,
290360
case ParameterConvention::Indirect_InoutAliasable:
291361
if (!isSelfParameter) return;
292362
if (type->getNominalOrBoundGenericNominal()) {
293-
considerNewTypeSource(SourceKind::GenericLValueMetadata,
363+
considerNewTypeSource(MetadataSource::Kind::GenericLValueMetadata,
294364
paramIndex, type, IsExact);
295365
}
296366
return;
@@ -301,8 +371,8 @@ void PolymorphicConvention::considerParameter(SILParameterInfo param,
301371
case ParameterConvention::Direct_Deallocating:
302372
// Classes are sources of metadata.
303373
if (type->getClassOrBoundGenericClass()) {
304-
considerNewTypeSource(SourceKind::ClassPointer, paramIndex, type,
305-
IsInexact);
374+
considerNewTypeSource(MetadataSource::Kind::ClassPointer,
375+
paramIndex, type, IsInexact);
306376
return;
307377
}
308378

@@ -318,8 +388,8 @@ void PolymorphicConvention::considerParameter(SILParameterInfo param,
318388
if (classDecl->usesObjCGenericsModel())
319389
return;
320390

321-
considerNewTypeSource(SourceKind::Metadata, paramIndex, objTy,
322-
IsInexact);
391+
considerNewTypeSource(MetadataSource::Kind::Metadata,
392+
paramIndex, objTy, IsInexact);
323393
return;
324394
}
325395

@@ -343,6 +413,62 @@ PolymorphicConvention::getFulfillmentForTypeMetadata(CanType type) const {
343413
return Fulfillments.getTypeMetadata(type);
344414
}
345415

416+
void irgen::enumerateGenericParamFulfillments(IRGenModule &IGM,
417+
CanSILFunctionType fnType,
418+
GenericParamFulfillfmentCallback callback) {
419+
PolymorphicConvention convention(IGM, fnType);
420+
421+
// Check if any requirements were fulfilled by metadata stored inside a
422+
// captured value.
423+
auto generics = fnType->getGenericSignature();
424+
425+
for (auto genericParam : generics->getGenericParams()) {
426+
auto genericParamType = genericParam->getCanonicalType();
427+
428+
auto fulfillment
429+
= convention.getFulfillmentForTypeMetadata(genericParamType);
430+
if (fulfillment == nullptr)
431+
continue;
432+
433+
auto &source = convention.getSource(fulfillment->SourceIndex);
434+
callback(genericParamType, source, fulfillment->Path);
435+
}
436+
}
437+
438+
namespace {
439+
440+
/// A class for binding type parameters of a generic function.
441+
class EmitPolymorphicParameters : public PolymorphicConvention {
442+
IRGenFunction &IGF;
443+
SILFunction &Fn;
444+
445+
public:
446+
EmitPolymorphicParameters(IRGenFunction &IGF, SILFunction &Fn);
447+
448+
void emit(Explosion &in, WitnessMetadata *witnessMetadata,
449+
const GetParameterFn &getParameter);
450+
451+
private:
452+
CanType getTypeInContext(CanType type) const;
453+
454+
CanType getArgTypeInContext(unsigned paramIndex) const;
455+
456+
/// Fulfill local type data from any extra information associated with
457+
/// the given source.
458+
void bindExtraSource(const MetadataSource &source, Explosion &in,
459+
WitnessMetadata *witnessMetadata);
460+
461+
void bindParameterSources(const GetParameterFn &getParameter);
462+
463+
void bindParameterSource(SILParameterInfo param, unsigned paramIndex,
464+
const GetParameterFn &getParameter) ;
465+
// Did the convention decide that the parameter at the given index
466+
// was a class-pointer source?
467+
bool isClassPointerSource(unsigned paramIndex);
468+
};
469+
470+
} // end anonymous namespace
471+
346472
EmitPolymorphicParameters::EmitPolymorphicParameters(IRGenFunction &IGF,
347473
SILFunction &Fn)
348474
: PolymorphicConvention(IGF.IGM, Fn.getLoweredFunctionType()),
@@ -357,15 +483,16 @@ CanType EmitPolymorphicParameters::getArgTypeInContext(unsigned paramIndex) cons
357483
return getTypeInContext(FnType->getParameters()[paramIndex].getType());
358484
}
359485

360-
void EmitPolymorphicParameters::bindExtraSource(const Source &source, Explosion &in,
361-
WitnessMetadata *witnessMetadata) {
486+
void EmitPolymorphicParameters::bindExtraSource(const MetadataSource &source,
487+
Explosion &in,
488+
WitnessMetadata *witnessMetadata) {
362489
switch (source.getKind()) {
363-
case SourceKind::Metadata:
364-
case SourceKind::ClassPointer:
490+
case MetadataSource::Kind::Metadata:
491+
case MetadataSource::Kind::ClassPointer:
365492
// Ignore these, we'll get to them when we walk the parameter list.
366493
return;
367494

368-
case SourceKind::GenericLValueMetadata: {
495+
case MetadataSource::Kind::GenericLValueMetadata: {
369496
CanType argTy = getArgTypeInContext(source.getParamIndex());
370497

371498
llvm::Value *metadata = in.claimNext();
@@ -375,7 +502,7 @@ void EmitPolymorphicParameters::bindExtraSource(const Source &source, Explosion
375502
return;
376503
}
377504

378-
case SourceKind::SelfMetadata: {
505+
case MetadataSource::Kind::SelfMetadata: {
379506
assert(witnessMetadata && "no metadata for witness method");
380507
llvm::Value *metadata = witnessMetadata->SelfMetadata;
381508
assert(metadata && "no Self metadata for witness method");
@@ -388,7 +515,7 @@ void EmitPolymorphicParameters::bindExtraSource(const Source &source, Explosion
388515
return;
389516
}
390517

391-
case SourceKind::SelfWitnessTable: {
518+
case MetadataSource::Kind::SelfWitnessTable: {
392519
assert(witnessMetadata && "no metadata for witness method");
393520
llvm::Value *wtable = witnessMetadata->SelfWitnessTable;
394521
assert(wtable && "no Self witness table for witness method");
@@ -460,7 +587,7 @@ void EmitPolymorphicParameters::bindParameterSource(SILParameterInfo param, unsi
460587

461588
bool EmitPolymorphicParameters::isClassPointerSource(unsigned paramIndex) {
462589
for (auto &source : getSources()) {
463-
if (source.getKind() == SourceKind::ClassPointer &&
590+
if (source.getKind() == MetadataSource::Kind::ClassPointer &&
464591
source.getParamIndex() == paramIndex) {
465592
return true;
466593
}
@@ -1727,7 +1854,7 @@ void EmitPolymorphicParameters::emit(Explosion &in,
17271854
WitnessMetadata *witnessMetadata,
17281855
const GetParameterFn &getParameter) {
17291856
// Collect any early sources and bind local type data from them.
1730-
for (const Source &source : getSources()) {
1857+
for (auto &source : getSources()) {
17311858
bindExtraSource(source, in, witnessMetadata);
17321859
}
17331860

@@ -2230,20 +2357,20 @@ namespace {
22302357
for (auto &source : getSources()) {
22312358
switch (source.getKind()) {
22322359
// Already accounted for in the parameters.
2233-
case SourceKind::ClassPointer:
2234-
case SourceKind::Metadata:
2360+
case MetadataSource::Kind::ClassPointer:
2361+
case MetadataSource::Kind::Metadata:
22352362
continue;
22362363

22372364
// Needs a special argument.
2238-
case SourceKind::GenericLValueMetadata: {
2365+
case MetadataSource::Kind::GenericLValueMetadata: {
22392366
out.add(IGF.emitTypeMetadataRef(getSubstSelfType(substFnType)));
22402367
continue;
22412368
}
22422369

22432370
// Witness 'Self' arguments are added as a special case in
22442371
// EmitPolymorphicArguments::emit.
2245-
case SourceKind::SelfMetadata:
2246-
case SourceKind::SelfWitnessTable:
2372+
case MetadataSource::Kind::SelfMetadata:
2373+
case MetadataSource::Kind::SelfWitnessTable:
22472374
continue;
22482375
}
22492376
llvm_unreachable("bad source kind!");
@@ -2281,23 +2408,23 @@ void EmitPolymorphicArguments::emit(CanSILFunctionType substFnType,
22812408
// For a witness call, add the Self argument metadata arguments last.
22822409
for (auto &source : getSources()) {
22832410
switch (source.getKind()) {
2284-
case SourceKind::Metadata:
2285-
case SourceKind::ClassPointer:
2411+
case MetadataSource::Kind::Metadata:
2412+
case MetadataSource::Kind::ClassPointer:
22862413
// Already accounted for in the arguments.
22872414
continue;
22882415

2289-
case SourceKind::GenericLValueMetadata:
2416+
case MetadataSource::Kind::GenericLValueMetadata:
22902417
// Added in the early phase.
22912418
continue;
22922419

2293-
case SourceKind::SelfMetadata: {
2420+
case MetadataSource::Kind::SelfMetadata: {
22942421
assert(witnessMetadata && "no metadata structure for witness method");
22952422
auto self = IGF.emitTypeMetadataRef(getSubstSelfType(substFnType));
22962423
witnessMetadata->SelfMetadata = self;
22972424
continue;
22982425
}
22992426

2300-
case SourceKind::SelfWitnessTable: {
2427+
case MetadataSource::Kind::SelfWitnessTable: {
23012428
// Added later.
23022429
continue;
23032430
}
@@ -2347,19 +2474,19 @@ NecessaryBindings::forFunctionInvocations(IRGenModule &IGM,
23472474
// - extra sources
23482475
for (auto &source : convention.getSources()) {
23492476
switch (source.getKind()) {
2350-
case PolymorphicConvention::SourceKind::Metadata:
2351-
case PolymorphicConvention::SourceKind::ClassPointer:
2477+
case MetadataSource::Kind::Metadata:
2478+
case MetadataSource::Kind::ClassPointer:
23522479
continue;
23532480

2354-
case PolymorphicConvention::SourceKind::GenericLValueMetadata:
2481+
case MetadataSource::Kind::GenericLValueMetadata:
23552482
bindings.addTypeMetadata(getSubstSelfType(substType));
23562483
continue;
23572484

2358-
case PolymorphicConvention::SourceKind::SelfMetadata:
2485+
case MetadataSource::Kind::SelfMetadata:
23592486
bindings.addTypeMetadata(getSubstSelfType(substType));
23602487
continue;
23612488

2362-
case PolymorphicConvention::SourceKind::SelfWitnessTable:
2489+
case MetadataSource::Kind::SelfWitnessTable:
23632490
// We'll just pass undef in cases like this.
23642491
continue;
23652492
}
@@ -2589,15 +2716,15 @@ namespace {
25892716

25902717
private:
25912718
/// Add signature elements for the source metadata.
2592-
void addEarlySource(const Source &source,
2719+
void addEarlySource(const MetadataSource &source,
25932720
SmallVectorImpl<llvm::Type*> &out) {
25942721
switch (source.getKind()) {
2595-
case SourceKind::ClassPointer: return; // already accounted for
2596-
case SourceKind::Metadata: return; // already accounted for
2597-
case SourceKind::GenericLValueMetadata:
2722+
case MetadataSource::Kind::ClassPointer: return; // already accounted for
2723+
case MetadataSource::Kind::Metadata: return; // already accounted for
2724+
case MetadataSource::Kind::GenericLValueMetadata:
25982725
return out.push_back(IGM.TypeMetadataPtrTy);
2599-
case SourceKind::SelfMetadata:
2600-
case SourceKind::SelfWitnessTable:
2726+
case MetadataSource::Kind::SelfMetadata:
2727+
case MetadataSource::Kind::SelfWitnessTable:
26012728
return; // handled as a special case in expand()
26022729
}
26032730
llvm_unreachable("bad source kind");

0 commit comments

Comments
 (0)