/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_
#define ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_

#include "compiler_ir.h"
#include "mir_graph.h"

namespace art {

  /*
   * This class supports iterating over lists of basic blocks in various
   * interesting orders.  Note that for efficiency, the visit orders have been pre-computed.
   * The order itself will not change during the iteration.  However, for some uses,
   * auxiliary data associated with the basic blocks may be changed during the iteration,
   * necessitating another pass over the list.
   *
   * To support this usage, we have is_iterative_.  If false, the iteration is a one-shot
   * pass through the pre-computed list using Next().  If true, the caller must tell the
   * iterator whether a change has been made that necessitates another pass.  Use
   * Next(had_change) for this.  The general idea is that the iterative_ use case means
   * that the iterator will keep repeating the full basic block list until a complete pass
   * is made through it with no changes.  Note that calling Next(true) does not affect
   * the iteration order or short-curcuit the current pass - it simply tells the iterator
   * that once it has finished walking through the block list it should reset and do another
   * full pass through the list.
   */
  class DataflowIterator {
    public:

      virtual ~DataflowIterator() {}

      // Return the next BasicBlock* to visit.
      BasicBlock* Next() {
        DCHECK(!is_iterative_);
        return NextBody(false);
      }

      /*
       * Return the next BasicBlock* to visit, and tell the iterator whether any change
       * has occurred that requires another full pass over the block list.
       */
      BasicBlock* Next(bool had_change) {
        DCHECK(is_iterative_);
        return NextBody(had_change);
      }

    protected:
      DataflowIterator(MIRGraph* mir_graph, bool is_iterative, int start_idx, int end_idx,
                       bool reverse)
          : mir_graph_(mir_graph),
            is_iterative_(is_iterative),
            start_idx_(start_idx),
            end_idx_(end_idx),
            reverse_(reverse),
            block_id_list_(NULL),
            idx_(0),
            changed_(false) {}

      virtual BasicBlock* NextBody(bool had_change) ALWAYS_INLINE;

      MIRGraph* const mir_graph_;
      const bool is_iterative_;
      const int start_idx_;
      const int end_idx_;
      const bool reverse_;
      GrowableArray<int>* block_id_list_;
      int idx_;
      bool changed_;

  }; // DataflowIterator

  class ReachableNodesIterator : public DataflowIterator {
    public:
      ReachableNodesIterator(MIRGraph* mir_graph, bool is_iterative)
          : DataflowIterator(mir_graph, is_iterative, 0,
                             mir_graph->GetNumReachableBlocks(), false) {
        idx_ = start_idx_;
        block_id_list_ = mir_graph->GetDfsOrder();
      }
  };

  class PreOrderDfsIterator : public DataflowIterator {
    public:
      PreOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
          : DataflowIterator(mir_graph, is_iterative, 0,
                             mir_graph->GetNumReachableBlocks(), false) {
        idx_ = start_idx_;
        block_id_list_ = mir_graph->GetDfsOrder();
      }
  };

  class PostOrderDfsIterator : public DataflowIterator {
    public:

      PostOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
          : DataflowIterator(mir_graph, is_iterative, 0,
                             mir_graph->GetNumReachableBlocks(), false) {
        idx_ = start_idx_;
        block_id_list_ = mir_graph->GetDfsPostOrder();
      }
  };

  class ReversePostOrderDfsIterator : public DataflowIterator {
    public:
      ReversePostOrderDfsIterator(MIRGraph* mir_graph, bool is_iterative)
          : DataflowIterator(mir_graph, is_iterative,
                             mir_graph->GetNumReachableBlocks() -1, 0, true) {
        idx_ = start_idx_;
        block_id_list_ = mir_graph->GetDfsPostOrder();
      }
  };

  class PostOrderDOMIterator : public DataflowIterator {
    public:
      PostOrderDOMIterator(MIRGraph* mir_graph, bool is_iterative)
          : DataflowIterator(mir_graph, is_iterative, 0,
                             mir_graph->GetNumReachableBlocks(), false) {
        idx_ = start_idx_;
        block_id_list_ = mir_graph->GetDomPostOrder();
      }
  };

  class AllNodesIterator : public DataflowIterator {
    public:
      AllNodesIterator(MIRGraph* mir_graph, bool is_iterative)
          : DataflowIterator(mir_graph, is_iterative, 0, 0, false) {
        all_nodes_iterator_ =
            new (mir_graph->GetArena()) GrowableArray<BasicBlock*>::Iterator (mir_graph->GetBlockList());
      }

      void Reset() {
        all_nodes_iterator_->Reset();
      }

      BasicBlock* NextBody(bool had_change) ALWAYS_INLINE;

    private:
      GrowableArray<BasicBlock*>::Iterator* all_nodes_iterator_;
  };

}  // namespace art

#endif  // ART_COMPILER_DEX_DATAFLOW_ITERATOR_H_
