// Copyright 2014 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_INSTRUCTION_SELECTOR_IMPL_H_
#define V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_

#include "src/compiler/instruction.h"
#include "src/compiler/instruction-selector.h"
#include "src/compiler/linkage.h"
#include "src/macro-assembler.h"

namespace v8 {
namespace internal {
namespace compiler {

// A helper class for the instruction selector that simplifies construction of
// Operands. This class implements a base for architecture-specific helpers.
class OperandGenerator {
 public:
  explicit OperandGenerator(InstructionSelector* selector)
      : selector_(selector) {}

  InstructionOperand* DefineAsRegister(Node* node) {
    return Define(node, new (zone())
                  UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER));
  }

  InstructionOperand* DefineSameAsFirst(Node* result) {
    return Define(result, new (zone())
                  UnallocatedOperand(UnallocatedOperand::SAME_AS_FIRST_INPUT));
  }

  InstructionOperand* DefineAsFixed(Node* node, Register reg) {
    return Define(node, new (zone())
                  UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
                                     Register::ToAllocationIndex(reg)));
  }

  InstructionOperand* DefineAsFixed(Node* node, DoubleRegister reg) {
    return Define(node, new (zone())
                  UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
                                     DoubleRegister::ToAllocationIndex(reg)));
  }

  InstructionOperand* DefineAsConstant(Node* node) {
    selector()->MarkAsDefined(node);
    int virtual_register = selector_->GetVirtualRegister(node);
    sequence()->AddConstant(virtual_register, ToConstant(node));
    return ConstantOperand::Create(virtual_register, zone());
  }

  InstructionOperand* DefineAsLocation(Node* node, LinkageLocation location,
                                       MachineType type) {
    return Define(node, ToUnallocatedOperand(location, type));
  }

  InstructionOperand* Use(Node* node) {
    return Use(
        node, new (zone()) UnallocatedOperand(
                  UnallocatedOperand::NONE, UnallocatedOperand::USED_AT_START));
  }

