//===- RegionIterator.h - Iterators to iteratate over Regions ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// This file defines the iterators to iterate over the elements of a Region.
//===----------------------------------------------------------------------===//

#ifndef LLVM_ANALYSIS_REGIONITERATOR_H
#define LLVM_ANALYSIS_REGIONITERATOR_H

#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Analysis/RegionInfo.h"
#include <cassert>
#include <iterator>
#include <type_traits>

namespace llvm {

class BasicBlock;
class RegionInfo;

//===----------------------------------------------------------------------===//
/// Hierarchical RegionNode successor iterator.
///
/// This iterator iterates over all successors of a RegionNode.
///
/// For a BasicBlock RegionNode it skips all BasicBlocks that are not part of
/// the parent Region.  Furthermore for BasicBlocks that start a subregion, a
/// RegionNode representing the subregion is returned.
///
/// For a subregion RegionNode there is just one successor. The RegionNode
/// representing the exit of the subregion.
template <class NodeRef, class BlockT, class RegionT> class RNSuccIterator {
public:
  using iterator_category = std::forward_iterator_tag;
  using value_type = NodeRef;
  using difference_type = std::ptrdiff_t;
  using pointer = value_type *;
  using reference = value_type &;

private:
  using BlockTraits = GraphTraits<BlockT *>;
  using SuccIterTy = typename BlockTraits::ChildIteratorType;

  // The iterator works in two modes, bb mode or region mode.
  enum ItMode {
    // In BB mode it returns all successors of this BasicBlock as its
    // successors.
    ItBB,
    // In region mode there is only one successor, thats the regionnode mapping
    // to the exit block of the regionnode
    ItRgBegin, // At the beginning of the regionnode successor.
    ItRgEnd    // At the end of the regionnode successor.
  };

  static_assert(std::is_pointer<NodeRef>::value,
                "FIXME: Currently RNSuccIterator only supports NodeRef as "
                "pointers due to the use of pointer-specific data structures "
                "(e.g. PointerIntPair and SmallPtrSet) internally. Generalize "
                "it to support non-pointer types");

  // Use two bit to represent the mode iterator.
  PointerIntPair<NodeRef, 2, ItMode> Node;

  // The block successor iterator.
  SuccIterTy BItor;

  // advanceRegionSucc - A region node has only one successor. It reaches end
  // once we advance it.
  void advanceRegionSucc() {
    assert(Node.getInt() == ItRgBegin && "Cannot advance region successor!");
    Node.setInt(ItRgEnd);
  }

  NodeRef getNode() const { return Node.getPointer(); }

  // isRegionMode - Is the current iterator in region mode?
  bool isRegionMode() const { return Node.getInt() != ItBB; }

  // Get the immediate successor. This function may return a Basic Block
  // RegionNode or a subregion RegionNode.
  NodeRef getISucc(BlockT *BB) const {
    NodeRef succ;
    succ = getNode()->getParent()->getNode(BB);
    assert(succ && "BB not in Region or entered subregion!");
    return succ;
  }

  // getRegionSucc - Return the successor basic block of a SubRegion RegionNode.
  inline BlockT* getRegionSucc() const {
    assert(Node.getInt() == ItRgBegin && "Cannot get the region successor!");
    return getNode()->template getNodeAs<RegionT>()->getExit();
  }

  // isExit - Is this the exit BB of the Region?
  inline bool isExit(BlockT* BB) const {
    return getNode()->getParent()->getExit() == BB;
  }

public:
  using Self = RNSuccIterator<NodeRef, BlockT, RegionT>;

  /// Create begin iterator of a RegionNode.
  inline RNSuccIterator(NodeRef node)
      : Node(node, node->isSubRegion() ? ItRgBegin : ItBB),
        BItor(BlockTraits::child_begin(node->getEntry())) {
    // Skip the exit block
    if (!isRegionMode())
      while (BlockTraits::child_end(node->getEntry()) != BItor && isExit(*BItor))
        ++BItor;

    if (isRegionMode() && isExit(getRegionSucc()))
      advanceRegionSucc();
  }

  /// Create an end iterator.
  inline RNSuccIterator(NodeRef node, bool)
      : Node(node, node->isSubRegion() ? ItRgEnd : ItBB),
        BItor(BlockTraits::child_end(node->getEntry())) {}

  inline bool operator==(const Self& x) const {
    assert(isRegionMode() == x.isRegionMode() && "Broken iterator!");
    if (isRegionMode())
      return Node.getInt() == x.Node.getInt();
    else
      return BItor == x.BItor;
  }

  inline bool operator!=(const Self& x) const { return !operator==(x); }

  inline value_type operator*() const {
    BlockT *BB = isRegionMode() ? getRegionSucc() : *BItor;
    assert(!isExit(BB) && "Iterator out of range!");
    return getISucc(BB);
  }

  inline Self& operator++() {
    if(isRegionMode()) {
      // The Region only has 1 successor.
      advanceRegionSucc();
    } else {
      // Skip the exit.
      do
        ++BItor;
      while (BItor != BlockTraits::child_end(getNode()->getEntry())
          && isExit(*BItor));
    }
    return *this;
  }

  inline Self operator++(int) {
    Self tmp = *this;
    ++*this;
    return tmp;
  }
};

//===----------------------------------------------------------------------===//
/// Flat RegionNode iterator.
///
/// The Flat Region iterator will iterate over all BasicBlock RegionNodes that
/// are contained in the Region and its subregions. This is close to a virtual
/// control flow graph of the Region.
template <class NodeRef, class BlockT, class RegionT>
class RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT> {
  using BlockTraits = GraphTraits<BlockT *>;
  using SuccIterTy = typename BlockTraits::ChildIteratorType;

