70
70
using namespace swift ;
71
71
using namespace irgen ;
72
72
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
+
73
141
PolymorphicConvention::PolymorphicConvention (IRGenModule &IGM,
74
142
CanSILFunctionType fnType)
75
143
: IGM(IGM), M(*IGM.getSwiftModule()), FnType(fnType) {
@@ -196,7 +264,7 @@ void PolymorphicConvention::initGenerics() {
196
264
Generics = FnType->getGenericSignature ();
197
265
}
198
266
199
- void PolymorphicConvention::considerNewTypeSource (SourceKind kind,
267
+ void PolymorphicConvention::considerNewTypeSource (MetadataSource::Kind kind,
200
268
unsigned paramIndex,
201
269
CanType type,
202
270
IsExact_t isExact) {
@@ -241,15 +309,17 @@ void PolymorphicConvention::considerWitnessSelf(CanSILFunctionType fnType) {
241
309
CanType selfTy = fnType->getSelfInstanceType ();
242
310
243
311
// First, bind type metadata for Self.
244
- Sources.emplace_back (SourceKind::SelfMetadata, InvalidSourceIndex,
312
+ Sources.emplace_back (MetadataSource::Kind::SelfMetadata,
313
+ MetadataSource::InvalidSourceIndex,
245
314
selfTy);
246
315
247
316
if (auto *proto = fnType->getDefaultWitnessMethodProtocol (M)) {
248
317
// The Self type is abstract, so we must pass in a witness table.
249
318
addSelfMetadataFulfillment (selfTy);
250
319
251
320
// 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,
253
323
selfTy);
254
324
addSelfWitnessTableFulfillment (selfTy, proto);
255
325
} else {
@@ -266,7 +336,7 @@ void PolymorphicConvention::considerObjCGenericSelf(CanSILFunctionType fnType) {
266
336
unsigned paramIndex = fnType->getParameters ().size () - 1 ;
267
337
268
338
// Bind type metadata for Self.
269
- Sources.emplace_back (SourceKind ::ClassPointer, paramIndex,
339
+ Sources.emplace_back (MetadataSource::Kind ::ClassPointer, paramIndex,
270
340
selfTy);
271
341
272
342
if (isa<GenericTypeParamType>(selfTy))
@@ -290,7 +360,7 @@ void PolymorphicConvention::considerParameter(SILParameterInfo param,
290
360
case ParameterConvention::Indirect_InoutAliasable:
291
361
if (!isSelfParameter) return ;
292
362
if (type->getNominalOrBoundGenericNominal ()) {
293
- considerNewTypeSource (SourceKind ::GenericLValueMetadata,
363
+ considerNewTypeSource (MetadataSource::Kind ::GenericLValueMetadata,
294
364
paramIndex, type, IsExact);
295
365
}
296
366
return ;
@@ -301,8 +371,8 @@ void PolymorphicConvention::considerParameter(SILParameterInfo param,
301
371
case ParameterConvention::Direct_Deallocating:
302
372
// Classes are sources of metadata.
303
373
if (type->getClassOrBoundGenericClass ()) {
304
- considerNewTypeSource (SourceKind:: ClassPointer, paramIndex, type ,
305
- IsInexact);
374
+ considerNewTypeSource (MetadataSource::Kind:: ClassPointer,
375
+ paramIndex, type, IsInexact);
306
376
return ;
307
377
}
308
378
@@ -318,8 +388,8 @@ void PolymorphicConvention::considerParameter(SILParameterInfo param,
318
388
if (classDecl->usesObjCGenericsModel ())
319
389
return ;
320
390
321
- considerNewTypeSource (SourceKind:: Metadata, paramIndex, objTy ,
322
- IsInexact);
391
+ considerNewTypeSource (MetadataSource::Kind:: Metadata,
392
+ paramIndex, objTy, IsInexact);
323
393
return ;
324
394
}
325
395
@@ -343,6 +413,62 @@ PolymorphicConvention::getFulfillmentForTypeMetadata(CanType type) const {
343
413
return Fulfillments.getTypeMetadata (type);
344
414
}
345
415
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
+
346
472
EmitPolymorphicParameters::EmitPolymorphicParameters (IRGenFunction &IGF,
347
473
SILFunction &Fn)
348
474
: PolymorphicConvention(IGF.IGM, Fn.getLoweredFunctionType()),
@@ -357,15 +483,16 @@ CanType EmitPolymorphicParameters::getArgTypeInContext(unsigned paramIndex) cons
357
483
return getTypeInContext (FnType->getParameters ()[paramIndex].getType ());
358
484
}
359
485
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) {
362
489
switch (source.getKind ()) {
363
- case SourceKind ::Metadata:
364
- case SourceKind ::ClassPointer:
490
+ case MetadataSource::Kind ::Metadata:
491
+ case MetadataSource::Kind ::ClassPointer:
365
492
// Ignore these, we'll get to them when we walk the parameter list.
366
493
return ;
367
494
368
- case SourceKind ::GenericLValueMetadata: {
495
+ case MetadataSource::Kind ::GenericLValueMetadata: {
369
496
CanType argTy = getArgTypeInContext (source.getParamIndex ());
370
497
371
498
llvm::Value *metadata = in.claimNext ();
@@ -375,7 +502,7 @@ void EmitPolymorphicParameters::bindExtraSource(const Source &source, Explosion
375
502
return ;
376
503
}
377
504
378
- case SourceKind ::SelfMetadata: {
505
+ case MetadataSource::Kind ::SelfMetadata: {
379
506
assert (witnessMetadata && " no metadata for witness method" );
380
507
llvm::Value *metadata = witnessMetadata->SelfMetadata ;
381
508
assert (metadata && " no Self metadata for witness method" );
@@ -388,7 +515,7 @@ void EmitPolymorphicParameters::bindExtraSource(const Source &source, Explosion
388
515
return ;
389
516
}
390
517
391
- case SourceKind ::SelfWitnessTable: {
518
+ case MetadataSource::Kind ::SelfWitnessTable: {
392
519
assert (witnessMetadata && " no metadata for witness method" );
393
520
llvm::Value *wtable = witnessMetadata->SelfWitnessTable ;
394
521
assert (wtable && " no Self witness table for witness method" );
@@ -460,7 +587,7 @@ void EmitPolymorphicParameters::bindParameterSource(SILParameterInfo param, unsi
460
587
461
588
bool EmitPolymorphicParameters::isClassPointerSource (unsigned paramIndex) {
462
589
for (auto &source : getSources ()) {
463
- if (source.getKind () == SourceKind ::ClassPointer &&
590
+ if (source.getKind () == MetadataSource::Kind ::ClassPointer &&
464
591
source.getParamIndex () == paramIndex) {
465
592
return true ;
466
593
}
@@ -1727,7 +1854,7 @@ void EmitPolymorphicParameters::emit(Explosion &in,
1727
1854
WitnessMetadata *witnessMetadata,
1728
1855
const GetParameterFn &getParameter) {
1729
1856
// Collect any early sources and bind local type data from them.
1730
- for (const Source &source : getSources ()) {
1857
+ for (auto &source : getSources ()) {
1731
1858
bindExtraSource (source, in, witnessMetadata);
1732
1859
}
1733
1860
@@ -2230,20 +2357,20 @@ namespace {
2230
2357
for (auto &source : getSources ()) {
2231
2358
switch (source.getKind ()) {
2232
2359
// Already accounted for in the parameters.
2233
- case SourceKind ::ClassPointer:
2234
- case SourceKind ::Metadata:
2360
+ case MetadataSource::Kind ::ClassPointer:
2361
+ case MetadataSource::Kind ::Metadata:
2235
2362
continue ;
2236
2363
2237
2364
// Needs a special argument.
2238
- case SourceKind ::GenericLValueMetadata: {
2365
+ case MetadataSource::Kind ::GenericLValueMetadata: {
2239
2366
out.add (IGF.emitTypeMetadataRef (getSubstSelfType (substFnType)));
2240
2367
continue ;
2241
2368
}
2242
2369
2243
2370
// Witness 'Self' arguments are added as a special case in
2244
2371
// EmitPolymorphicArguments::emit.
2245
- case SourceKind ::SelfMetadata:
2246
- case SourceKind ::SelfWitnessTable:
2372
+ case MetadataSource::Kind ::SelfMetadata:
2373
+ case MetadataSource::Kind ::SelfWitnessTable:
2247
2374
continue ;
2248
2375
}
2249
2376
llvm_unreachable (" bad source kind!" );
@@ -2281,23 +2408,23 @@ void EmitPolymorphicArguments::emit(CanSILFunctionType substFnType,
2281
2408
// For a witness call, add the Self argument metadata arguments last.
2282
2409
for (auto &source : getSources ()) {
2283
2410
switch (source.getKind ()) {
2284
- case SourceKind ::Metadata:
2285
- case SourceKind ::ClassPointer:
2411
+ case MetadataSource::Kind ::Metadata:
2412
+ case MetadataSource::Kind ::ClassPointer:
2286
2413
// Already accounted for in the arguments.
2287
2414
continue ;
2288
2415
2289
- case SourceKind ::GenericLValueMetadata:
2416
+ case MetadataSource::Kind ::GenericLValueMetadata:
2290
2417
// Added in the early phase.
2291
2418
continue ;
2292
2419
2293
- case SourceKind ::SelfMetadata: {
2420
+ case MetadataSource::Kind ::SelfMetadata: {
2294
2421
assert (witnessMetadata && " no metadata structure for witness method" );
2295
2422
auto self = IGF.emitTypeMetadataRef (getSubstSelfType (substFnType));
2296
2423
witnessMetadata->SelfMetadata = self;
2297
2424
continue ;
2298
2425
}
2299
2426
2300
- case SourceKind ::SelfWitnessTable: {
2427
+ case MetadataSource::Kind ::SelfWitnessTable: {
2301
2428
// Added later.
2302
2429
continue ;
2303
2430
}
@@ -2347,19 +2474,19 @@ NecessaryBindings::forFunctionInvocations(IRGenModule &IGM,
2347
2474
// - extra sources
2348
2475
for (auto &source : convention.getSources ()) {
2349
2476
switch (source.getKind ()) {
2350
- case PolymorphicConvention::SourceKind ::Metadata:
2351
- case PolymorphicConvention::SourceKind ::ClassPointer:
2477
+ case MetadataSource::Kind ::Metadata:
2478
+ case MetadataSource::Kind ::ClassPointer:
2352
2479
continue ;
2353
2480
2354
- case PolymorphicConvention::SourceKind ::GenericLValueMetadata:
2481
+ case MetadataSource::Kind ::GenericLValueMetadata:
2355
2482
bindings.addTypeMetadata (getSubstSelfType (substType));
2356
2483
continue ;
2357
2484
2358
- case PolymorphicConvention::SourceKind ::SelfMetadata:
2485
+ case MetadataSource::Kind ::SelfMetadata:
2359
2486
bindings.addTypeMetadata (getSubstSelfType (substType));
2360
2487
continue ;
2361
2488
2362
- case PolymorphicConvention::SourceKind ::SelfWitnessTable:
2489
+ case MetadataSource::Kind ::SelfWitnessTable:
2363
2490
// We'll just pass undef in cases like this.
2364
2491
continue ;
2365
2492
}
@@ -2589,15 +2716,15 @@ namespace {
2589
2716
2590
2717
private:
2591
2718
// / Add signature elements for the source metadata.
2592
- void addEarlySource (const Source &source,
2719
+ void addEarlySource (const MetadataSource &source,
2593
2720
SmallVectorImpl<llvm::Type*> &out) {
2594
2721
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:
2598
2725
return out.push_back (IGM.TypeMetadataPtrTy );
2599
- case SourceKind ::SelfMetadata:
2600
- case SourceKind ::SelfWitnessTable:
2726
+ case MetadataSource::Kind ::SelfMetadata:
2727
+ case MetadataSource::Kind ::SelfWitnessTable:
2601
2728
return ; // handled as a special case in expand()
2602
2729
}
2603
2730
llvm_unreachable (" bad source kind" );
0 commit comments