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

#include "include/dart_api.h"
#include "vm/bootstrap_natives.h"
#include "vm/class_finalizer.h"
#include "vm/compiler/assembler/assembler.h"
#include "vm/compiler/ffi.h"
#include "vm/exceptions.h"
#include "vm/log.h"
#include "vm/native_arguments.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/symbols.h"

namespace dart {

// The following functions are runtime checks on type arguments.
// Some checks are also performed in kernel transformation, these are asserts.
// Some checks are only performed at runtime to allow for generic code, these
// throw ArgumentExceptions.

static void ThrowTypeArgumentError(const AbstractType& type_arg,
                                   const char* expected) {
  const String& error = String::Handle(String::NewFormatted(
      "Type argument (%s) should be a %s",
      String::Handle(type_arg.UserVisibleName()).ToCString(), expected));
  Exceptions::ThrowArgumentError(error);
}

static bool IsPointerType(const AbstractType& type) {
  // Do a fast check for predefined types.
  classid_t type_cid = type.type_class_id();
  if (RawObject::IsFfiPointerClassId(type_cid)) {
    return true;
  }

  // Do a slow check for subtyping.
  const Class& pointer_class =
      Class::Handle(Isolate::Current()->object_store()->ffi_pointer_class());
  AbstractType& pointer_type =
      AbstractType::Handle(pointer_class.DeclarationType());
  pointer_type = pointer_type.InstantiateFrom(Object::null_type_arguments(),
                                              Object::null_type_arguments(),
                                              kNoneFree, NULL, Heap::kNew);
  ASSERT(pointer_type.IsInstantiated());
  ASSERT(type.IsInstantiated());
  return type.IsSubtypeOf(pointer_type, Heap::kNew);
}

static bool IsConcreteNativeType(const AbstractType& type) {
  // Do a fast check for predefined types.
  classid_t type_cid = type.type_class_id();
  if (RawObject::IsFfiNativeTypeTypeClassId(type_cid)) {
    return false;
  }
  if (RawObject::IsFfiTypeClassId(type_cid)) {
    return true;
  }

  // Do a slow check for subtyping.
  const Class& native_type_class = Class::Handle(
      Isolate::Current()->object_store()->ffi_native_type_class());
  AbstractType& native_type_type =
      AbstractType::Handle(native_type_class.DeclarationType());
  return type.IsSubtypeOf(native_type_type, Heap::kNew);
}

static void CheckIsConcreteNativeType(const AbstractType& type) {
  if (!IsConcreteNativeType(type)) {
    ThrowTypeArgumentError(type, "concrete sub type of NativeType");
  }
}

static bool IsNativeFunction(const AbstractType& type_arg) {
  classid_t type_cid = type_arg.type_class_id();
  return RawObject::IsFfiTypeNativeFunctionClassId(type_cid);
}

static void CheckSized(const AbstractType& type_arg) {
  classid_t type_cid = type_arg.type_class_id();
  if (RawObject::IsFfiTypeVoidClassId(type_cid) ||
      RawObject::IsFfiTypeNativeFunctionClassId(type_cid)) {
    const String& error = String::Handle(String::NewFormatted(
        "%s does not have a predefined size (@unsized). "
        "Unsized NativeTypes do not support [sizeOf] because their size "
        "is unknown. "
        "Consequently, [allocate], [Pointer.load], [Pointer.store], and "
        "[Pointer.elementAt] are not available.",
        String::Handle(type_arg.UserVisibleName()).ToCString()));
    Exceptions::ThrowArgumentError(error);
  }
}

// Checks that a dart type correspond to a [NativeType].
// Because this is checked already in a kernel transformation, it does not throw
// an ArgumentException but a boolean which should be asserted.
//
// [Int8]                               -> [int]
// [Int16]                              -> [int]
// [Int32]                              -> [int]
// [Int64]                              -> [int]
// [Uint8]                              -> [int]
// [Uint16]                             -> [int]
// [Uint32]                             -> [int]
// [Uint64]                             -> [int]
// [IntPtr]                             -> [int]
// [Double]                             -> [double]
// [Float]                              -> [double]
// [Pointer]<T>                         -> [Pointer]<T>
// T extends [Pointer]                  -> T
// [NativeFunction]<T1 Function(T2, T3) -> S1 Function(S2, S3)
//    where DartRepresentationOf(Tn) -> Sn
static bool DartAndCTypeCorrespond(const AbstractType& native_type,
                                   const AbstractType& dart_type) {
  classid_t native_type_cid = native_type.type_class_id();
  if (RawObject::IsFfiTypeIntClassId(native_type_cid)) {
    return dart_type.IsSubtypeOf(AbstractType::Handle(Type::IntType()),
                                 Heap::kNew);
  }
  if (RawObject::IsFfiTypeDoubleClassId(native_type_cid)) {
    return dart_type.IsSubtypeOf(AbstractType::Handle(Type::Double()),
                                 Heap::kNew);
  }
  if (RawObject::IsFfiPointerClassId(native_type_cid)) {
    return native_type.Equals(dart_type) || dart_type.IsNullType();
  }
  if (RawObject::IsFfiTypeNativeFunctionClassId(native_type_cid)) {
    if (!dart_type.IsFunctionType()) {
      return false;
    }
    TypeArguments& nativefunction_type_args =
        TypeArguments::Handle(native_type.arguments());
    AbstractType& nativefunction_type_arg =
        AbstractType::Handle(nativefunction_type_args.TypeAt(0));
    if (!nativefunction_type_arg.IsFunctionType()) {
      return false;
    }
    Function& dart_function = Function::Handle(((Type&)dart_type).signature());
    if (dart_function.NumTypeParameters() != 0 ||
        dart_function.HasOptionalPositionalParameters() ||
        dart_function.HasOptionalNamedParameters()) {
      return false;
    }
    Function& nativefunction_function =
        Function::Handle(((Type&)nativefunction_type_arg).signature());
    if (nativefunction_function.NumTypeParameters() != 0 ||
        nativefunction_function.HasOptionalPositionalParameters() ||
        nativefunction_function.HasOptionalNamedParameters()) {
      return false;
    }
    if (!(dart_function.NumParameters() ==
          nativefunction_function.NumParameters())) {
      return false;
    }
    if (!DartAndCTypeCorrespond(
            AbstractType::Handle(nativefunction_function.result_type()),
            AbstractType::Handle(dart_function.result_type()))) {
      return false;
    }
    for (intptr_t i = 0; i < dart_function.NumParameters(); i++) {
      if (!DartAndCTypeCorrespond(
              AbstractType::Handle(nativefunction_function.ParameterTypeAt(i)),
              AbstractType::Handle(dart_function.ParameterTypeAt(i)))) {
        return false;
      }
    }
  }
  return true;
}

// The following functions are runtime checks on arguments.

// Note that expected_from and expected_to are inclusive.
static void CheckRange(const Integer& argument_value,
                       intptr_t expected_from,
                       intptr_t expected_to,
                       const char* argument_name) {
  int64_t value = argument_value.AsInt64Value();
  if (value < expected_from || expected_to < value) {
    Exceptions::ThrowRangeError(argument_name, argument_value, expected_from,
                                expected_to);
  }
}

static const Pointer& AsPointer(const Instance& instance) {
  if (!instance.IsPointer()) {
    const String& error = String::Handle(String::NewFormatted(
        "Expected a Pointer object but found %s", instance.ToCString()));
    Exceptions::ThrowArgumentError(error);
  }
  return Pointer::Cast(instance);
}

static const Integer& AsInteger(const Instance& instance) {
  if (!instance.IsInteger()) {
    const String& error = String::Handle(String::NewFormatted(
        "Expected an int but found %s", instance.ToCString()));
    Exceptions::ThrowArgumentError(error);
  }
  return Integer::Cast(instance);
}

static const Double& AsDouble(const Instance& instance) {
  if (!instance.IsDouble()) {
    const String& error = String::Handle(String::NewFormatted(
        "Expected a double but found %s", instance.ToCString()));
    Exceptions::ThrowArgumentError(error);
  }
  return Double::Cast(instance);
}

// The remainder of this file implements the dart:ffi native methods.

DEFINE_NATIVE_ENTRY(Ffi_allocate, 1, 1) {
  // TODO(dacoharkes): When we have a way of determining the size of structs in
  // the VM, change the signature so we can allocate structs, subtype of
  // Pointer. https://github.com/dart-lang/sdk/issues/35782
  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));

  CheckIsConcreteNativeType(type_arg);
  CheckSized(type_arg);

  GET_NON_NULL_NATIVE_ARGUMENT(Integer, argCount, arguments->NativeArgAt(0));
  int64_t count = argCount.AsInt64Value();
  classid_t type_cid = type_arg.type_class_id();
  int64_t max_count = INTPTR_MAX / compiler::ffi::ElementSizeInBytes(type_cid);
  CheckRange(argCount, 1, max_count, "count");

  size_t size = compiler::ffi::ElementSizeInBytes(type_cid) * count;
  uint64_t memory = reinterpret_cast<uint64_t>(malloc(size));
  if (memory == 0) {
    const String& error = String::Handle(String::NewFormatted(
        "allocating (%" Pd ") bytes of memory failed", size));
    Exceptions::ThrowArgumentError(error);
  }

  RawPointer* result = Pointer::New(
      type_arg, Integer::Handle(zone, Integer::NewFromUint64(memory)));
  return result;
}