  InstructionOperand* UseRegister(Node* node) {
    return Use(node, new (zone())
               UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
                                  UnallocatedOperand::USED_AT_START));
  }

  // Use register or operand for the node. If a register is chosen, it won't
  // alias any temporary or output registers.
  InstructionOperand* UseUnique(Node* node) {
    return Use(node, new (zone()) UnallocatedOperand(UnallocatedOperand::NONE));
  }

  // Use a unique register for the node that does not alias any temporary or
  // output registers.
  InstructionOperand* UseUniqueRegister(Node* node) {
    return Use(node, new (zone())
               UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER));
  }

  InstructionOperand* UseFixed(Node* node, Register reg) {
    return Use(node, new (zone())
               UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
                                  Register::ToAllocationIndex(reg)));
  }

  InstructionOperand* UseFixed(Node* node, DoubleRegister reg) {
    return Use(node, new (zone())
               UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
                                  DoubleRegister::ToAllocationIndex(reg)));
  }

  InstructionOperand* UseImmediate(Node* node) {
    int index = sequence()->AddImmediate(ToConstant(node));
    return ImmediateOperand::Create(index, zone());
  }

  InstructionOperand* UseLocation(Node* node, LinkageLocation location,
                                  MachineType type) {
    return Use(node, ToUnallocatedOperand(location, type));
  }

  InstructionOperand* TempRegister() {
    UnallocatedOperand* op =
        new (zone()) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
                                        UnallocatedOperand::USED_AT_START);
    op->set_virtual_register(sequence()->NextVirtualRegister());
    return op;
  }

  InstructionOperand* TempDoubleRegister() {
    UnallocatedOperand* op =
        new (zone()) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
                                        UnallocatedOperand::USED_AT_START);
    op->set_virtual_register(sequence()->NextVirtualRegister());
    sequence()->MarkAsDouble(op->virtual_register());
    return op;
  }

  InstructionOperand* TempRegister(Register reg) {
    return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
                                           Register::ToAllocationIndex(reg));
  }

  InstructionOperand* TempImmediate(int32_t imm) {
    int index = sequence()->AddImmediate(Constant(imm));
    return ImmediateOperand::Create(index, zone());
  }

  InstructionOperand* TempLocation(LinkageLocation location, MachineType type) {
    UnallocatedOperand* op = ToUnallocatedOperand(location, type);
    op->set_virtual_register(sequence()->NextVirtualRegister());
    return op;
  }

  InstructionOperand* Label(BasicBlock* block) {
    int index = sequence()->AddImmediate(Constant(block->GetRpoNumber()));
    return ImmediateOperand::Create(index, zone());
  }

 protected:
  InstructionSelector* selector() const { return selector_; }
  InstructionSequence* sequence() const { return selector()->sequence(); }
  Isolate* isolate() const { return zone()->isolate(); }
  Zone* zone() const { return selector()->instruction_zone(); }

 private:
  static Constant ToConstant(const Node* node) {
    switch (node->opcode()) {
      case IrOpcode::kInt32Constant:
        return Constant(OpParameter<int32_t>(node));
      case IrOpcode::kInt64Constant:
        return Constant(OpParameter<int64_t>(node));
      case IrOpcode::kFloat32Constant:
        return Constant(OpParameter<float>(node));
      case IrOpcode::kFloat64Constant:
      case IrOpcode::kNumberConstant:
        return Constant(OpParameter<double>(node));
      case IrOpcode::kExternalConstant:
        return Constant(OpParameter<ExternalReference>(node));
      case IrOpcode::kHeapConstant:
        return Constant(OpParameter<Unique<HeapObject> >(node).handle());
      default:
        break;
    }
    UNREACHABLE();
    return Constant(static_cast<int32_t>(0));
  }

  UnallocatedOperand* Define(Node* node, UnallocatedOperand* operand) {
    DCHECK_NOT_NULL(node);
    DCHECK_NOT_NULL(operand);
    operand->set_virtual_register(selector_->GetVirtualRegister(node));
    selector()->MarkAsDefined(node);
    return operand;
  }

  UnallocatedOperand* Use(Node* node, UnallocatedOperand* operand) {
    DCHECK_NOT_NULL(node);
    DCHECK_NOT_NULL(operand);
    operand->set_virtual_register(selector_->GetVirtualRegister(node));
    selector()->MarkAsUsed(node);
    return operand;
  }

  UnallocatedOperand* ToUnallocatedOperand(LinkageLocation location,
                                           MachineType type) {
    if (location.location_ == LinkageLocation::ANY_REGISTER) {
      return new (zone())
          UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER);
    }
    if (location.location_ < 0) {
      return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
                                             location.location_);
    }
    if (RepresentationOf(type) == kRepFloat64) {
      return new (zone()) UnallocatedOperand(
          UnallocatedOperand::FIXED_DOUBLE_REGISTER, location.location_);
    }
    return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
                                           location.location_);
  }

  InstructionSelector* selector_;
};


// The flags continuation is a way to combine a branch or a materialization
// of a boolean value with an instruction that sets the flags register.
// The whole instruction is treated as a unit by the register allocator, and
// thus no spills or moves can be introduced between the flags-setting
// instruction and the branch or set it should be combined with.
class FlagsContinuation FINAL {
 public:
  FlagsContinuation() : mode_(kFlags_none) {}

  // Creates a new flags continuation from the given condition and true/false
  // blocks.
  FlagsContinuation(FlagsCondition condition, BasicBlock* true_block,
                    BasicBlock* false_block)
      : mode_(kFlags_branch),
        condition_(condition),
        true_block_(true_block),
        false_block_(false_block) {
    DCHECK_NOT_NULL(true_block);
    DCHECK_NOT_NULL(false_block);
  }

  // Creates a new flags continuation from the given condition and result node.
  FlagsContinuation(FlagsCondition condition, Node* result)
      : mode_(kFlags_set), condition_(condition), result_(result) {
    DCHECK_NOT_NULL(result);
  }

