@@ -414,6 +414,8 @@ namespace {
414
414
unsigned NumParams = 0 ;
415
415
unsigned NumRequirements = 0 ;
416
416
unsigned NumGenericKeyArguments = 0 ;
417
+ SmallVector<CanType, 2 > ShapeClasses;
418
+ SmallVector<GenericPackArgument, 2 > GenericPackArguments;
417
419
418
420
GenericSignatureHeaderBuilder (IRGenModule &IGM,
419
421
ConstantStructBuilder &builder)
@@ -422,13 +424,26 @@ namespace {
422
424
NumGenericKeyArgumentsPP(builder.addPlaceholderWithSize(IGM.Int16Ty)),
423
425
FlagsPP(builder.addPlaceholderWithSize(IGM.Int16Ty)) {}
424
426
425
- void adjustAfterRequirements (const GenericRequirementsMetadata &info) {
427
+ void add (const GenericArgumentMetadata &info) {
428
+ ShapeClasses.append (info.ShapeClasses .begin (),
429
+ info.ShapeClasses .end ());
430
+
426
431
NumParams += info.NumParams ;
427
432
NumRequirements += info.NumRequirements ;
433
+
434
+ for (auto pack : info.GenericPackArguments ) {
435
+ // Compute the final index.
436
+ pack.Index += NumGenericKeyArguments + ShapeClasses.size ();
437
+ GenericPackArguments.push_back (pack);
438
+ }
439
+
428
440
NumGenericKeyArguments += info.NumGenericKeyArguments ;
429
441
}
430
442
431
443
void finish (IRGenModule &IGM, ConstantStructBuilder &b) {
444
+ assert (GenericPackArguments.empty () == ShapeClasses.empty () &&
445
+ " Can't have one without the other" );
446
+
432
447
assert (NumParams <= UINT16_MAX && " way too generic" );
433
448
b.fillPlaceholderWithInt (NumParamsPP, IGM.Int16Ty , NumParams);
434
449
@@ -438,9 +453,9 @@ namespace {
438
453
439
454
assert (NumGenericKeyArguments <= UINT16_MAX && " way too generic" );
440
455
b.fillPlaceholderWithInt (NumGenericKeyArgumentsPP, IGM.Int16Ty ,
441
- NumGenericKeyArguments);
456
+ NumGenericKeyArguments + ShapeClasses. size () );
442
457
443
- bool hasTypePacks = false ;
458
+ bool hasTypePacks = !GenericPackArguments. empty () ;
444
459
GenericContextDescriptorFlags flags (hasTypePacks);
445
460
b.fillPlaceholderWithInt (FlagsPP, IGM.Int16Ty ,
446
461
flags.getIntValue ());
@@ -495,6 +510,7 @@ namespace {
495
510
asImpl ().addGenericParametersHeader ();
496
511
asImpl ().addGenericParameters ();
497
512
asImpl ().addGenericRequirements ();
513
+ asImpl ().addGenericPackShapeDescriptors ();
498
514
asImpl ().finishGenericParameters ();
499
515
}
500
516
@@ -512,7 +528,7 @@ namespace {
512
528
/* implicit=*/ false );
513
529
assert (metadata.NumParams == metadata.NumParamsEmitted &&
514
530
" We can't use implicit GenericParamDescriptors here" );
515
- SignatureHeader->adjustAfterRequirements (metadata);
531
+ SignatureHeader->add (metadata);
516
532
517
533
// Pad the structure up to four bytes for the following requirements.
518
534
addPaddingAfterGenericParamDescriptors (IGM, B,
@@ -524,13 +540,49 @@ namespace {
524
540
irgen::addGenericRequirements (IGM, B,
525
541
asImpl ().getGenericSignature (),
526
542
asImpl ().getGenericSignature ().getRequirements ());
527
- SignatureHeader->adjustAfterRequirements (metadata);
543
+ SignatureHeader->add (metadata);
528
544
}
529
545
530
546
void finishGenericParameters () {
531
547
SignatureHeader->finish (IGM, B);
532
548
}
533
549
550
+ void addGenericPackShapeDescriptors () {
551
+ const auto &shapes = SignatureHeader->ShapeClasses ;
552
+ const auto &packArgs = SignatureHeader->GenericPackArguments ;
553
+ assert (shapes.empty () == packArgs.empty () &&
554
+ " Can't have one without the other" );
555
+
556
+ // If we don't have any pack arguments, there is nothing to emit.
557
+ if (packArgs.empty ())
558
+ return ;
559
+
560
+ // Emit the GenericPackShapeHeader first.
561
+
562
+ // NumPacks
563
+ B.addInt (IGM.Int16Ty , packArgs.size ());
564
+
565
+ // NumShapes
566
+ B.addInt (IGM.Int16Ty , shapes.size ());
567
+
568
+ // Emit each GenericPackShapeDescriptor collected previously.
569
+ for (const auto &packArg : packArgs) {
570
+ // Kind
571
+ B.addInt (IGM.Int16Ty , uint16_t (packArg.Kind ));
572
+
573
+ // Index
574
+ B.addInt (IGM.Int16Ty , packArg.Index );
575
+
576
+ // ShapeClass
577
+ auto found = std::find (shapes.begin (), shapes.end (), packArg.ReducedShape );
578
+ assert (found != shapes.end ());
579
+ B.addInt (IGM.Int16Ty , found - shapes.begin ());
580
+
581
+ // Unused
582
+ B.addInt (IGM.Int16Ty , 0 );
583
+ }
584
+ }
585
+
534
586
uint8_t getVersion () {
535
587
return 0 ;
536
588
}
@@ -6061,7 +6113,9 @@ void IRGenModule::emitProtocolDecl(ProtocolDecl *protocol) {
6061
6113
6062
6114
static GenericParamDescriptor
6063
6115
getGenericParamDescriptor (GenericTypeParamType *param, bool canonical) {
6064
- return GenericParamDescriptor (GenericParamKind::Type,
6116
+ return GenericParamDescriptor (param->isParameterPack ()
6117
+ ? GenericParamKind::TypePack
6118
+ : GenericParamKind::Type,
6065
6119
/* key argument*/ canonical);
6066
6120
}
6067
6121
@@ -6077,13 +6131,13 @@ static bool canUseImplicitGenericParamDescriptors(CanGenericSignature sig) {
6077
6131
return allImplicit && count <= MaxNumImplicitGenericParamDescriptors;
6078
6132
}
6079
6133
6080
- GenericRequirementsMetadata
6134
+ GenericArgumentMetadata
6081
6135
irgen::addGenericParameters (IRGenModule &IGM, ConstantStructBuilder &B,
6082
6136
GenericSignature sig, bool implicit) {
6083
6137
assert (sig);
6084
6138
auto canSig = sig.getCanonicalSignature ();
6085
6139
6086
- GenericRequirementsMetadata metadata;
6140
+ GenericArgumentMetadata metadata;
6087
6141
6088
6142
canSig->forEachParam ([&](GenericTypeParamType *param, bool canonical) {
6089
6143
// Currently, there are only type parameters. The parameter is a key
@@ -6098,6 +6152,19 @@ irgen::addGenericParameters(IRGenModule &IGM, ConstantStructBuilder &B,
6098
6152
6099
6153
++metadata.NumParams ;
6100
6154
6155
+ // Only key arguments count toward NumGenericPackArguments.
6156
+ if (descriptor.hasKeyArgument () &&
6157
+ descriptor.getKind () == GenericParamKind::TypePack) {
6158
+ auto reducedShape = canSig->getReducedShape (param)->getCanonicalType ();
6159
+ metadata.GenericPackArguments .emplace_back (
6160
+ GenericPackKind::Metadata,
6161
+ metadata.NumGenericKeyArguments ,
6162
+ reducedShape);
6163
+
6164
+ if (reducedShape->isEqual (param))
6165
+ metadata.ShapeClasses .push_back (reducedShape);
6166
+ }
6167
+
6101
6168
if (descriptor.hasKeyArgument ())
6102
6169
++metadata.NumGenericKeyArguments ;
6103
6170
});
@@ -6121,11 +6188,21 @@ static void addRelativeAddressOfTypeRef(IRGenModule &IGM,
6121
6188
6122
6189
// / Add a generic requirement to the given constant struct builder.
6123
6190
static void addGenericRequirement (IRGenModule &IGM, ConstantStructBuilder &B,
6124
- GenericRequirementsMetadata &metadata,
6191
+ GenericArgumentMetadata &metadata,
6125
6192
GenericSignature sig,
6126
6193
GenericRequirementFlags flags,
6127
6194
Type paramType,
6128
6195
llvm::function_ref<void ()> addReference) {
6196
+ // Only key arguments (ie, conformance requirements) count toward
6197
+ // NumGenericPackArguments.
6198
+ if (flags.hasKeyArgument () && flags.isPackRequirement ()) {
6199
+ assert (flags.getKind () == GenericRequirementKind::Protocol);
6200
+ metadata.GenericPackArguments .emplace_back (
6201
+ GenericPackKind::WitnessTable,
6202
+ metadata.NumGenericKeyArguments ,
6203
+ sig->getReducedShape (paramType)->getCanonicalType ());
6204
+ }
6205
+
6129
6206
if (flags.hasKeyArgument ())
6130
6207
++metadata.NumGenericKeyArguments ;
6131
6208
@@ -6134,13 +6211,13 @@ static void addGenericRequirement(IRGenModule &IGM, ConstantStructBuilder &B,
6134
6211
addReference ();
6135
6212
}
6136
6213
6137
- GenericRequirementsMetadata irgen::addGenericRequirements (
6214
+ GenericArgumentMetadata irgen::addGenericRequirements (
6138
6215
IRGenModule &IGM, ConstantStructBuilder &B,
6139
6216
GenericSignature sig,
6140
6217
ArrayRef<Requirement> requirements) {
6141
6218
assert (sig);
6142
6219
6143
- GenericRequirementsMetadata metadata;
6220
+ GenericArgumentMetadata metadata;
6144
6221
for (auto &requirement : requirements) {
6145
6222
auto kind = requirement.getKind ();
6146
6223
bool isPackRequirement = requirement.getFirstType ()->isParameterPack ();
@@ -6504,7 +6581,7 @@ irgen::emitExtendedExistentialTypeShape(IRGenModule &IGM,
6504
6581
GenericSignatureHeaderBuilder &header,
6505
6582
bool implicit) {
6506
6583
auto info = irgen::addGenericParameters (IGM, b, sig, implicit);
6507
- header.adjustAfterRequirements (info);
6584
+ header.add (info);
6508
6585
totalParamDescriptors += info.NumParamsEmitted ;
6509
6586
};
6510
6587
addParamDescriptors (reqSig, reqHeader, flags.hasImplicitReqSigParams ());
@@ -6516,7 +6593,7 @@ irgen::emitExtendedExistentialTypeShape(IRGenModule &IGM,
6516
6593
auto addRequirementDescriptors = [&](CanGenericSignature sig,
6517
6594
GenericSignatureHeaderBuilder &header) {
6518
6595
auto info = addGenericRequirements (IGM, b, sig, sig.getRequirements ());
6519
- header.adjustAfterRequirements (info);
6596
+ header.add (info);
6520
6597
header.finish (IGM, b);
6521
6598
};
6522
6599
@@ -6526,6 +6603,15 @@ irgen::emitExtendedExistentialTypeShape(IRGenModule &IGM,
6526
6603
addRequirementDescriptors (genSig, *genHeader);
6527
6604
}
6528
6605
6606
+ // The 'Self' parameter in an existential is not variadic
6607
+ assert (reqHeader.GenericPackArguments .empty () &&
6608
+ " Generic parameter packs should not ever appear here" );
6609
+
6610
+ // You can have a superclass with a generic parameter pack in a composition,
6611
+ // like `C<each T> & P<Int>`
6612
+ assert (genHeader->GenericPackArguments .empty () &&
6613
+ " Generic parameter packs not supported here yet" );
6614
+
6529
6615
return b.finishAndCreateFuture ();
6530
6616
}, [&](llvm::GlobalVariable *var) {
6531
6617
var->setConstant (true );
0 commit comments