42 const intptr_t num_arguments =
44 auto& argument_representations =
48 for (intptr_t
i = 0;
i < num_arguments;
i++) {
50 const bool varargs = arg_type.
type_class() == object_store->varargs_class();
54 variadic_arguments_index =
i;
55 ASSERT(arg_type.IsRecordType());
56 const auto& record_type = RecordType::Cast(arg_type);
57 const intptr_t num_fields = record_type.NumFields();
59 for (intptr_t
i = 0;
i < num_fields;
i++) {
60 field_type ^= record_type.FieldTypeAt(
i);
62 if (*
error !=
nullptr) {
65 argument_representations.Add(rep);
69 if (*
error !=
nullptr) {
72 argument_representations.Add(rep);
76 const auto& result_type =
78 const auto result_representation =
80 if (*
error !=
nullptr) {
84 const auto result =
new (zone)
86 variadic_arguments_index);
92 intptr_t function_params_start_at,
97 const auto native_function_signature =
99 if (*
error !=
nullptr) {
102 const auto& native_calling_convention =
114 const auto& parameter_types =
116 const intptr_t parameter_type_length = parameter_types.Length();
117 const intptr_t last_param_index = parameter_type_length - 1;
121 const bool has_varargs =
122 last_arg_type.type_class() == object_store->varargs_class();
127 if (has_varargs && real_arg_index >= last_param_index) {
132 if (var_args_type_arg.IsRecordType()) {
133 const intptr_t index_in_record = real_arg_index - last_param_index;
134 const auto& record_type = RecordType::Cast(var_args_type_arg);
135 ASSERT(index_in_record < record_type.NumFields());
136 return record_type.FieldTypeAt(index_in_record);
138 ASSERT(!var_args_type_arg.IsNull());
139 return var_args_type_arg.ptr();
196 return type.type_class() ==
203 if (cls.id() == compiler_state.CompoundClass().id() ||
204 cls.id() == compiler_state.ArrayClass().id()) {
207 cls ^= cls.SuperClass();
208 if (cls.id() == compiler_state.StructClass().id() ||
209 cls.id() == compiler_state.UnionClass().id()) {
262 const auto& loc =
Location(arg_index);
263 const auto&
type = loc.payload_type();
269 if (
type.IsPrimitive()) {
276 ASSERT(!loc.IsPointerToMemory());
277 if (loc.IsMultiple()) {
279 const auto& multiple = loc.AsMultiple();
280 return multiple.locations().length();
286 const intptr_t size_in_bytes =
type.SizeInBytes();
287 const intptr_t num_defs =
295 const auto& loc =
Location(arg_index);
296 const auto&
type = loc.payload_type();
297 if (
type.IsCompound() && loc.IsPointerToMemory()) {
308 const auto& loc =
Location(arg_index);
309 const auto&
type = loc.payload_type();
310 if (
type.IsCompound() && loc.IsPointerToMemory()) {
334 if (loc.IsMultiple()) {
335 const auto&
type = loc.payload_type();
375 intptr_t arg_index = 0;
376 for (; arg_index <
num_args(); arg_index++) {
378 if (
defs > def_index_global) {
390 intptr_t num_defs = 0;
391 for (intptr_t
i = 0;
i < arg_index;
i++) {
398 intptr_t arg_index)
const {
413 intptr_t arg_index)
const {
455 const auto& location =
Location(arg_index);
456 if (location.container_type().IsPrimitive()) {
459 ASSERT(location.container_type().IsCompound());
461 if (location.IsStack()) {
466 if (location.IsMultiple()) {
467 const intptr_t def_index_in_arg =
469 const auto& def_loc =
470 *(location.AsMultiple().locations()[def_index_in_arg]);
499 const auto& location =
Location(arg_index);
507 const intptr_t def_index_in_arg =
524 intptr_t def_index_global)
const {
532 const auto& location =
Location(arg_index);
533 if (location.IsPointerToMemory()) {
555 for (
int i = 0;
i < num_definitions;
i++) {
574 const bool is_atomic =
575 rep_in_ffi_call == kUnboxedDouble || rep_in_ffi_call == kUnboxedFloat;
588#if defined(TARGET_ARCH_ARM)
591 if (fpu_loc.IsLowestBits()) {
592 return fpu_loc.WidenToQFpuRegister(zone).
AsLocation();
620 const intptr_t def_index_in_arg =
623 if (def_loc.IsStack()) {
629 if (def_loc.IsFpuRegisters()) {
633 return def_loc.AsLocation();
637 const intptr_t def_index_in_arg =
641 if (pointer_location.IsStack()) {
646 return pointer_location.AsLocation();
654 const intptr_t def_index_in_arg =
697 (arg_index >= 0 && arg_index <
num_args()) ||
700 intptr_t stack_offset = 0;
705#if (defined(DART_TARGET_OS_MACOS_IOS) || defined(DART_TARGET_OS_MACOS)) && \
706 defined(TARGET_ARCH_ARM64)
719 if (result_location.IsPointerToMemory()) {
720 stack_offset += result_location.payload_type().SizeInBytes();
726 if (arg_index ==
i) {
730 if (arg_location.IsPointerToMemory()) {
731 stack_offset += arg_location.payload_type().SizeInBytes();
766 argument_locations.
length() + (treat_return_loc ? 1 : 0)));
769 for (intptr_t
i = 0, n = argument_locations.
length();
i < n;
i++) {
770 translator.AllocateArgument(*argument_locations[
i]);
772 if (treat_return_loc) {
773 translator.AllocateArgument(return_loc);
775 for (intptr_t
i = 0, n = argument_locations.
length();
i < n; ++
i) {
777 &translator.TranslateArgument(zone, *argument_locations[
i]));
779 if (treat_return_loc) {
780 pushed_locs.Add(&translator.TranslateArgument(zone, return_loc));
796 argument_slots_required_ += 1;
800 for (intptr_t
i = 0;
i < multiple.locations().
length();
i++) {
801 AllocateArgument(*multiple.locations().At(
i));
805 const auto& both = arg.
AsBoth();
806 AllocateArgument(both.location(0));
810 const NativeLocation& TranslateArgument(Zone* zone,
811 const NativeLocation& arg) {
821 const intptr_t stack_delta =
823 FfiCallbackMetadata::kNativeCallbackTrampolineStackDelta;
827 (argument_slots_required_ + stack_delta) *
829 return rebase.Rebase(arg);
832 if (arg.IsRegisters()) {
833 const auto&
result = *
new (zone) NativeStackLocation(
834 arg.payload_type(), arg.container_type(),
SPREG,
836 argument_slots_used_ += arg.AsRegisters().num_regs();
840 if (arg.IsFpuRegisters()) {
841 const auto&
result = *
new (zone) NativeStackLocation(
842 arg.payload_type(), arg.container_type(),
SPREG,
848 if (arg.IsPointerToMemory()) {
849 const auto& pointer_loc = arg.AsPointerToMemory().pointer_location();
850 const auto& pointer_ret_loc =
851 arg.AsPointerToMemory().pointer_return_location();
852 const auto& pointer_translated = TranslateArgument(zone, pointer_loc);
853 return *
new (zone) PointerToMemoryLocation(
854 pointer_translated, pointer_ret_loc, arg.payload_type().AsCompound());
857 if (arg.IsMultiple()) {
858 const auto& multiple = arg.AsMultiple();
861 for (intptr_t
i = 0;
i < multiple.locations().length();
i++) {
862 multiple_locations.Add(
863 &TranslateArgument(zone, *multiple.locations().At(
i)));
865 return *
new (zone) MultipleNativeLocations(
866 multiple.payload_type().AsCompound(), multiple_locations);
870 const auto& both = arg.AsBoth();
872 return TranslateArgument(zone, both.location(0));
875 intptr_t argument_slots_used_ = 0;
876 intptr_t argument_slots_required_ = 0;
881 const char**
error) {
885 const auto native_function_signature =
887 if (*
error !=
nullptr) {
890 const auto& native_calling_convention =
892 const auto& callback_locs =
894 zone, native_calling_convention.argument_locations(),
895 native_calling_convention.return_location());
901 intptr_t def_index)
const {
904 const auto& result_loc =
Location(arg_index);
905 if (result_loc.IsPointerToMemory()) {
915 ASSERT(loc.IsStack() || loc.IsPointerToMemory() || loc.IsMultiple());
918 if (loc.payload_type().IsPrimitive()) {
924 }
else if (loc.IsPointerToMemory()) {
925 const auto& pointer_loc = loc.AsPointerToMemory().pointer_location();
926 ASSERT(pointer_loc.IsStack() &&
927 pointer_loc.AsStack().base_register() ==
SPREG);
930 const auto& multiple = loc.AsMultiple();
932 const auto& multi_loc = *multiple.locations().At(index);
933 ASSERT(multi_loc.IsStack() && multi_loc.AsStack().base_register() ==
SPREG);
#define DEBUG_ASSERT(cond)
#define ASSERT_EQUAL(expected, actual)
virtual ClassPtr type_class() const
const T & At(intptr_t index) const
static constexpr Register kReturnReg
const Class & TypedDataClass()
AbstractTypePtr ParameterTypeAt(intptr_t index) const
bool ContainsHandles() const
AbstractTypePtr result_type() const
intptr_t NumOptionalPositionalParameters() const
intptr_t num_fixed_parameters() const
intptr_t NumOptionalParameters() const
ArrayPtr parameter_types() const
ArrayPtr parameter_types() const
AbstractTypePtr ParameterTypeAt(intptr_t index) const
AbstractTypePtr result_type() const
ObjectStore * object_store() const
static IsolateGroup * Current()
static Location Pair(Location first, Location second)
static Location RequiresStack()
static Location RegisterLocation(Register reg)
static Object & ZoneHandle()
static Thread * Current()
CompilerState & compiler_state()
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
bool IsPointerPointer(intptr_t arg_index) const
bool IsCompoundPointer(intptr_t arg_index) const
bool IsBool(intptr_t arg_index) const
bool IsPointerDartType(intptr_t arg_index) const
intptr_t DefinitionIndex(intptr_t def_index_in_arg, intptr_t arg_index) const
const FunctionType & c_signature() const
bool ArgumentIndexIsReturn(intptr_t arg_index) const
bool IsPointerCType(intptr_t arg_index) const
const NativeCallingConvention & native_calling_convention_
bool IsCompoundCType(intptr_t arg_index) const
void RepsInFfiCall(intptr_t arg_index, GrowableArray< Representation > *out) const
bool DefinitionIndexIsReturn(intptr_t def_index_global) const
virtual intptr_t NumReturnDefinitions() const =0
intptr_t FirstDefinitionIndex(intptr_t arg_index) const
const FunctionType & c_signature_
virtual Representation RepInFfiCall(intptr_t def_index_global) const
const intptr_t dart_signature_params_start_at_
Representation RepInDart(intptr_t arg_index) const
bool IsTypedDataPointer(intptr_t arg_index) const
intptr_t ArgumentIndex(intptr_t def_index_global) const
const Function & dart_signature_
const NativeLocation & Location(intptr_t arg_index) const
bool IsHandleCType(intptr_t arg_index) const
virtual intptr_t NumDefinitions(intptr_t arg_index) const
intptr_t NumArgumentDefinitions() const
AbstractTypePtr CType(intptr_t arg_index) const
bool ContainsHandles() const
intptr_t DefinitionInArgument(intptr_t def_index_global, intptr_t arg_index) const
AbstractTypePtr DartType(intptr_t arg_index) const
intptr_t num_args() const
const NativeLocation & location(intptr_t index) const
virtual intptr_t NumDefinitions(intptr_t arg_index) const
CallMarshaller(Zone *zone, const Function &dart_signature, intptr_t dart_signature_params_start_at, const FunctionType &c_signature, const NativeCallingConvention &native_calling_convention)
intptr_t PassByPointerStackOffset(intptr_t arg_index) const
dart::Location LocInFfiCall(intptr_t def_index_global) const
virtual intptr_t NumReturnDefinitions() const
intptr_t RequiredStackSpaceInBytes() const
static CallMarshaller * FromFunction(Zone *zone, const Function &function, intptr_t function_params_start_at, const FunctionType &c_signature, const char **error)
bool ReturnsCompound() const
virtual Representation RepInFfiCall(intptr_t def_index_global) const
intptr_t CompoundReturnSizeInBytes() const
static NativeLocations & TranslateArgumentLocations(Zone *zone, const NativeLocations &argument_locations, const NativeLocation &return_loc)
const NativeLocation & NativeLocationOfNativeParameter(intptr_t def_index) const
virtual intptr_t NumDefinitions(intptr_t arg_index) const
virtual Representation RepInFfiCall(intptr_t def_index_global) const
const NativeLocations & callback_locs_
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)
virtual intptr_t NumReturnDefinitions() const
const NativeLocations & locations() const
static const NativeCallingConvention & FromSignature(Zone *zone, const NativeFunctionType &signature)
intptr_t StackTopInBytes() const
virtual Location AsLocation() const
static constexpr intptr_t kNoVariadicArguments
virtual bool IsMultiple() const
virtual bool IsFpuRegisters() const
virtual bool IsPointerToMemory() const
virtual bool IsBoth() const
const MultipleNativeLocations & AsMultiple() const
virtual Location AsLocation() const
const NativeType & container_type() const
virtual bool IsStack() const
const NativeRegistersLocation & AsRegisters() const
const PointerToMemoryLocation & AsPointerToMemory() const
const NativeStackLocation & AsStack() const
virtual bool IsRegisters() const
const BothNativeLocations & AsBoth() const
const NativeFpuRegistersLocation & AsFpuRegisters() const
const NativeType & payload_type() const
intptr_t num_regs() const
Representation AsRepresentationOverApprox(Zone *zone_) const
virtual bool IsInt() const
static const NativeType * FromAbstractType(Zone *zone, const AbstractType &type, const char **error)
virtual bool IsFloat() const
virtual intptr_t SizeInBytes() const =0
virtual bool IsPrimitive() const
const NativeLocation & pointer_location() const
const uint8_t uint32_t uint32_t GError ** error
Dart_NativeFunction function
static int SizeInBytes(Dart_TypedData_Type type)
static bool IsCompound(Zone *zone, const AbstractType &type)
const intptr_t kAfterLastArgumentIndex
static Location SelectFpuLocationInIL(Zone *zone, const NativeLocation &location)
const intptr_t kNativeParamsStartAt
static const intptr_t kOffsetInBytesIndex
static const intptr_t kTypedDataBaseIndex
static Representation SelectRepresentationInIL(Zone *zone, const NativeLocation &location)
static Location ConvertToAnyLocation(const NativeStackLocation &loc, Representation rep_in_ffi_call)
const intptr_t kResultIndex
ZoneGrowableArray< const NativeLocation * > NativeLocations
const NativeFunctionType * NativeFunctionTypeFromFunctionType(Zone *zone, const FunctionType &c_signature, const char **error)
static constexpr intptr_t kWordSize
static constexpr Representation kUnboxedUword
static constexpr Representation kUnboxedWord
constexpr intptr_t kIntptrMax
constexpr intptr_t kCallbackSlotsBeforeSavedArguments