DEFINE_NATIVE_ENTRY(Ffi_fromAddress, 1, 1) {
  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
  TypeArguments& type_args = TypeArguments::Handle(type_arg.arguments());
  AbstractType& native_type = AbstractType::Handle(
      type_args.TypeAtNullSafe(Pointer::kNativeTypeArgPos));
  CheckIsConcreteNativeType(native_type);
  GET_NON_NULL_NATIVE_ARGUMENT(Integer, arg_ptr, arguments->NativeArgAt(0));

  // TODO(dacoharkes): should this return NULL if address is 0?
  // https://github.com/dart-lang/sdk/issues/35756

  RawPointer* result =
      Pointer::New(native_type, arg_ptr, type_arg.type_class_id());
  return result;
}

DEFINE_NATIVE_ENTRY(Ffi_elementAt, 0, 2) {
  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
  AbstractType& pointer_type_arg =
      AbstractType::Handle(zone, pointer.type_argument());
  CheckSized(pointer_type_arg);

  classid_t class_id = pointer_type_arg.type_class_id();
  Integer& address = Integer::Handle(zone, pointer.GetCMemoryAddress());
  address = Integer::New(address.AsInt64Value() +
                         index.AsInt64Value() *
                             compiler::ffi::ElementSizeInBytes(class_id));
  RawPointer* result = Pointer::New(pointer_type_arg, address);
  return result;
}

