// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_COMPILER_SCHEDULE_H_
#define V8_COMPILER_SCHEDULE_H_

#include <iosfwd>

#include "src/base/compiler-specific.h"
#include "src/common/globals.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {
namespace compiler {

// Forward declarations.
class BasicBlock;
class BasicBlockInstrumentor;
class Node;

using BasicBlockVector = ZoneVector<BasicBlock*>;
using NodeVector = ZoneVector<Node*>;

// A basic block contains an ordered list of nodes and ends with a control
// node. Note that if a basic block has phis, then all phis must appear as the
// first nodes in the block.
class V8_EXPORT_PRIVATE BasicBlock final
    : public NON_EXPORTED_BASE(ZoneObject) {
 public:
  // Possible control nodes that can end a block.
  enum Control {
    kNone,        // Control not initialized yet.
    kGoto,        // Goto a single successor block.
    kCall,        // Call with continuation as first successor, exception
                  // second.
    kBranch,      // Branch if true to first successor, otherwise second.
    kSwitch,      // Table dispatch to one of the successor blocks.
    kDeoptimize,  // Return a value from this method.
    kTailCall,    // Tail call another method from this method.
    kReturn,      // Return a value from this method.
    kThrow        // Throw an exception.
  };

  class Id {
   public:
    int ToInt() const { return static_cast<int>(index_); }
    size_t ToSize() const { return index_; }
    static Id FromSize(size_t index) { return Id(index); }
    static Id FromInt(int index) { return Id(static_cast<size_t>(index)); }

   private:
    explicit Id(size_t index) : index_(index) {}
    size_t index_;
  };

  BasicBlock(Zone* zone, Id id);
  BasicBlock(const BasicBlock&) = delete;
  BasicBlock& operator=(const BasicBlock&) = delete;

  Id id() const { return id_; }
#if DEBUG
  void set_debug_info(AssemblerDebugInfo debug_info) {
    debug_info_ = debug_info;
  }
  AssemblerDebugInfo debug_info() const { return debug_info_; }
#endif  // DEBUG

  void Print();

  // Predecessors.
  BasicBlockVector& predecessors() { return predecessors_; }
  const BasicBlockVector& predecessors() const { return predecessors_; }
  size_t PredecessorCount() const { return predecessors_.size(); }
  BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; }
  void ClearPredecessors() { predecessors_.clear(); }
  void AddPredecessor(BasicBlock* predecessor);
  void RemovePredecessor(size_t index);

  // Successors.
  BasicBlockVector& successors() { return successors_; }
  const BasicBlockVector& successors() const { return successors_; }
  size_t SuccessorCount() const { return successors_.size(); }
  BasicBlock* SuccessorAt(size_t index) { return successors_[index]; }
  void ClearSuccessors() { successors_.clear(); }
  void AddSuccessor(BasicBlock* successor);

  // Nodes in the basic block.
  using value_type = Node*;
  bool empty() const { return nodes_.empty(); }
  size_t size() const { return nodes_.size(); }
  Node* NodeAt(size_t index) { return nodes_[index]; }
  size_t NodeCount() const { return nodes_.size(); }

  value_type& front() { return nodes_.front(); }
  value_type const& front() const { return nodes_.front(); }

  using iterator = NodeVector::iterator;
  iterator begin() { return nodes_.begin(); }
  iterator end() { return nodes_.end(); }

  void RemoveNode(iterator it) { nodes_.erase(it); }

  using const_iterator = NodeVector::const_iterator;
  const_iterator begin() const { return nodes_.begin(); }
  const_iterator end() const { return nodes_.end(); }

  using reverse_iterator = NodeVector::reverse_iterator;
  reverse_iterator rbegin() { return nodes_.rbegin(); }
  reverse_iterator rend() { return nodes_.rend(); }

  void AddNode(Node* node);
  template <class InputIterator>
  void InsertNodes(iterator insertion_point, InputIterator insertion_start,
                   InputIterator insertion_end) {
    nodes_.insert(insertion_point, insertion_start, insertion_end);
  }

