// 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/marshaller.h"

#include "vm/compiler/ffi/frame_rebase.h"
#include "vm/compiler/ffi/native_location.h"
#include "vm/compiler/ffi/native_type.h"
#include "vm/raw_object.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"

namespace dart {

namespace compiler {

namespace ffi {

#if !defined(DART_PRECOMPILED_RUNTIME)

Location CallMarshaller::LocInFfiCall(intptr_t arg_index) const {
  if (arg_index == kResultIndex) {
    return Location(arg_index).AsLocation();
  }

  // Floating point values are never split: they are either in a single "FPU"
  // register or a contiguous 64-bit slot on the stack. Unboxed 64-bit integer
  // values, in contrast, can be split between any two registers on a 32-bit
  // system.
  //
  // There is an exception for iOS and Android 32-bit ARM, where
  // floating-point values are treated as integers as far as the calling
  // convention is concerned. However, the representation of these arguments
  // are set to kUnboxedInt32 or kUnboxedInt64 already, so we don't have to
  // account for that here.
  const bool is_atomic = RepInFfiCall(arg_index) == kUnboxedDouble ||
                         RepInFfiCall(arg_index) == kUnboxedFloat;

  const NativeLocation& loc = this->Location(arg_index);
  // Don't pin stack locations, they need to be moved anyway.
  if (loc.IsStack()) {
    if (loc.payload_type().SizeInBytes() == 2 * compiler::target::kWordSize &&
        !is_atomic) {
      return Location::Pair(Location::Any(), Location::Any());
    }
    return Location::Any();
  }

#if defined(TARGET_ARCH_ARM)
  // Only pin FPU register if it is the lowest bits.
  if (loc.IsFpuRegisters()) {
    const auto& fpu_loc = loc.AsFpuRegisters();
    if (fpu_loc.IsLowestBits()) {
      return fpu_loc.WidenToQFpuRegister(zone_).AsLocation();
    }
    return Location::Any();
  }
#endif  // defined(TARGET_ARCH_ARM)

  return loc.AsLocation();
}

// This classes translates the ABI location of arguments into the locations they
// will inhabit after entry-frame setup in the invocation of a native callback.
//
// Native -> Dart callbacks must push all the arguments before executing any
// Dart code because the reading the Thread from TLS requires calling a native
// stub, and the argument registers are volatile on all ABIs we support.
//
// To avoid complicating initial definitions, all callback arguments are read
// off the stack from their pushed locations, so this class updates the argument
// positions to account for this.
//
// See 'NativeEntryInstr::EmitNativeCode' for details.
class CallbackArgumentTranslator : public ValueObject {
 public:
  static NativeLocations& TranslateArgumentLocations(
      const NativeLocations& arg_locs,
      Zone* zone) {
    auto& pushed_locs = *(new NativeLocations(arg_locs.length()));

    CallbackArgumentTranslator translator;
    for (intptr_t i = 0, n = arg_locs.length(); i < n; i++) {
      translator.AllocateArgument(*arg_locs[i]);
    }
    for (intptr_t i = 0, n = arg_locs.length(); i < n; ++i) {
      pushed_locs.Add(&translator.TranslateArgument(*arg_locs[i], zone));
    }

    return pushed_locs;
  }

 private:
  void AllocateArgument(const NativeLocation& arg) {
    if (arg.IsStack()) return;

    ASSERT(arg.IsRegisters() || arg.IsFpuRegisters());
    if (arg.IsRegisters()) {
      argument_slots_required_ += arg.AsRegisters().num_regs();
    } else {
      argument_slots_required_ += 8 / target::kWordSize;
    }
  }

  const NativeLocation& TranslateArgument(const NativeLocation& arg,
                                          Zone* zone) {
    if (arg.IsStack()) {
      // Add extra slots after the saved arguments for the return address and
      // frame pointer of the dummy arguments frame, which will be between the
      // saved argument registers and stack arguments. Also add slots for the
      // shadow space if present (factored into
      // kCallbackSlotsBeforeSavedArguments).
      //
      // Finally, if we are using NativeCallbackTrampolines, factor in the extra
      // stack space corresponding to those trampolines' frames (above the entry
      // frame).
      intptr_t stack_delta = kCallbackSlotsBeforeSavedArguments;
      if (NativeCallbackTrampolines::Enabled()) {
        stack_delta += StubCodeCompiler::kNativeCallbackTrampolineStackDelta;
      }
      FrameRebase rebase(
          /*old_base=*/SPREG, /*new_base=*/SPREG,
          /*stack_delta=*/(argument_slots_required_ + stack_delta) *
              compiler::target::kWordSize,
          zone);
      return rebase.Rebase(arg);
    }

    if (arg.IsRegisters()) {
      const auto& result = *new (zone) NativeStackLocation(
          arg.payload_type(), arg.container_type(), SPREG,
          argument_slots_used_ * compiler::target::kWordSize);
      argument_slots_used_ += arg.AsRegisters().num_regs();
      return result;
    }

    ASSERT(arg.IsFpuRegisters());
    const auto& result = *new (zone) NativeStackLocation(
        arg.payload_type(), arg.container_type(), SPREG,
        argument_slots_used_ * compiler::target::kWordSize);
    argument_slots_used_ += 8 / target::kWordSize;
    return result;
  }

  intptr_t argument_slots_used_ = 0;
  intptr_t argument_slots_required_ = 0;
};

CallbackMarshaller::CallbackMarshaller(Zone* zone,
                                       const Function& dart_signature)
    : BaseMarshaller(zone, dart_signature),
      callback_locs_(
          CallbackArgumentTranslator::TranslateArgumentLocations(arg_locs_,
                                                                 zone_)) {}

#endif  // !defined(DART_PRECOMPILED_RUNTIME)

}  // namespace ffi

}  // namespace compiler

}  // namespace dart