DEFINE_NATIVE_ENTRY(Ffi_offsetBy, 0, 2) {
  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Integer, offset, arguments->NativeArgAt(1));
  AbstractType& pointer_type_arg =
      AbstractType::Handle(pointer.type_argument());

  intptr_t address =
      Integer::Handle(zone, pointer.GetCMemoryAddress()).AsInt64Value() +
      offset.AsInt64Value();
  RawPointer* result = Pointer::New(
      pointer_type_arg, Integer::Handle(zone, Integer::New(address)));
  return result;
}

DEFINE_NATIVE_ENTRY(Ffi_cast, 1, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
  TypeArguments& type_args = TypeArguments::Handle(type_arg.arguments());
  AbstractType& native_type = AbstractType::Handle(
      type_args.TypeAtNullSafe(Pointer::kNativeTypeArgPos));
  CheckIsConcreteNativeType(native_type);

  const Integer& address = Integer::Handle(zone, pointer.GetCMemoryAddress());
  RawPointer* result =
      Pointer::New(native_type, address, type_arg.type_class_id());
  return result;
}

DEFINE_NATIVE_ENTRY(Ffi_free, 0, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));

  const Integer& address = Integer::Handle(zone, pointer.GetCMemoryAddress());
  free(reinterpret_cast<void*>(address.AsInt64Value()));
  pointer.SetCMemoryAddress(Integer::Handle(zone, Integer::New(0)));
  return Object::null();
}

DEFINE_NATIVE_ENTRY(Ffi_address, 0, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
  return pointer.GetCMemoryAddress();
}

static RawInstance* BoxLoadPointer(Zone* zone,
                                   uint8_t* address,
                                   const AbstractType& instance_type_arg,
                                   intptr_t type_cid) {
  // TODO(dacoharkes): should this return NULL if addres is 0?
  // https://github.com/dart-lang/sdk/issues/35756
  if (address == nullptr) {
    return Instance::null();
  }
  AbstractType& type_arg =
      AbstractType::Handle(TypeArguments::Handle(instance_type_arg.arguments())
                               .TypeAt(Pointer::kNativeTypeArgPos));
  return Pointer::New(
      type_arg,
      Integer::Handle(zone, Integer::New(reinterpret_cast<intptr_t>(address))),
      type_cid);
}

