@@ -538,20 +538,26 @@ struct BasicBlock : private LIR::Range
538
538
};
539
539
540
540
public:
541
+ #ifdef DEBUG
542
+ // When creating a block with a jump, we require its jump kind and target be initialized simultaneously.
543
+ // In a few edge cases (for example, in Compiler::impImportLeave), we don't know the jump target at block creation.
544
+ // In these cases, temporarily set the jump target to bbTempJumpDest, and update the jump target later.
545
+ // We won't check jump targets against bbTempJumpDest in Release builds.
546
+ static BasicBlock bbTempJumpDest;
547
+ #endif // DEBUG
548
+
541
549
BBjumpKinds GetJumpKind () const
542
550
{
543
551
return bbJumpKind;
544
552
}
545
553
546
- void SetJumpKind (BBjumpKinds jumpKind DEBUG_ARG (Compiler* compiler) )
554
+ void SetJumpKind (BBjumpKinds jumpKind)
547
555
{
548
- #ifdef DEBUG
549
- // BBJ_NONE should only be assigned when optimizing jumps in Compiler::optOptimizeLayout
550
- // TODO: Change assert to check if compiler is in appropriate optimization phase to use BBJ_NONE
551
- // (right now, this assertion does the null check to avoid unused variable warnings)
552
- assert ((jumpKind != BBJ_NONE) || (compiler != nullptr ));
553
- #endif // DEBUG
556
+ // If this block's jump kind requires a target, ensure it is already set
557
+ assert (HasJump () || !KindIs (BBJ_ALWAYS, BBJ_CALLFINALLY, BBJ_COND, BBJ_EHCATCHRET, BBJ_LEAVE));
554
558
bbJumpKind = jumpKind;
559
+ // If new jump kind requires a target, ensure a target is already set
560
+ assert (HasJump () || !KindIs (BBJ_ALWAYS, BBJ_CALLFINALLY, BBJ_COND, BBJ_EHCATCHRET, BBJ_LEAVE));
555
561
}
556
562
557
563
BasicBlock* Prev () const
@@ -611,54 +617,84 @@ struct BasicBlock : private LIR::Range
611
617
return bbJumpOffs;
612
618
}
613
619
614
- void SetJumpOffs ( unsigned jumpOffs)
620
+ void SetJumpKindAndTarget (BBjumpKinds jumpKind, unsigned jumpOffs)
615
621
{
622
+ bbJumpKind = jumpKind;
616
623
bbJumpOffs = jumpOffs;
624
+ assert (KindIs (BBJ_ALWAYS, BBJ_COND, BBJ_LEAVE));
617
625
}
618
626
619
627
BasicBlock* GetJumpDest () const
620
628
{
629
+ // If bbJumpKind indicates this block has a jump, bbJumpDest cannot be null
630
+ assert (HasJump () || !KindIs (BBJ_ALWAYS, BBJ_CALLFINALLY, BBJ_COND, BBJ_EHCATCHRET, BBJ_LEAVE));
621
631
return bbJumpDest;
622
632
}
623
633
624
634
void SetJumpDest (BasicBlock* jumpDest)
625
635
{
636
+ // If bbJumpKind indicates this block has a jump,
637
+ // bbJumpDest should have previously been set in SetJumpKindAndTarget().
638
+ assert (HasJump () || !KindIs (BBJ_ALWAYS, BBJ_CALLFINALLY, BBJ_COND, BBJ_EHCATCHRET, BBJ_LEAVE));
639
+
640
+ // SetJumpKindAndTarget() nulls jumpDest for non-jump kinds,
641
+ // so don't use SetJumpDest() to null bbJumpDest without updating bbJumpKind.
626
642
bbJumpDest = jumpDest;
643
+ assert (HasJump ());
627
644
}
628
645
629
- void SetJumpKindAndTarget (BBjumpKinds jumpKind, BasicBlock* jumpDest)
646
+ void SetJumpKindAndTarget (BBjumpKinds jumpKind, BasicBlock* jumpDest DEBUG_ARG (Compiler* compiler) )
630
647
{
631
- assert (jumpDest != nullptr );
648
+ #ifdef DEBUG
649
+ // BBJ_NONE should only be assigned when optimizing jumps in Compiler::optOptimizeLayout
650
+ // TODO: Change assert to check if compiler is in appropriate optimization phase to use BBJ_NONE
651
+ //
652
+ // (right now, this assertion does the null check to avoid unused variable warnings)
653
+ assert ((jumpKind != BBJ_NONE) || (compiler != nullptr ));
654
+ #endif // DEBUG
655
+
632
656
bbJumpKind = jumpKind;
633
657
bbJumpDest = jumpDest;
634
- assert (KindIs (BBJ_ALWAYS, BBJ_CALLFINALLY, BBJ_COND, BBJ_EHCATCHRET, BBJ_LEAVE));
658
+
659
+ // If bbJumpKind indicates this block has a jump, bbJumpDest cannot be null
660
+ assert (HasJump () || !KindIs (BBJ_ALWAYS, BBJ_CALLFINALLY, BBJ_COND, BBJ_EHCATCHRET, BBJ_LEAVE));
661
+ }
662
+
663
+ void SetJumpKindAndTarget (BBjumpKinds jumpKind DEBUG_ARG (Compiler* compiler))
664
+ {
665
+ BasicBlock* jumpDest = nullptr ;
666
+ SetJumpKindAndTarget (jumpKind, jumpDest DEBUG_ARG (compiler));
667
+ }
668
+
669
+ bool HasJump () const
670
+ {
671
+ return (bbJumpDest != nullptr );
635
672
}
636
673
637
674
bool HasJumpTo (const BasicBlock* jumpDest) const
638
675
{
676
+ assert (HasJump ());
677
+ assert (!KindIs (BBJ_SWITCH, BBJ_EHFINALLYRET));
639
678
return (bbJumpDest == jumpDest);
640
679
}
641
680
642
681
bool JumpsToNext () const
643
682
{
683
+ assert (HasJump ());
644
684
return (bbJumpDest == bbNext);
645
685
}
646
686
647
687
BBswtDesc* GetJumpSwt () const
648
688
{
689
+ assert (KindIs (BBJ_SWITCH));
690
+ assert (bbJumpSwt != nullptr );
649
691
return bbJumpSwt;
650
692
}
651
693
652
- void SetJumpSwt (BBswtDesc* jumpSwt)
694
+ void SetSwitchKindAndTarget (BBswtDesc* jumpSwt)
653
695
{
654
- bbJumpSwt = jumpSwt;
655
- }
656
-
657
- void SetJumpKindAndTarget (BBjumpKinds jumpKind, BBswtDesc* jumpSwt)
658
- {
659
- assert (jumpKind == BBJ_SWITCH);
660
696
assert (jumpSwt != nullptr );
661
- bbJumpKind = jumpKind ;
697
+ bbJumpKind = BBJ_SWITCH ;
662
698
bbJumpSwt = jumpSwt;
663
699
}
664
700
@@ -1739,7 +1775,7 @@ inline BBArrayIterator BBEhfSuccList::end() const
1739
1775
inline BasicBlock::BBSuccList::BBSuccList (const BasicBlock* block)
1740
1776
{
1741
1777
assert (block != nullptr );
1742
- switch (block->GetJumpKind () )
1778
+ switch (block->bbJumpKind )
1743
1779
{
1744
1780
case BBJ_THROW:
1745
1781
case BBJ_RETURN:
@@ -1754,19 +1790,19 @@ inline BasicBlock::BBSuccList::BBSuccList(const BasicBlock* block)
1754
1790
case BBJ_EHCATCHRET:
1755
1791
case BBJ_EHFILTERRET:
1756
1792
case BBJ_LEAVE:
1757
- m_succs[0 ] = block->GetJumpDest () ;
1793
+ m_succs[0 ] = block->bbJumpDest ;
1758
1794
m_begin = &m_succs[0 ];
1759
1795
m_end = &m_succs[1 ];
1760
1796
break ;
1761
1797
1762
1798
case BBJ_NONE:
1763
- m_succs[0 ] = block->Next () ;
1799
+ m_succs[0 ] = block->bbNext ;
1764
1800
m_begin = &m_succs[0 ];
1765
1801
m_end = &m_succs[1 ];
1766
1802
break ;
1767
1803
1768
1804
case BBJ_COND:
1769
- m_succs[0 ] = block->Next () ;
1805
+ m_succs[0 ] = block->bbNext ;
1770
1806
m_begin = &m_succs[0 ];
1771
1807
1772
1808
// If both fall-through and branch successors are identical, then only include
@@ -1777,7 +1813,7 @@ inline BasicBlock::BBSuccList::BBSuccList(const BasicBlock* block)
1777
1813
}
1778
1814
else
1779
1815
{
1780
- m_succs[1 ] = block->GetJumpDest () ;
1816
+ m_succs[1 ] = block->bbJumpDest ;
1781
1817
m_end = &m_succs[2 ];
1782
1818
}
1783
1819
break ;
@@ -1800,10 +1836,10 @@ inline BasicBlock::BBSuccList::BBSuccList(const BasicBlock* block)
1800
1836
1801
1837
case BBJ_SWITCH:
1802
1838
// We don't use the m_succs in-line data for switches; use the existing jump table in the block.
1803
- assert (block->GetJumpSwt () != nullptr );
1804
- assert (block->GetJumpSwt () ->bbsDstTab != nullptr );
1805
- m_begin = block->GetJumpSwt () ->bbsDstTab ;
1806
- m_end = block->GetJumpSwt () ->bbsDstTab + block->GetJumpSwt () ->bbsCount ;
1839
+ assert (block->bbJumpSwt != nullptr );
1840
+ assert (block->bbJumpSwt ->bbsDstTab != nullptr );
1841
+ m_begin = block->bbJumpSwt ->bbsDstTab ;
1842
+ m_end = block->bbJumpSwt ->bbsDstTab + block->bbJumpSwt ->bbsCount ;
1807
1843
break ;
1808
1844
1809
1845
default :
0 commit comments