  // Trim basic block to end at {new_end}.
  void TrimNodes(iterator new_end);

  void ResetRPOInfo();

  // Accessors.
  Control control() const { return control_; }
  void set_control(Control control);

  Node* control_input() const { return control_input_; }
  void set_control_input(Node* control_input);

  bool deferred() const { return deferred_; }
  void set_deferred(bool deferred) { deferred_ = deferred; }

  int32_t dominator_depth() const { return dominator_depth_; }
  void set_dominator_depth(int32_t depth) { dominator_depth_ = depth; }

  BasicBlock* dominator() const { return dominator_; }
  void set_dominator(BasicBlock* dominator) { dominator_ = dominator; }

  BasicBlock* rpo_next() const { return rpo_next_; }
  void set_rpo_next(BasicBlock* rpo_next) { rpo_next_ = rpo_next; }

  BasicBlock* loop_header() const { return loop_header_; }
  void set_loop_header(BasicBlock* loop_header);

  BasicBlock* loop_end() const { return loop_end_; }
  void set_loop_end(BasicBlock* loop_end);

  int32_t loop_depth() const { return loop_depth_; }
  void set_loop_depth(int32_t loop_depth);

  int32_t loop_number() const { return loop_number_; }
  void set_loop_number(int32_t loop_number) { loop_number_ = loop_number; }

  int32_t rpo_number() const { return rpo_number_; }
  void set_rpo_number(int32_t rpo_number);

  NodeVector* nodes() { return &nodes_; }

  // Loop membership helpers.
  inline bool IsLoopHeader() const { return loop_end_ != nullptr; }
  bool LoopContains(BasicBlock* block) const;

  // Computes the immediate common dominator of {b1} and {b2}. The worst time
  // complexity is O(N) where N is the height of the dominator tree.
  static BasicBlock* GetCommonDominator(BasicBlock* b1, BasicBlock* b2);

 private:
  int32_t loop_number_;      // loop number of the block.
  int32_t rpo_number_;       // special RPO number of the block.
  bool deferred_;            // true if the block contains deferred code.
  int32_t dominator_depth_;  // Depth within the dominator tree.
  BasicBlock* dominator_;    // Immediate dominator of the block.
  BasicBlock* rpo_next_;     // Link to next block in special RPO order.
  BasicBlock* loop_header_;  // Pointer to dominating loop header basic block,
  // nullptr if none. For loop headers, this points to
  // enclosing loop header.
  BasicBlock* loop_end_;  // end of the loop, if this block is a loop header.
  int32_t loop_depth_;    // loop nesting, 0 is top-level

  Control control_;      // Control at the end of the block.
  Node* control_input_;  // Input value for control.
  NodeVector nodes_;     // nodes of this block in forward order.

  BasicBlockVector successors_;
  BasicBlockVector predecessors_;
#if DEBUG
  AssemblerDebugInfo debug_info_;
#endif
  Id id_;
};

std::ostream& operator<<(std::ostream&, const BasicBlock&);
std::ostream& operator<<(std::ostream&, const BasicBlock::Control&);
std::ostream& operator<<(std::ostream&, const BasicBlock::Id&);

// A schedule represents the result of assigning nodes to basic blocks
// and ordering them within basic blocks. Prior to computing a schedule,
// a graph has no notion of control flow ordering other than that induced
// by the graph's dependencies. A schedule is required to generate code.
class V8_EXPORT_PRIVATE Schedule final : public NON_EXPORTED_BASE(ZoneObject) {
 public:
  explicit Schedule(Zone* zone, size_t node_count_hint = 0);
  Schedule(const Schedule&) = delete;
  Schedule& operator=(const Schedule&) = delete;

  // Return the block which contains {node}, if any.
  BasicBlock* block(Node* node) const;