static RawInstance* LoadValue(Zone* zone,
                              uint8_t* address,
                              const AbstractType& instance_type_arg) {
  classid_t type_cid = instance_type_arg.type_class_id();
  switch (type_cid) {
    case kFfiInt8Cid:
      return Integer::New(*reinterpret_cast<int8_t*>(address));
    case kFfiInt16Cid:
      return Integer::New(*reinterpret_cast<int16_t*>(address));
    case kFfiInt32Cid:
      return Integer::New(*reinterpret_cast<int32_t*>(address));
    case kFfiInt64Cid:
      return Integer::New(*reinterpret_cast<int64_t*>(address));
    case kFfiUint8Cid:
      return Integer::NewFromUint64(*reinterpret_cast<uint8_t*>(address));
    case kFfiUint16Cid:
      return Integer::NewFromUint64(*reinterpret_cast<uint16_t*>(address));
    case kFfiUint32Cid:
      return Integer::NewFromUint64(*reinterpret_cast<uint32_t*>(address));
    case kFfiUint64Cid:
      return Integer::NewFromUint64(*reinterpret_cast<uint64_t*>(address));
    case kFfiIntPtrCid:
      return Integer::New(*reinterpret_cast<intptr_t*>(address));
    case kFfiFloatCid:
      return Double::New(*reinterpret_cast<float_t*>(address));
    case kFfiDoubleCid:
      return Double::New(*reinterpret_cast<double_t*>(address));
    case kFfiPointerCid:
    default:
      ASSERT(IsPointerType(instance_type_arg));
      return BoxLoadPointer(zone, *reinterpret_cast<uint8_t**>(address),
                            instance_type_arg, type_cid);
  }
}

DEFINE_NATIVE_ENTRY(Ffi_load, 1, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
  AbstractType& pointer_type_arg =
      AbstractType::Handle(pointer.type_argument());
  CheckSized(pointer_type_arg);
  ASSERT(DartAndCTypeCorrespond(pointer_type_arg, type_arg));

  uint8_t* address = reinterpret_cast<uint8_t*>(
      Integer::Handle(pointer.GetCMemoryAddress()).AsInt64Value());
  return LoadValue(zone, address, pointer_type_arg);
}

static void StoreValue(Zone* zone,
                       const Pointer& pointer,
                       classid_t type_cid,
                       const Instance& new_value) {
  uint8_t* address = reinterpret_cast<uint8_t*>(
      Integer::Handle(pointer.GetCMemoryAddress()).AsInt64Value());
  AbstractType& pointer_type_arg =
      AbstractType::Handle(pointer.type_argument());
  switch (type_cid) {
    case kFfiInt8Cid:
      *reinterpret_cast<int8_t*>(address) = AsInteger(new_value).AsInt64Value();
      break;
    case kFfiInt16Cid:
      *reinterpret_cast<int16_t*>(address) =
          AsInteger(new_value).AsInt64Value();
      break;
    case kFfiInt32Cid:
      *reinterpret_cast<int32_t*>(address) =
          AsInteger(new_value).AsInt64Value();
      break;
    case kFfiInt64Cid:
      *reinterpret_cast<int64_t*>(address) =
          AsInteger(new_value).AsInt64Value();
      break;
    case kFfiUint8Cid:
      *reinterpret_cast<uint8_t*>(address) =
          AsInteger(new_value).AsInt64Value();
      break;
    case kFfiUint16Cid:
      *reinterpret_cast<uint16_t*>(address) =
          AsInteger(new_value).AsInt64Value();
      break;
    case kFfiUint32Cid:
      *reinterpret_cast<uint32_t*>(address) =
          AsInteger(new_value).AsInt64Value();
      break;
    case kFfiUint64Cid:
      *reinterpret_cast<uint64_t*>(address) =
          AsInteger(new_value).AsInt64Value();
      break;
    case kFfiIntPtrCid:
      *reinterpret_cast<intptr_t*>(address) =
          AsInteger(new_value).AsInt64Value();
      break;
    case kFfiFloatCid:
      *reinterpret_cast<float*>(address) = AsDouble(new_value).value();
      break;
    case kFfiDoubleCid:
      *reinterpret_cast<double*>(address) = AsDouble(new_value).value();
      break;
    case kFfiPointerCid:
    default: {
      ASSERT(IsPointerType(pointer_type_arg));
      intptr_t new_value_unwrapped = 0;
      if (!new_value.IsNull()) {
        ASSERT(new_value.IsPointer());
        new_value_unwrapped =
            Integer::Handle(AsPointer(new_value).GetCMemoryAddress())
                .AsInt64Value();
        // TODO(dacoharkes): should this return NULL if addres is 0?
        // https://github.com/dart-lang/sdk/issues/35756
      }
      *reinterpret_cast<intptr_t*>(address) = new_value_unwrapped;
    } break;
  }
}

