// 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.

#ifndef RUNTIME_VM_COMPILER_FFI_MARSHALLER_H_
#define RUNTIME_VM_COMPILER_FFI_MARSHALLER_H_

#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif  // defined(DART_PRECOMPILED_RUNTIME)

#include <platform/globals.h>

#include "vm/compiler/backend/locations.h"
#include "vm/compiler/ffi/callback.h"
#include "vm/compiler/ffi/native_calling_convention.h"
#include "vm/compiler/ffi/native_location.h"
#include "vm/compiler/ffi/native_type.h"
#include "vm/object.h"

namespace dart {

namespace compiler {

namespace ffi {

// Values below 0 index result (result might be multiple if composite).
const intptr_t kResultIndex = -1;

// Inspects the function signature and transitively any class and field
// definitions and annotations.
const NativeFunctionType* NativeFunctionTypeFromFunctionType(
    Zone* zone,
    const FunctionType& c_signature,
    const char** error);

// Provides the mapping from the native calling convention to the Dart calling
// convention.
//
// This class is set up in a query-able way so that it's underlying logic can
// be extended to support more native ABI features and calling conventions.
class BaseMarshaller : public ZoneAllocated {
 public:
  intptr_t num_args() const {
    return native_calling_convention_.argument_locations().length();
  }

  // Number of definitions passed to FfiCall, number of NativeParams, or number
  // of definitions passed to NativeReturn in IL.
  //
  // All non-struct values have 1 definition, struct values can have either 1
  // or multiple definitions. If a struct has multiple definitions, they either
  // correspond to the number of native locations in the native ABI or to word-
  // sized chunks.
  //
  // `arg_index` is the index of an argument.
  // `def_index_in_argument` is the definition in one argument.
  // `def_index_global` is the index of the definition in all arguments.
  intptr_t NumArgumentDefinitions() const;
  virtual intptr_t NumDefinitions(intptr_t arg_index) const;
  virtual intptr_t NumReturnDefinitions() const = 0;
  bool ArgumentIndexIsReturn(intptr_t arg_index) const;
  bool DefinitionIndexIsReturn(intptr_t def_index_global) const;
  intptr_t ArgumentIndex(intptr_t def_index_global) const;
  intptr_t FirstDefinitionIndex(intptr_t arg_index) const;
  intptr_t DefinitionInArgument(intptr_t def_index_global,
                                intptr_t arg_index) const;
  intptr_t DefinitionIndex(intptr_t def_index_in_arg, intptr_t arg_index) const;

  // The location of the argument at `arg_index`.
  const NativeLocation& Location(intptr_t arg_index) const {
    if (arg_index == kResultIndex) {
      return native_calling_convention_.return_location();
    }
    return *native_calling_convention_.argument_locations().At(arg_index);
  }

  // Unboxed representation on how the value is passed or received from regular
  // Dart code.
  //
  // Implemented in BaseMarshaller because most Representations are the same
  // in Calls and Callbacks.
  Representation RepInDart(intptr_t arg_index) const;

  // Representation on how the value is passed to or received from the FfiCall
  // instruction or StaticCall, NativeParameter, and NativeReturn instructions.
  virtual Representation RepInFfiCall(intptr_t def_index_global) const;
  void RepsInFfiCall(intptr_t arg_index,
                     GrowableArray<Representation>* out) const;

  // Bitcasting floats to ints, only required in SoftFP.
  bool RequiresBitCast(intptr_t index) const {
    return Location(index).payload_type().IsFloat() &&
           Location(index).container_type().IsInt();
  }

  // 8 or 16 bit int value to sign extend from.
  const NativeType& SignExtendFrom(intptr_t arg_index) const {
    return Location(arg_index).payload_type();
  }

  // The C Type (expressed in a Dart Type) of the argument at `arg_index`.
  //
  // Excluding the #0 argument which is the function pointer.
  //
  // Recurses into VarArgs if needed.
  AbstractTypePtr CType(intptr_t arg_index) const;

  AbstractTypePtr DartType(intptr_t arg_index) const;

 protected:
  bool IsPointerDartType(intptr_t arg_index) const;
  bool IsPointerCType(intptr_t arg_index) const;

 public:
  // The Dart and C Type is Pointer.
  //
  // Requires boxing or unboxing the Pointer object to int.
  bool IsPointerPointer(intptr_t arg_index) const;

  // The Dart type is TypedData and the C type is Pointer.
  //
  // Requires passing the typed data base in as tagged pointer.
  //
  // TODO(https://dartbug.com/55444): The typed data address load could be
  // done in IL.
  bool IsTypedDataPointer(intptr_t arg_index) const;

  // The Dart type is a compound (for example an Array or a TypedData+offset),
  // and the C type is Pointer.
  //
  // Requires passing in two definitions in IL: TypedDataBase + offset.
  //
  // TODO(https://dartbug.com/55444): The typed data address load could be
  // done in IL.
  bool IsCompoundPointer(intptr_t arg_index) const;

  // The C type is Handle, the Dart type can be anything.
  //
  // Requires passing the pointer to the Dart object in a handle.
  bool IsHandleCType(intptr_t arg_index) const;

