// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/compiler/ffi/native_location.h"

#include "vm/zone_text_buffer.h"

namespace dart {

namespace compiler {

namespace ffi {

#if !defined(FFI_UNIT_TESTS)
bool NativeLocation::LocationCanBeExpressed(Location loc, Representation rep) {
  switch (loc.kind()) {
    case Location::Kind::kRegister:
    case Location::Kind::kFpuRegister:
    case Location::Kind::kStackSlot:
    case Location::Kind::kDoubleStackSlot:
      return true;
    default:
      break;
  }
  if (loc.IsPairLocation()) {
    return false;
  }
  return false;
}

NativeLocation& NativeLocation::FromLocation(Zone* zone,
                                             Location loc,
                                             Representation rep) {
  ASSERT(LocationCanBeExpressed(loc, rep));

  const NativeType& native_rep =
      NativeType::FromUnboxedRepresentation(zone, rep);

  switch (loc.kind()) {
    case Location::Kind::kRegister:
      return *new (zone)
          NativeRegistersLocation(zone, native_rep, native_rep, loc.reg());
    case Location::Kind::kFpuRegister:
      return *new (zone)
          NativeFpuRegistersLocation(native_rep, native_rep, loc.fpu_reg());
    case Location::Kind::kStackSlot:
      return *new (zone)
          NativeStackLocation(native_rep, native_rep, loc.base_reg(),
                              loc.stack_index() * compiler::target::kWordSize);
    case Location::Kind::kDoubleStackSlot:
      return *new (zone)
          NativeStackLocation(native_rep, native_rep, loc.base_reg(),
                              loc.stack_index() * compiler::target::kWordSize);
    default:
      break;
  }

  UNREACHABLE();
}

NativeLocation& NativeLocation::FromPairLocation(Zone* zone,
                                                 Location pair_loc,
                                                 Representation pair_rep,
                                                 intptr_t index) {
  ASSERT(pair_loc.IsPairLocation());
  ASSERT(index == 0 || index == 1);
  const Representation rep =
      NativeType::FromUnboxedRepresentation(zone, pair_rep)
          .Split(zone, index)
          .AsRepresentation();
  const Location loc = pair_loc.AsPairLocation()->At(index);
  return FromLocation(zone, loc, rep);
}
#endif

const NativeRegistersLocation& NativeLocation::AsRegisters() const {
  ASSERT(IsRegisters());
  return static_cast<const NativeRegistersLocation&>(*this);
}

const NativeFpuRegistersLocation& NativeLocation::AsFpuRegisters() const {
  ASSERT(IsFpuRegisters());
  return static_cast<const NativeFpuRegistersLocation&>(*this);
}

const NativeStackLocation& NativeLocation::AsStack() const {
  ASSERT(IsStack());
  return static_cast<const NativeStackLocation&>(*this);
}

const MultipleNativeLocations& NativeLocation::AsMultiple() const {
  ASSERT(IsMultiple());
  return static_cast<const MultipleNativeLocations&>(*this);
}

const PointerToMemoryLocation& NativeLocation::AsPointerToMemory() const {
  ASSERT(IsPointerToMemory());
  return static_cast<const PointerToMemoryLocation&>(*this);
}

#if !defined(FFI_UNIT_TESTS)
Location NativeRegistersLocation::AsLocation() const {
  ASSERT(IsExpressibleAsLocation());
  switch (num_regs()) {
    case 1:
      return Location::RegisterLocation(regs_->At(0));
    case 2:
      return Location::Pair(Location::RegisterLocation(regs_->At(0)),
                            Location::RegisterLocation(regs_->At(1)));
  }
  UNREACHABLE();
}

Location NativeStackLocation::AsLocation() const {
  ASSERT(IsExpressibleAsLocation());
  if (payload_type().IsInt()) {
    const intptr_t size = payload_type().SizeInBytes();
    const intptr_t size_slots = size / compiler::target::kWordSize;
    switch (size_slots) {
      case 1:
        return Location::StackSlot(offset_in_words(), base_register_);
      case 2:
        return Location::Pair(
            Location::StackSlot(offset_in_words(), base_register_),
            Location::StackSlot(offset_in_words() + 1, base_register_));
    }
  } else {
    ASSERT(payload_type().IsFloat());
    if (payload_type().AsPrimitive().representation() == kFloat) {
      return Location::StackSlot(offset_in_words(), base_register_);
    } else {
      ASSERT(payload_type().AsPrimitive().representation() == kDouble);
      return Location::DoubleStackSlot(offset_in_words(), base_register_);
    }
  }
  UNREACHABLE();
}
#endif

NativeRegistersLocation& NativeRegistersLocation::Split(Zone* zone,
                                                        intptr_t num_parts,
                                                        intptr_t index) const {
  ASSERT(num_parts == 2);
  ASSERT(num_regs() == num_parts);
  return *new (zone) NativeRegistersLocation(
      zone, payload_type().Split(zone, index),
      container_type().Split(zone, index), reg_at(index));
}

NativeStackLocation& NativeStackLocation::Split(Zone* zone,
                                                intptr_t num_parts,
                                                intptr_t index) const {
  const intptr_t size = payload_type().SizeInBytes();

  if (payload_type().IsPrimitive()) {
    ASSERT(num_parts == 2);
    return *new (zone) NativeStackLocation(
        payload_type().Split(zone, index), container_type().Split(zone, index),
        base_register_, offset_in_bytes_ + size / num_parts * index);
  } else {
    const intptr_t size_rounded_up =
        Utils::RoundUp(size, compiler::target::kWordSize);
    ASSERT(size_rounded_up / compiler::target::kWordSize == num_parts);

    // Blocks of compiler::target::kWordSize.
    return *new (zone) NativeStackLocation(
        *new (zone) NativePrimitiveType(
            compiler::target::kWordSize == 8 ? kInt64 : kInt32),
        *new (zone) NativePrimitiveType(
            compiler::target::kWordSize == 8 ? kInt64 : kInt32),
        base_register_, offset_in_bytes_ + compiler::target::kWordSize * index);
  }
}

intptr_t MultipleNativeLocations::StackTopInBytes() const {
  intptr_t height = 0;
  for (int i = 0; i < locations_.length(); i++) {
    height = Utils::Maximum(height, locations_[i]->StackTopInBytes());
  }
  return height;
}

NativeLocation& NativeLocation::WidenTo4Bytes(Zone* zone) const {
  return WithOtherNativeType(zone, payload_type().WidenTo4Bytes(zone),
                             container_type().WidenTo4Bytes(zone));
}

#if defined(TARGET_ARCH_ARM)
const NativeLocation& NativeLocation::WidenToQFpuRegister(Zone* zone) const {
  if (!IsFpuRegisters()) {
    return *this;
  }
  const auto& fpu_loc = AsFpuRegisters();
  switch (fpu_loc.fpu_reg_kind()) {
    case kQuadFpuReg:
      return *this;
    case kDoubleFpuReg: {
      return *new (zone) NativeFpuRegistersLocation(
          payload_type_, container_type_, QRegisterOf(fpu_loc.fpu_d_reg()));
    }
    case kSingleFpuReg: {
      return *new (zone) NativeFpuRegistersLocation(
          payload_type_, container_type_, QRegisterOf(fpu_loc.fpu_s_reg()));
    }
  }
  UNREACHABLE();
}
#endif  // defined(TARGET_ARCH_ARM)

bool NativeRegistersLocation::Equals(const NativeLocation& other) const {
  if (!other.IsRegisters()) {
    return false;
  }
  const auto& other_regs = other.AsRegisters();
  if (other_regs.num_regs() != num_regs()) {
    return false;
  }
  for (intptr_t i = 0; i < num_regs(); i++) {
    if (other_regs.reg_at(i) != reg_at(i)) {
      return false;
    }
  }
  return true;
}

bool NativeFpuRegistersLocation::Equals(const NativeLocation& other) const {
  if (!other.IsFpuRegisters()) {
    return false;
  }
  return other.AsFpuRegisters().fpu_reg_ == fpu_reg_;
}

bool NativeStackLocation::Equals(const NativeLocation& other) const {
  if (!other.IsStack()) {
    return false;
  }
  const auto& other_stack = other.AsStack();
  if (other_stack.base_register_ != base_register_) {
    return false;
  }
  return other_stack.offset_in_bytes_ == offset_in_bytes_;
}

bool PointerToMemoryLocation::Equals(const NativeLocation& other) const {
  if (!other.IsPointerToMemory()) {
    return false;
  }
  const auto& other_pointer = other.AsPointerToMemory();
  if (!other_pointer.pointer_location_.Equals(pointer_location_)) {
    return false;
  }
  return other_pointer.payload_type().Equals(payload_type());
}

#if !defined(FFI_UNIT_TESTS)
compiler::Address NativeLocationToStackSlotAddress(
    const NativeStackLocation& loc) {
  return compiler::Address(loc.base_register(), loc.offset_in_bytes());
}
#endif

static void PrintRepresentations(BaseTextBuffer* f, const NativeLocation& loc) {
  f->AddString(" ");
  loc.container_type().PrintTo(f, /*multi_line=*/false, /*verbose=*/false);
  if (!loc.container_type().Equals(loc.payload_type())) {
    f->AddString("[");
    loc.payload_type().PrintTo(f, /*multi_line=*/false, /*verbose=*/false);
    f->AddString("]");
  }
}

void NativeLocation::PrintTo(BaseTextBuffer* f) const {
  f->AddString("I");
  PrintRepresentations(f, *this);
}

void NativeRegistersLocation::PrintTo(BaseTextBuffer* f) const {
  if (num_regs() == 1) {
    f->Printf("%s", RegisterNames::RegisterAbiName(regs_->At(0)));
  } else {
    f->AddString("(");
    for (intptr_t i = 0; i < num_regs(); i++) {
      if (i != 0) {
        f->Printf(", ");
      }
      f->Printf("%s", RegisterNames::RegisterAbiName(regs_->At(i)));
    }
    f->AddString(")");
  }
  PrintRepresentations(f, *this);
}

void NativeFpuRegistersLocation::PrintTo(BaseTextBuffer* f) const {
  switch (fpu_reg_kind()) {
    case kQuadFpuReg:
      f->Printf("%s", RegisterNames::FpuRegisterName(fpu_reg()));
      break;
#if defined(TARGET_ARCH_ARM)
    case kDoubleFpuReg:
      f->Printf("%s", RegisterNames::FpuDRegisterName(fpu_d_reg()));
      break;
    case kSingleFpuReg:
      f->Printf("%s", RegisterNames::FpuSRegisterName(fpu_s_reg()));
      break;
#endif  // defined(TARGET_ARCH_ARM)
    default:
      UNREACHABLE();
  }

  PrintRepresentations(f, *this);
}

void NativeStackLocation::PrintTo(BaseTextBuffer* f) const {
  f->Printf("S%+" Pd, offset_in_bytes_);
  PrintRepresentations(f, *this);
}

const char* NativeLocation::ToCString(Zone* zone) const {
  ZoneTextBuffer textBuffer(zone);
  PrintTo(&textBuffer);
  return textBuffer.buffer();
}

void PointerToMemoryLocation::PrintTo(BaseTextBuffer* f) const {
  f->Printf("P(");
  pointer_location().PrintTo(f);
  if (!pointer_location().Equals(pointer_return_location())) {
    f->Printf(", ret:");
    pointer_return_location().PrintTo(f);
  }
  f->Printf(")");
  PrintRepresentations(f, *this);
}

void MultipleNativeLocations::PrintTo(BaseTextBuffer* f) const {
  f->Printf("M(");
  for (intptr_t i = 0; i < locations_.length(); i++) {
    if (i != 0) f->Printf(", ");
    locations_[i]->PrintTo(f);
  }
  f->Printf(")");
  PrintRepresentations(f, *this);
}

#if !defined(FFI_UNIT_TESTS)
const char* NativeLocation::ToCString() const {
  return ToCString(Thread::Current()->zone());
}
#endif

intptr_t SizeFromFpuRegisterKind(enum FpuRegisterKind kind) {
  switch (kind) {
    case kQuadFpuReg:
      return 16;
    case kDoubleFpuReg:
      return 8;
    case kSingleFpuReg:
      return 4;
  }
  UNREACHABLE();
}
enum FpuRegisterKind FpuRegisterKindFromSize(intptr_t size_in_bytes) {
  switch (size_in_bytes) {
    case 16:
      return kQuadFpuReg;
    case 8:
      return kDoubleFpuReg;
    case 4:
      return kSingleFpuReg;
  }
  UNREACHABLE();
}

#if defined(TARGET_ARCH_ARM)
DRegister NativeFpuRegistersLocation::fpu_as_d_reg() const {
  switch (fpu_reg_kind_) {
    case kQuadFpuReg:
      return EvenDRegisterOf(fpu_reg());
    case kDoubleFpuReg:
      return fpu_d_reg();
    case kSingleFpuReg:
      return DRegisterOf(fpu_s_reg());
  }
  UNREACHABLE();
}

SRegister NativeFpuRegistersLocation::fpu_as_s_reg() const {
  switch (fpu_reg_kind_) {
    case kQuadFpuReg:
      return EvenSRegisterOf(EvenDRegisterOf(fpu_reg()));
    case kDoubleFpuReg:
      return EvenSRegisterOf(fpu_d_reg());
    case kSingleFpuReg:
      return fpu_s_reg();
  }
  UNREACHABLE();
}

bool NativeFpuRegistersLocation::IsLowestBits() const {
  switch (fpu_reg_kind()) {
    case kQuadFpuReg:
      return true;
    case kDoubleFpuReg: {
      return fpu_d_reg() % 2 == 0;
    }
    case kSingleFpuReg: {
      return fpu_s_reg() % 4 == 0;
    }
  }
  UNREACHABLE();
}
#endif  // defined(TARGET_ARCH_ARM)

}  // namespace ffi

}  // namespace compiler

}  // namespace dart
