@@ -345,11 +345,14 @@ static llvm::Value *emitPackExpansionElementMetadata(
345
345
return element;
346
346
}
347
347
348
- static void emitPackExpansionType (IRGenFunction &IGF, Address pack,
349
- CanPackExpansionType expansionTy,
350
- llvm::Value *dynamicIndex,
351
- llvm::Value *dynamicLength,
352
- DynamicMetadataRequest request) {
348
+ // / Store the values corresponding to the specified pack expansion \p
349
+ // / expansionTy for each index in its range [dynamicIndex, dynamicIndex +
350
+ // / dynamicLength) produced by the provided function \p elementForIndex into
351
+ // / the indicated buffer \p pack.
352
+ static void emitPackExpansionPack (
353
+ IRGenFunction &IGF, Address pack, CanPackExpansionType expansionTy,
354
+ llvm::Value *dynamicIndex, llvm::Value *dynamicLength,
355
+ function_ref<llvm::Value *(llvm::Value *)> elementForIndex) {
353
356
auto *prev = IGF.Builder .GetInsertBlock ();
354
357
auto *check = IGF.createBasicBlock (" pack-expansion-check" );
355
358
auto *loop = IGF.createBasicBlock (" pack-expansion-loop" );
@@ -368,8 +371,7 @@ static void emitPackExpansionType(IRGenFunction &IGF, Address pack,
368
371
369
372
IGF.Builder .emitBlock (loop);
370
373
371
- auto *element =
372
- emitPackExpansionElementMetadata (IGF, expansionTy, phi, request);
374
+ auto *element = elementForIndex (phi);
373
375
374
376
// Store the element metadata into to the current destination index.
375
377
auto *eltIndex = IGF.Builder .CreateAdd (dynamicIndex, phi);
@@ -395,6 +397,18 @@ static void emitPackExpansionType(IRGenFunction &IGF, Address pack,
395
397
IGF.Builder .emitBlock (rest);
396
398
}
397
399
400
+ static void emitPackExpansionMetadataPack (IRGenFunction &IGF, Address pack,
401
+ CanPackExpansionType expansionTy,
402
+ llvm::Value *dynamicIndex,
403
+ llvm::Value *dynamicLength,
404
+ DynamicMetadataRequest request) {
405
+ emitPackExpansionPack (IGF, pack, expansionTy, dynamicIndex, dynamicLength,
406
+ [&](auto *index) {
407
+ return emitPackExpansionElementMetadata (
408
+ IGF, expansionTy, index, request);
409
+ });
410
+ }
411
+
398
412
StackAddress
399
413
irgen::emitTypeMetadataPack (IRGenFunction &IGF,
400
414
CanPackType packType,
@@ -421,8 +435,8 @@ irgen::emitTypeMetadataPack(IRGenFunction &IGF,
421
435
}
422
436
423
437
if (auto expansionTy = dyn_cast<PackExpansionType>(eltTy)) {
424
- emitPackExpansionType (IGF, pack.getAddress (), expansionTy,
425
- dynamicIndex, dynamicLength, request);
438
+ emitPackExpansionMetadataPack (IGF, pack.getAddress (), expansionTy,
439
+ dynamicIndex, dynamicLength, request);
426
440
} else {
427
441
Address eltPtr (
428
442
IGF.Builder .CreateInBoundsGEP (pack.getAddress ().getElementType (),
@@ -508,52 +522,17 @@ static llvm::Value *emitPackExpansionElementWitnessTable(
508
522
return wtable;
509
523
}
510
524
511
- static void emitExpansionWitnessTablePack (IRGenFunction &IGF, Address pack,
512
- CanPackExpansionType expansionTy,
513
- ProtocolConformanceRef conformance,
514
- llvm::Value *dynamicIndex,
515
- llvm::Value *dynamicLength) {
516
- auto *prev = IGF.Builder .GetInsertBlock ();
517
- auto *check = IGF.createBasicBlock (" pack-expansion-check" );
518
- auto *loop = IGF.createBasicBlock (" pack-expansion-loop" );
519
- auto *rest = IGF.createBasicBlock (" pack-expansion-rest" );
520
-
521
- IGF.Builder .CreateBr (check);
522
- IGF.Builder .emitBlock (check);
523
-
524
- // An index into the source witness table pack.
525
- auto *phi = IGF.Builder .CreatePHI (IGF.IGM .SizeTy , 2 );
526
- phi->addIncoming (llvm::ConstantInt::get (IGF.IGM .SizeTy , 0 ), prev);
527
-
528
- // If we reach the end, jump to the continuation block.
529
- auto *cond = IGF.Builder .CreateICmpULT (phi, dynamicLength);
530
- IGF.Builder .CreateCondBr (cond, loop, rest);
531
-
532
- IGF.Builder .emitBlock (loop);
533
-
534
- llvm::Value *_metadata = nullptr ;
535
- auto *element = emitPackExpansionElementWitnessTable (
536
- IGF, expansionTy, conformance, /* srcMetadataCache=*/ &_metadata, phi);
537
-
538
- // Store the element witness table into to the current destination index.
539
- auto *eltIndex = IGF.Builder .CreateAdd (dynamicIndex, phi);
540
- Address eltPtr (IGF.Builder .CreateInBoundsGEP (pack.getElementType (),
541
- pack.getAddress (), eltIndex),
542
- pack.getElementType (), pack.getAlignment ());
543
-
544
- IGF.Builder .CreateStore (element, eltPtr);
545
-
546
- // Increment our counter.
547
- auto *next =
548
- IGF.Builder .CreateAdd (phi, llvm::ConstantInt::get (IGF.IGM .SizeTy , 1 ));
549
-
550
- phi->addIncoming (next, loop);
551
-
552
- // Repeat the loop.
553
- IGF.Builder .CreateBr (check);
554
-
555
- // Fall through.
556
- IGF.Builder .emitBlock (rest);
525
+ static void emitPackExpansionWitnessTablePack (
526
+ IRGenFunction &IGF, Address pack, CanPackExpansionType expansionTy,
527
+ ProtocolConformanceRef conformance, llvm::Value *dynamicIndex,
528
+ llvm::Value *dynamicLength) {
529
+ emitPackExpansionPack (IGF, pack, expansionTy, dynamicIndex, dynamicLength,
530
+ [&](auto *index) {
531
+ llvm::Value *_metadata = nullptr ;
532
+ return emitPackExpansionElementWitnessTable (
533
+ IGF, expansionTy, conformance,
534
+ /* srcMetadataCache=*/ &_metadata, index);
535
+ });
557
536
}
558
537
559
538
StackAddress irgen::emitWitnessTablePack (IRGenFunction &IGF,
@@ -582,8 +561,9 @@ StackAddress irgen::emitWitnessTablePack(IRGenFunction &IGF,
582
561
583
562
auto conformance = packConformance->getPatternConformances ()[index];
584
563
if (auto expansionTy = dyn_cast<PackExpansionType>(eltTy)) {
585
- emitExpansionWitnessTablePack (IGF, pack.getAddress (), expansionTy,
586
- conformance, dynamicIndex, dynamicLength);
564
+ emitPackExpansionWitnessTablePack (IGF, pack.getAddress (), expansionTy,
565
+ conformance, dynamicIndex,
566
+ dynamicLength);
587
567
} else {
588
568
Address eltPtr (
589
569
IGF.Builder .CreateInBoundsGEP (pack.getAddress ().getElementType (),
0 commit comments