// 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/compiler/jit/compiler.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 native code into Dart.
static uword CompileNativeCallback(const Function& c_signature,
                                   const Function& dart_target) {
#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
  UNREACHABLE();
#elif defined(TARGET_ARCH_DBC)
  // https://github.com/dart-lang/sdk/issues/35774
  // FFI is supported, but callbacks are not.
  Exceptions::ThrowUnsupportedError(
      "FFI callbacks are not yet supported on DBC.");
#else
  Thread* const thread = Thread::Current();
  const int32_t callback_id = thread->AllocateFfiCallbackId();

  // Create a new Function named 'FfiCallback' and stick it in the 'dart:ffi'
  // library. Note that these functions will never be invoked by Dart, so it
  // doesn't matter that they all have the same name.
  Zone* const Z = thread->zone();
  const String& name =
      String::ZoneHandle(Symbols::New(Thread::Current(), "FfiCallback"));
  const Library& lib = Library::Handle(Library::FfiLibrary());
  const Class& owner_class = Class::Handle(lib.toplevel_class());
  const Function& function =
      Function::Handle(Z, 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);

  // Set callback-specific fields which the flow-graph builder needs to generate
  // the body.
  function.SetFfiCSignature(c_signature);
  function.SetFfiCallbackId(callback_id);
  function.SetFfiCallbackTarget(dart_target);

  // We compile the callback immediately because we need to return a pointer to
  // the entry-point. Native calls do not use patching like Dart calls, so we
  // cannot compile it lazily.
  const Object& result =
      Object::Handle(Z, Compiler::CompileOptimizedFunction(thread, function));
  if (result.IsError()) {
    Exceptions::PropagateError(Error::Cast(result));
  }
  ASSERT(result.IsCode());
  const Code& code = Code::Cast(result);

  thread->SetFfiCallbackCode(callback_id, code);

  return code.EntryPoint();
#endif
}

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

  const Function& native_signature =
      Function::Handle(((Type&)type_arg).signature());
  Function& func = Function::Handle(closure.function());
  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();

  // The FE verifies that the target of a 'fromFunction' is a static method, so
  // the value we see here must be a static tearoff. See ffi_use_sites.dart for
  // details.
  //
  // TODO(36748): Define hot-reload semantics of native callbacks. We may need
  // to look up the target by name.
  ASSERT(func.IsImplicitClosureFunction());
  func = func.parent_function();
  ASSERT(func.is_static());

  const uword address = CompileNativeCallback(native_signature, func);

  const 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() || loc.IsDoubleStackSlot());
      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
