// Copyright (c) 2019, 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.h"

#include <algorithm>

#include "platform/globals.h"
#include "vm/compiler/backend/locations.h"
#include "vm/compiler/runtime_api.h"

namespace dart {

namespace compiler {

namespace ffi {

static const size_t kSizeUnknown = 0;

static const intptr_t kNumElementSizes = kFfiVoidCid - kFfiPointerCid + 1;

static const size_t element_size_table[kNumElementSizes] = {
    target::kWordSize,  // kFfiPointerCid
    kSizeUnknown,       // kFfiNativeFunctionCid
    1,                  // kFfiInt8Cid
    2,                  // kFfiInt16Cid
    4,                  // kFfiInt32Cid
    8,                  // kFfiInt64Cid
    1,                  // kFfiUint8Cid
    2,                  // kFfiUint16Cid
    4,                  // kFfiUint32Cid
    8,                  // kFfiUint64Cid
    target::kWordSize,  // kFfiIntPtrCid
    4,                  // kFfiFloatCid
    8,                  // kFfiDoubleCid
    kSizeUnknown,       // kFfiVoidCid
};

size_t ElementSizeInBytes(intptr_t class_id) {
  ASSERT(class_id != kFfiNativeFunctionCid);
  ASSERT(class_id != kFfiVoidCid);
  if (!RawObject::IsFfiTypeClassId(class_id)) {
    // subtype of Pointer
    class_id = kFfiPointerCid;
  }
  intptr_t index = class_id - kFfiPointerCid;
  return element_size_table[index];
}

#if !defined(DART_PRECOMPILED_RUNTIME)

Representation TypeRepresentation(const AbstractType& result_type) {
  switch (result_type.type_class_id()) {
    case kFfiFloatCid:
      return kUnboxedFloat;
    case kFfiDoubleCid:
      return kUnboxedDouble;
    case kFfiInt8Cid:
    case kFfiInt16Cid:
    case kFfiInt32Cid:
      return kUnboxedInt32;
    case kFfiUint8Cid:
    case kFfiUint16Cid:
    case kFfiUint32Cid:
      return kUnboxedUint32;
    case kFfiInt64Cid:
    case kFfiUint64Cid:
      return kUnboxedInt64;
    case kFfiIntPtrCid:
    case kFfiPointerCid:
    default:  // Subtypes of Pointer.
      return kUnboxedFfiIntPtr;
  }
}

SmallRepresentation TypeSmallRepresentation(const AbstractType& ffi_type) {
  switch (ffi_type.type_class_id()) {
    case kFfiInt8Cid:
      return kSmallUnboxedInt8;
    case kFfiInt16Cid:
      return kSmallUnboxedInt16;
    case kFfiUint8Cid:
      return kSmallUnboxedUint8;
    case kFfiUint16Cid:
      return kSmallUnboxedUint16;
    default:
      return kNoSmallRepresentation;
  }
}

bool NativeTypeIsVoid(const AbstractType& result_type) {
  return result_type.type_class_id() == kFfiVoidCid;
}

bool NativeTypeIsPointer(const AbstractType& result_type) {
  switch (result_type.type_class_id()) {
    case kFfiVoidCid:
    case kFfiFloatCid:
    case kFfiDoubleCid:
    case kFfiInt8Cid:
    case kFfiInt16Cid:
    case kFfiInt32Cid:
    case kFfiUint8Cid:
    case kFfiUint16Cid:
    case kFfiUint32Cid:
    case kFfiInt64Cid:
    case kFfiUint64Cid:
    case kFfiIntPtrCid:
      return false;
    case kFfiPointerCid:
    default:
      return true;
  }
}

// Converts a Ffi [signature] to a list of Representations.
// Note that this ignores first argument (receiver) which is dynamic.
template <class CallingConventions>
ZoneGrowableArray<Representation>* ArgumentRepresentationsBase(
    const Function& signature) {
  intptr_t num_arguments = signature.num_fixed_parameters() - 1;
  auto result = new ZoneGrowableArray<Representation>(num_arguments);
  for (intptr_t i = 0; i < num_arguments; i++) {
    AbstractType& arg_type =
        AbstractType::Handle(signature.ParameterTypeAt(i + 1));
    Representation rep = TypeRepresentation(arg_type);
    // In non simulator mode host::CallingConventions == CallingConventions.
    // In simulator mode convert arguments to host representation.
    if (rep == kUnboxedFloat && CallingConventions::kAbiSoftFP) {
      rep = kUnboxedInt32;
    } else if (rep == kUnboxedDouble && CallingConventions::kAbiSoftFP) {
      rep = kUnboxedInt64;
    }
    result->Add(rep);
  }
  return result;
}

template <class CallingConventions>
Representation ResultRepresentationBase(const Function& signature) {
  AbstractType& arg_type = AbstractType::Handle(signature.result_type());
  Representation rep = TypeRepresentation(arg_type);
  if (rep == kUnboxedFloat && CallingConventions::kAbiSoftFP) {
    rep = kUnboxedInt32;
  } else if (rep == kUnboxedDouble && CallingConventions::kAbiSoftFP) {
    rep = kUnboxedInt64;
  }
  return rep;
}

#if !defined(TARGET_ARCH_DBC)

ZoneGrowableArray<Representation>* ArgumentRepresentations(
    const Function& signature) {
  return ArgumentRepresentationsBase<CallingConventions>(signature);
}

Representation ResultRepresentation(const Function& signature) {
  return ResultRepresentationBase<CallingConventions>(signature);
}

#endif  // !defined(TARGET_ARCH_DBC)

#if defined(USING_SIMULATOR)

ZoneGrowableArray<Representation>* ArgumentHostRepresentations(
    const Function& signature) {
  return ArgumentRepresentationsBase<host::CallingConventions>(signature);
}

Representation ResultHostRepresentation(const Function& signature) {
  return ResultRepresentationBase<host::CallingConventions>(signature);
}

#endif  // defined(USING_SIMULATOR)

// Represents the state of a stack frame going into a call, between allocations
// of argument locations. Acts like a register allocator but for arguments in
// the native ABI.
template <class CallingConventions,
          class Location,
          class Register,
          class FpuRegister>
class ArgumentFrameState : public ValueObject {
 public:
  Location AllocateArgument(Representation rep) {
    switch (rep) {
      case kUnboxedFloat:
      case kUnboxedDouble: {
        Location result = AllocateFpuRegister();
        if (!result.IsUnallocated()) return result;
        break;
      }
      case kUnboxedInt64:
      case kUnboxedUint32:
      case kUnboxedInt32: {
        Location result =
            rep == kUnboxedInt64 && compiler::target::kWordSize == 4
                ? AllocateAlignedRegisterPair()
                : AllocateCpuRegister();
        if (!result.IsUnallocated()) return result;
        break;
      }
      default:
        UNREACHABLE();
    }

    // Argument must be spilled.
    if ((rep == kUnboxedInt64 || rep == kUnboxedDouble) &&
        compiler::target::kWordSize == 4) {
      return AllocateAlignedStackSlots(rep);
    } else {
      return AllocateStackSlot();
    }
  }