DEFINE_NATIVE_ENTRY(Ffi_store, 0, 2) {
  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
  GET_NATIVE_ARGUMENT(Instance, new_value, arguments->NativeArgAt(1));
  AbstractType& arg_type = AbstractType::Handle(new_value.GetType(Heap::kNew));
  AbstractType& pointer_type_arg =
      AbstractType::Handle(pointer.type_argument());
  CheckSized(pointer_type_arg);
  ASSERT(DartAndCTypeCorrespond(pointer_type_arg, arg_type));

  classid_t type_cid = pointer_type_arg.type_class_id();
  StoreValue(zone, pointer, type_cid, new_value);
  return Object::null();
}

DEFINE_NATIVE_ENTRY(Ffi_sizeOf, 1, 0) {
  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
  CheckIsConcreteNativeType(type_arg);
  CheckSized(type_arg);

  classid_t type_cid = type_arg.type_class_id();
  return Smi::New(compiler::ffi::ElementSizeInBytes(type_cid));
}

// TODO(dacoharkes): Cache the trampolines.
// We can possibly address simultaniously with 'precaching' in AOT.
static RawFunction* TrampolineFunction(const Function& dart_signature,
                                       const Function& c_signature) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  String& name =
      String::ZoneHandle(Symbols::New(Thread::Current(), "FfiTrampoline"));
  const Library& lib = Library::Handle(Library::FfiLibrary());
  const Class& owner_class = Class::Handle(lib.toplevel_class());
  Function& function =
      Function::Handle(zone, Function::New(name, RawFunction::kFfiTrampoline,
                                           /*is_static=*/true,
                                           /*is_const=*/false,
                                           /*is_abstract=*/false,
                                           /*is_external=*/false,
                                           /*is_native=*/false, owner_class,
                                           TokenPosition::kMinSource));
  function.set_is_debuggable(false);
  function.set_num_fixed_parameters(dart_signature.num_fixed_parameters());
  function.set_result_type(AbstractType::Handle(dart_signature.result_type()));
  function.set_parameter_types(Array::Handle(dart_signature.parameter_types()));

  // The signature function won't have any names for the parameters. We need to
  // assign unique names for scope building and error messages.
  const intptr_t num_params = dart_signature.num_fixed_parameters();
  const Array& parameter_names = Array::Handle(Array::New(num_params));
  for (intptr_t i = 0; i < num_params; ++i) {
    if (i == 0) {
      name = Symbols::ClosureParameter().raw();
    } else {
      name = Symbols::NewFormatted(thread, ":ffiParam%" Pd, i);
    }
    parameter_names.SetAt(i, name);
  }
  function.set_parameter_names(parameter_names);
  function.SetFfiCSignature(c_signature);

  return function.raw();
}

DEFINE_NATIVE_ENTRY(Ffi_asFunction, 1, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
  AbstractType& pointer_type_arg =
      AbstractType::Handle(pointer.type_argument());
  ASSERT(IsNativeFunction(pointer_type_arg));
  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
  ASSERT(DartAndCTypeCorrespond(pointer_type_arg, type_arg));

  Function& dart_signature = Function::Handle(Type::Cast(type_arg).signature());
  TypeArguments& nativefunction_type_args =
      TypeArguments::Handle(pointer_type_arg.arguments());
  AbstractType& nativefunction_type_arg =
      AbstractType::Handle(nativefunction_type_args.TypeAt(0));
  Function& c_signature =
      Function::Handle(Type::Cast(nativefunction_type_arg).signature());
  Function& function =
      Function::Handle(TrampolineFunction(dart_signature, c_signature));

  // Set the c function pointer in the context of the closure rather than in
  // the function so that we can reuse the function for each c function with
  // the same signature.
  Context& context = Context::Handle(Context::New(1));
  context.SetAt(0, Integer::Handle(zone, pointer.GetCMemoryAddress()));

  RawClosure* raw_closure =
      Closure::New(Object::null_type_arguments(), Object::null_type_arguments(),
                   function, context, Heap::kOld);

  return raw_closure;
}