  bool IsNone() const { return mode_ == kFlags_none; }
  bool IsBranch() const { return mode_ == kFlags_branch; }
  bool IsSet() const { return mode_ == kFlags_set; }
  FlagsCondition condition() const {
    DCHECK(!IsNone());
    return condition_;
  }
  Node* result() const {
    DCHECK(IsSet());
    return result_;
  }
  BasicBlock* true_block() const {
    DCHECK(IsBranch());
    return true_block_;
  }
  BasicBlock* false_block() const {
    DCHECK(IsBranch());
    return false_block_;
  }

  void Negate() {
    DCHECK(!IsNone());
    condition_ = NegateFlagsCondition(condition_);
  }

  void Commute() {
    DCHECK(!IsNone());
    switch (condition_) {
      case kEqual:
      case kNotEqual:
      case kOverflow:
      case kNotOverflow:
        return;
      case kSignedLessThan:
        condition_ = kSignedGreaterThan;
        return;
      case kSignedGreaterThanOrEqual:
        condition_ = kSignedLessThanOrEqual;
        return;
      case kSignedLessThanOrEqual:
        condition_ = kSignedGreaterThanOrEqual;
        return;
      case kSignedGreaterThan:
        condition_ = kSignedLessThan;
        return;
      case kUnsignedLessThan:
        condition_ = kUnsignedGreaterThan;
        return;
      case kUnsignedGreaterThanOrEqual:
        condition_ = kUnsignedLessThanOrEqual;
        return;
      case kUnsignedLessThanOrEqual:
        condition_ = kUnsignedGreaterThanOrEqual;
        return;
      case kUnsignedGreaterThan:
        condition_ = kUnsignedLessThan;
        return;
      case kUnorderedEqual:
      case kUnorderedNotEqual:
        return;
      case kUnorderedLessThan:
        condition_ = kUnorderedGreaterThan;
        return;
      case kUnorderedGreaterThanOrEqual:
        condition_ = kUnorderedLessThanOrEqual;
        return;
      case kUnorderedLessThanOrEqual:
        condition_ = kUnorderedGreaterThanOrEqual;
        return;
      case kUnorderedGreaterThan:
        condition_ = kUnorderedLessThan;
        return;
    }
    UNREACHABLE();
  }

  void OverwriteAndNegateIfEqual(FlagsCondition condition) {
    bool negate = condition_ == kEqual;
    condition_ = condition;
    if (negate) Negate();
  }

  // Encodes this flags continuation into the given opcode.
  InstructionCode Encode(InstructionCode opcode) {
    opcode |= FlagsModeField::encode(mode_);
    if (mode_ != kFlags_none) {
      opcode |= FlagsConditionField::encode(condition_);
    }
    return opcode;
  }

 private:
  FlagsMode mode_;
  FlagsCondition condition_;
  Node* result_;             // Only valid if mode_ == kFlags_set.
  BasicBlock* true_block_;   // Only valid if mode_ == kFlags_branch.
  BasicBlock* false_block_;  // Only valid if mode_ == kFlags_branch.
};


// An internal helper class for generating the operands to calls.
// TODO(bmeurer): Get rid of the CallBuffer business and make
// InstructionSelector::VisitCall platform independent instead.
struct CallBuffer {
  CallBuffer(Zone* zone, const CallDescriptor* descriptor,
             FrameStateDescriptor* frame_state);

  const CallDescriptor* descriptor;
  FrameStateDescriptor* frame_state_descriptor;
  NodeVector output_nodes;
  InstructionOperandVector outputs;
  InstructionOperandVector instruction_args;
  NodeVector pushed_nodes;

  size_t input_count() const { return descriptor->InputCount(); }

  size_t frame_state_count() const { return descriptor->FrameStateCount(); }

  size_t frame_state_value_count() const {
    return (frame_state_descriptor == NULL)
               ? 0
               : (frame_state_descriptor->GetTotalSize() +
                  1);  // Include deopt id.
  }
};

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

#endif  // V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_