 private:
  Location AllocateStackSlot() {
    return Location::StackSlot(stack_height_in_slots++,
                               CallingConventions::kStackPointerRegister);
  }

  // Allocates a pair of stack slots where the first stack slot is aligned to an
  // 8-byte boundary, if necessary.
  Location AllocateAlignedStackSlots(Representation rep) {
    if (CallingConventions::kAlignArguments &&
        compiler::target::kWordSize == 4) {
      stack_height_in_slots += stack_height_in_slots % 2;
    }

    Location result;
    if (rep == kUnboxedDouble) {
      result = Location::DoubleStackSlot(
          stack_height_in_slots, CallingConventions::kStackPointerRegister);
      stack_height_in_slots += 2;
    } else {
      const Location low = AllocateStackSlot();
      const Location high = AllocateStackSlot();
      result = Location::Pair(low, high);
    }
    return result;
  }

  Location AllocateFpuRegister() {
    if (fpu_regs_used == CallingConventions::kNumFpuArgRegs) {
      return Location::RequiresFpuRegister();
    }

    const Location result = Location::FpuRegisterLocation(
        CallingConventions::FpuArgumentRegisters[fpu_regs_used]);
    fpu_regs_used++;
    if (CallingConventions::kArgumentIntRegXorFpuReg) {
      cpu_regs_used++;
    }
    return result;
  }

