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.

279 lines
10 KiB

  1. //===- llvm/ADT/PostOrderIterator.h - PostOrder 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 a generic graph
  11. // post order iterator. This should work over any graph type that has a
  12. // GraphTraits specialization.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #ifndef LLVM_ADT_POSTORDERITERATOR_H
  16. #define LLVM_ADT_POSTORDERITERATOR_H
  17. #include "llvm/ADT/GraphTraits.h"
  18. #include "llvm/ADT/SmallPtrSet.h"
  19. #include <set>
  20. #include <vector>
  21. namespace llvm {
  22. // The po_iterator_storage template provides access to the set of already
  23. // visited nodes during the po_iterator's depth-first traversal.
  24. //
  25. // The default implementation simply contains a set of visited nodes, while
  26. // the Extended=true version uses a reference to an external set.
  27. //
  28. // It is possible to prune the depth-first traversal in several ways:
  29. //
  30. // - When providing an external set that already contains some graph nodes,
  31. // those nodes won't be visited again. This is useful for restarting a
  32. // post-order traversal on a graph with nodes that aren't dominated by a
  33. // single node.
  34. //
  35. // - By providing a custom SetType class, unwanted graph nodes can be excluded
  36. // by having the insert() function return false. This could for example
  37. // confine a CFG traversal to blocks in a specific loop.
  38. //
  39. // - Finally, by specializing the po_iterator_storage template itself, graph
  40. // edges can be pruned by returning false in the insertEdge() function. This
  41. // could be used to remove loop back-edges from the CFG seen by po_iterator.
  42. //
  43. // A specialized po_iterator_storage class can observe both the pre-order and
  44. // the post-order. The insertEdge() function is called in a pre-order, while
  45. // the finishPostorder() function is called just before the po_iterator moves
  46. // on to the next node.
  47. /// Default po_iterator_storage implementation with an internal set object.
  48. template<class SetType, bool External>
  49. class po_iterator_storage {
  50. SetType Visited;
  51. public:
  52. // Return true if edge destination should be visited.
  53. template<typename NodeType>
  54. bool insertEdge(NodeType *From, NodeType *To) {
  55. return Visited.insert(To);
  56. }
  57. // Called after all children of BB have been visited.
  58. template<typename NodeType>
  59. void finishPostorder(NodeType *BB) {}
  60. };
  61. /// Specialization of po_iterator_storage that references an external set.
  62. template<class SetType>
  63. class po_iterator_storage<SetType, true> {
  64. SetType &Visited;
  65. public:
  66. po_iterator_storage(SetType &VSet) : Visited(VSet) {}
  67. po_iterator_storage(const po_iterator_storage &S) : Visited(S.Visited) {}
  68. // Return true if edge destination should be visited, called with From = 0 for
  69. // the root node.
  70. // Graph edges can be pruned by specializing this function.
  71. template<class NodeType>
  72. bool insertEdge(NodeType *From, NodeType *To) { return Visited.insert(To); }
  73. // Called after all children of BB have been visited.
  74. template<class NodeType>
  75. void finishPostorder(NodeType *BB) {}
  76. };
  77. template<class GraphT,
  78. class SetType = llvm::SmallPtrSet<typename GraphTraits<GraphT>::NodeType*, 8>,
  79. bool ExtStorage = false,
  80. class GT = GraphTraits<GraphT> >
  81. class po_iterator : public std::iterator<std::forward_iterator_tag,
  82. typename GT::NodeType, ptrdiff_t>,
  83. public po_iterator_storage<SetType, ExtStorage> {
  84. typedef std::iterator<std::forward_iterator_tag,
  85. typename GT::NodeType, ptrdiff_t> super;
  86. typedef typename GT::NodeType NodeType;
  87. typedef typename GT::ChildIteratorType ChildItTy;
  88. // VisitStack - Used to maintain the ordering. Top = current block
  89. // First element is basic block pointer, second is the 'next child' to visit
  90. std::vector<std::pair<NodeType *, ChildItTy> > VisitStack;
  91. void traverseChild() {
  92. while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) {
  93. NodeType *BB = *VisitStack.back().second++;
  94. if (this->insertEdge(VisitStack.back().first, BB)) {
  95. // If the block is not visited...
  96. VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
  97. }
  98. }
  99. }
  100. inline po_iterator(NodeType *BB) {
  101. this->insertEdge((NodeType*)0, BB);
  102. VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
  103. traverseChild();
  104. }
  105. inline po_iterator() {} // End is when stack is empty.
  106. inline po_iterator(NodeType *BB, SetType &S) :
  107. po_iterator_storage<SetType, ExtStorage>(S) {
  108. if (this->insertEdge((NodeType*)0, BB)) {
  109. VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
  110. traverseChild();
  111. }
  112. }
  113. inline po_iterator(SetType &S) :
  114. po_iterator_storage<SetType, ExtStorage>(S) {
  115. } // End is when stack is empty.
  116. public:
  117. typedef typename super::pointer pointer;
  118. typedef po_iterator<GraphT, SetType, ExtStorage, GT> _Self;
  119. // Provide static "constructors"...
  120. static inline _Self begin(GraphT G) { return _Self(GT::getEntryNode(G)); }
  121. static inline _Self end (GraphT G) { return _Self(); }
  122. static inline _Self begin(GraphT G, SetType &S) {
  123. return _Self(GT::getEntryNode(G), S);
  124. }
  125. static inline _Self end (GraphT G, SetType &S) { return _Self(S); }
  126. inline bool operator==(const _Self& x) const {
  127. return VisitStack == x.VisitStack;
  128. }
  129. inline bool operator!=(const _Self& x) const { return !operator==(x); }
  130. inline pointer operator*() const {
  131. return VisitStack.back().first;
  132. }
  133. // This is a nonstandard operator-> that dereferences the pointer an extra
  134. // time... so that you can actually call methods ON the BasicBlock, because
  135. // the contained type is a pointer. This allows BBIt->getTerminator() f.e.
  136. //
  137. inline NodeType *operator->() const { return operator*(); }
  138. inline _Self& operator++() { // Preincrement
  139. this->finishPostorder(VisitStack.back().first);
  140. VisitStack.pop_back();
  141. if (!VisitStack.empty())
  142. traverseChild();
  143. return *this;
  144. }
  145. inline _Self operator++(int) { // Postincrement
  146. _Self tmp = *this; ++*this; return tmp;
  147. }
  148. };
  149. // Provide global constructors that automatically figure out correct types...
  150. //
  151. template <class T>
  152. po_iterator<T> po_begin(T G) { return po_iterator<T>::begin(G); }
  153. template <class T>
  154. po_iterator<T> po_end (T G) { return po_iterator<T>::end(G); }
  155. // Provide global definitions of external postorder iterators...
  156. template<class T, class SetType=std::set<typename GraphTraits<T>::NodeType*> >
  157. struct po_ext_iterator : public po_iterator<T, SetType, true> {
  158. po_ext_iterator(const po_iterator<T, SetType, true> &V) :
  159. po_iterator<T, SetType, true>(V) {}
  160. };
  161. template<class T, class SetType>
  162. po_ext_iterator<T, SetType> po_ext_begin(T G, SetType &S) {
  163. return po_ext_iterator<T, SetType>::begin(G, S);
  164. }
  165. template<class T, class SetType>
  166. po_ext_iterator<T, SetType> po_ext_end(T G, SetType &S) {
  167. return po_ext_iterator<T, SetType>::end(G, S);
  168. }
  169. // Provide global definitions of inverse post order iterators...
  170. template <class T,
  171. class SetType = std::set<typename GraphTraits<T>::NodeType*>,
  172. bool External = false>
  173. struct ipo_iterator : public po_iterator<Inverse<T>, SetType, External > {
  174. ipo_iterator(const po_iterator<Inverse<T>, SetType, External> &V) :
  175. po_iterator<Inverse<T>, SetType, External> (V) {}
  176. };
  177. template <class T>
  178. ipo_iterator<T> ipo_begin(T G, bool Reverse = false) {
  179. return ipo_iterator<T>::begin(G, Reverse);
  180. }
  181. template <class T>
  182. ipo_iterator<T> ipo_end(T G){
  183. return ipo_iterator<T>::end(G);
  184. }
  185. // Provide global definitions of external inverse postorder iterators...
  186. template <class T,
  187. class SetType = std::set<typename GraphTraits<T>::NodeType*> >
  188. struct ipo_ext_iterator : public ipo_iterator<T, SetType, true> {
  189. ipo_ext_iterator(const ipo_iterator<T, SetType, true> &V) :
  190. ipo_iterator<T, SetType, true>(V) {}
  191. ipo_ext_iterator(const po_iterator<Inverse<T>, SetType, true> &V) :
  192. ipo_iterator<T, SetType, true>(V) {}
  193. };
  194. template <class T, class SetType>
  195. ipo_ext_iterator<T, SetType> ipo_ext_begin(T G, SetType &S) {
  196. return ipo_ext_iterator<T, SetType>::begin(G, S);
  197. }
  198. template <class T, class SetType>
  199. ipo_ext_iterator<T, SetType> ipo_ext_end(T G, SetType &S) {
  200. return ipo_ext_iterator<T, SetType>::end(G, S);
  201. }
  202. //===--------------------------------------------------------------------===//
  203. // Reverse Post Order CFG iterator code
  204. //===--------------------------------------------------------------------===//
  205. //
  206. // This is used to visit basic blocks in a method in reverse post order. This
  207. // class is awkward to use because I don't know a good incremental algorithm to
  208. // computer RPO from a graph. Because of this, the construction of the
  209. // ReversePostOrderTraversal object is expensive (it must walk the entire graph
  210. // with a postorder iterator to build the data structures). The moral of this
  211. // story is: Don't create more ReversePostOrderTraversal classes than necessary.
  212. //
  213. // This class should be used like this:
  214. // {
  215. // ReversePostOrderTraversal<Function*> RPOT(FuncPtr); // Expensive to create
  216. // for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) {
  217. // ...
  218. // }
  219. // for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) {
  220. // ...
  221. // }
  222. // }
  223. //
  224. template<class GraphT, class GT = GraphTraits<GraphT> >
  225. class ReversePostOrderTraversal {
  226. typedef typename GT::NodeType NodeType;
  227. std::vector<NodeType*> Blocks; // Block list in normal PO order
  228. inline void Initialize(NodeType *BB) {
  229. std::copy(po_begin(BB), po_end(BB), std::back_inserter(Blocks));
  230. }
  231. public:
  232. typedef typename std::vector<NodeType*>::reverse_iterator rpo_iterator;
  233. inline ReversePostOrderTraversal(GraphT G) {
  234. Initialize(GT::getEntryNode(G));
  235. }
  236. // Because we want a reverse post order, use reverse iterators from the vector
  237. inline rpo_iterator begin() { return Blocks.rbegin(); }
  238. inline rpo_iterator end() { return Blocks.rend(); }
  239. };
  240. } // End llvm namespace
  241. #endif