// 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.

#include "src/interpreter/bytecode-decoder.h"

#include <iomanip>

#include "src/interpreter/interpreter-intrinsics.h"
#include "src/objects/contexts.h"
#include "src/objects/objects-inl.h"

namespace v8 {
namespace internal {
namespace interpreter {

// static
Register BytecodeDecoder::DecodeRegisterOperand(Address operand_start,
                                                OperandType operand_type,
                                                OperandScale operand_scale) {
  DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
  int32_t operand =
      DecodeSignedOperand(operand_start, operand_type, operand_scale);
  return Register::FromOperand(operand);
}

// static
RegisterList BytecodeDecoder::DecodeRegisterListOperand(
    Address operand_start, uint32_t count, OperandType operand_type,
    OperandScale operand_scale) {
  Register first_reg =
      DecodeRegisterOperand(operand_start, operand_type, operand_scale);
  return RegisterList(first_reg.index(), static_cast<int>(count));
}

// static
int32_t BytecodeDecoder::DecodeSignedOperand(Address operand_start,
                                             OperandType operand_type,
                                             OperandScale operand_scale) {
  DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
  switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
    case OperandSize::kByte:
      return *reinterpret_cast<const int8_t*>(operand_start);
    case OperandSize::kShort:
      return static_cast<int16_t>(
          base::ReadUnalignedValue<uint16_t>(operand_start));
    case OperandSize::kQuad:
      return static_cast<int32_t>(
          base::ReadUnalignedValue<uint32_t>(operand_start));
    case OperandSize::kNone:
      UNREACHABLE();
  }
  return 0;
}

// static
uint32_t BytecodeDecoder::DecodeUnsignedOperand(Address operand_start,
                                                OperandType operand_type,
                                                OperandScale operand_scale) {
  DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
  switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
    case OperandSize::kByte:
      return *reinterpret_cast<const uint8_t*>(operand_start);
    case OperandSize::kShort:
      return base::ReadUnalignedValue<uint16_t>(operand_start);
    case OperandSize::kQuad:
      return base::ReadUnalignedValue<uint32_t>(operand_start);
    case OperandSize::kNone:
      UNREACHABLE();
  }
  return 0;
}

namespace {

const char* NameForRuntimeId(Runtime::FunctionId idx) {
  return Runtime::FunctionForId(idx)->name;
}

const char* NameForNativeContextIndex(uint32_t idx) {
  switch (idx) {
#define CASE(index_name, type, name) \
  case Context::index_name:          \
    return #name;
    NATIVE_CONTEXT_FIELDS(CASE)
#undef CASE
    default:
      UNREACHABLE();
  }
}

}  // anonymous namespace

// static
std::ostream& BytecodeDecoder::Decode(std::ostream& os,
                                      const uint8_t* bytecode_start,
                                      int parameter_count) {
  Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
  int prefix_offset = 0;
  OperandScale operand_scale = OperandScale::kSingle;
  if (Bytecodes::IsPrefixScalingBytecode(bytecode)) {
    prefix_offset = 1;
    operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode);
    bytecode = Bytecodes::FromByte(bytecode_start[1]);
  }

  // Prepare to print bytecode and operands as hex digits.
  std::ios saved_format(nullptr);
  saved_format.copyfmt(saved_format);
  os.fill('0');
  os.flags(std::ios::hex);

  int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
  for (int i = 0; i < prefix_offset + bytecode_size; i++) {
    os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
  }
  os.copyfmt(saved_format);

  const int kBytecodeColumnSize = 6;
  for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
    os << "   ";
  }

  os << Bytecodes::ToString(bytecode, operand_scale) << " ";

  // Operands for the debug break are from the original instruction.
  if (Bytecodes::IsDebugBreak(bytecode)) return os;

  int number_of_operands = Bytecodes::NumberOfOperands(bytecode);
  for (int i = 0; i < number_of_operands; i++) {
    OperandType op_type = Bytecodes::GetOperandType(bytecode, i);
    int operand_offset =
        Bytecodes::GetOperandOffset(bytecode, i, operand_scale);
    Address operand_start = reinterpret_cast<Address>(
        &bytecode_start[prefix_offset + operand_offset]);
    switch (op_type) {
      case interpreter::OperandType::kIdx:
      case interpreter::OperandType::kUImm:
        os << "["
           << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
           << "]";
        break;
      case interpreter::OperandType::kIntrinsicId: {
        auto id = static_cast<IntrinsicsHelper::IntrinsicId>(
            DecodeUnsignedOperand(operand_start, op_type, operand_scale));
        os << "[" << NameForRuntimeId(IntrinsicsHelper::ToRuntimeId(id)) << "]";
        break;
      }
      case interpreter::OperandType::kNativeContextIndex: {
        auto id = DecodeUnsignedOperand(operand_start, op_type, operand_scale);
        os << "[" << NameForNativeContextIndex(id) << "]";
        break;
      }
      case interpreter::OperandType::kRuntimeId:
        os << "["
           << NameForRuntimeId(static_cast<Runtime::FunctionId>(
                  DecodeUnsignedOperand(operand_start, op_type, operand_scale)))
           << "]";
        break;
      case interpreter::OperandType::kImm:
        os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
           << "]";
        break;
      case interpreter::OperandType::kFlag8:
        os << "#"
           << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
        break;
      case interpreter::OperandType::kReg:
      case interpreter::OperandType::kRegOut: {
        Register reg =
            DecodeRegisterOperand(operand_start, op_type, operand_scale);
        os << reg.ToString(parameter_count);
        break;
      }
      case interpreter::OperandType::kRegOutTriple: {
        RegisterList reg_list =
            DecodeRegisterListOperand(operand_start, 3, op_type, operand_scale);
        os << reg_list.first_register().ToString(parameter_count) << "-"
           << reg_list.last_register().ToString(parameter_count);
        break;
      }
      case interpreter::OperandType::kRegOutPair:
      case interpreter::OperandType::kRegPair: {
        RegisterList reg_list =
            DecodeRegisterListOperand(operand_start, 2, op_type, operand_scale);
        os << reg_list.first_register().ToString(parameter_count) << "-"
           << reg_list.last_register().ToString(parameter_count);
        break;
      }
      case interpreter::OperandType::kRegOutList:
      case interpreter::OperandType::kRegList: {
        DCHECK_LT(i, number_of_operands - 1);
        DCHECK_EQ(Bytecodes::GetOperandType(bytecode, i + 1),
                  OperandType::kRegCount);
        int reg_count_offset =
            Bytecodes::GetOperandOffset(bytecode, i + 1, operand_scale);
        Address reg_count_operand = reinterpret_cast<Address>(
            &bytecode_start[prefix_offset + reg_count_offset]);
        uint32_t count = DecodeUnsignedOperand(
            reg_count_operand, OperandType::kRegCount, operand_scale);
        RegisterList reg_list = DecodeRegisterListOperand(
            operand_start, count, op_type, operand_scale);
        os << reg_list.first_register().ToString(parameter_count) << "-"
           << reg_list.last_register().ToString(parameter_count);
        i++;  // Skip kRegCount.
        break;
      }
      case interpreter::OperandType::kNone:
      case interpreter::OperandType::kRegCount:  // Dealt with in kRegList.
        UNREACHABLE();
        break;
    }
    if (i != number_of_operands - 1) {
      os << ", ";
    }
  }
  return os;
}

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