// Copyright 2015 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_INTERPRETER_BYTECODE_PIPELINE_H_
#define V8_INTERPRETER_BYTECODE_PIPELINE_H_

#include "src/interpreter/bytecode-register-allocator.h"
#include "src/interpreter/bytecode-register.h"
#include "src/interpreter/bytecodes.h"
#include "src/objects.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {
namespace interpreter {

class BytecodeLabel;
class BytecodeNode;
class BytecodeSourceInfo;

// Interface for bytecode pipeline stages.
class BytecodePipelineStage {
 public:
  virtual ~BytecodePipelineStage() {}

  // Write bytecode node |node| into pipeline. The node is only valid
  // for the duration of the call. Callee's should clone it if
  // deferring Write() to the next stage.
  virtual void Write(BytecodeNode* node) = 0;

  // Write jump bytecode node |node| which jumps to |label| into pipeline.
  // The node and label are only valid for the duration of the call. This call
  // implicitly ends the current basic block so should always write to the next
  // stage.
  virtual void WriteJump(BytecodeNode* node, BytecodeLabel* label) = 0;

  // Binds |label| to the current bytecode location. This call implicitly
  // ends the current basic block and so any deferred bytecodes should be
  // written to the next stage.
  virtual void BindLabel(BytecodeLabel* label) = 0;

  // Binds |label| to the location of |target|. This call implicitly
  // ends the current basic block and so any deferred bytecodes should be
  // written to the next stage.
  virtual void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) = 0;

  // Flush the pipeline and generate a bytecode array.
  virtual Handle<BytecodeArray> ToBytecodeArray(
      Isolate* isolate, int fixed_register_count, int parameter_count,
      Handle<FixedArray> handler_table) = 0;
};

// Source code position information.
class BytecodeSourceInfo final {
 public:
  static const int kUninitializedPosition = -1;

  BytecodeSourceInfo()
      : position_type_(PositionType::kNone),
        source_position_(kUninitializedPosition) {}

  BytecodeSourceInfo(int source_position, bool is_statement)
      : position_type_(is_statement ? PositionType::kStatement
                                    : PositionType::kExpression),
        source_position_(source_position) {
    DCHECK_GE(source_position, 0);
  }

  // Makes instance into a statement position.
  void MakeStatementPosition(int source_position) {
    // Statement positions can be replaced by other statement
    // positions. For example , "for (x = 0; x < 3; ++x) 7;" has a
    // statement position associated with 7 but no bytecode associated
    // with it. Then Next is emitted after the body and has
    // statement position and overrides the existing one.
    position_type_ = PositionType::kStatement;
    source_position_ = source_position;
  }

  // Makes instance into an expression position. Instance should not
  // be a statement position otherwise it could be lost and impair the
  // debugging experience.
  void MakeExpressionPosition(int source_position) {
    DCHECK(!is_statement());
    position_type_ = PositionType::kExpression;
    source_position_ = source_position;
  }

  // Forces an instance into an expression position.
  void ForceExpressionPosition(int source_position) {
    position_type_ = PositionType::kExpression;
    source_position_ = source_position;
  }

  // Clones a source position. The current instance is expected to be
  // invalid.
  void Clone(const BytecodeSourceInfo& other) {
    DCHECK(!is_valid());
    position_type_ = other.position_type_;
    source_position_ = other.source_position_;
  }

  int source_position() const {
    DCHECK(is_valid());
    return source_position_;
  }

  bool is_statement() const {
    return position_type_ == PositionType::kStatement;
  }
  bool is_expression() const {
    return position_type_ == PositionType::kExpression;
  }

  bool is_valid() const { return position_type_ != PositionType::kNone; }
  void set_invalid() {
    position_type_ = PositionType::kNone;
    source_position_ = kUninitializedPosition;
  }

  bool operator==(const BytecodeSourceInfo& other) const {
    return position_type_ == other.position_type_ &&
           source_position_ == other.source_position_;
  }

  bool operator!=(const BytecodeSourceInfo& other) const {
    return position_type_ != other.position_type_ ||
           source_position_ != other.source_position_;
  }

 private:
  enum class PositionType : uint8_t { kNone, kExpression, kStatement };

  PositionType position_type_;
  int source_position_;

  DISALLOW_COPY_AND_ASSIGN(BytecodeSourceInfo);
};

// A container for a generated bytecode, it's operands, and source information.
// These must be allocated by a BytecodeNodeAllocator instance.
class BytecodeNode final : ZoneObject {
 public:
  explicit BytecodeNode(Bytecode bytecode = Bytecode::kIllegal);
  BytecodeNode(Bytecode bytecode, uint32_t operand0);
  BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1);
  BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
               uint32_t operand2);
  BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
               uint32_t operand2, uint32_t operand3);

  BytecodeNode(const BytecodeNode& other);
  BytecodeNode& operator=(const BytecodeNode& other);

  // Replace the bytecode of this node with |bytecode| and keep the operands.
  void replace_bytecode(Bytecode bytecode) {
    DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode_),
              Bytecodes::NumberOfOperands(bytecode));
    bytecode_ = bytecode;
  }
  void set_bytecode(Bytecode bytecode) {
    DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
    bytecode_ = bytecode;
  }
  void set_bytecode(Bytecode bytecode, uint32_t operand0) {
    DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1);
    bytecode_ = bytecode;
    operands_[0] = operand0;
  }
  void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1) {
    DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2);
    bytecode_ = bytecode;
    operands_[0] = operand0;
    operands_[1] = operand1;
  }
  void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
                    uint32_t operand2) {
    DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3);
    bytecode_ = bytecode;
    operands_[0] = operand0;
    operands_[1] = operand1;
    operands_[2] = operand2;
  }

  // Clone |other|.
  void Clone(const BytecodeNode* const other);

  // Print to stream |os|.
  void Print(std::ostream& os) const;

  // Transform to a node representing |new_bytecode| which has one
  // operand more than the current bytecode.
  void Transform(Bytecode new_bytecode, uint32_t extra_operand);

  Bytecode bytecode() const { return bytecode_; }

  uint32_t operand(int i) const {
    DCHECK_LT(i, operand_count());
    return operands_[i];
  }
  uint32_t* operands() { return operands_; }
  const uint32_t* operands() const { return operands_; }

  int operand_count() const { return Bytecodes::NumberOfOperands(bytecode_); }

  const BytecodeSourceInfo& source_info() const { return source_info_; }
  BytecodeSourceInfo& source_info() { return source_info_; }

  bool operator==(const BytecodeNode& other) const;
  bool operator!=(const BytecodeNode& other) const { return !(*this == other); }

 private:
  static const int kInvalidPosition = kMinInt;

  Bytecode bytecode_;
  uint32_t operands_[Bytecodes::kMaxOperands];
  BytecodeSourceInfo source_info_;
};

std::ostream& operator<<(std::ostream& os, const BytecodeSourceInfo& info);
std::ostream& operator<<(std::ostream& os, const BytecodeNode& node);

}  // namespace interpreter
}  // namespace internal
}  // namespace v8

#endif  // V8_INTERPRETER_BYTECODE_PIPELINE_H_