  NodeRef Node;
  SuccIterTy Itor;

public:
  using iterator_category = std::forward_iterator_tag;
  using value_type = NodeRef;
  using difference_type = std::ptrdiff_t;
  using pointer = value_type *;
  using reference = value_type &;

  using Self = RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>;

  /// Create the iterator from a RegionNode.
  ///
  /// Note that the incoming node must be a bb node, otherwise it will trigger
  /// an assertion when we try to get a BasicBlock.
  inline RNSuccIterator(NodeRef node)
      : Node(node), Itor(BlockTraits::child_begin(node->getEntry())) {
    assert(!Node->isSubRegion() &&
           "Subregion node not allowed in flat iterating mode!");
    assert(Node->getParent() && "A BB node must have a parent!");

    // Skip the exit block of the iterating region.
    while (BlockTraits::child_end(Node->getEntry()) != Itor &&
           Node->getParent()->getExit() == *Itor)
      ++Itor;
  }

  /// Create an end iterator
  inline RNSuccIterator(NodeRef node, bool)
      : Node(node), Itor(BlockTraits::child_end(node->getEntry())) {
    assert(!Node->isSubRegion() &&
           "Subregion node not allowed in flat iterating mode!");
  }

  inline bool operator==(const Self& x) const {
    assert(Node->getParent() == x.Node->getParent()
           && "Cannot compare iterators of different regions!");

    return Itor == x.Itor && Node == x.Node;
  }

  inline bool operator!=(const Self& x) const { return !operator==(x); }

  inline value_type operator*() const {
    BlockT *BB = *Itor;

    // Get the iterating region.
    RegionT *Parent = Node->getParent();

    // The only case that the successor reaches out of the region is it reaches
    // the exit of the region.
    assert(Parent->getExit() != BB && "iterator out of range!");

    return Parent->getBBNode(BB);
  }

  inline Self& operator++() {
    // Skip the exit block of the iterating region.
    do
      ++Itor;
    while (Itor != succ_end(Node->getEntry())
        && Node->getParent()->getExit() == *Itor);

    return *this;
  }