  // The Dart and C Types are boolean.
  //
  // Requires converting the boolean into an int in IL.
  bool IsBool(intptr_t arg_index) const;

  // The Dart and C Types are compound (pass by value).
  bool IsCompoundCType(intptr_t arg_index) const;

  // Treated as a null constant in Dart.
  bool IsVoid(intptr_t arg_index) const {
    return AbstractType::Handle(zone_, CType(arg_index)).type_class_id() ==
           kFfiVoidCid;
  }

  bool ContainsHandles() const;

  bool contains_varargs() const {
    return native_calling_convention_.contains_varargs();
  }

  // Note that the Dart arguments are indexed starting at
  // `dart_signature_params_start_at()`.
  //
  // Closures created by `asFunction` have the pointer as first parameter.
  // `@Native`s don't have an implicit first parameter.
  const Function& dart_signature() const { return dart_signature_; }
  intptr_t dart_signature_params_start_at() const {
    return dart_signature_params_start_at_;
  }
  const FunctionType& c_signature() const { return c_signature_; }
  StringPtr function_name() const { return dart_signature_.name(); }

 protected:
  BaseMarshaller(Zone* zone,
                 const Function& dart_signature,
                 intptr_t dart_signature_params_start_at,
                 const FunctionType& c_signature,
                 const NativeCallingConvention& native_calling_convention)
      : zone_(zone),
        dart_signature_(dart_signature),
        dart_signature_params_start_at_(dart_signature_params_start_at),
        c_signature_(c_signature),
        native_calling_convention_(native_calling_convention) {}

  ~BaseMarshaller() {}

  Zone* zone_;
  // Contains the function pointer as argument #0.
  // The Dart signature is used for the function and argument names.
  const Function& dart_signature_;
  const intptr_t dart_signature_params_start_at_;
  const FunctionType& c_signature_;
  const NativeCallingConvention& native_calling_convention_;
};

class CallMarshaller : public BaseMarshaller {
 public:
  static CallMarshaller* FromFunction(Zone* zone,
                                      const Function& function,
                                      intptr_t function_params_start_at,
                                      const FunctionType& c_signature,
                                      const char** error);

  CallMarshaller(Zone* zone,
                 const Function& dart_signature,
                 intptr_t dart_signature_params_start_at,
                 const FunctionType& c_signature,
                 const NativeCallingConvention& native_calling_convention)
      : BaseMarshaller(zone,
                       dart_signature,
                       dart_signature_params_start_at,
                       c_signature,
                       native_calling_convention) {}

  virtual intptr_t NumDefinitions(intptr_t arg_index) const;
  virtual intptr_t NumReturnDefinitions() const;

  virtual Representation RepInFfiCall(intptr_t def_index_global) const;

  // The location of the inputs to the IL FfiCall instruction.
  dart::Location LocInFfiCall(intptr_t def_index_global) const;

  // Allocate a TypedData before the FfiCall and pass it into the FfiCall so
  // that it can be populated in assembly.
  bool ReturnsCompound() const;
  intptr_t CompoundReturnSizeInBytes() const;

  // We allocate space for PointerToMemory arguments and PointerToMemory return
  // locations on the stack. This is faster than allocation ExternalTypedData.
  // Normal TypedData is not an option, as these might be relocated by GC
  // during FFI calls.
  intptr_t PassByPointerStackOffset(intptr_t arg_index) const;

  // The total amount of stack space required for FFI trampolines.
  intptr_t RequiredStackSpaceInBytes() const;

 protected:
  ~CallMarshaller() {}
};

class CallbackMarshaller : public BaseMarshaller {
 public:
  static CallbackMarshaller* FromFunction(Zone* zone,
                                          const Function& function,
                                          const char** error);

  CallbackMarshaller(Zone* zone,
                     const Function& dart_signature,
                     const FunctionType& c_signature,
                     const NativeCallingConvention& native_calling_convention,
                     const NativeLocations& callback_locs)
      : BaseMarshaller(zone,
                       dart_signature,
                       /*dart_signature_params_start_at=*/0,
                       c_signature,
                       native_calling_convention),
        callback_locs_(callback_locs) {}

  virtual Representation RepInFfiCall(intptr_t def_index_global) const;

  virtual intptr_t NumDefinitions(intptr_t arg_index) const;
  virtual intptr_t NumReturnDefinitions() const;

  // All parameters are saved on stack to do safe-point transition.
  const NativeLocation& NativeLocationOfNativeParameter(
      intptr_t def_index) const;

  // All parameters are saved on stack to do safe-point transition.
  dart::Location LocationOfNativeParameter(intptr_t def_index) const {
    const auto& native_loc = NativeLocationOfNativeParameter(def_index);
    if (native_loc.IsPointerToMemory()) {
      return native_loc.AsPointerToMemory().pointer_location().AsLocation();
    }
    return native_loc.AsLocation();
  }

 protected:
  ~CallbackMarshaller() {}

  const NativeLocations& callback_locs_;
};

}  // namespace ffi

}  // namespace compiler

}  // namespace dart

#endif  // RUNTIME_VM_COMPILER_FFI_MARSHALLER_H_
