llvm.org GIT mirror llvm / f039516
enhance DepthFirstIterator to support more robust operations in the face of code mutating the graph while it is being traversed. Patch by Olaf Krzikalla! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76869 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 10 years ago
1 changed file(s) with 51 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
3535 #include "llvm/ADT/GraphTraits.h"
3636 #include "llvm/ADT/iterator.h"
3737 #include "llvm/ADT/SmallPtrSet.h"
38 #include "llvm/ADT/PointerIntPair.h"
3839 #include
3940 #include
4041
6768
6869 typedef typename GT::NodeType NodeType;
6970 typedef typename GT::ChildIteratorType ChildItTy;
71 typedef PointerIntPair PointerIntTy;
7072
7173 // VisitStack - Used to maintain the ordering. Top = current block
7274 // First element is node pointer, second is the 'next child' to visit
73 std::vector > VisitStack;
75 // if the int in PointerIntTy is 0, the 'next child' to visit is invalid
76 std::vector > VisitStack;
7477 private:
7578 inline df_iterator(NodeType *Node) {
7679 this->Visited.insert(Node);
77 VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node)));
78 }
79 inline df_iterator() { /* End is when stack is empty */ }
80
80 VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0),
81 GT::child_begin(Node)));
82 }
83 inline df_iterator() {
84 // End is when stack is empty
85 }
8186 inline df_iterator(NodeType *Node, SetType &S)
8287 : df_iterator_storage(S) {
8388 if (!S.count(Node)) {
89 VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0),
90 GT::child_begin(Node)));
8491 this->Visited.insert(Node);
85 VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node)));
8692 }
8793 }
8894 inline df_iterator(SetType &S)
9096 // End is when stack is empty
9197 }
9298
99 inline void toNext() {
100 do {
101 std::pair &Top = VisitStack.back();
102 NodeType *Node = Top.first.getPointer();
103 ChildItTy &It = Top.second;
104 if (!Top.first.getInt()) {
105 // now retrieve the real begin of the children before we dive in
106 It = GT::child_begin(Node);
107 Top.first.setInt(1);
108 }
109
110 while (It != GT::child_end(Node)) {
111 NodeType *Next = *It++;
112 // Has our next sibling been visited?
113 if (Next && !this->Visited.count(Next)) {
114 // No, do it now.
115 this->Visited.insert(Next);
116 VisitStack.push_back(std::make_pair(PointerIntTy(Next, 0),
117 GT::child_begin(Next)));
118 return;
119 }
120 }
121
122 // Oops, ran out of successors... go up a level on the stack.
123 VisitStack.pop_back();
124 } while (!VisitStack.empty());
125 }
126
93127 public:
94128 typedef typename super::pointer pointer;
95129 typedef df_iterator _Self;
113147 inline bool operator!=(const _Self& x) const { return !operator==(x); }
114148
115149 inline pointer operator*() const {
116 return VisitStack.back().first;
150 return VisitStack.back().first.getPointer();
117151 }
118152
119153 // This is a nonstandard operator-> that dereferences the pointer an extra
123157 inline NodeType *operator->() const { return operator*(); }
124158
125159 inline _Self& operator++() { // Preincrement
126 do {
127 std::pair &Top = VisitStack.back();
128 NodeType *Node = Top.first;
129 ChildItTy &It = Top.second;
130
131 while (It != GT::child_end(Node)) {
132 NodeType *Next = *It++;
133 if (!this->Visited.count(Next)) { // Has our next sibling been visited?
134 // No, do it now.
135 this->Visited.insert(Next);
136 VisitStack.push_back(std::make_pair(Next, GT::child_begin(Next)));
137 return *this;
138 }
139 }
140
141 // Oops, ran out of successors... go up a level on the stack.
142 VisitStack.pop_back();
143 } while (!VisitStack.empty());
160 toNext();
161 return *this;
162 }
163
164 // skips all children of the current node and traverses to next node
165 //
166 inline _Self& skipChildren() {
167 VisitStack.pop_back();
168 if (!VisitStack.empty())
169 toNext();
144170 return *this;
145171 }
146172