// Generates assembly to trampoline from C++ back into Dart.
static void* GenerateFfiInverseTrampoline(const Function& signature,
                                          void* dart_entry_point) {
#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
  UNREACHABLE();
#elif !defined(TARGET_ARCH_X64)
  // https://github.com/dart-lang/sdk/issues/35774
  UNREACHABLE();
#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS) &&                \
    !defined(TARGET_OS_WINDOWS)
  // https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
  // https://github.com/dart-lang/sdk/issues/35772 Arm64
  // https://github.com/dart-lang/sdk/issues/35773 DBC
  UNREACHABLE();
#else

  // TODO(dacoharkes): Implement this.
  // https://github.com/dart-lang/sdk/issues/35761
  // Look at StubCode::GenerateInvokeDartCodeStub.
  UNREACHABLE();
#endif
}

// TODO(dacoharkes): Implement this feature.
// https://github.com/dart-lang/sdk/issues/35761
// For now, it always returns Pointer with address 0.
DEFINE_NATIVE_ENTRY(Ffi_fromFunction, 1, 1) {
  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(Closure, closure, arguments->NativeArgAt(0));

  Function& c_signature = Function::Handle(((Type&)type_arg).signature());

  Function& func = Function::Handle(closure.function());
  Code& code = Code::Handle(func.EnsureHasCode());
  void* entryPoint = reinterpret_cast<void*>(code.EntryPoint());

  THR_Print("Ffi_fromFunction: %s\n", type_arg.ToCString());
  THR_Print("Ffi_fromFunction: %s\n", c_signature.ToCString());
  THR_Print("Ffi_fromFunction: %s\n", closure.ToCString());
  THR_Print("Ffi_fromFunction: %s\n", func.ToCString());
  THR_Print("Ffi_fromFunction: %s\n", code.ToCString());
  THR_Print("Ffi_fromFunction: %p\n", entryPoint);
  THR_Print("Ffi_fromFunction: %" Pd "\n", code.Size());

  intptr_t address = reinterpret_cast<intptr_t>(
      GenerateFfiInverseTrampoline(c_signature, entryPoint));

  TypeArguments& type_args = TypeArguments::Handle(zone);
  type_args = TypeArguments::New(1);
  type_args.SetTypeAt(Pointer::kNativeTypeArgPos, type_arg);
  type_args = type_args.Canonicalize();

  Class& native_function_class = Class::Handle(
      Isolate::Current()->class_table()->At(kFfiNativeFunctionCid));
  native_function_class.EnsureIsFinalized(Thread::Current());

  Type& native_function_type = Type::Handle(
      Type::New(native_function_class, type_args, TokenPosition::kNoSource));
  native_function_type ^=
      ClassFinalizer::FinalizeType(Class::Handle(), native_function_type);
  native_function_type ^= native_function_type.Canonicalize();

  address = 0;  // https://github.com/dart-lang/sdk/issues/35761

  Pointer& result = Pointer::Handle(Pointer::New(
      native_function_type, Integer::Handle(zone, Integer::New(address))));

  return result.raw();
}

#if defined(TARGET_ARCH_DBC)

void FfiMarshalledArguments::SetFunctionAddress(uint64_t value) const {
  data_[kOffsetFunctionAddress] = value;
}

static intptr_t ArgumentHostRegisterIndex(host::Register reg) {
  for (intptr_t i = 0; i < host::CallingConventions::kNumArgRegs; i++) {
    if (host::CallingConventions::ArgumentRegisters[i] == reg) {
      return i;
    }
  }
  UNREACHABLE();
}

void FfiMarshalledArguments::SetRegister(host::Register reg,
                                         uint64_t value) const {
  const intptr_t reg_index = ArgumentHostRegisterIndex(reg);
  ASSERT(host::CallingConventions::ArgumentRegisters[reg_index] == reg);
  const intptr_t index = kOffsetRegisters + reg_index;
  data_[index] = value;
}

