//===- Region.h - MLIR Region Class -----------------------------*- 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 Region class.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_IR_REGION_H
#define MLIR_IR_REGION_H

#include "mlir/IR/Block.h"

namespace mlir {
class TypeRange;
template <typename ValueRangeT>
class ValueTypeRange;
class BlockAndValueMapping;

/// This class contains a list of basic blocks and a link to the parent
/// operation it is attached to.
class Region {
public:
  Region() = default;
  explicit Region(Operation *container);
  ~Region();

  /// Return the context this region is inserted in.  The region must have a
  /// valid parent container.
  MLIRContext *getContext();

  /// Return a location for this region. This is the location attached to the
  /// parent container. The region must have a valid parent container.
  Location getLoc();

  //===--------------------------------------------------------------------===//
  // Block list management
  //===--------------------------------------------------------------------===//

  using BlockListType = llvm::iplist<Block>;
  BlockListType &getBlocks() { return blocks; }
  Block &emplaceBlock() {
    push_back(new Block);
    return back();
  }

  // Iteration over the blocks in the region.
  using iterator = BlockListType::iterator;
  using reverse_iterator = BlockListType::reverse_iterator;

  iterator begin() { return blocks.begin(); }
  iterator end() { return blocks.end(); }
  reverse_iterator rbegin() { return blocks.rbegin(); }
  reverse_iterator rend() { return blocks.rend(); }

  bool empty() { return blocks.empty(); }
  void push_back(Block *block) { blocks.push_back(block); }
  void push_front(Block *block) { blocks.push_front(block); }

  Block &back() { return blocks.back(); }
  Block &front() { return blocks.front(); }

  /// Return true if this region has exactly one block.
  bool hasOneBlock() { return !empty() && std::next(begin()) == end(); }

  /// getSublistAccess() - Returns pointer to member of region.
  static BlockListType Region::*getSublistAccess(Block *) {
    return &Region::blocks;
  }

  //===--------------------------------------------------------------------===//
  // Argument Handling
  //===--------------------------------------------------------------------===//

  // This is the list of arguments to the block.
  using BlockArgListType = MutableArrayRef<BlockArgument>;
  BlockArgListType getArguments() {
    return empty() ? BlockArgListType() : front().getArguments();
  }

  ValueTypeRange<BlockArgListType> getArgumentTypes();

  using args_iterator = BlockArgListType::iterator;
  using reverse_args_iterator = BlockArgListType::reverse_iterator;
  args_iterator args_begin() { return getArguments().begin(); }
  args_iterator args_end() { return getArguments().end(); }
  reverse_args_iterator args_rbegin() { return getArguments().rbegin(); }
  reverse_args_iterator args_rend() { return getArguments().rend(); }

  bool args_empty() { return getArguments().empty(); }

  /// Add one value to the argument list.
  BlockArgument addArgument(Type type) { return front().addArgument(type); }

  /// Insert one value to the position in the argument list indicated by the
  /// given iterator. The existing arguments are shifted. The block is expected
  /// not to have predecessors.
  BlockArgument insertArgument(args_iterator it, Type type) {
    return front().insertArgument(it, type);
  }

  /// Add one argument to the argument list for each type specified in the list.
  iterator_range<args_iterator> addArguments(TypeRange types);

  /// Add one value to the argument list at the specified position.
  BlockArgument insertArgument(unsigned index, Type type) {
    return front().insertArgument(index, type);
  }

  /// Erase the argument at 'index' and remove it from the argument list.
  void eraseArgument(unsigned index) { front().eraseArgument(index); }

  unsigned getNumArguments() { return getArguments().size(); }
  BlockArgument getArgument(unsigned i) { return getArguments()[i]; }

  //===--------------------------------------------------------------------===//
  // Operation list utilities
  //===--------------------------------------------------------------------===//

