DepthFirstIterator.h [plain text]
#ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H
#define LLVM_ADT_DEPTHFIRSTITERATOR_H
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/iterator_range.h"
#include <set>
#include <vector>
namespace llvm {
template<class SetType, bool External> class df_iterator_storage {
public:
SetType Visited;
};
template<class SetType>
class df_iterator_storage<SetType, true> {
public:
df_iterator_storage(SetType &VSet) : Visited(VSet) {}
df_iterator_storage(const df_iterator_storage &S) : Visited(S.Visited) {}
SetType &Visited;
};
template<class GraphT,
class SetType = llvm::SmallPtrSet<typename GraphTraits<GraphT>::NodeType*, 8>,
bool ExtStorage = false, class GT = GraphTraits<GraphT> >
class df_iterator : public std::iterator<std::forward_iterator_tag,
typename GT::NodeType, ptrdiff_t>,
public df_iterator_storage<SetType, ExtStorage> {
typedef std::iterator<std::forward_iterator_tag,
typename GT::NodeType, ptrdiff_t> super;
typedef typename GT::NodeType NodeType;
typedef typename GT::ChildIteratorType ChildItTy;
typedef PointerIntPair<NodeType*, 1> PointerIntTy;
std::vector<std::pair<PointerIntTy, ChildItTy>> VisitStack;
private:
inline df_iterator(NodeType *Node) {
this->Visited.insert(Node);
VisitStack.push_back(
std::make_pair(PointerIntTy(Node, 0), GT::child_begin(Node)));
}
inline df_iterator() {
}
inline df_iterator(NodeType *Node, SetType &S)
: df_iterator_storage<SetType, ExtStorage>(S) {
if (!S.count(Node)) {
VisitStack.push_back(
std::make_pair(PointerIntTy(Node, 0), GT::child_begin(Node)));
this->Visited.insert(Node);
}
}
inline df_iterator(SetType &S)
: df_iterator_storage<SetType, ExtStorage>(S) {
}
inline void toNext() {
do {
std::pair<PointerIntTy, ChildItTy> &Top = VisitStack.back();
NodeType *Node = Top.first.getPointer();
ChildItTy &It = Top.second;
if (!Top.first.getInt()) {
It = GT::child_begin(Node);
Top.first.setInt(1);
}
while (It != GT::child_end(Node)) {
NodeType *Next = *It++;
if (Next && this->Visited.insert(Next).second) {
VisitStack.push_back(
std::make_pair(PointerIntTy(Next, 0), GT::child_begin(Next)));
return;
}
}
VisitStack.pop_back();
} while (!VisitStack.empty());
}
public:
typedef typename super::pointer pointer;
static df_iterator begin(const GraphT &G) {
return df_iterator(GT::getEntryNode(G));
}
static df_iterator end(const GraphT &G) { return df_iterator(); }
static df_iterator begin(const GraphT &G, SetType &S) {
return df_iterator(GT::getEntryNode(G), S);
}
static df_iterator end(const GraphT &G, SetType &S) { return df_iterator(S); }
bool operator==(const df_iterator &x) const {
return VisitStack == x.VisitStack;
}
bool operator!=(const df_iterator &x) const { return !(*this == x); }
pointer operator*() const { return VisitStack.back().first.getPointer(); }
NodeType *operator->() const { return **this; }
df_iterator &operator++() { toNext();
return *this;
}
df_iterator &skipChildren() {
VisitStack.pop_back();
if (!VisitStack.empty())
toNext();
return *this;
}
df_iterator operator++(int) { df_iterator tmp = *this;
++*this;
return tmp;
}
bool nodeVisited(NodeType *Node) const {
return this->Visited.count(Node) != 0;
}
unsigned getPathLength() const { return VisitStack.size(); }
NodeType *getPath(unsigned n) const {
return VisitStack[n].first.getPointer();
}
};
template <class T>
df_iterator<T> df_begin(const T& G) {
return df_iterator<T>::begin(G);
}
template <class T>
df_iterator<T> df_end(const T& G) {
return df_iterator<T>::end(G);
}
template <class T>
iterator_range<df_iterator<T>> depth_first(const T& G) {
return make_range(df_begin(G), df_end(G));
}
template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> >
struct df_ext_iterator : public df_iterator<T, SetTy, true> {
df_ext_iterator(const df_iterator<T, SetTy, true> &V)
: df_iterator<T, SetTy, true>(V) {}
};
template <class T, class SetTy>
df_ext_iterator<T, SetTy> df_ext_begin(const T& G, SetTy &S) {
return df_ext_iterator<T, SetTy>::begin(G, S);
}
template <class T, class SetTy>
df_ext_iterator<T, SetTy> df_ext_end(const T& G, SetTy &S) {
return df_ext_iterator<T, SetTy>::end(G, S);
}
template <class T, class SetTy>
iterator_range<df_ext_iterator<T, SetTy>> depth_first_ext(const T& G,
SetTy &S) {
return make_range(df_ext_begin(G, S), df_ext_end(G, S));
}
template <class T,
class SetTy = llvm::SmallPtrSet<typename GraphTraits<T>::NodeType*, 8>,
bool External = false>
struct idf_iterator : public df_iterator<Inverse<T>, SetTy, External> {
idf_iterator(const df_iterator<Inverse<T>, SetTy, External> &V)
: df_iterator<Inverse<T>, SetTy, External>(V) {}
};
template <class T>
idf_iterator<T> idf_begin(const T& G) {
return idf_iterator<T>::begin(Inverse<T>(G));
}
template <class T>
idf_iterator<T> idf_end(const T& G){
return idf_iterator<T>::end(Inverse<T>(G));
}
template <class T>
iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) {
return make_range(idf_begin(G), idf_end(G));
}
template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> >
struct idf_ext_iterator : public idf_iterator<T, SetTy, true> {
idf_ext_iterator(const idf_iterator<T, SetTy, true> &V)
: idf_iterator<T, SetTy, true>(V) {}
idf_ext_iterator(const df_iterator<Inverse<T>, SetTy, true> &V)
: idf_iterator<T, SetTy, true>(V) {}
};
template <class T, class SetTy>
idf_ext_iterator<T, SetTy> idf_ext_begin(const T& G, SetTy &S) {
return idf_ext_iterator<T, SetTy>::begin(Inverse<T>(G), S);
}
template <class T, class SetTy>
idf_ext_iterator<T, SetTy> idf_ext_end(const T& G, SetTy &S) {
return idf_ext_iterator<T, SetTy>::end(Inverse<T>(G), S);
}
template <class T, class SetTy>
iterator_range<idf_ext_iterator<T, SetTy>> inverse_depth_first_ext(const T& G,
SetTy &S) {
return make_range(idf_ext_begin(G, S), idf_ext_end(G, S));
}
}
#endif