File indexing completed on 2026-05-10 08:43:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H
0035 #define LLVM_ADT_DEPTHFIRSTITERATOR_H
0036
0037 #include "llvm/ADT/GraphTraits.h"
0038 #include "llvm/ADT/SmallPtrSet.h"
0039 #include "llvm/ADT/iterator_range.h"
0040 #include <iterator>
0041 #include <optional>
0042 #include <type_traits>
0043 #include <utility>
0044 #include <vector>
0045
0046 namespace llvm {
0047
0048
0049
0050 template<class SetType, bool External>
0051 class df_iterator_storage {
0052 public:
0053 SetType Visited;
0054 };
0055
0056 template<class SetType>
0057 class df_iterator_storage<SetType, true> {
0058 public:
0059 df_iterator_storage(SetType &VSet) : Visited(VSet) {}
0060 df_iterator_storage(const df_iterator_storage &S) : Visited(S.Visited) {}
0061
0062 SetType &Visited;
0063 };
0064
0065
0066
0067
0068
0069 template <typename NodeRef, unsigned SmallSize=8>
0070 struct df_iterator_default_set : public SmallPtrSet<NodeRef, SmallSize> {
0071 using BaseSet = SmallPtrSet<NodeRef, SmallSize>;
0072 using iterator = typename BaseSet::iterator;
0073
0074 std::pair<iterator,bool> insert(NodeRef N) { return BaseSet::insert(N); }
0075 template <typename IterT>
0076 void insert(IterT Begin, IterT End) { BaseSet::insert(Begin,End); }
0077
0078 void completed(NodeRef) {}
0079 };
0080
0081
0082 template <class GraphT,
0083 class SetType =
0084 df_iterator_default_set<typename GraphTraits<GraphT>::NodeRef>,
0085 bool ExtStorage = false, class GT = GraphTraits<GraphT>>
0086 class df_iterator : public df_iterator_storage<SetType, ExtStorage> {
0087 public:
0088
0089 using iterator_category =
0090 std::conditional_t<ExtStorage, std::input_iterator_tag,
0091 std::forward_iterator_tag>;
0092 using value_type = typename GT::NodeRef;
0093 using difference_type = std::ptrdiff_t;
0094 using pointer = value_type *;
0095 using reference = const value_type &;
0096
0097 private:
0098 using NodeRef = typename GT::NodeRef;
0099 using ChildItTy = typename GT::ChildIteratorType;
0100
0101
0102
0103
0104 using StackElement = std::pair<NodeRef, std::optional<ChildItTy>>;
0105
0106
0107 std::vector<StackElement> VisitStack;
0108
0109 inline df_iterator(NodeRef Node) {
0110 this->Visited.insert(Node);
0111 VisitStack.push_back(StackElement(Node, std::nullopt));
0112 }
0113
0114 inline df_iterator() = default;
0115
0116 inline df_iterator(NodeRef Node, SetType &S)
0117 : df_iterator_storage<SetType, ExtStorage>(S) {
0118 if (this->Visited.insert(Node).second)
0119 VisitStack.push_back(StackElement(Node, std::nullopt));
0120 }
0121
0122 inline df_iterator(SetType &S)
0123 : df_iterator_storage<SetType, ExtStorage>(S) {
0124
0125 }
0126
0127 inline void toNext() {
0128 do {
0129 NodeRef Node = VisitStack.back().first;
0130 std::optional<ChildItTy> &Opt = VisitStack.back().second;
0131
0132 if (!Opt)
0133 Opt.emplace(GT::child_begin(Node));
0134
0135
0136
0137
0138 while (*Opt != GT::child_end(Node)) {
0139 NodeRef Next = *(*Opt)++;
0140
0141 if (this->Visited.insert(Next).second) {
0142
0143 VisitStack.push_back(StackElement(Next, std::nullopt));
0144 return;
0145 }
0146 }
0147 this->Visited.completed(Node);
0148
0149
0150 VisitStack.pop_back();
0151 } while (!VisitStack.empty());
0152 }
0153
0154 public:
0155
0156 static df_iterator begin(const GraphT &G) {
0157 return df_iterator(GT::getEntryNode(G));
0158 }
0159 static df_iterator end(const GraphT &G) { return df_iterator(); }
0160
0161
0162 static df_iterator begin(const GraphT &G, SetType &S) {
0163 return df_iterator(GT::getEntryNode(G), S);
0164 }
0165 static df_iterator end(const GraphT &G, SetType &S) { return df_iterator(S); }
0166
0167 bool operator==(const df_iterator &x) const {
0168 return VisitStack == x.VisitStack;
0169 }
0170 bool operator!=(const df_iterator &x) const { return !(*this == x); }
0171
0172 reference operator*() const { return VisitStack.back().first; }
0173
0174
0175
0176
0177
0178 NodeRef operator->() const { return **this; }
0179
0180 df_iterator &operator++() {
0181 toNext();
0182 return *this;
0183 }
0184
0185
0186
0187
0188
0189 df_iterator &skipChildren() {
0190 VisitStack.pop_back();
0191 if (!VisitStack.empty())
0192 toNext();
0193 return *this;
0194 }
0195
0196 df_iterator operator++(int) {
0197 df_iterator tmp = *this;
0198 ++*this;
0199 return tmp;
0200 }
0201
0202
0203
0204
0205
0206 bool nodeVisited(NodeRef Node) const {
0207 return this->Visited.contains(Node);
0208 }
0209
0210
0211
0212 unsigned getPathLength() const { return VisitStack.size(); }
0213
0214
0215
0216 NodeRef getPath(unsigned n) const { return VisitStack[n].first; }
0217 };
0218
0219
0220
0221 template <class T>
0222 df_iterator<T> df_begin(const T& G) {
0223 return df_iterator<T>::begin(G);
0224 }
0225
0226 template <class T>
0227 df_iterator<T> df_end(const T& G) {
0228 return df_iterator<T>::end(G);
0229 }
0230
0231
0232 template <class T>
0233 iterator_range<df_iterator<T>> depth_first(const T& G) {
0234 return make_range(df_begin(G), df_end(G));
0235 }
0236
0237
0238 template <class T, class SetTy = df_iterator_default_set<typename GraphTraits<T>::NodeRef>>
0239 struct df_ext_iterator : public df_iterator<T, SetTy, true> {
0240 df_ext_iterator(const df_iterator<T, SetTy, true> &V)
0241 : df_iterator<T, SetTy, true>(V) {}
0242 };
0243
0244 template <class T, class SetTy>
0245 df_ext_iterator<T, SetTy> df_ext_begin(const T& G, SetTy &S) {
0246 return df_ext_iterator<T, SetTy>::begin(G, S);
0247 }
0248
0249 template <class T, class SetTy>
0250 df_ext_iterator<T, SetTy> df_ext_end(const T& G, SetTy &S) {
0251 return df_ext_iterator<T, SetTy>::end(G, S);
0252 }
0253
0254 template <class T, class SetTy>
0255 iterator_range<df_ext_iterator<T, SetTy>> depth_first_ext(const T& G,
0256 SetTy &S) {
0257 return make_range(df_ext_begin(G, S), df_ext_end(G, S));
0258 }
0259
0260
0261 template <class T,
0262 class SetTy =
0263 df_iterator_default_set<typename GraphTraits<T>::NodeRef>,
0264 bool External = false>
0265 struct idf_iterator : public df_iterator<Inverse<T>, SetTy, External> {
0266 idf_iterator(const df_iterator<Inverse<T>, SetTy, External> &V)
0267 : df_iterator<Inverse<T>, SetTy, External>(V) {}
0268 };
0269
0270 template <class T>
0271 idf_iterator<T> idf_begin(const T& G) {
0272 return idf_iterator<T>::begin(Inverse<T>(G));
0273 }
0274
0275 template <class T>
0276 idf_iterator<T> idf_end(const T& G){
0277 return idf_iterator<T>::end(Inverse<T>(G));
0278 }
0279
0280
0281 template <class T>
0282 iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) {
0283 return make_range(idf_begin(G), idf_end(G));
0284 }
0285
0286
0287 template <class T, class SetTy = df_iterator_default_set<typename GraphTraits<T>::NodeRef>>
0288 struct idf_ext_iterator : public idf_iterator<T, SetTy, true> {
0289 idf_ext_iterator(const idf_iterator<T, SetTy, true> &V)
0290 : idf_iterator<T, SetTy, true>(V) {}
0291 idf_ext_iterator(const df_iterator<Inverse<T>, SetTy, true> &V)
0292 : idf_iterator<T, SetTy, true>(V) {}
0293 };
0294
0295 template <class T, class SetTy>
0296 idf_ext_iterator<T, SetTy> idf_ext_begin(const T& G, SetTy &S) {
0297 return idf_ext_iterator<T, SetTy>::begin(Inverse<T>(G), S);
0298 }
0299
0300 template <class T, class SetTy>
0301 idf_ext_iterator<T, SetTy> idf_ext_end(const T& G, SetTy &S) {
0302 return idf_ext_iterator<T, SetTy>::end(Inverse<T>(G), S);
0303 }
0304
0305 template <class T, class SetTy>
0306 iterator_range<idf_ext_iterator<T, SetTy>> inverse_depth_first_ext(const T& G,
0307 SetTy &S) {
0308 return make_range(idf_ext_begin(G, S), idf_ext_end(G, S));
0309 }
0310
0311 }
0312
0313 #endif