  /// This class provides iteration over the held operations of blocks directly
  /// within a region.
  class OpIterator final
      : public llvm::iterator_facade_base<OpIterator, std::forward_iterator_tag,
                                          Operation> {
  public:
    /// Initialize OpIterator for a region, specify `end` to return the iterator
    /// to last operation.
    explicit OpIterator(Region *region, bool end = false);

    using llvm::iterator_facade_base<OpIterator, std::forward_iterator_tag,
                                     Operation>::operator++;
    OpIterator &operator++();
    Operation *operator->() const { return &*operation; }
    Operation &operator*() const { return *operation; }

    /// Compare this iterator with another.
    bool operator==(const OpIterator &rhs) const {
      return operation == rhs.operation;
    }
    bool operator!=(const OpIterator &rhs) const { return !(*this == rhs); }

  private:
    void skipOverBlocksWithNoOps();

    /// The region whose operations are being iterated over.
    Region *region;
    /// The block of 'region' whose operations are being iterated over.
    Region::iterator block;
    /// The current operation within 'block'.
    Block::iterator operation;
  };

  /// This class provides iteration over the held operations of a region for a
  /// specific operation type.
  template <typename OpT>
  using op_iterator = detail::op_iterator<OpT, OpIterator>;

  /// Return iterators that walk the operations nested directly within this
  /// region.
  OpIterator op_begin() { return OpIterator(this); }
  OpIterator op_end() { return OpIterator(this, /*end=*/true); }
  iterator_range<OpIterator> getOps() { return {op_begin(), op_end()}; }

  /// Return iterators that walk operations of type 'T' nested directly within
  /// this region.
  template <typename OpT>
  op_iterator<OpT> op_begin() {
    return detail::op_filter_iterator<OpT, OpIterator>(op_begin(), op_end());
  }
  template <typename OpT>
  op_iterator<OpT> op_end() {
    return detail::op_filter_iterator<OpT, OpIterator>(op_end(), op_end());
  }
  template <typename OpT>
  iterator_range<op_iterator<OpT>> getOps() {
    auto endIt = op_end();
    return {detail::op_filter_iterator<OpT, OpIterator>(op_begin(), endIt),
            detail::op_filter_iterator<OpT, OpIterator>(endIt, endIt)};
  }

  //===--------------------------------------------------------------------===//
  // Misc. utilities
  //===--------------------------------------------------------------------===//

  /// Return the region containing this region or nullptr if the region is
  /// attached to a top-level operation.
  Region *getParentRegion();

  /// Return the parent operation this region is attached to.
  Operation *getParentOp() { return container; }

  /// Find the first parent operation of the given type, or nullptr if there is
  /// no ancestor operation.
  template <typename ParentT>
  ParentT getParentOfType() {
    auto *region = this;
    do {
      if (auto parent = dyn_cast_or_null<ParentT>(region->container))
        return parent;
    } while ((region = region->getParentRegion()));
    return ParentT();
  }

  /// Return the number of this region in the parent operation.
  unsigned getRegionNumber();

  /// Return true if this region is a proper ancestor of the `other` region.
  bool isProperAncestor(Region *other);

  /// Return true if this region is ancestor of the `other` region.  A region
  /// is considered as its own ancestor, use `isProperAncestor` to avoid this.
  bool isAncestor(Region *other) {
    return this == other || isProperAncestor(other);
  }

  /// Clone the internal blocks from this region into dest. Any
  /// cloned blocks are appended to the back of dest. If the mapper
  /// contains entries for block arguments, these arguments are not included
  /// in the respective cloned block.
  void cloneInto(Region *dest, BlockAndValueMapping &mapper);
  /// Clone this region into 'dest' before the given position in 'dest'.
  void cloneInto(Region *dest, Region::iterator destPos,
                 BlockAndValueMapping &mapper);

  /// Takes body of another region (that region will have no body after this
  /// operation completes).  The current body of this region is cleared.
  void takeBody(Region &other) {
    blocks.clear();
    blocks.splice(blocks.end(), other.getBlocks());
  }

  /// Returns 'block' if 'block' lies in this region, or otherwise finds the
  /// ancestor of 'block' that lies in this region. Returns nullptr if the
  /// latter fails.
  Block *findAncestorBlockInRegion(Block &block);

  /// Returns 'op' if 'op' lies in this region, or otherwise finds the
  /// ancestor of 'op' that lies in this region. Returns nullptr if the
  /// latter fails.
  Operation *findAncestorOpInRegion(Operation &op);

  /// Drop all operand uses from operations within this region, which is
  /// an essential step in breaking cyclic dependences between references when
  /// they are to be deleted.
  void dropAllReferences();