  inline Self operator++(int) {
    Self tmp = *this;
    ++*this;
    return tmp;
  }
};

template <class NodeRef, class BlockT, class RegionT>
inline RNSuccIterator<NodeRef, BlockT, RegionT> succ_begin(NodeRef Node) {
  return RNSuccIterator<NodeRef, BlockT, RegionT>(Node);
}

template <class NodeRef, class BlockT, class RegionT>
inline RNSuccIterator<NodeRef, BlockT, RegionT> succ_end(NodeRef Node) {
  return RNSuccIterator<NodeRef, BlockT, RegionT>(Node, true);
}

//===--------------------------------------------------------------------===//
// RegionNode GraphTraits specialization so the bbs in the region can be
// iterate by generic graph iterators.
//
// NodeT can either be region node or const region node, otherwise child_begin
// and child_end fail.

#define RegionNodeGraphTraits(NodeT, BlockT, RegionT)                          \
  template <> struct GraphTraits<NodeT *> {                                    \
    using NodeRef = NodeT *;                                                   \
    using ChildIteratorType = RNSuccIterator<NodeRef, BlockT, RegionT>;        \
    static NodeRef getEntryNode(NodeRef N) { return N; }                       \
    static inline ChildIteratorType child_begin(NodeRef N) {                   \
      return RNSuccIterator<NodeRef, BlockT, RegionT>(N);                      \
    }                                                                          \
    static inline ChildIteratorType child_end(NodeRef N) {                     \
      return RNSuccIterator<NodeRef, BlockT, RegionT>(N, true);                \
    }                                                                          \
  };                                                                           \
  template <> struct GraphTraits<FlatIt<NodeT *>> {                            \
    using NodeRef = NodeT *;                                                   \
    using ChildIteratorType =                                                  \
        RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>;                      \
    static NodeRef getEntryNode(NodeRef N) { return N; }                       \
    static inline ChildIteratorType child_begin(NodeRef N) {                   \
      return RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>(N);              \
    }                                                                          \
    static inline ChildIteratorType child_end(NodeRef N) {                     \
      return RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>(N, true);        \
    }                                                                          \
  }

#define RegionGraphTraits(RegionT, NodeT)                                      \
  template <> struct GraphTraits<RegionT *> : public GraphTraits<NodeT *> {    \
    using nodes_iterator = df_iterator<NodeRef>;                               \
    static NodeRef getEntryNode(RegionT *R) {                                  \
      return R->getNode(R->getEntry());                                        \
    }                                                                          \
    static nodes_iterator nodes_begin(RegionT *R) {                            \
      return nodes_iterator::begin(getEntryNode(R));                           \
    }                                                                          \
    static nodes_iterator nodes_end(RegionT *R) {                              \
      return nodes_iterator::end(getEntryNode(R));                             \
    }                                                                          \
  };                                                                           \
  template <>                                                                  \
  struct GraphTraits<FlatIt<RegionT *>>                                        \
      : public GraphTraits<FlatIt<NodeT *>> {                                  \
    using nodes_iterator =                                                     \
        df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false,          \
                    GraphTraits<FlatIt<NodeRef>>>;                             \
    static NodeRef getEntryNode(RegionT *R) {                                  \
      return R->getBBNode(R->getEntry());                                      \
    }                                                                          \
    static nodes_iterator nodes_begin(RegionT *R) {                            \
      return nodes_iterator::begin(getEntryNode(R));                           \
    }                                                                          \
    static nodes_iterator nodes_end(RegionT *R) {                              \
      return nodes_iterator::end(getEntryNode(R));                             \
    }                                                                          \
  }

RegionNodeGraphTraits(RegionNode, BasicBlock, Region);
RegionNodeGraphTraits(const RegionNode, BasicBlock, Region);

RegionGraphTraits(Region, RegionNode);
RegionGraphTraits(const Region, const RegionNode);

template <> struct GraphTraits<RegionInfo*>
  : public GraphTraits<FlatIt<RegionNode*>> {
  using nodes_iterator =
      df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false,
                  GraphTraits<FlatIt<NodeRef>>>;

  static NodeRef getEntryNode(RegionInfo *RI) {
    return GraphTraits<FlatIt<Region*>>::getEntryNode(RI->getTopLevelRegion());
  }

  static nodes_iterator nodes_begin(RegionInfo* RI) {
    return nodes_iterator::begin(getEntryNode(RI));
  }

  static nodes_iterator nodes_end(RegionInfo *RI) {
    return nodes_iterator::end(getEntryNode(RI));
  }
};

template <> struct GraphTraits<RegionInfoPass*>
  : public GraphTraits<RegionInfo *> {
  using nodes_iterator =
      df_iterator<NodeRef, df_iterator_default_set<NodeRef>, false,
                  GraphTraits<FlatIt<NodeRef>>>;

  static NodeRef getEntryNode(RegionInfoPass *RI) {
    return GraphTraits<RegionInfo*>::getEntryNode(&RI->getRegionInfo());
  }

  static nodes_iterator nodes_begin(RegionInfoPass* RI) {
    return GraphTraits<RegionInfo*>::nodes_begin(&RI->getRegionInfo());
  }

  static nodes_iterator nodes_end(RegionInfoPass *RI) {
    return GraphTraits<RegionInfo*>::nodes_end(&RI->getRegionInfo());
  }
};

} // end namespace llvm

#endif // LLVM_ANALYSIS_REGIONITERATOR_H