  Location AllocateCpuRegister() {
    if (cpu_regs_used == CallingConventions::kNumArgRegs) {
      return Location::RequiresRegister();
    }

    const Location result = Location::RegisterLocation(
        CallingConventions::ArgumentRegisters[cpu_regs_used]);
    cpu_regs_used++;
    if (CallingConventions::kArgumentIntRegXorFpuReg) {
      fpu_regs_used++;
    }
    return result;
  }

  // Allocates a pair of registers where the first register index is even, if
  // necessary.
  Location AllocateAlignedRegisterPair() {
    if (CallingConventions::kAlignArguments) {
      cpu_regs_used += cpu_regs_used % 2;
    }
    if (cpu_regs_used > CallingConventions::kNumArgRegs - 2) {
      return Location::Any();
    }
    return Location::Pair(AllocateCpuRegister(), AllocateCpuRegister());
  }

  intptr_t cpu_regs_used = 0;
  intptr_t fpu_regs_used = 0;
  intptr_t stack_height_in_slots = 0;
};

// Takes a list of argument representations, and converts it to a list of
// argument locations based on calling convention.
template <class CallingConventions,
          class Location,
          class Register,
          class FpuRegister>
ZoneGrowableArray<Location>* ArgumentLocationsBase(
    const ZoneGrowableArray<Representation>& arg_reps) {
  intptr_t num_arguments = arg_reps.length();
  auto result = new ZoneGrowableArray<Location>(num_arguments);

  // Loop through all arguments and assign a register or a stack location.
  ArgumentFrameState<CallingConventions, Location, Register, FpuRegister>
      frame_state;
  for (intptr_t i = 0; i < num_arguments; i++) {
    Representation rep = arg_reps[i];
    result->Add(frame_state.AllocateArgument(rep));
  }
  return result;
}

ZoneGrowableArray<Location>* ArgumentLocations(
    const ZoneGrowableArray<Representation>& arg_reps) {
#if !defined(TARGET_ARCH_DBC)
  return ArgumentLocationsBase<dart::CallingConventions, Location,
                               dart::Register, dart::FpuRegister>(arg_reps);
#else
  intptr_t next_free_register = compiler::ffi::kFirstArgumentRegister;
  intptr_t num_arguments = arg_reps.length();
  auto result = new ZoneGrowableArray<Location>(num_arguments);
  for (intptr_t i = 0; i < num_arguments; i++) {
    // TODO(dacoharkes): In 32 bits, use pair locations.
    result->Add(Location::RegisterLocation(next_free_register));
    next_free_register++;
  }
  return result;
#endif
}

#if defined(TARGET_ARCH_DBC)
ZoneGrowableArray<HostLocation>* HostArgumentLocations(
    const ZoneGrowableArray<Representation>& arg_reps) {
  return ArgumentLocationsBase<dart::host::CallingConventions, HostLocation,
                               dart::host::Register, dart::host::FpuRegister>(
      arg_reps);
}
#endif

Location ResultLocation(Representation result_rep) {
#ifndef TARGET_ARCH_DBC
  switch (result_rep) {
    case kUnboxedFloat:
    case kUnboxedDouble:
#if defined(TARGET_ARCH_IA32)
      // The result is returned in ST0, but we don't allocate ST registers, so
      // the FFI trampoline will move it to XMM0.
      return Location::FpuRegisterLocation(XMM0);
#else
      return Location::FpuRegisterLocation(CallingConventions::kReturnFpuReg);
#endif
    case kUnboxedInt32:
    case kUnboxedUint32:
      return Location::RegisterLocation(CallingConventions::kReturnReg);
    case kUnboxedInt64:
      if (compiler::target::kWordSize == 4) {
        return Location::Pair(
            Location::RegisterLocation(CallingConventions::kReturnReg),
            Location::RegisterLocation(CallingConventions::kSecondReturnReg));
      } else {
        return Location::RegisterLocation(CallingConventions::kReturnReg);
      }
    default:
      UNREACHABLE();
  }
#else
  // TODO(dacoharkes): Support 64 bit result values on 32 bit DBC.
  return Location::RegisterLocation(0);
#endif
}

// Accounts for alignment, where some stack slots are used as padding.
template <class Location>
intptr_t TemplateNumStackSlots(const ZoneGrowableArray<Location>& locations) {
  intptr_t num_arguments = locations.length();
  intptr_t max_height_in_slots = 0;
  for (intptr_t i = 0; i < num_arguments; i++) {
    intptr_t height = 0;
    if (locations.At(i).IsStackSlot()) {
      height = locations.At(i).stack_index() + 1;
    } else if (locations.At(i).IsDoubleStackSlot()) {
      height = locations.At(i).stack_index() + 8 / compiler::target::kWordSize;
    } else if (locations.At(i).IsPairLocation()) {
      const Location first = locations.At(i).AsPairLocation()->At(0);
      const Location second = locations.At(i).AsPairLocation()->At(1);
      height = std::max(first.IsStackSlot() ? first.stack_index() + 1 : 0,
                        second.IsStackSlot() ? second.stack_index() + 1 : 0);
    }
    max_height_in_slots = std::max(height, max_height_in_slots);
  }
  return max_height_in_slots;
}

intptr_t NumStackSlots(const ZoneGrowableArray<Location>& locations) {
  return TemplateNumStackSlots(locations);
}

#if defined(TARGET_ARCH_DBC)

static RawTypedData* typed_data_new_uintptr(intptr_t length) {
#if defined(ARCH_IS_32_BIT)
  return TypedData::New(kTypedDataUint32ArrayCid, length);
#else
  return TypedData::New(kTypedDataUint64ArrayCid, length);
#endif
}

static void typed_data_set_uintptr(const TypedData& typed_data,
                                   intptr_t index,
                                   uintptr_t value) {
#if defined(ARCH_IS_32_BIT)
  typed_data.SetUint32(target::kWordSize * index, value);
#else
  typed_data.SetUint64(target::kWordSize * index, value);
#endif
}

static uintptr_t typed_data_get_uintptr(const TypedData& typed_data,
                                        intptr_t index) {
#if defined(ARCH_IS_32_BIT)
  return typed_data.GetUint32(target::kWordSize * index);
#else
  return typed_data.GetUint64(target::kWordSize * index);
#endif
}

// Number of host stack slots used in 'locations'.
static intptr_t HostNumStackSlots(
    const ZoneGrowableArray<HostLocation>& locations) {
  return TemplateNumStackSlots(locations);
}

RawTypedData* FfiSignatureDescriptor::New(
    const ZoneGrowableArray<HostLocation>& arg_host_locations,
    const Representation result_representation) {
  const uintptr_t num_arguments = arg_host_locations.length();
  const uintptr_t num_stack_slots = HostNumStackSlots(arg_host_locations);

  const TypedData& result = TypedData::Handle(
      typed_data_new_uintptr(kOffsetArgumentLocations + num_arguments));

  typed_data_set_uintptr(result, kOffsetNumArguments, num_arguments);
  typed_data_set_uintptr(result, kOffsetNumStackSlots, num_stack_slots);
  typed_data_set_uintptr(result, kOffsetResultRepresentation,
                         result_representation);

  for (uintptr_t i = 0; i < num_arguments; i++) {
    typed_data_set_uintptr(result, kOffsetArgumentLocations + i,
                           arg_host_locations.At(i).write());
  }

  return result.raw();
}

intptr_t FfiSignatureDescriptor::length() const {
  return typed_data_get_uintptr(typed_data_, kOffsetNumArguments);
}

intptr_t FfiSignatureDescriptor::num_stack_slots() const {
  return typed_data_get_uintptr(typed_data_, kOffsetNumStackSlots);
}

HostLocation FfiSignatureDescriptor::LocationAt(intptr_t index) const {
  return HostLocation::read(
      typed_data_get_uintptr(typed_data_, kOffsetArgumentLocations + index));
}

Representation FfiSignatureDescriptor::ResultRepresentation() const {
  uintptr_t result_int =
      typed_data_get_uintptr(typed_data_, kOffsetResultRepresentation);
  ASSERT(result_int < kNumRepresentations);
  return static_cast<Representation>(result_int);
}

#endif  // defined(TARGET_ARCH_DBC)

#endif  // !defined(DART_PRECOMPILED_RUNTIME)

}  // namespace ffi

}  // namespace compiler

}  // namespace dart