  //===--------------------------------------------------------------------===//
  // Operation Walkers
  //===--------------------------------------------------------------------===//

  /// Walk the operations in this region. The callback method is called for each
  /// nested region, block or operation, depending on the callback provided.
  /// Regions, blocks and operations at the same nesting level are visited in
  /// lexicographical order. The walk order for enclosing regions, blocks and
  /// operations with respect to their nested ones is specified by 'Order'
  /// (post-order by default). This method is invoked for void-returning
  /// callbacks. A callback on a block or operation is allowed to erase that
  /// block or operation only if the walk is in post-order. See non-void method
  /// for pre-order erasure. See Operation::walk for more details.
  template <WalkOrder Order = WalkOrder::PostOrder, typename FnT,
            typename RetT = detail::walkResultType<FnT>>
  typename std::enable_if<std::is_same<RetT, void>::value, RetT>::type
  walk(FnT &&callback) {
    for (auto &block : *this)
      block.walk<Order>(callback);
  }

  /// Walk the operations in this region. The callback method is called for each
  /// nested region, block or operation, depending on the callback provided.
  /// Regions, blocks and operations at the same nesting level are visited in
  /// lexicographical order. The walk order for enclosing regions, blocks and
  /// operations with respect to their nested ones is specified by 'Order'
  /// (post-order by default). This method is invoked for skippable or
  /// interruptible callbacks. A callback on a block or operation is allowed to
  /// erase that block or operation if either:
  ///   * the walk is in post-order,
  ///   * or the walk is in pre-order and the walk is skipped after the erasure.
  /// See Operation::walk for more details.
  template <WalkOrder Order = WalkOrder::PostOrder, typename FnT,
            typename RetT = detail::walkResultType<FnT>>
  typename std::enable_if<std::is_same<RetT, WalkResult>::value, RetT>::type
  walk(FnT &&callback) {
    for (auto &block : *this)
      if (block.walk<Order>(callback).wasInterrupted())
        return WalkResult::interrupt();
    return WalkResult::advance();
  }

  //===--------------------------------------------------------------------===//
  // CFG view utilities
  //===--------------------------------------------------------------------===//

  /// Displays the CFG in a window. This is for use from the debugger and
  /// depends on Graphviz to generate the graph.
  /// This function is defined in ViewOpGraph.cpp and only works with that
  /// target linked.
  void viewGraph(const Twine &regionName);
  void viewGraph();

private:
  BlockListType blocks;

  /// This is the object we are part of.
  Operation *container = nullptr;
};

/// This class provides an abstraction over the different types of ranges over
/// Regions. In many cases, this prevents the need to explicitly materialize a
/// SmallVector/std::vector. This class should be used in places that are not
/// suitable for a more derived type (e.g. ArrayRef) or a template range
/// parameter.
class RegionRange
    : public llvm::detail::indexed_accessor_range_base<
          RegionRange, PointerUnion<Region *, const std::unique_ptr<Region> *>,
          Region *, Region *, Region *> {
  /// The type representing the owner of this range. This is either a list of
  /// values, operands, or results.
  using OwnerT = PointerUnion<Region *, const std::unique_ptr<Region> *>;

public:
  using RangeBaseT::RangeBaseT;

  RegionRange(MutableArrayRef<Region> regions = llvm::None);

  template <typename Arg,
            typename = typename std::enable_if_t<std::is_constructible<
                ArrayRef<std::unique_ptr<Region>>, Arg>::value>>
  RegionRange(Arg &&arg)
      : RegionRange(ArrayRef<std::unique_ptr<Region>>(std::forward<Arg>(arg))) {
  }
  RegionRange(ArrayRef<std::unique_ptr<Region>> regions);

private:
  /// See `llvm::detail::indexed_accessor_range_base` for details.
  static OwnerT offset_base(const OwnerT &owner, ptrdiff_t index);
  /// See `llvm::detail::indexed_accessor_range_base` for details.
  static Region *dereference_iterator(const OwnerT &owner, ptrdiff_t index);

  /// Allow access to `offset_base` and `dereference_iterator`.
  friend RangeBaseT;
};

} // end namespace mlir

#endif // MLIR_IR_REGION_H
