@@ -610,6 +610,144 @@ class CFGBlock {
610
610
bool empty () const { return Impl.empty (); }
611
611
};
612
612
613
+ // / A convenience class for comparing CFGElements, since methods of CFGBlock
614
+ // / like operator[] return CFGElements by value. This is practically a wrapper
615
+ // / around a (CFGBlock, Index) pair.
616
+ template <bool IsConst> class ElementRefImpl {
617
+
618
+ template <bool IsOtherConst> friend class ElementRefImpl ;
619
+
620
+ using CFGBlockPtr =
621
+ typename std::conditional<IsConst, const CFGBlock *, CFGBlock *>::type;
622
+
623
+ using CFGElementPtr = typename std::conditional<IsConst, const CFGElement *,
624
+ CFGElement *>::type;
625
+
626
+ protected:
627
+ CFGBlockPtr Parent;
628
+ size_t Index;
629
+
630
+ public:
631
+ ElementRefImpl (CFGBlockPtr Parent, size_t Index)
632
+ : Parent(Parent), Index(Index) {}
633
+
634
+ template <bool IsOtherConst>
635
+ ElementRefImpl (ElementRefImpl<IsOtherConst> Other)
636
+ : ElementRefImpl(Other.Parent, Other.Index) {}
637
+
638
+ size_t getIndexInBlock () const { return Index; }
639
+
640
+ CFGBlockPtr getParent () { return Parent; }
641
+ CFGBlockPtr getParent () const { return Parent; }
642
+
643
+ bool operator <(ElementRefImpl Other) const {
644
+ return std::make_pair (Parent, Index) <
645
+ std::make_pair (Other.Parent , Other.Index );
646
+ }
647
+
648
+ bool operator ==(ElementRefImpl Other) const {
649
+ return Parent == Other.Parent && Index == Other.Index ;
650
+ }
651
+
652
+ bool operator !=(ElementRefImpl Other) const { return !(*this == Other); }
653
+ CFGElement operator *() { return (*Parent)[Index]; }
654
+ CFGElementPtr operator ->() { return &*(Parent->begin () + Index); }
655
+ };
656
+
657
+ template <bool IsReverse, bool IsConst> class ElementRefIterator {
658
+
659
+ template <bool IsOtherReverse, bool IsOtherConst>
660
+ friend class ElementRefIterator ;
661
+
662
+ using CFGBlockRef =
663
+ typename std::conditional<IsConst, const CFGBlock *, CFGBlock *>::type;
664
+
665
+ using UnderlayingIteratorTy = typename std::conditional<
666
+ IsConst,
667
+ typename std::conditional<IsReverse,
668
+ ElementList::const_reverse_iterator,
669
+ ElementList::const_iterator>::type,
670
+ typename std::conditional<IsReverse, ElementList::reverse_iterator,
671
+ ElementList::iterator>::type>::type;
672
+
673
+ using IteratorTraits = typename std::iterator_traits<UnderlayingIteratorTy>;
674
+ using ElementRef = typename CFGBlock::ElementRefImpl<IsConst>;
675
+
676
+ public:
677
+ using difference_type = typename IteratorTraits::difference_type;
678
+ using value_type = ElementRef;
679
+ using pointer = ElementRef *;
680
+ using iterator_category = typename IteratorTraits::iterator_category;
681
+
682
+ private:
683
+ CFGBlockRef Parent;
684
+ UnderlayingIteratorTy Pos;
685
+
686
+ public:
687
+ ElementRefIterator (CFGBlockRef Parent, UnderlayingIteratorTy Pos)
688
+ : Parent(Parent), Pos(Pos) {}
689
+
690
+ template <bool IsOtherConst>
691
+ ElementRefIterator (ElementRefIterator<false , IsOtherConst> E)
692
+ : ElementRefIterator(E.Parent, E.Pos.base()) {}
693
+
694
+ template <bool IsOtherConst>
695
+ ElementRefIterator (ElementRefIterator<true , IsOtherConst> E)
696
+ : ElementRefIterator(E.Parent, llvm::make_reverse_iterator(E.Pos)) {}
697
+
698
+ bool operator <(ElementRefIterator Other) const {
699
+ assert (Parent == Other.Parent );
700
+ return Pos < Other.Pos ;
701
+ }
702
+
703
+ bool operator ==(ElementRefIterator Other) const {
704
+ return Parent == Other.Parent && Pos == Other.Pos ;
705
+ }
706
+
707
+ bool operator !=(ElementRefIterator Other) const {
708
+ return !(*this == Other);
709
+ }
710
+
711
+ private:
712
+ template <bool IsOtherConst>
713
+ static size_t
714
+ getIndexInBlock (CFGBlock::ElementRefIterator<true , IsOtherConst> E) {
715
+ return E.Parent ->size () - (E.Pos - E.Parent ->rbegin ()) - 1 ;
716
+ }
717
+
718
+ template <bool IsOtherConst>
719
+ static size_t
720
+ getIndexInBlock (CFGBlock::ElementRefIterator<false , IsOtherConst> E) {
721
+ return E.Pos - E.Parent ->begin ();
722
+ }
723
+
724
+ public:
725
+ value_type operator *() { return {Parent, getIndexInBlock (*this )}; }
726
+
727
+ difference_type operator -(ElementRefIterator Other) const {
728
+ return Pos - Other.Pos ;
729
+ }
730
+
731
+ ElementRefIterator operator ++() {
732
+ ++this ->Pos ;
733
+ return *this ;
734
+ }
735
+ ElementRefIterator operator ++(int ) {
736
+ ElementRefIterator Ret = *this ;
737
+ ++*this ;
738
+ return Ret;
739
+ }
740
+ ElementRefIterator operator +(size_t count) {
741
+ this ->Pos += count;
742
+ return *this ;
743
+ }
744
+ ElementRefIterator operator -(size_t count) {
745
+ this ->Pos -= count;
746
+ return *this ;
747
+ }
748
+ };
749
+
750
+ public:
613
751
// / The set of statements in the basic block.
614
752
ElementList Elements;
615
753
@@ -715,6 +853,8 @@ class CFGBlock {
715
853
using reverse_iterator = ElementList::reverse_iterator;
716
854
using const_reverse_iterator = ElementList::const_reverse_iterator;
717
855
856
+ size_t getIndexInCFG () const ;
857
+
718
858
CFGElement front () const { return Elements.front (); }
719
859
CFGElement back () const { return Elements.back (); }
720
860
@@ -728,6 +868,38 @@ class CFGBlock {
728
868
const_reverse_iterator rbegin () const { return Elements.rbegin (); }
729
869
const_reverse_iterator rend () const { return Elements.rend (); }
730
870
871
+ using CFGElementRef = ElementRefImpl<false >;
872
+ using ConstCFGElementRef = ElementRefImpl<true >;
873
+
874
+ using ref_iterator = ElementRefIterator<false , false >;
875
+ using ref_iterator_range = llvm::iterator_range<ref_iterator>;
876
+ using const_ref_iterator = ElementRefIterator<false , true >;
877
+ using const_ref_iterator_range = llvm::iterator_range<const_ref_iterator>;
878
+
879
+ using reverse_ref_iterator = ElementRefIterator<true , false >;
880
+ using reverse_ref_iterator_range = llvm::iterator_range<reverse_ref_iterator>;
881
+
882
+ using const_reverse_ref_iterator = ElementRefIterator<true , true >;
883
+ using const_reverse_ref_iterator_range =
884
+ llvm::iterator_range<const_reverse_ref_iterator>;
885
+
886
+ ref_iterator ref_begin () { return {this , begin ()}; }
887
+ ref_iterator ref_end () { return {this , end ()}; }
888
+ const_ref_iterator ref_begin () const { return {this , begin ()}; }
889
+ const_ref_iterator ref_end () const { return {this , end ()}; }
890
+
891
+ reverse_ref_iterator rref_begin () { return {this , rbegin ()}; }
892
+ reverse_ref_iterator rref_end () { return {this , rend ()}; }
893
+ const_reverse_ref_iterator rref_begin () const { return {this , rbegin ()}; }
894
+ const_reverse_ref_iterator rref_end () const { return {this , rend ()}; }
895
+
896
+ ref_iterator_range refs () { return {ref_begin (), ref_end ()}; }
897
+ const_ref_iterator_range refs () const { return {ref_begin (), ref_end ()}; }
898
+ reverse_ref_iterator_range rrefs () { return {rref_begin (), rref_end ()}; }
899
+ const_reverse_ref_iterator_range rrefs () const {
900
+ return {rref_begin (), rref_end ()};
901
+ }
902
+
731
903
unsigned size () const { return Elements.size (); }
732
904
bool empty () const { return Elements.empty (); }
733
905
@@ -898,7 +1070,7 @@ class CFGBlock {
898
1070
void printTerminator (raw_ostream &OS, const LangOptions &LO) const ;
899
1071
void printTerminatorJson (raw_ostream &Out, const LangOptions &LO,
900
1072
bool AddQuotes) const ;
901
-
1073
+
902
1074
void printAsOperand (raw_ostream &OS, bool /* PrintType*/ ) {
903
1075
OS << " BB#" << getBlockID ();
904
1076
}
@@ -1014,7 +1186,6 @@ class CFGBlock {
1014
1186
*I = CFGScopeEnd (VD, S);
1015
1187
return ++I;
1016
1188
}
1017
-
1018
1189
};
1019
1190
1020
1191
// / CFGCallback defines methods that should be called when a logical
0 commit comments