@@ -435,18 +435,11 @@ static llvm::Value *computeExtraTagBytes(IRGenFunction &IGF, IRBuilder &Builder,
435
435
static void emitSpecializedMemOperation (
436
436
IRGenFunction &IGF,
437
437
llvm::function_ref<void (IRBuilder &, Size)> emitMemOpFn,
438
- llvm::Value *size) {
438
+ llvm::Value *size,
439
+ const std::array<Size, 4> &sizes) {
439
440
auto &Ctx = IGF.IGM .getLLVMContext ();
440
441
auto &Builder = IGF.Builder ;
441
442
442
- // Sizes to try. Tested in order.
443
- const std::array<Size, 4 > sizes = {
444
- Size (0 ),
445
- Size (1 ),
446
- Size (2 ),
447
- Size (4 ),
448
- };
449
-
450
443
// Block to jump to after successful match.
451
444
auto *returnBB = llvm::BasicBlock::Create (Ctx);
452
445
@@ -488,12 +481,13 @@ static void emitSpecializedMemOperation(
488
481
Builder.emitBlock (returnBB);
489
482
}
490
483
491
- // / Emit a load of a \p size byte integer value zero extended to 4 bytes.
492
- // / \p size may be 0, 1, 2 or 4 .
493
- static llvm::Value *emitGetTag (IRGenFunction &IGF,
494
- Address from ,
495
- llvm::Value *size ) {
484
+ // / Emit a load of the \p size byte integer values zero extended to 4 bytes. \p
485
+ // / size maybe any of the four values specified in the \p sizes array .
486
+ static llvm::Value *emitLoadBytes (IRGenFunction &IGF, Address from ,
487
+ llvm::Value *size ,
488
+ const std::array<Size, 4 > &sizes ) {
496
489
auto *phi = llvm::PHINode::Create (IGF.IGM .Int32Ty , 4 );
490
+
497
491
emitSpecializedMemOperation (IGF,
498
492
[=](IRBuilder &B, Size s) {
499
493
if (s == Size (0 )) {
@@ -507,16 +501,45 @@ static llvm::Value *emitGetTag(IRGenFunction &IGF,
507
501
auto *val = B.CreateZExtOrTrunc (B.CreateLoad (addr), B.getInt32Ty ());
508
502
phi->addIncoming (val, B.GetInsertBlock ());
509
503
},
510
- size);
504
+ size,
505
+ sizes);
511
506
IGF.Builder .Insert (phi);
512
507
return phi;
513
508
}
514
509
515
- // / Emit a store of \p val truncated to \p size bytes.
510
+ // / Emit a load of a \p size byte integer value zero extended to 4 bytes \p size
511
+ // / may be 1, 2, 3, or 4.
512
+ llvm::Value *irgen::emitLoad1to4Bytes (IRGenFunction &IGF, Address from,
513
+ llvm::Value *size) {
514
+ // Sizes to try. Tested in order.
515
+ const std::array<Size, 4 > sizes = {
516
+ Size (1 ),
517
+ Size (2 ),
518
+ Size (3 ),
519
+ Size (4 ),
520
+ };
521
+ return emitLoadBytes (IGF, from, size, sizes);
522
+ }
523
+
524
+ // / Emit a load of a \p size byte integer value zero extended to 4 bytes.
516
525
// / \p size may be 0, 1, 2 or 4.
517
- static void emitSetTag (IRGenFunction &IGF,
518
- Address to, llvm::Value *val,
519
- llvm::Value *size) {
526
+ llvm::Value *irgen::emitGetTag (IRGenFunction &IGF, Address from,
527
+ llvm::Value *size) {
528
+ // Sizes to try. Tested in order.
529
+ const std::array<Size, 4 > sizes = {
530
+ Size (0 ),
531
+ Size (1 ),
532
+ Size (2 ),
533
+ Size (4 ),
534
+ };
535
+ return emitLoadBytes (IGF, from, size, sizes);
536
+ }
537
+
538
+ // / Emit a store of \p val truncated to \p size bytes.
539
+ // / \p size may be one of the entries in the \p sizes array.
540
+ static void emitStoreBytes (IRGenFunction &IGF, Address to, llvm::Value *val,
541
+ llvm::Value *size,
542
+ const std::array<Size, 4 > &sizes) {
520
543
emitSpecializedMemOperation (IGF,
521
544
[=](IRBuilder &B, Size s) {
522
545
if (s == Size (0 )) {
@@ -529,7 +552,37 @@ static void emitSetTag(IRGenFunction &IGF,
529
552
Address addr = B.CreateBitCast (to, type->getPointerTo ());
530
553
B.CreateStore (trunc, addr);
531
554
},
532
- size);
555
+ size,
556
+ sizes);
557
+ }
558
+
559
+ // / Emit a store of \p val truncated to \p size bytes.
560
+ // / \p size may be 1, 2, 3, or 4.
561
+ void irgen::emitStore1to4Bytes (IRGenFunction &IGF, Address to, llvm::Value *val,
562
+ llvm::Value *size) {
563
+ // Sizes to try. Tested in order.
564
+ const std::array<Size, 4 > sizes = {
565
+ Size (1 ),
566
+ Size (2 ),
567
+ Size (3 ),
568
+ Size (4 ),
569
+ };
570
+ emitStoreBytes (IGF, to, val, size, sizes);
571
+ }
572
+
573
+ // / Emit a store of \p val truncated to \p size bytes.
574
+ // / \p size may be 0, 1, 2 or 4.
575
+ void irgen::emitSetTag (IRGenFunction &IGF,
576
+ Address to, llvm::Value *val,
577
+ llvm::Value *size) {
578
+ // Sizes to try. Tested in order.
579
+ const std::array<Size, 4 > sizes = {
580
+ Size (0 ),
581
+ Size (1 ),
582
+ Size (2 ),
583
+ Size (4 ),
584
+ };
585
+ emitStoreBytes (IGF, to, val, size, sizes);
533
586
}
534
587
535
588
llvm::Value *FixedTypeInfo::getEnumTagSinglePayload (IRGenFunction &IGF,
@@ -547,14 +600,30 @@ llvm::Value *irgen::getFixedTypeEnumTagSinglePayload(IRGenFunction &IGF,
547
600
Address enumAddr,
548
601
SILType T,
549
602
bool isOutlined) {
603
+ auto *size = ti.getSize (IGF, T);
604
+ Size fixedSize = ti.getFixedSize ();
605
+ auto fixedExtraInhabitantCount = ti.getFixedExtraInhabitantCount (IGF.IGM );
606
+
607
+ return getFixedTypeEnumTagSinglePayload (
608
+ IGF, numEmptyCases, enumAddr, size, fixedSize, fixedExtraInhabitantCount,
609
+ [&](Address addr) -> llvm::Value * {
610
+ return ti.getExtraInhabitantIndex (IGF, addr, T, false );
611
+ },
612
+ isOutlined);
613
+ }
614
+
615
+ llvm::Value *irgen::getFixedTypeEnumTagSinglePayload (
616
+ IRGenFunction &IGF, llvm::Value *numEmptyCases, Address enumAddr,
617
+ llvm::Value *size, Size fixedSize, unsigned fixedExtraInhabitantCount,
618
+ llvm::function_ref<llvm::Value *(Address)> getExtraInhabitantIndex,
619
+ bool isOutlined) {
620
+
550
621
auto &IGM = IGF.IGM ;
551
622
auto &Ctx = IGF.IGM .getLLVMContext ();
552
623
auto &Builder = IGF.Builder ;
553
624
554
- auto *size = ti.getSize (IGF, T);
555
- Size fixedSize = ti.getFixedSize ();
556
625
auto *numExtraInhabitants =
557
- llvm::ConstantInt::get (IGM.Int32Ty , ti. getFixedExtraInhabitantCount (IGM) );
626
+ llvm::ConstantInt::get (IGM.Int32Ty , fixedExtraInhabitantCount );
558
627
559
628
auto *zero = llvm::ConstantInt::get (IGM.Int32Ty , 0U );
560
629
auto *one = llvm::ConstantInt::get (IGM.Int32Ty , 1U );
@@ -632,8 +701,8 @@ llvm::Value *irgen::getFixedTypeEnumTagSinglePayload(IRGenFunction &IGF,
632
701
Builder.emitBlock (noExtraTagBitsBB);
633
702
// If there are extra inhabitants, see whether the payload is valid.
634
703
llvm::Value *result0;
635
- if (ti. mayHaveExtraInhabitants (IGM) ) {
636
- result0 = ti. getExtraInhabitantIndex (IGF, enumAddr, T, false );
704
+ if (fixedExtraInhabitantCount > 0 ) {
705
+ result0 = getExtraInhabitantIndex (enumAddr);
637
706
noExtraTagBitsBB = Builder.GetInsertBlock ();
638
707
} else {
639
708
result0 = llvm::ConstantInt::getSigned (IGM.Int32Ty , -1 );
@@ -671,6 +740,26 @@ void irgen::storeFixedTypeEnumTagSinglePayload(IRGenFunction &IGF,
671
740
Address enumAddr,
672
741
SILType T,
673
742
bool isOutlined) {
743
+ auto fixedSize = ti.getFixedSize ();
744
+ auto *size = ti.getSize (IGF, T);
745
+ auto fixedExtraInhabitantCount = ti.getFixedExtraInhabitantCount (IGF.IGM );
746
+ storeFixedTypeEnumTagSinglePayload (
747
+ IGF, whichCase, numEmptyCases, enumAddr, size, fixedSize,
748
+ fixedExtraInhabitantCount,
749
+ [&](llvm::Value *nonPayloadElementIndex, Address enumAddr) {
750
+ ti.storeExtraInhabitant (IGF, nonPayloadElementIndex, enumAddr, T,
751
+ /* outlined*/ false );
752
+ },
753
+ isOutlined);
754
+ }
755
+
756
+ void irgen::storeFixedTypeEnumTagSinglePayload (
757
+ IRGenFunction &IGF, llvm::Value *whichCase, llvm::Value *numEmptyCases,
758
+ Address enumAddr, llvm::Value *size, Size fixedSize,
759
+ unsigned fixedExtraInhabitantCount,
760
+ llvm::function_ref<void (llvm::Value *, Address)> storeExtraInhabitant,
761
+ bool isOutlined) {
762
+
674
763
auto &IGM = IGF.IGM ;
675
764
auto &Ctx = IGF.IGM .getLLVMContext ();
676
765
auto &Builder = IGF.Builder ;
@@ -681,15 +770,13 @@ void irgen::storeFixedTypeEnumTagSinglePayload(IRGenFunction &IGF,
681
770
auto *four = llvm::ConstantInt::get (int32Ty, 4U );
682
771
auto *eight = llvm::ConstantInt::get (int32Ty, 8U );
683
772
684
- auto fixedSize = ti.getFixedSize ();
685
773
686
774
Address valueAddr = Builder.CreateElementBitCast (enumAddr, IGM.Int8Ty );
687
775
Address extraTagBitsAddr =
688
776
Builder.CreateConstByteArrayGEP (valueAddr, fixedSize);
689
777
690
778
auto *numExtraInhabitants =
691
- llvm::ConstantInt::get (IGM.Int32Ty , ti.getFixedExtraInhabitantCount (IGM));
692
- auto *size = ti.getSize (IGF, T);
779
+ llvm::ConstantInt::get (IGM.Int32Ty , fixedExtraInhabitantCount);
693
780
694
781
// Do we need extra tag bytes.
695
782
auto *entryBB = Builder.GetInsertBlock ();
@@ -731,11 +818,10 @@ void irgen::storeFixedTypeEnumTagSinglePayload(IRGenFunction &IGF,
731
818
Builder.CreateCondBr (isPayload, returnBB, storeInhabitantBB);
732
819
733
820
Builder.emitBlock (storeInhabitantBB);
734
- if (ti. mayHaveExtraInhabitants (IGM) ) {
821
+ if (fixedExtraInhabitantCount > 0 ) {
735
822
// Store an index in the range [0..ElementsWithNoPayload-1].
736
823
auto *nonPayloadElementIndex = Builder.CreateSub (whichCase, one);
737
- ti.storeExtraInhabitant (IGF, nonPayloadElementIndex, enumAddr, T,
738
- /* outlined*/ false );
824
+ storeExtraInhabitant (nonPayloadElementIndex, enumAddr);
739
825
}
740
826
Builder.CreateBr (returnBB);
741
827
0 commit comments