  bool IsScheduled(Node* node);
  BasicBlock* GetBlockById(BasicBlock::Id block_id);
  void ClearBlockById(BasicBlock::Id block_id);

  size_t BasicBlockCount() const { return all_blocks_.size(); }
  size_t RpoBlockCount() const { return rpo_order_.size(); }

  // Check if nodes {a} and {b} are in the same block.
  bool SameBasicBlock(Node* a, Node* b) const;

  // BasicBlock building: create a new block.
  BasicBlock* NewBasicBlock();

  // BasicBlock building: records that a node will later be added to a block but
  // doesn't actually add the node to the block.
  void PlanNode(BasicBlock* block, Node* node);

  // BasicBlock building: add a node to the end of the block.
  void AddNode(BasicBlock* block, Node* node);

  // BasicBlock building: add a goto to the end of {block}.
  void AddGoto(BasicBlock* block, BasicBlock* succ);

  // BasicBlock building: add a call at the end of {block}.
  void AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
               BasicBlock* exception_block);

  // BasicBlock building: add a branch at the end of {block}.
  void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
                 BasicBlock* fblock);

  // BasicBlock building: add a switch at the end of {block}.
  void AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
                 size_t succ_count);

  // BasicBlock building: add a deoptimize at the end of {block}.
  void AddDeoptimize(BasicBlock* block, Node* input);

  // BasicBlock building: add a tailcall at the end of {block}.
  void AddTailCall(BasicBlock* block, Node* input);

  // BasicBlock building: add a return at the end of {block}.
  void AddReturn(BasicBlock* block, Node* input);

  // BasicBlock building: add a throw at the end of {block}.
  void AddThrow(BasicBlock* block, Node* input);

  // BasicBlock mutation: insert a branch into the end of {block}.
  void InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
                    BasicBlock* tblock, BasicBlock* fblock);

  // BasicBlock mutation: insert a switch into the end of {block}.
  void InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
                    BasicBlock** succ_blocks, size_t succ_count);

  // Exposed publicly for testing only.
  void AddSuccessorForTesting(BasicBlock* block, BasicBlock* succ) {
    return AddSuccessor(block, succ);
  }

  const BasicBlockVector* all_blocks() const { return &all_blocks_; }
  BasicBlockVector* rpo_order() { return &rpo_order_; }
  const BasicBlockVector* rpo_order() const { return &rpo_order_; }

  BasicBlock* start() { return start_; }
  BasicBlock* end() { return end_; }

  Zone* zone() const { return zone_; }

 private:
  friend class GraphAssembler;
  friend class Scheduler;
  friend class BasicBlockInstrumentor;
  friend class RawMachineAssembler;

  // For CSA/Torque: Ensure properties of the CFG assumed by further stages.
  void EnsureCFGWellFormedness();
  // For CSA/Torque: Eliminates unnecessary phi nodes, including phis with a
  // single input. The latter is necessary to ensure the property required for
  // SSA deconstruction that the target block of a control flow split has no
  // phis.
  void EliminateRedundantPhiNodes();
  // Ensure split-edge form for a hand-assembled schedule.
  void EnsureSplitEdgeForm(BasicBlock* block);
  // Move Phi operands to newly created merger blocks
  void MovePhis(BasicBlock* from, BasicBlock* to);
  // Copy deferred block markers down as far as possible
  void PropagateDeferredMark();

  void AddSuccessor(BasicBlock* block, BasicBlock* succ);
  void MoveSuccessors(BasicBlock* from, BasicBlock* to);

  void SetControlInput(BasicBlock* block, Node* node);
  void SetBlockForNode(BasicBlock* block, Node* node);

  Zone* zone_;
  BasicBlockVector all_blocks_;       // All basic blocks in the schedule.
  BasicBlockVector nodeid_to_block_;  // Map from node to containing block.
  BasicBlockVector rpo_order_;        // Reverse-post-order block list.
  BasicBlock* start_;
  BasicBlock* end_;
};

V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, const Schedule&);

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_SCHEDULE_H_
