diff --git a/runtime/bin/ffi_test/ffi_test_functions_generated.cc b/runtime/bin/ffi_test/ffi_test_functions_generated.cc index c42221f208a..40f039faf1f 100644 --- a/runtime/bin/ffi_test/ffi_test_functions_generated.cc +++ b/runtime/bin/ffi_test/ffi_test_functions_generated.cc @@ -22996,6 +22996,38 @@ DART_EXPORT int64_t VariadicAt1Int64x7Struct12BytesHomogeneousInt32(int64_t a0, return result; } +// Used for testing structs and unions by value. +// Variadic arguments test on macos_arm64. +DART_EXPORT int32_t VariadicAt1Struct12BytesHomogeneousInt32Int32x4( + Struct12BytesHomogeneousInt32 a0, + ...) { + va_list var_args; + va_start(var_args, a0); + int32_t a1 = va_arg(var_args, int32_t); + int32_t a2 = va_arg(var_args, int32_t); + int32_t a3 = va_arg(var_args, int32_t); + int32_t a4 = va_arg(var_args, int32_t); + va_end(var_args); + + std::cout << "VariadicAt1Struct12BytesHomogeneousInt32Int32x4" << "((" + << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), " << a1 << ", " + << a2 << ", " << a3 << ", " << a4 << ")" << "\n"; + + int32_t result = 0; + + result += a0.a0; + result += a0.a1; + result += a0.a2; + result += a1; + result += a2; + result += a3; + result += a4; + + std::cout << "result = " << result << "\n"; + + return result; +} + // Used for testing structs and unions by value. // Single variadic argument. DART_EXPORT intptr_t TestVariadicAt1Int64x2( @@ -23897,4 +23929,50 @@ DART_EXPORT intptr_t TestVariadicAt1Int64x7Struct12BytesHomogeneousInt32( return 0; } +// Used for testing structs and unions by value. +// Variadic arguments test on macos_arm64. +DART_EXPORT intptr_t TestVariadicAt1Struct12BytesHomogeneousInt32Int32x4( + // NOLINTNEXTLINE(whitespace/parens) + int32_t (*f)(Struct12BytesHomogeneousInt32 a0, ...)) { + Struct12BytesHomogeneousInt32 a0 = {}; + int32_t a1; + int32_t a2; + int32_t a3; + int32_t a4; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1 = 4; + a2 = -5; + a3 = 6; + a4 = -7; + + std::cout << "Calling TestVariadicAt1Struct12BytesHomogeneousInt32Int32x4(" + << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), " << a1 + << ", " << a2 << ", " << a3 << ", " << a4 << ")" << ")\n"; + + int32_t result = f(a0, a1, a2, a3, a4); + + std::cout << "result = " << result << "\n"; + + CHECK_EQ(-4, result); + + // Pass argument that will make the Dart callback throw. + a0.a0 = 42; + + result = f(a0, a1, a2, a3, a4); + + CHECK_EQ(0, result); + + // Pass argument that will make the Dart callback return null. + a0.a0 = 84; + + result = f(a0, a1, a2, a3, a4); + + CHECK_EQ(0, result); + + return 0; +} + } // namespace dart diff --git a/runtime/vm/compiler/ffi/native_calling_convention.cc b/runtime/vm/compiler/ffi/native_calling_convention.cc index 3914afe326d..a555193b9bb 100644 --- a/runtime/vm/compiler/ffi/native_calling_convention.cc +++ b/runtime/vm/compiler/ffi/native_calling_convention.cc @@ -242,7 +242,7 @@ class ArgumentAllocator : public ValueObject { zone_, payload_type, container_type, AllocateCpuRegister()); } } - return AllocateStack(payload_type); + return AllocateStack(payload_type, is_vararg); } // Constructs a container type. diff --git a/runtime/vm/compiler/ffi/native_calling_convention_test.cc b/runtime/vm/compiler/ffi/native_calling_convention_test.cc index 456a6936465..5be3304d8cb 100644 --- a/runtime/vm/compiler/ffi/native_calling_convention_test.cc +++ b/runtime/vm/compiler/ffi/native_calling_convention_test.cc @@ -969,6 +969,28 @@ UNIT_TEST_CASE_WITH_ZONE( RunSignatureTest(Z, "variadic_stradle_last_register", native_signature); } +// Struct parameter that potentially is partially allocated to a register and +// partially to the stack. Mainly interesting on ARM64 and RISC-V. +// +// See the *.expect in ./unit_tests for this behavior. +UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_variadic_less_than_word) { +#if defined(TARGET_ARCH_IS_32_BIT) + const auto& halfptr_type = *new (Z) NativePrimitiveType(kInt16); +#elif defined(TARGET_ARCH_IS_64_BIT) + const auto& halfptr_type = *new (Z) NativePrimitiveType(kInt32); +#endif + + auto& arguments = *new (Z) NativeTypes(Z, 12); + for (intptr_t i = 0; i < 12; i++) { + arguments.Add(&halfptr_type); + } + + const auto& native_signature = *new (Z) NativeFunctionType( + arguments, halfptr_type, /*variadic_arguments_index=*/1); + + RunSignatureTest(Z, "variadic_less_than_word", native_signature); +} + } // namespace ffi } // namespace compiler } // namespace dart diff --git a/runtime/vm/compiler/ffi/native_type.cc b/runtime/vm/compiler/ffi/native_type.cc index 368fcbd72b0..b0c86f9bbcb 100644 --- a/runtime/vm/compiler/ffi/native_type.cc +++ b/runtime/vm/compiler/ffi/native_type.cc @@ -152,7 +152,10 @@ intptr_t NativePrimitiveType::SizeInBytes() const { } intptr_t NativePrimitiveType::AlignmentInBytesStack(bool is_vararg) const { - switch (CallingConventions::kArgumentStackAlignment) { + const auto alignment = + is_vararg ? CallingConventions::kArgumentStackAlignmentVarArgs + : CallingConventions::kArgumentStackAlignment; + switch (alignment) { case kAlignedToWordSize: // The default is to align stack arguments to word size. return compiler::target::kWordSize; diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_android.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_android.expect new file mode 100644 index 00000000000..abd76a4f1a3 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_android.expect @@ -0,0 +1,14 @@ +r0 int32 +r1 int32 +r2 int32 +r3 int32 +r4 int32 +r5 int32 +r6 int32 +r7 int32 +S+0 int32 +S+8 int32 +S+16 int32 +S+24 int32 +=> +r0 int32 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_fuchsia.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_fuchsia.expect new file mode 100644 index 00000000000..abd76a4f1a3 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_fuchsia.expect @@ -0,0 +1,14 @@ +r0 int32 +r1 int32 +r2 int32 +r3 int32 +r4 int32 +r5 int32 +r6 int32 +r7 int32 +S+0 int32 +S+8 int32 +S+16 int32 +S+24 int32 +=> +r0 int32 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_ios.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_ios.expect new file mode 100644 index 00000000000..e70c7a8db69 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_ios.expect @@ -0,0 +1,14 @@ +r0 int32 +S+0 int32 +S+8 int32 +S+16 int32 +S+24 int32 +S+32 int32 +S+40 int32 +S+48 int32 +S+56 int32 +S+64 int32 +S+72 int32 +S+80 int32 +=> +r0 int32 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_linux.expect new file mode 100644 index 00000000000..abd76a4f1a3 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_linux.expect @@ -0,0 +1,14 @@ +r0 int32 +r1 int32 +r2 int32 +r3 int32 +r4 int32 +r5 int32 +r6 int32 +r7 int32 +S+0 int32 +S+8 int32 +S+16 int32 +S+24 int32 +=> +r0 int32 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_macos.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_macos.expect new file mode 100644 index 00000000000..e70c7a8db69 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_macos.expect @@ -0,0 +1,14 @@ +r0 int32 +S+0 int32 +S+8 int32 +S+16 int32 +S+24 int32 +S+32 int32 +S+40 int32 +S+48 int32 +S+56 int32 +S+64 int32 +S+72 int32 +S+80 int32 +=> +r0 int32 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_win.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_win.expect new file mode 100644 index 00000000000..abd76a4f1a3 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm64_win.expect @@ -0,0 +1,14 @@ +r0 int32 +r1 int32 +r2 int32 +r3 int32 +r4 int32 +r5 int32 +r6 int32 +r7 int32 +S+0 int32 +S+8 int32 +S+16 int32 +S+24 int32 +=> +r0 int32 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm_android.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm_android.expect new file mode 100644 index 00000000000..69e01c41048 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm_android.expect @@ -0,0 +1,14 @@ +r0 int32[int16] +r1 int32[int16] +r2 int32[int16] +r3 int32[int16] +S+0 int32[int16] +S+4 int32[int16] +S+8 int32[int16] +S+12 int32[int16] +S+16 int32[int16] +S+20 int32[int16] +S+24 int32[int16] +S+28 int32[int16] +=> +r0 int32[int16] diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm_ios.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm_ios.expect new file mode 100644 index 00000000000..69e01c41048 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm_ios.expect @@ -0,0 +1,14 @@ +r0 int32[int16] +r1 int32[int16] +r2 int32[int16] +r3 int32[int16] +S+0 int32[int16] +S+4 int32[int16] +S+8 int32[int16] +S+12 int32[int16] +S+16 int32[int16] +S+20 int32[int16] +S+24 int32[int16] +S+28 int32[int16] +=> +r0 int32[int16] diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm_linux.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm_linux.expect new file mode 100644 index 00000000000..69e01c41048 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/arm_linux.expect @@ -0,0 +1,14 @@ +r0 int32[int16] +r1 int32[int16] +r2 int32[int16] +r3 int32[int16] +S+0 int32[int16] +S+4 int32[int16] +S+8 int32[int16] +S+12 int32[int16] +S+16 int32[int16] +S+20 int32[int16] +S+24 int32[int16] +S+28 int32[int16] +=> +r0 int32[int16] diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/ia32_android.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/ia32_android.expect new file mode 100644 index 00000000000..2505a8afd27 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/ia32_android.expect @@ -0,0 +1,14 @@ +S+0 int32[int16] +S+4 int32[int16] +S+8 int32[int16] +S+12 int32[int16] +S+16 int32[int16] +S+20 int32[int16] +S+24 int32[int16] +S+28 int32[int16] +S+32 int32[int16] +S+36 int32[int16] +S+40 int32[int16] +S+44 int32[int16] +=> +eax int16 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/ia32_linux.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/ia32_linux.expect new file mode 100644 index 00000000000..2505a8afd27 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/ia32_linux.expect @@ -0,0 +1,14 @@ +S+0 int32[int16] +S+4 int32[int16] +S+8 int32[int16] +S+12 int32[int16] +S+16 int32[int16] +S+20 int32[int16] +S+24 int32[int16] +S+28 int32[int16] +S+32 int32[int16] +S+36 int32[int16] +S+40 int32[int16] +S+44 int32[int16] +=> +eax int16 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/ia32_win.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/ia32_win.expect new file mode 100644 index 00000000000..2505a8afd27 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/ia32_win.expect @@ -0,0 +1,14 @@ +S+0 int32[int16] +S+4 int32[int16] +S+8 int32[int16] +S+12 int32[int16] +S+16 int32[int16] +S+20 int32[int16] +S+24 int32[int16] +S+28 int32[int16] +S+32 int32[int16] +S+36 int32[int16] +S+40 int32[int16] +S+44 int32[int16] +=> +eax int16 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/riscv32_linux.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/riscv32_linux.expect new file mode 100644 index 00000000000..bd7f07fe503 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/riscv32_linux.expect @@ -0,0 +1,14 @@ +a0 int32[int16] +a1 int32[int16] +a2 int32[int16] +t3 int32[int16] +t4 int32[int16] +t5 int32[int16] +a6 int32[int16] +a7 int32[int16] +S+0 int32[int16] +S+4 int32[int16] +S+8 int32[int16] +S+12 int32[int16] +=> +a0 int32[int16] diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/riscv64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/riscv64_linux.expect new file mode 100644 index 00000000000..7c1201ad6e0 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/riscv64_linux.expect @@ -0,0 +1,14 @@ +a0 int64[int32] +a1 int64[int32] +a2 int64[int32] +t3 int64[int32] +t4 int64[int32] +t5 int64[int32] +a6 int64[int32] +a7 int64[int32] +S+0 int64[int32] +S+8 int64[int32] +S+16 int64[int32] +S+24 int64[int32] +=> +a0 int64[int32] diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_fuchsia.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_fuchsia.expect new file mode 100644 index 00000000000..c61096aac55 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_fuchsia.expect @@ -0,0 +1,14 @@ +rdi int32 +rsi int32 +rdx int32 +rcx int32 +r8 int32 +r9 int32 +S+0 int32 +S+8 int32 +S+16 int32 +S+24 int32 +S+32 int32 +S+40 int32 +=> +rax int32 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_ios.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_ios.expect new file mode 100644 index 00000000000..c61096aac55 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_ios.expect @@ -0,0 +1,14 @@ +rdi int32 +rsi int32 +rdx int32 +rcx int32 +r8 int32 +r9 int32 +S+0 int32 +S+8 int32 +S+16 int32 +S+24 int32 +S+32 int32 +S+40 int32 +=> +rax int32 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_linux.expect new file mode 100644 index 00000000000..c61096aac55 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_linux.expect @@ -0,0 +1,14 @@ +rdi int32 +rsi int32 +rdx int32 +rcx int32 +r8 int32 +r9 int32 +S+0 int32 +S+8 int32 +S+16 int32 +S+24 int32 +S+32 int32 +S+40 int32 +=> +rax int32 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_macos.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_macos.expect new file mode 100644 index 00000000000..c61096aac55 --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_macos.expect @@ -0,0 +1,14 @@ +rdi int32 +rsi int32 +rdx int32 +rcx int32 +r8 int32 +r9 int32 +S+0 int32 +S+8 int32 +S+16 int32 +S+24 int32 +S+32 int32 +S+40 int32 +=> +rax int32 diff --git a/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_win.expect b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_win.expect new file mode 100644 index 00000000000..c288554e51b --- /dev/null +++ b/runtime/vm/compiler/ffi/unit_tests/variadic_less_than_word/x64_win.expect @@ -0,0 +1,14 @@ +rcx int32 +rdx int32 +r8 int32 +r9 int32 +S+0 int32 +S+8 int32 +S+16 int32 +S+24 int32 +S+32 int32 +S+40 int32 +S+48 int32 +S+56 int32 +=> +rax int32 diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h index 80b5b7929be..c2f4c00c5c1 100644 --- a/runtime/vm/constants_arm.h +++ b/runtime/vm/constants_arm.h @@ -718,6 +718,8 @@ class CallingConventions { // How stack arguments are aligned. static constexpr AlignmentStrategy kArgumentStackAlignment = kAlignedToWordSizeAndValueSize; + static constexpr AlignmentStrategy kArgumentStackAlignmentVarArgs = + kArgumentStackAlignment; // How fields in compounds are aligned. #if defined(DART_TARGET_OS_MACOS_IOS) diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h index 0930e81b3c7..26bb32878d5 100644 --- a/runtime/vm/constants_arm64.h +++ b/runtime/vm/constants_arm64.h @@ -584,9 +584,14 @@ class CallingConventions { // https://developer.apple.com/documentation/xcode/writing_arm64_code_for_apple_platforms static constexpr AlignmentStrategy kArgumentStackAlignment = kAlignedToValueSize; + // Varargs are aligned to wordsize. + static constexpr AlignmentStrategy kArgumentStackAlignmentVarArgs = + kAlignedToWordSize; #else static constexpr AlignmentStrategy kArgumentStackAlignment = kAlignedToWordSize; + static constexpr AlignmentStrategy kArgumentStackAlignmentVarArgs = + kArgumentStackAlignment; #endif // How fields in compounds are aligned. diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h index 8903cff7b84..d209d42ac1d 100644 --- a/runtime/vm/constants_ia32.h +++ b/runtime/vm/constants_ia32.h @@ -503,6 +503,8 @@ class CallingConventions { // How stack arguments are aligned. static constexpr AlignmentStrategy kArgumentStackAlignment = kAlignedToWordSize; + static constexpr AlignmentStrategy kArgumentStackAlignmentVarArgs = + kArgumentStackAlignment; // How fields in compounds are aligned. #if defined(DART_TARGET_OS_WINDOWS) diff --git a/runtime/vm/constants_riscv.h b/runtime/vm/constants_riscv.h index 90df737a77a..ab10687b616 100644 --- a/runtime/vm/constants_riscv.h +++ b/runtime/vm/constants_riscv.h @@ -557,6 +557,8 @@ class CallingConventions { // How stack arguments are aligned. static constexpr AlignmentStrategy kArgumentStackAlignment = kAlignedToWordSizeAndValueSize; + static constexpr AlignmentStrategy kArgumentStackAlignmentVarArgs = + kArgumentStackAlignment; // How fields in compounds are aligned. static constexpr AlignmentStrategy kFieldAlignment = kAlignedToValueSize; diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h index 548ee1fb677..208618358bb 100644 --- a/runtime/vm/constants_x64.h +++ b/runtime/vm/constants_x64.h @@ -571,6 +571,8 @@ class CallingConventions { // How stack arguments are aligned. static constexpr AlignmentStrategy kArgumentStackAlignment = kAlignedToWordSize; + static constexpr AlignmentStrategy kArgumentStackAlignmentVarArgs = + kArgumentStackAlignment; // How fields in compounds are aligned. static constexpr AlignmentStrategy kFieldAlignment = kAlignedToValueSize; @@ -641,6 +643,8 @@ class CallingConventions { // How stack arguments are aligned. static constexpr AlignmentStrategy kArgumentStackAlignment = kAlignedToWordSize; + static constexpr AlignmentStrategy kArgumentStackAlignmentVarArgs = + kArgumentStackAlignment; // How fields in compounds are aligned. static constexpr AlignmentStrategy kFieldAlignment = kAlignedToValueSize; diff --git a/tests/ffi/function_callbacks_varargs_generated_test.dart b/tests/ffi/function_callbacks_varargs_generated_test.dart index b3abfac2b96..ef27956403d 100644 --- a/tests/ffi/function_callbacks_varargs_generated_test.dart +++ b/tests/ffi/function_callbacks_varargs_generated_test.dart @@ -124,6 +124,11 @@ final testCases = [ Pointer.fromFunction( variadicAt1Int64x7Struct12BytesHomogeneousInt32, 0), variadicAt1Int64x7Struct12BytesHomogeneousInt32AfterCallback), + CallbackTest.withCheck( + "VariadicAt1Struct12BytesHomogeneousInt32Int32x4", + Pointer.fromFunction( + variadicAt1Struct12BytesHomogeneousInt32Int32x4, 0), + variadicAt1Struct12BytesHomogeneousInt32Int32x4AfterCallback), ]; typedef VariadicAt1Int64x2Type = Int64 Function(Int64, VarArgs<(Int64,)>); @@ -1488,3 +1493,70 @@ void variadicAt1Int64x7Struct12BytesHomogeneousInt32AfterCallback() { Expect.equals(5, result); } + +typedef VariadicAt1Struct12BytesHomogeneousInt32Int32x4Type = Int32 Function( + Struct12BytesHomogeneousInt32, VarArgs<(Int32, Int32, Int32, Int32)>); + +// Global variables to be able to test inputs after callback returned. +Struct12BytesHomogeneousInt32 + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a0 = + Pointer.fromAddress(0).ref; +int variadicAt1Struct12BytesHomogeneousInt32Int32x4_a1 = 0; +int variadicAt1Struct12BytesHomogeneousInt32Int32x4_a2 = 0; +int variadicAt1Struct12BytesHomogeneousInt32Int32x4_a3 = 0; +int variadicAt1Struct12BytesHomogeneousInt32Int32x4_a4 = 0; + +// Result variable also global, so we can delete it after the callback. +int variadicAt1Struct12BytesHomogeneousInt32Int32x4Result = 0; + +int variadicAt1Struct12BytesHomogeneousInt32Int32x4CalculateResult() { + int result = 0; + + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a0.a0; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a0.a1; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a0.a2; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a1; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a2; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a3; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a4; + + variadicAt1Struct12BytesHomogeneousInt32Int32x4Result = result; + + return result; +} + +/// Variadic arguments test on macos_arm64. +int variadicAt1Struct12BytesHomogeneousInt32Int32x4( + Struct12BytesHomogeneousInt32 a0, int a1, int a2, int a3, int a4) { + print( + "variadicAt1Struct12BytesHomogeneousInt32Int32x4(${a0}, ${a1}, ${a2}, ${a3}, ${a4})"); + + // Possibly throw. + if (a0.a0 == 42 || a0.a0 == 84) { + print("throwing!"); + throw Exception( + "VariadicAt1Struct12BytesHomogeneousInt32Int32x4 throwing on purpose!"); + } + + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a0 = a0; + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a1 = a1; + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a2 = a2; + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a3 = a3; + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a4 = a4; + + final result = + variadicAt1Struct12BytesHomogeneousInt32Int32x4CalculateResult(); + + print("result = $result"); + + return result; +} + +void variadicAt1Struct12BytesHomogeneousInt32Int32x4AfterCallback() { + final result = + variadicAt1Struct12BytesHomogeneousInt32Int32x4CalculateResult(); + + print("after callback result = $result"); + + Expect.equals(-4, result); +} diff --git a/tests/ffi/function_callbacks_varargs_native_callable_generated_test.dart b/tests/ffi/function_callbacks_varargs_native_callable_generated_test.dart index 9c30f252c0f..8602c9ffedc 100644 --- a/tests/ffi/function_callbacks_varargs_native_callable_generated_test.dart +++ b/tests/ffi/function_callbacks_varargs_native_callable_generated_test.dart @@ -145,6 +145,13 @@ final testCases = [ variadicAt1Int64x7Struct12BytesHomogeneousInt32, exceptionalReturn: 0), variadicAt1Int64x7Struct12BytesHomogeneousInt32AfterCallback), + CallbackTest.withCheck( + "VariadicAt1Struct12BytesHomogeneousInt32Int32x4", + NativeCallable< + VariadicAt1Struct12BytesHomogeneousInt32Int32x4Type>.isolateLocal( + variadicAt1Struct12BytesHomogeneousInt32Int32x4, + exceptionalReturn: 0), + variadicAt1Struct12BytesHomogeneousInt32Int32x4AfterCallback), ]; typedef VariadicAt1Int64x2Type = Int64 Function(Int64, VarArgs<(Int64,)>); @@ -1509,3 +1516,70 @@ void variadicAt1Int64x7Struct12BytesHomogeneousInt32AfterCallback() { Expect.equals(5, result); } + +typedef VariadicAt1Struct12BytesHomogeneousInt32Int32x4Type = Int32 Function( + Struct12BytesHomogeneousInt32, VarArgs<(Int32, Int32, Int32, Int32)>); + +// Global variables to be able to test inputs after callback returned. +Struct12BytesHomogeneousInt32 + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a0 = + Pointer.fromAddress(0).ref; +int variadicAt1Struct12BytesHomogeneousInt32Int32x4_a1 = 0; +int variadicAt1Struct12BytesHomogeneousInt32Int32x4_a2 = 0; +int variadicAt1Struct12BytesHomogeneousInt32Int32x4_a3 = 0; +int variadicAt1Struct12BytesHomogeneousInt32Int32x4_a4 = 0; + +// Result variable also global, so we can delete it after the callback. +int variadicAt1Struct12BytesHomogeneousInt32Int32x4Result = 0; + +int variadicAt1Struct12BytesHomogeneousInt32Int32x4CalculateResult() { + int result = 0; + + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a0.a0; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a0.a1; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a0.a2; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a1; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a2; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a3; + result += variadicAt1Struct12BytesHomogeneousInt32Int32x4_a4; + + variadicAt1Struct12BytesHomogeneousInt32Int32x4Result = result; + + return result; +} + +/// Variadic arguments test on macos_arm64. +int variadicAt1Struct12BytesHomogeneousInt32Int32x4( + Struct12BytesHomogeneousInt32 a0, int a1, int a2, int a3, int a4) { + print( + "variadicAt1Struct12BytesHomogeneousInt32Int32x4(${a0}, ${a1}, ${a2}, ${a3}, ${a4})"); + + // Possibly throw. + if (a0.a0 == 42 || a0.a0 == 84) { + print("throwing!"); + throw Exception( + "VariadicAt1Struct12BytesHomogeneousInt32Int32x4 throwing on purpose!"); + } + + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a0 = a0; + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a1 = a1; + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a2 = a2; + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a3 = a3; + variadicAt1Struct12BytesHomogeneousInt32Int32x4_a4 = a4; + + final result = + variadicAt1Struct12BytesHomogeneousInt32Int32x4CalculateResult(); + + print("result = $result"); + + return result; +} + +void variadicAt1Struct12BytesHomogeneousInt32Int32x4AfterCallback() { + final result = + variadicAt1Struct12BytesHomogeneousInt32Int32x4CalculateResult(); + + print("after callback result = $result"); + + Expect.equals(-4, result); +} diff --git a/tests/ffi/function_varargs_generated_leaf_test.dart b/tests/ffi/function_varargs_generated_leaf_test.dart index 33236271265..d035e67e564 100644 --- a/tests/ffi/function_varargs_generated_leaf_test.dart +++ b/tests/ffi/function_varargs_generated_leaf_test.dart @@ -43,6 +43,7 @@ void main() { testVariadicAt1DoubleInt64Int32Struct20BytesHomogeneouLeaf(); testVariadicAt5Doublex5Leaf(); testVariadicAt1Int64x7Struct12BytesHomogeneousInt32Leaf(); + testVariadicAt1Struct12BytesHomogeneousInt32Int32x4Leaf(); } } @@ -804,3 +805,38 @@ void testVariadicAt1Int64x7Struct12BytesHomogeneousInt32Leaf() { calloc.free(a7Pointer); } + +final variadicAt1Struct12BytesHomogeneousInt32Int32x4Leaf = + ffiTestFunctions.lookupFunction< + Int32 Function(Struct12BytesHomogeneousInt32, + VarArgs<(Int32, Int32, Int32, Int32)>), + int Function(Struct12BytesHomogeneousInt32, int, int, int, int)>( + "VariadicAt1Struct12BytesHomogeneousInt32Int32x4", + isLeaf: true); + +/// Variadic arguments test on macos_arm64. +void testVariadicAt1Struct12BytesHomogeneousInt32Int32x4Leaf() { + final a0Pointer = calloc(); + final Struct12BytesHomogeneousInt32 a0 = a0Pointer.ref; + int a1; + int a2; + int a3; + int a4; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1 = 4; + a2 = -5; + a3 = 6; + a4 = -7; + + final result = + variadicAt1Struct12BytesHomogeneousInt32Int32x4Leaf(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(-4, result); + + calloc.free(a0Pointer); +} diff --git a/tests/ffi/function_varargs_generated_native_leaf_test.dart b/tests/ffi/function_varargs_generated_native_leaf_test.dart index 2e777352941..83103e83f83 100644 --- a/tests/ffi/function_varargs_generated_native_leaf_test.dart +++ b/tests/ffi/function_varargs_generated_native_leaf_test.dart @@ -46,6 +46,7 @@ void main() { testVariadicAt1DoubleInt64Int32Struct20BytesHomogeneouNativeLeaf(); testVariadicAt5Doublex5NativeLeaf(); testVariadicAt1Int64x7Struct12BytesHomogeneousInt32NativeLeaf(); + testVariadicAt1Struct12BytesHomogeneousInt32Int32x4NativeLeaf(); } } @@ -799,3 +800,37 @@ void testVariadicAt1Int64x7Struct12BytesHomogeneousInt32NativeLeaf() { calloc.free(a7Pointer); } + +@Native< + Int32 Function(Struct12BytesHomogeneousInt32, + VarArgs<(Int32, Int32, Int32, Int32)>)>( + symbol: 'VariadicAt1Struct12BytesHomogeneousInt32Int32x4', isLeaf: true) +external int variadicAt1Struct12BytesHomogeneousInt32Int32x4NativeLeaf( + Struct12BytesHomogeneousInt32 a0, int a1, int a2, int a3, int a4); + +/// Variadic arguments test on macos_arm64. +void testVariadicAt1Struct12BytesHomogeneousInt32Int32x4NativeLeaf() { + final a0Pointer = calloc(); + final Struct12BytesHomogeneousInt32 a0 = a0Pointer.ref; + int a1; + int a2; + int a3; + int a4; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1 = 4; + a2 = -5; + a3 = 6; + a4 = -7; + + final result = variadicAt1Struct12BytesHomogeneousInt32Int32x4NativeLeaf( + a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(-4, result); + + calloc.free(a0Pointer); +} diff --git a/tests/ffi/function_varargs_generated_native_test.dart b/tests/ffi/function_varargs_generated_native_test.dart index d6eee23a541..8b2f0207e3b 100644 --- a/tests/ffi/function_varargs_generated_native_test.dart +++ b/tests/ffi/function_varargs_generated_native_test.dart @@ -46,6 +46,7 @@ void main() { testVariadicAt1DoubleInt64Int32Struct20BytesHomogeneouNative(); testVariadicAt5Doublex5Native(); testVariadicAt1Int64x7Struct12BytesHomogeneousInt32Native(); + testVariadicAt1Struct12BytesHomogeneousInt32Int32x4Native(); } } @@ -794,3 +795,37 @@ void testVariadicAt1Int64x7Struct12BytesHomogeneousInt32Native() { calloc.free(a7Pointer); } + +@Native< + Int32 Function(Struct12BytesHomogeneousInt32, + VarArgs<(Int32, Int32, Int32, Int32)>)>( + symbol: 'VariadicAt1Struct12BytesHomogeneousInt32Int32x4') +external int variadicAt1Struct12BytesHomogeneousInt32Int32x4Native( + Struct12BytesHomogeneousInt32 a0, int a1, int a2, int a3, int a4); + +/// Variadic arguments test on macos_arm64. +void testVariadicAt1Struct12BytesHomogeneousInt32Int32x4Native() { + final a0Pointer = calloc(); + final Struct12BytesHomogeneousInt32 a0 = a0Pointer.ref; + int a1; + int a2; + int a3; + int a4; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1 = 4; + a2 = -5; + a3 = 6; + a4 = -7; + + final result = + variadicAt1Struct12BytesHomogeneousInt32Int32x4Native(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(-4, result); + + calloc.free(a0Pointer); +} diff --git a/tests/ffi/function_varargs_generated_test.dart b/tests/ffi/function_varargs_generated_test.dart index 4790fb28bff..ee3af04534e 100644 --- a/tests/ffi/function_varargs_generated_test.dart +++ b/tests/ffi/function_varargs_generated_test.dart @@ -43,6 +43,7 @@ void main() { testVariadicAt1DoubleInt64Int32Struct20BytesHomogeneou(); testVariadicAt5Doublex5(); testVariadicAt1Int64x7Struct12BytesHomogeneousInt32(); + testVariadicAt1Struct12BytesHomogeneousInt32Int32x4(); } } @@ -769,3 +770,37 @@ void testVariadicAt1Int64x7Struct12BytesHomogeneousInt32() { calloc.free(a7Pointer); } + +final variadicAt1Struct12BytesHomogeneousInt32Int32x4 = + ffiTestFunctions.lookupFunction< + Int32 Function(Struct12BytesHomogeneousInt32, + VarArgs<(Int32, Int32, Int32, Int32)>), + int Function(Struct12BytesHomogeneousInt32, int, int, int, + int)>("VariadicAt1Struct12BytesHomogeneousInt32Int32x4"); + +/// Variadic arguments test on macos_arm64. +void testVariadicAt1Struct12BytesHomogeneousInt32Int32x4() { + final a0Pointer = calloc(); + final Struct12BytesHomogeneousInt32 a0 = a0Pointer.ref; + int a1; + int a2; + int a3; + int a4; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1 = 4; + a2 = -5; + a3 = 6; + a4 = -7; + + final result = + variadicAt1Struct12BytesHomogeneousInt32Int32x4(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(-4, result); + + calloc.free(a0Pointer); +} diff --git a/tests/ffi/generator/structs_by_value_tests_configuration.dart b/tests/ffi/generator/structs_by_value_tests_configuration.dart index 60126ea40fa..d1a0043f257 100644 --- a/tests/ffi/generator/structs_by_value_tests_configuration.dart +++ b/tests/ffi/generator/structs_by_value_tests_configuration.dart @@ -847,6 +847,18 @@ https://github.com/dart-lang/sdk/issues/49460""", int64, "Struct stradles last argument register, variadic", ), + FunctionType( + varArgsIndex: 1, + [ + struct12bytesInt, + int32, + int32, + int32, + int32, + ], + int32, + "Variadic arguments test on macos_arm64.", + ), ]; final struct1byteBool = StructType([bool_]);