Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
8.9 KiB

  1. //===- llvm/ADT/DepthFirstIterator.h - Depth First iterator -----*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file builds on the ADT/GraphTraits.h file to build generic depth
  11. // first graph iterator. This file exposes the following functions/types:
  12. //
  13. // df_begin/df_end/df_iterator
  14. // * Normal depth-first iteration - visit a node and then all of its children.
  15. //
  16. // idf_begin/idf_end/idf_iterator
  17. // * Depth-first iteration on the 'inverse' graph.
  18. //
  19. // df_ext_begin/df_ext_end/df_ext_iterator
  20. // * Normal depth-first iteration - visit a node and then all of its children.
  21. // This iterator stores the 'visited' set in an external set, which allows
  22. // it to be more efficient, and allows external clients to use the set for
  23. // other purposes.
  24. //
  25. // idf_ext_begin/idf_ext_end/idf_ext_iterator
  26. // * Depth-first iteration on the 'inverse' graph.
  27. // This iterator stores the 'visited' set in an external set, which allows
  28. // it to be more efficient, and allows external clients to use the set for
  29. // other purposes.
  30. //
  31. //===----------------------------------------------------------------------===//
  32. #ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H
  33. #define LLVM_ADT_DEPTHFIRSTITERATOR_H
  34. #include "llvm/ADT/GraphTraits.h"
  35. #include "llvm/ADT/PointerIntPair.h"
  36. #include "llvm/ADT/SmallPtrSet.h"
  37. #include <set>
  38. #include <vector>
  39. namespace llvm {
  40. // df_iterator_storage - A private class which is used to figure out where to
  41. // store the visited set.
  42. template<class SetType, bool External> // Non-external set
  43. class df_iterator_storage {
  44. public:
  45. SetType Visited;
  46. };
  47. template<class SetType>
  48. class df_iterator_storage<SetType, true> {
  49. public:
  50. df_iterator_storage(SetType &VSet) : Visited(VSet) {}
  51. df_iterator_storage(const df_iterator_storage &S) : Visited(S.Visited) {}
  52. SetType &Visited;
  53. };
  54. // Generic Depth First Iterator
  55. template<class GraphT,
  56. class SetType = llvm::SmallPtrSet<typename GraphTraits<GraphT>::NodeType*, 8>,
  57. bool ExtStorage = false, class GT = GraphTraits<GraphT> >
  58. class df_iterator : public std::iterator<std::forward_iterator_tag,
  59. typename GT::NodeType, ptrdiff_t>,
  60. public df_iterator_storage<SetType, ExtStorage> {
  61. typedef std::iterator<std::forward_iterator_tag,
  62. typename GT::NodeType, ptrdiff_t> super;
  63. typedef typename GT::NodeType NodeType;
  64. typedef typename GT::ChildIteratorType ChildItTy;
  65. typedef PointerIntPair<NodeType*, 1> PointerIntTy;
  66. // VisitStack - Used to maintain the ordering. Top = current block
  67. // First element is node pointer, second is the 'next child' to visit
  68. // if the int in PointerIntTy is 0, the 'next child' to visit is invalid
  69. std::vector<std::pair<PointerIntTy, ChildItTy> > VisitStack;
  70. private:
  71. inline df_iterator(NodeType *Node) {
  72. this->Visited.insert(Node);
  73. VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0),
  74. GT::child_begin(Node)));
  75. }
  76. inline df_iterator() {
  77. // End is when stack is empty
  78. }
  79. inline df_iterator(NodeType *Node, SetType &S)
  80. : df_iterator_storage<SetType, ExtStorage>(S) {
  81. if (!S.count(Node)) {
  82. VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0),
  83. GT::child_begin(Node)));
  84. this->Visited.insert(Node);
  85. }
  86. }
  87. inline df_iterator(SetType &S)
  88. : df_iterator_storage<SetType, ExtStorage>(S) {
  89. // End is when stack is empty
  90. }
  91. inline void toNext() {
  92. do {
  93. std::pair<PointerIntTy, ChildItTy> &Top = VisitStack.back();
  94. NodeType *Node = Top.first.getPointer();
  95. ChildItTy &It = Top.second;
  96. if (!Top.first.getInt()) {
  97. // now retrieve the real begin of the children before we dive in
  98. It = GT::child_begin(Node);
  99. Top.first.setInt(1);
  100. }
  101. while (It != GT::child_end(Node)) {
  102. NodeType *Next = *It++;
  103. // Has our next sibling been visited?
  104. if (Next && !this->Visited.count(Next)) {
  105. // No, do it now.
  106. this->Visited.insert(Next);
  107. VisitStack.push_back(std::make_pair(PointerIntTy(Next, 0),
  108. GT::child_begin(Next)));
  109. return;
  110. }
  111. }
  112. // Oops, ran out of successors... go up a level on the stack.
  113. VisitStack.pop_back();
  114. } while (!VisitStack.empty());
  115. }
  116. public:
  117. typedef typename super::pointer pointer;
  118. typedef df_iterator<GraphT, SetType, ExtStorage, GT> _Self;
  119. // Provide static begin and end methods as our public "constructors"
  120. static inline _Self begin(const GraphT& G) {
  121. return _Self(GT::getEntryNode(G));
  122. }
  123. static inline _Self end(const GraphT& G) { return _Self(); }
  124. // Static begin and end methods as our public ctors for external iterators
  125. static inline _Self begin(const GraphT& G, SetType &S) {
  126. return _Self(GT::getEntryNode(G), S);
  127. }
  128. static inline _Self end(const GraphT& G, SetType &S) { return _Self(S); }
  129. inline bool operator==(const _Self& x) const {
  130. return VisitStack == x.VisitStack;
  131. }
  132. inline bool operator!=(const _Self& x) const { return !operator==(x); }
  133. inline pointer operator*() const {
  134. return VisitStack.back().first.getPointer();
  135. }
  136. // This is a nonstandard operator-> that dereferences the pointer an extra
  137. // time... so that you can actually call methods ON the Node, because
  138. // the contained type is a pointer. This allows BBIt->getTerminator() f.e.
  139. //
  140. inline NodeType *operator->() const { return operator*(); }
  141. inline _Self& operator++() { // Preincrement
  142. toNext();
  143. return *this;
  144. }
  145. // skips all children of the current node and traverses to next node
  146. //
  147. inline _Self& skipChildren() {
  148. VisitStack.pop_back();
  149. if (!VisitStack.empty())
  150. toNext();
  151. return *this;
  152. }
  153. inline _Self operator++(int) { // Postincrement
  154. _Self tmp = *this; ++*this; return tmp;
  155. }
  156. // nodeVisited - return true if this iterator has already visited the
  157. // specified node. This is public, and will probably be used to iterate over
  158. // nodes that a depth first iteration did not find: ie unreachable nodes.
  159. //
  160. inline bool nodeVisited(NodeType *Node) const {
  161. return this->Visited.count(Node) != 0;
  162. }
  163. /// getPathLength - Return the length of the path from the entry node to the
  164. /// current node, counting both nodes.
  165. unsigned getPathLength() const { return VisitStack.size(); }
  166. /// getPath - Return the n'th node in the path from the entry node to the
  167. /// current node.
  168. NodeType *getPath(unsigned n) const {
  169. return VisitStack[n].first.getPointer();
  170. }
  171. };
  172. // Provide global constructors that automatically figure out correct types...
  173. //
  174. template <class T>
  175. df_iterator<T> df_begin(const T& G) {
  176. return df_iterator<T>::begin(G);
  177. }
  178. template <class T>
  179. df_iterator<T> df_end(const T& G) {
  180. return df_iterator<T>::end(G);
  181. }
  182. // Provide global definitions of external depth first iterators...
  183. template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> >
  184. struct df_ext_iterator : public df_iterator<T, SetTy, true> {
  185. df_ext_iterator(const df_iterator<T, SetTy, true> &V)
  186. : df_iterator<T, SetTy, true>(V) {}
  187. };
  188. template <class T, class SetTy>
  189. df_ext_iterator<T, SetTy> df_ext_begin(const T& G, SetTy &S) {
  190. return df_ext_iterator<T, SetTy>::begin(G, S);
  191. }
  192. template <class T, class SetTy>
  193. df_ext_iterator<T, SetTy> df_ext_end(const T& G, SetTy &S) {
  194. return df_ext_iterator<T, SetTy>::end(G, S);
  195. }
  196. // Provide global definitions of inverse depth first iterators...
  197. template <class T,
  198. class SetTy = llvm::SmallPtrSet<typename GraphTraits<T>::NodeType*, 8>,
  199. bool External = false>
  200. struct idf_iterator : public df_iterator<Inverse<T>, SetTy, External> {
  201. idf_iterator(const df_iterator<Inverse<T>, SetTy, External> &V)
  202. : df_iterator<Inverse<T>, SetTy, External>(V) {}
  203. };
  204. template <class T>
  205. idf_iterator<T> idf_begin(const T& G) {
  206. return idf_iterator<T>::begin(Inverse<T>(G));
  207. }
  208. template <class T>
  209. idf_iterator<T> idf_end(const T& G){
  210. return idf_iterator<T>::end(Inverse<T>(G));
  211. }
  212. // Provide global definitions of external inverse depth first iterators...
  213. template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> >
  214. struct idf_ext_iterator : public idf_iterator<T, SetTy, true> {
  215. idf_ext_iterator(const idf_iterator<T, SetTy, true> &V)
  216. : idf_iterator<T, SetTy, true>(V) {}
  217. idf_ext_iterator(const df_iterator<Inverse<T>, SetTy, true> &V)
  218. : idf_iterator<T, SetTy, true>(V) {}
  219. };
  220. template <class T, class SetTy>
  221. idf_ext_iterator<T, SetTy> idf_ext_begin(const T& G, SetTy &S) {
  222. return idf_ext_iterator<T, SetTy>::begin(Inverse<T>(G), S);
  223. }
  224. template <class T, class SetTy>
  225. idf_ext_iterator<T, SetTy> idf_ext_end(const T& G, SetTy &S) {
  226. return idf_ext_iterator<T, SetTy>::end(Inverse<T>(G), S);
  227. }
  228. } // End llvm namespace
  229. #endif