// 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);
}

const BothNativeLocations& NativeLocation::AsBoth() const {
  ASSERT(IsBoth());
  return static_cast<const BothNativeLocations&>(*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;
  }
  auto& other_fpu_reg = other.AsFpuRegisters();
  if (other_fpu_reg.fpu_reg_kind() != fpu_reg_kind()) {
    return false;
  }
  // We can only compare `fpu_reg_` if the kind is the same.
  // Q5 is not the same register as (nor overlaps) D5.
  return other_fpu_reg.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 {
  if (base_register_ != SPREG) {
    f->Printf("S(%s)+%" Pd, RegisterNames::RegisterAbiName(base_register_),
              offset_in_bytes_);
  } else {
    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);
}

void BothNativeLocations::PrintTo(BaseTextBuffer* f) const {
  f->Printf("B(");
  location0_.PrintTo(f);
  f->Printf(", ");
  location1_.PrintTo(f);
  f->Printf(")");
}

#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