void FfiMarshalledArguments::SetFpuRegister(host::FpuRegister reg,
                                            uint64_t value) const {
  const intptr_t fpu_index = static_cast<intptr_t>(reg);
  ASSERT(host::CallingConventions::FpuArgumentRegisters[fpu_index] == reg);
  const intptr_t index = kOffsetFpuRegisters + fpu_index;
  data_[index] = value;
}

void FfiMarshalledArguments::SetNumStackSlots(intptr_t num_args) const {
  data_[kOffsetNumStackSlots] = num_args;
}

intptr_t FfiMarshalledArguments::GetNumStackSlots() const {
  return data_[kOffsetNumStackSlots];
}

void FfiMarshalledArguments::SetStackSlotValue(intptr_t index,
                                               uint64_t value) const {
  ASSERT(0 <= index && index < GetNumStackSlots());
  data_[kOffsetStackSlotValues + index] = value;
}

uint64_t* FfiMarshalledArguments::New(
    const compiler::ffi::FfiSignatureDescriptor& signature,
    const uint64_t* arg_values) {
  const intptr_t num_stack_slots = signature.num_stack_slots();
  const intptr_t size =
      FfiMarshalledArguments::kOffsetStackSlotValues + num_stack_slots;
  uint64_t* data = Thread::Current()->GetFfiMarshalledArguments(size);
  const auto& descr = FfiMarshalledArguments(data);

  descr.SetFunctionAddress(arg_values[compiler::ffi::kFunctionAddressRegister]);
  const intptr_t num_args = signature.length();
  descr.SetNumStackSlots(num_stack_slots);
  for (int i = 0; i < num_args; i++) {
    uint64_t arg_value = arg_values[compiler::ffi::kFirstArgumentRegister + i];
    HostLocation loc = signature.LocationAt(i);
    // TODO(36809): For 32 bit, support pair locations.
    if (loc.IsRegister()) {
      descr.SetRegister(loc.reg(), arg_value);
    } else if (loc.IsFpuRegister()) {
      descr.SetFpuRegister(loc.fpu_reg(), arg_value);
    } else {
      ASSERT(loc.IsStackSlot());
      ASSERT(loc.stack_index() < num_stack_slots);
      descr.SetStackSlotValue(loc.stack_index(), arg_value);
    }
  }

  return data;
}

#if defined(DEBUG)
void FfiMarshalledArguments::Print() const {
  OS::PrintErr("FfiMarshalledArguments data_ 0x%" Pp "\n",
               reinterpret_cast<intptr_t>(data_));
  OS::PrintErr("  00 0x%016" Px64 " (function address, int result)\n",
               data_[0]);
  for (intptr_t i = 0; i < host::CallingConventions::kNumArgRegs; i++) {
    const intptr_t index = kOffsetRegisters + i;
    const char* result_str = i == 0 ? ", float result" : "";
    OS::PrintErr("  %02" Pd " 0x%016" Px64 " (%s%s)\n", index, data_[index],
                 RegisterNames::RegisterName(
                     host::CallingConventions::ArgumentRegisters[i]),
                 result_str);
  }
  for (intptr_t i = 0; i < host::CallingConventions::kNumFpuArgRegs; i++) {
    const intptr_t index = kOffsetFpuRegisters + i;
    OS::PrintErr("  %02" Pd " 0x%016" Px64 " (%s)\n", index, data_[index],
                 RegisterNames::FpuRegisterName(
                     host::CallingConventions::FpuArgumentRegisters[i]));
  }
  const intptr_t index = kOffsetNumStackSlots;
  const intptr_t num_stack_slots = data_[index];
  OS::PrintErr("  %02" Pd " 0x%" Pp " (number of stack slots)\n", index,
               num_stack_slots);
  for (intptr_t i = 0; i < num_stack_slots; i++) {
    const intptr_t index = kOffsetStackSlotValues + i;
    OS::PrintErr("  %02" Pd " 0x%016" Px64 " (stack slot %" Pd ")\n", index,
                 data_[index], i);
  }
}
#endif  // defined(DEBUG)

#endif  // defined(TARGET_ARCH_DBC)

}  // namespace dart
