From ddafaa0775951917265b667eabadd6d12d6b7ca1 Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Fri, 11 Jun 2021 12:00:26 +0000 Subject: [PATCH] [vm/ffi] Update tests to cover MacOS arm64 after-struct alignment Expands the test PassStruct9BytesPackedMixedx10DoubleInt32 to see how the second integer is allocated. Updates runtime/vm/compiler/ffi/unit_tests/structPacked to have the same signature. Fixes the structs by value test generator to output // @dart 2.9 for legacy mode. Deletes the copy of the test generator from tests/ffi, the copy did not run in legacy mode. TEST=only test changes Change-Id: I65b7db56225a8e7963493dbccc2f296faca6fee1 Cq-Include-Trybots: luci.dart.try:vm-kernel-mac-release-arm64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/202968 Reviewed-by: Tess Strickland --- runtime/bin/ffi_test/ffi_test_functions.cc | 3 +- .../ffi_test/ffi_test_functions_generated.cc | 29 +- .../ffi/native_calling_convention_test.cc | 16 +- .../structPacked/arm64_android.expect | 13 +- .../unit_tests/structPacked/arm64_ios.expect | 13 +- .../structPacked/arm64_linux.expect | 13 +- .../structPacked/arm64_macos.expect | 13 +- .../structPacked/arm_android.expect | 19 +- .../unit_tests/structPacked/arm_ios.expect | 17 +- .../unit_tests/structPacked/arm_linux.expect | 17 +- .../structPacked/ia32_android.expect | 19 +- .../unit_tests/structPacked/ia32_linux.expect | 19 +- .../unit_tests/structPacked/ia32_win.expect | 19 +- .../unit_tests/structPacked/x64_ios.expect | 13 +- .../unit_tests/structPacked/x64_linux.expect | 13 +- .../unit_tests/structPacked/x64_macos.expect | 13 +- .../unit_tests/structPacked/x64_win.expect | 15 +- ...backs_structs_by_value_generated_test.dart | 129 +- ...ction_structs_by_value_generated_test.dart | 36 +- .../structs_by_value_tests_configuration.dart | 2 +- .../structs_by_value_tests_generator.dart | 24 +- ...backs_structs_by_value_generated_test.dart | 129 +- ...ction_structs_by_value_generated_test.dart | 36 +- tests/ffi_2/generator/c_types.dart | 461 ------- .../structs_by_value_tests_configuration.dart | 812 ------------- .../structs_by_value_tests_generator.dart | 1059 ----------------- tests/ffi_2/generator/utils.dart | 24 - 27 files changed, 401 insertions(+), 2575 deletions(-) delete mode 100644 tests/ffi_2/generator/c_types.dart delete mode 100644 tests/ffi_2/generator/structs_by_value_tests_configuration.dart delete mode 100644 tests/ffi_2/generator/structs_by_value_tests_generator.dart delete mode 100644 tests/ffi_2/generator/utils.dart diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc index 3cf56b0d7d8..1784af3c170 100644 --- a/runtime/bin/ffi_test/ffi_test_functions.cc +++ b/runtime/bin/ffi_test/ffi_test_functions.cc @@ -170,8 +170,7 @@ DART_EXPORT intptr_t TakeMaxUint8x10(uint8_t a, << static_cast(d) << ", " << static_cast(e) << ", " << static_cast(f) << ", " << static_cast(g) << ", " << static_cast(h) << ", " << static_cast(i) << ", " - << static_cast(j) << ", " - << ")\n"; + << static_cast(j) << ")\n"; return (a == 0xff && b == 0xff && c == 0xff && d == 0xff && e == 0xff && f == 0xff && g == 0xff && h == 0xff && i == 0xff && j == 0xff) ? 1 diff --git a/runtime/bin/ffi_test/ffi_test_functions_generated.cc b/runtime/bin/ffi_test/ffi_test_functions_generated.cc index 8a23e246f77..1e882494432 100644 --- a/runtime/bin/ffi_test/ffi_test_functions_generated.cc +++ b/runtime/bin/ffi_test/ffi_test_functions_generated.cc @@ -4231,7 +4231,7 @@ DART_EXPORT int64_t PassStruct8BytesPackedIntx10(Struct8BytesPackedInt a0, // Used for testing structs and unions by value. // Struct with mis-aligned member. // Tests backfilling of CPU and FPU registers. -DART_EXPORT double PassStruct9BytesPackedMixedx10DoubleInt32( +DART_EXPORT double PassStruct9BytesPackedMixedx10DoubleInt32x2( Struct9BytesPackedMixed a0, Struct9BytesPackedMixed a1, Struct9BytesPackedMixed a2, @@ -4243,8 +4243,9 @@ DART_EXPORT double PassStruct9BytesPackedMixedx10DoubleInt32( Struct9BytesPackedMixed a8, Struct9BytesPackedMixed a9, double a10, - int32_t a11) { - std::cout << "PassStruct9BytesPackedMixedx10DoubleInt32" + int32_t a11, + int32_t a12) { + std::cout << "PassStruct9BytesPackedMixedx10DoubleInt32x2" << "((" << static_cast(a0.a0) << ", " << a0.a1 << "), (" << static_cast(a1.a0) << ", " << a1.a1 << "), (" << static_cast(a2.a0) << ", " << a2.a1 << "), (" @@ -4255,7 +4256,7 @@ DART_EXPORT double PassStruct9BytesPackedMixedx10DoubleInt32( << static_cast(a7.a0) << ", " << a7.a1 << "), (" << static_cast(a8.a0) << ", " << a8.a1 << "), (" << static_cast(a9.a0) << ", " << a9.a1 << "), " << a10 << ", " - << a11 << ")" + << a11 << ", " << a12 << ")" << "\n"; double result = 0; @@ -4282,6 +4283,7 @@ DART_EXPORT double PassStruct9BytesPackedMixedx10DoubleInt32( result += a9.a1; result += a10; result += a11; + result += a12; std::cout << "result = " << result << "\n"; @@ -11492,7 +11494,7 @@ DART_EXPORT intptr_t TestPassStruct8BytesPackedIntx10( // Used for testing structs and unions by value. // Struct with mis-aligned member. // Tests backfilling of CPU and FPU registers. -DART_EXPORT intptr_t TestPassStruct9BytesPackedMixedx10DoubleInt32( +DART_EXPORT intptr_t TestPassStruct9BytesPackedMixedx10DoubleInt32x2( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Struct9BytesPackedMixed a0, Struct9BytesPackedMixed a1, @@ -11505,7 +11507,8 @@ DART_EXPORT intptr_t TestPassStruct9BytesPackedMixedx10DoubleInt32( Struct9BytesPackedMixed a8, Struct9BytesPackedMixed a9, double a10, - int32_t a11)) { + int32_t a11, + int32_t a12)) { Struct9BytesPackedMixed a0; Struct9BytesPackedMixed a1; Struct9BytesPackedMixed a2; @@ -11518,6 +11521,7 @@ DART_EXPORT intptr_t TestPassStruct9BytesPackedMixedx10DoubleInt32( Struct9BytesPackedMixed a9; double a10; int32_t a11; + int32_t a12; a0.a0 = 1; a0.a1 = 2.0; @@ -11541,8 +11545,9 @@ DART_EXPORT intptr_t TestPassStruct9BytesPackedMixedx10DoubleInt32( a9.a1 = 20.0; a10 = -21.0; a11 = 22; + a12 = -23; - std::cout << "Calling TestPassStruct9BytesPackedMixedx10DoubleInt32(" + std::cout << "Calling TestPassStruct9BytesPackedMixedx10DoubleInt32x2(" << "((" << static_cast(a0.a0) << ", " << a0.a1 << "), (" << static_cast(a1.a0) << ", " << a1.a1 << "), (" << static_cast(a2.a0) << ", " << a2.a1 << "), (" @@ -11553,26 +11558,26 @@ DART_EXPORT intptr_t TestPassStruct9BytesPackedMixedx10DoubleInt32( << static_cast(a7.a0) << ", " << a7.a1 << "), (" << static_cast(a8.a0) << ", " << a8.a1 << "), (" << static_cast(a9.a0) << ", " << a9.a1 << "), " << a10 << ", " - << a11 << ")" + << a11 << ", " << a12 << ")" << ")\n"; - double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); std::cout << "result = " << result << "\n"; - CHECK_APPROX(211.0, result); + CHECK_APPROX(188.0, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; - result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0 = 84; - result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); CHECK_APPROX(0.0, result); diff --git a/runtime/vm/compiler/ffi/native_calling_convention_test.cc b/runtime/vm/compiler/ffi/native_calling_convention_test.cc index e1fdfb0e6a1..1d1ae2801f6 100644 --- a/runtime/vm/compiler/ffi/native_calling_convention_test.cc +++ b/runtime/vm/compiler/ffi/native_calling_convention_test.cc @@ -494,6 +494,7 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_struct8bytesPackedx10) { // See the *.expect in ./unit_tests for this behavior. UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_structPacked) { const auto& int8_type = *new (Z) NativePrimitiveType(kInt8); + const auto& int32_type = *new (Z) NativePrimitiveType(kInt32); const auto& double_type = *new (Z) NativePrimitiveType(kDouble); auto& member_types = *new (Z) NativeTypes(Z, 2); @@ -504,13 +505,22 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_structPacked) { EXPECT_EQ(9, struct_type.SizeInBytes()); EXPECT(struct_type.ContainsUnalignedMembers()); - auto& arguments = *new (Z) NativeTypes(Z, 11); + auto& arguments = *new (Z) NativeTypes(Z, 13); + arguments.Add(&struct_type); + arguments.Add(&struct_type); + arguments.Add(&struct_type); + arguments.Add(&struct_type); + arguments.Add(&struct_type); + arguments.Add(&struct_type); + arguments.Add(&struct_type); + arguments.Add(&struct_type); arguments.Add(&struct_type); arguments.Add(&struct_type); - arguments.Add(&int8_type); // Backfilling int registers. arguments.Add(&double_type); // Backfilling float registers. + arguments.Add(&int32_type); // Backfilling int registers. + arguments.Add(&int32_type); // Backfilling int registers. - RunSignatureTest(Z, "structPacked", arguments, struct_type); + RunSignatureTest(Z, "structPacked", arguments, double_type); } // The union is only 5 bytes because it's members are packed. diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_android.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_android.expect index 0af60bd4903..9653167b2ff 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_android.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_android.expect @@ -1,6 +1,15 @@ M(r0 int64, r1 int64) Struct(size: 9) M(r2 int64, r3 int64) Struct(size: 9) -r4 int8 +M(r4 int64, r5 int64) Struct(size: 9) +M(r6 int64, r7 int64) Struct(size: 9) +S+0 Struct(size: 9) +S+16 Struct(size: 9) +S+32 Struct(size: 9) +S+48 Struct(size: 9) +S+64 Struct(size: 9) +S+80 Struct(size: 9) v0 double +S+96 int32 +S+104 int32 => -M(r0 int64, r1 int64) Struct(size: 9) +v0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_ios.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_ios.expect index 975b4417503..e0f48fe393b 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_ios.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_ios.expect @@ -1,6 +1,15 @@ M(r0 int64, r1 int64) Struct(size: 9) M(r2 int64, r3 int64) Struct(size: 9) -r4 int32[int8] +M(r4 int64, r5 int64) Struct(size: 9) +M(r6 int64, r7 int64) Struct(size: 9) +S+0 Struct(size: 9) +S+16 Struct(size: 9) +S+32 Struct(size: 9) +S+48 Struct(size: 9) +S+64 Struct(size: 9) +S+80 Struct(size: 9) v0 double +S+92 int32 +S+96 int32 => -M(r0 int64, r1 int64) Struct(size: 9) +v0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_linux.expect index 0af60bd4903..9653167b2ff 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_linux.expect @@ -1,6 +1,15 @@ M(r0 int64, r1 int64) Struct(size: 9) M(r2 int64, r3 int64) Struct(size: 9) -r4 int8 +M(r4 int64, r5 int64) Struct(size: 9) +M(r6 int64, r7 int64) Struct(size: 9) +S+0 Struct(size: 9) +S+16 Struct(size: 9) +S+32 Struct(size: 9) +S+48 Struct(size: 9) +S+64 Struct(size: 9) +S+80 Struct(size: 9) v0 double +S+96 int32 +S+104 int32 => -M(r0 int64, r1 int64) Struct(size: 9) +v0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_macos.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_macos.expect index 0af60bd4903..e0f48fe393b 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_macos.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm64_macos.expect @@ -1,6 +1,15 @@ M(r0 int64, r1 int64) Struct(size: 9) M(r2 int64, r3 int64) Struct(size: 9) -r4 int8 +M(r4 int64, r5 int64) Struct(size: 9) +M(r6 int64, r7 int64) Struct(size: 9) +S+0 Struct(size: 9) +S+16 Struct(size: 9) +S+32 Struct(size: 9) +S+48 Struct(size: 9) +S+64 Struct(size: 9) +S+80 Struct(size: 9) v0 double +S+92 int32 +S+96 int32 => -M(r0 int64, r1 int64) Struct(size: 9) +v0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_android.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_android.expect index dedbb9396dd..ec8c36bb876 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_android.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_android.expect @@ -1,6 +1,15 @@ -M(r1 int32, r2 int32, r3 int32) Struct(size: 9) -M(S+0 int32, S+4 int32, S+8 int32) Struct(size: 9) -S+12 int32[int8] -S+16 double +M(r0 int32, r1 int32, r2 int32) Struct(size: 9) +M(r3 int32, S+0 int32, S+4 int32) Struct(size: 9) +M(S+8 int32, S+12 int32, S+16 int32) Struct(size: 9) +M(S+20 int32, S+24 int32, S+28 int32) Struct(size: 9) +M(S+32 int32, S+36 int32, S+40 int32) Struct(size: 9) +M(S+44 int32, S+48 int32, S+52 int32) Struct(size: 9) +M(S+56 int32, S+60 int32, S+64 int32) Struct(size: 9) +M(S+68 int32, S+72 int32, S+76 int32) Struct(size: 9) +M(S+80 int32, S+84 int32, S+88 int32) Struct(size: 9) +M(S+92 int32, S+96 int32, S+100 int32) Struct(size: 9) +S+104 double +S+112 int32 +S+116 int32 => -P(r0 uint32) Struct(size: 9) +(r0, r1) int64[double] diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_ios.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_ios.expect index f362c98ab39..78ee91b61f6 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_ios.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_ios.expect @@ -1,6 +1,15 @@ -M(r1 int32, r2 int32, r3 int32) Struct(size: 9) -M(S+0 int32, S+4 int32, S+8 int32) Struct(size: 9) -S+12 int32[int8] +M(r0 int32, r1 int32, r2 int32) Struct(size: 9) +M(r3 int32, S+0 int32, S+4 int32) Struct(size: 9) +M(S+8 int32, S+12 int32, S+16 int32) Struct(size: 9) +M(S+20 int32, S+24 int32, S+28 int32) Struct(size: 9) +M(S+32 int32, S+36 int32, S+40 int32) Struct(size: 9) +M(S+44 int32, S+48 int32, S+52 int32) Struct(size: 9) +M(S+56 int32, S+60 int32, S+64 int32) Struct(size: 9) +M(S+68 int32, S+72 int32, S+76 int32) Struct(size: 9) +M(S+80 int32, S+84 int32, S+88 int32) Struct(size: 9) +M(S+92 int32, S+96 int32, S+100 int32) Struct(size: 9) d0 double +S+104 int32 +S+108 int32 => -P(r0 uint32) Struct(size: 9) +q0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_linux.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_linux.expect index f362c98ab39..78ee91b61f6 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/arm_linux.expect @@ -1,6 +1,15 @@ -M(r1 int32, r2 int32, r3 int32) Struct(size: 9) -M(S+0 int32, S+4 int32, S+8 int32) Struct(size: 9) -S+12 int32[int8] +M(r0 int32, r1 int32, r2 int32) Struct(size: 9) +M(r3 int32, S+0 int32, S+4 int32) Struct(size: 9) +M(S+8 int32, S+12 int32, S+16 int32) Struct(size: 9) +M(S+20 int32, S+24 int32, S+28 int32) Struct(size: 9) +M(S+32 int32, S+36 int32, S+40 int32) Struct(size: 9) +M(S+44 int32, S+48 int32, S+52 int32) Struct(size: 9) +M(S+56 int32, S+60 int32, S+64 int32) Struct(size: 9) +M(S+68 int32, S+72 int32, S+76 int32) Struct(size: 9) +M(S+80 int32, S+84 int32, S+88 int32) Struct(size: 9) +M(S+92 int32, S+96 int32, S+100 int32) Struct(size: 9) d0 double +S+104 int32 +S+108 int32 => -P(r0 uint32) Struct(size: 9) +q0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_android.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_android.expect index 8a22e1d44a5..8540652d0eb 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_android.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_android.expect @@ -1,6 +1,15 @@ -S+4 Struct(size: 9) -S+16 Struct(size: 9) -S+28 int32[int8] -S+32 double +S+0 Struct(size: 9) +S+12 Struct(size: 9) +S+24 Struct(size: 9) +S+36 Struct(size: 9) +S+48 Struct(size: 9) +S+60 Struct(size: 9) +S+72 Struct(size: 9) +S+84 Struct(size: 9) +S+96 Struct(size: 9) +S+108 Struct(size: 9) +S+120 double +S+128 int32 +S+132 int32 => -P(S+0 uint32, ret:eax uint32) Struct(size: 9) +xmm0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_linux.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_linux.expect index 8a22e1d44a5..8540652d0eb 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_linux.expect @@ -1,6 +1,15 @@ -S+4 Struct(size: 9) -S+16 Struct(size: 9) -S+28 int32[int8] -S+32 double +S+0 Struct(size: 9) +S+12 Struct(size: 9) +S+24 Struct(size: 9) +S+36 Struct(size: 9) +S+48 Struct(size: 9) +S+60 Struct(size: 9) +S+72 Struct(size: 9) +S+84 Struct(size: 9) +S+96 Struct(size: 9) +S+108 Struct(size: 9) +S+120 double +S+128 int32 +S+132 int32 => -P(S+0 uint32, ret:eax uint32) Struct(size: 9) +xmm0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_win.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_win.expect index 8a22e1d44a5..8540652d0eb 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_win.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/ia32_win.expect @@ -1,6 +1,15 @@ -S+4 Struct(size: 9) -S+16 Struct(size: 9) -S+28 int32[int8] -S+32 double +S+0 Struct(size: 9) +S+12 Struct(size: 9) +S+24 Struct(size: 9) +S+36 Struct(size: 9) +S+48 Struct(size: 9) +S+60 Struct(size: 9) +S+72 Struct(size: 9) +S+84 Struct(size: 9) +S+96 Struct(size: 9) +S+108 Struct(size: 9) +S+120 double +S+128 int32 +S+132 int32 => -P(S+0 uint32, ret:eax uint32) Struct(size: 9) +xmm0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_ios.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_ios.expect index 5753935c483..404a10f656f 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_ios.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_ios.expect @@ -1,6 +1,15 @@ S+0 Struct(size: 9) S+16 Struct(size: 9) -rsi int32[int8] +S+32 Struct(size: 9) +S+48 Struct(size: 9) +S+64 Struct(size: 9) +S+80 Struct(size: 9) +S+96 Struct(size: 9) +S+112 Struct(size: 9) +S+128 Struct(size: 9) +S+144 Struct(size: 9) xmm0 double +rdi int32 +rsi int32 => -P(rdi int64, ret:rax int64) Struct(size: 9) +xmm0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_linux.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_linux.expect index 5753935c483..404a10f656f 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_linux.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_linux.expect @@ -1,6 +1,15 @@ S+0 Struct(size: 9) S+16 Struct(size: 9) -rsi int32[int8] +S+32 Struct(size: 9) +S+48 Struct(size: 9) +S+64 Struct(size: 9) +S+80 Struct(size: 9) +S+96 Struct(size: 9) +S+112 Struct(size: 9) +S+128 Struct(size: 9) +S+144 Struct(size: 9) xmm0 double +rdi int32 +rsi int32 => -P(rdi int64, ret:rax int64) Struct(size: 9) +xmm0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_macos.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_macos.expect index 5753935c483..404a10f656f 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_macos.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_macos.expect @@ -1,6 +1,15 @@ S+0 Struct(size: 9) S+16 Struct(size: 9) -rsi int32[int8] +S+32 Struct(size: 9) +S+48 Struct(size: 9) +S+64 Struct(size: 9) +S+80 Struct(size: 9) +S+96 Struct(size: 9) +S+112 Struct(size: 9) +S+128 Struct(size: 9) +S+144 Struct(size: 9) xmm0 double +rdi int32 +rsi int32 => -P(rdi int64, ret:rax int64) Struct(size: 9) +xmm0 double diff --git a/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_win.expect b/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_win.expect index 3311a61f922..21374d96cbe 100644 --- a/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_win.expect +++ b/runtime/vm/compiler/ffi/unit_tests/structPacked/x64_win.expect @@ -1,6 +1,15 @@ +P(rcx int64) Struct(size: 9) P(rdx int64) Struct(size: 9) P(r8 int64) Struct(size: 9) -r9 int8 -S+0 double +P(r9 int64) Struct(size: 9) +P(S+0 int64) Struct(size: 9) +P(S+8 int64) Struct(size: 9) +P(S+16 int64) Struct(size: 9) +P(S+24 int64) Struct(size: 9) +P(S+32 int64) Struct(size: 9) +P(S+40 int64) Struct(size: 9) +S+48 double +S+56 int32 +S+64 int32 => -P(rcx int64, ret:rax int64) Struct(size: 9) +xmm0 double diff --git a/tests/ffi/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart index d13cf550b7f..f843c7ce1c2 100644 --- a/tests/ffi/function_callbacks_structs_by_value_generated_test.dart +++ b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart @@ -295,10 +295,10 @@ final testCases = [ passStruct8BytesPackedIntx10, 0), passStruct8BytesPackedIntx10AfterCallback), CallbackTest.withCheck( - "PassStruct9BytesPackedMixedx10DoubleInt32", - Pointer.fromFunction( - passStruct9BytesPackedMixedx10DoubleInt32, 0.0), - passStruct9BytesPackedMixedx10DoubleInt32AfterCallback), + "PassStruct9BytesPackedMixedx10DoubleInt32x2", + Pointer.fromFunction( + passStruct9BytesPackedMixedx10DoubleInt32x2, 0.0), + passStruct9BytesPackedMixedx10DoubleInt32x2AfterCallback), CallbackTest.withCheck( "PassStruct5BytesPackedMixed", Pointer.fromFunction( @@ -6545,7 +6545,7 @@ void passStruct8BytesPackedIntx10AfterCallback() { Expect.equals(1275, result); } -typedef PassStruct9BytesPackedMixedx10DoubleInt32Type = Double Function( +typedef PassStruct9BytesPackedMixedx10DoubleInt32x2Type = Double Function( Struct9BytesPackedMixed, Struct9BytesPackedMixed, Struct9BytesPackedMixed, @@ -6557,69 +6557,72 @@ typedef PassStruct9BytesPackedMixedx10DoubleInt32Type = Double Function( Struct9BytesPackedMixed, Struct9BytesPackedMixed, Double, + Int32, Int32); // Global variables to be able to test inputs after callback returned. -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a0 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a0 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a1 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a1 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a2 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a2 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a3 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a3 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a4 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a4 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a5 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a5 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a6 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a6 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a7 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a7 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a8 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a8 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a9 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a9 = Struct9BytesPackedMixed(); -double passStruct9BytesPackedMixedx10DoubleInt32_a10 = 0.0; -int passStruct9BytesPackedMixedx10DoubleInt32_a11 = 0; +double passStruct9BytesPackedMixedx10DoubleInt32x2_a10 = 0.0; +int passStruct9BytesPackedMixedx10DoubleInt32x2_a11 = 0; +int passStruct9BytesPackedMixedx10DoubleInt32x2_a12 = 0; // Result variable also global, so we can delete it after the callback. -double passStruct9BytesPackedMixedx10DoubleInt32Result = 0.0; +double passStruct9BytesPackedMixedx10DoubleInt32x2Result = 0.0; -double passStruct9BytesPackedMixedx10DoubleInt32CalculateResult() { +double passStruct9BytesPackedMixedx10DoubleInt32x2CalculateResult() { double result = 0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a0.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a0.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a1.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a1.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a2.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a2.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a3.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a3.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a4.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a4.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a5.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a5.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a6.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a6.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a7.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a7.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a8.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a8.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a9.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a9.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a10; - result += passStruct9BytesPackedMixedx10DoubleInt32_a11; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a0.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a0.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a1.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a1.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a2.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a2.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a3.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a3.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a4.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a4.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a5.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a5.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a6.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a6.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a7.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a7.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a8.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a8.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a9.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a9.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a10; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a11; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a12; - passStruct9BytesPackedMixedx10DoubleInt32Result = result; + passStruct9BytesPackedMixedx10DoubleInt32x2Result = result; return result; } /// Struct with mis-aligned member. /// Tests backfilling of CPU and FPU registers. -double passStruct9BytesPackedMixedx10DoubleInt32( +double passStruct9BytesPackedMixedx10DoubleInt32x2( Struct9BytesPackedMixed a0, Struct9BytesPackedMixed a1, Struct9BytesPackedMixed a2, @@ -6631,9 +6634,10 @@ double passStruct9BytesPackedMixedx10DoubleInt32( Struct9BytesPackedMixed a8, Struct9BytesPackedMixed a9, double a10, - int a11) { + int a11, + int a12) { print( - "passStruct9BytesPackedMixedx10DoubleInt32(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11})"); + "passStruct9BytesPackedMixedx10DoubleInt32x2(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11}, ${a12})"); // In legacy mode, possibly return null. @@ -6641,35 +6645,36 @@ double passStruct9BytesPackedMixedx10DoubleInt32( if (a0.a0 == 42 || a0.a0 == 84) { print("throwing!"); throw Exception( - "PassStruct9BytesPackedMixedx10DoubleInt32 throwing on purpose!"); + "PassStruct9BytesPackedMixedx10DoubleInt32x2 throwing on purpose!"); } - passStruct9BytesPackedMixedx10DoubleInt32_a0 = a0; - passStruct9BytesPackedMixedx10DoubleInt32_a1 = a1; - passStruct9BytesPackedMixedx10DoubleInt32_a2 = a2; - passStruct9BytesPackedMixedx10DoubleInt32_a3 = a3; - passStruct9BytesPackedMixedx10DoubleInt32_a4 = a4; - passStruct9BytesPackedMixedx10DoubleInt32_a5 = a5; - passStruct9BytesPackedMixedx10DoubleInt32_a6 = a6; - passStruct9BytesPackedMixedx10DoubleInt32_a7 = a7; - passStruct9BytesPackedMixedx10DoubleInt32_a8 = a8; - passStruct9BytesPackedMixedx10DoubleInt32_a9 = a9; - passStruct9BytesPackedMixedx10DoubleInt32_a10 = a10; - passStruct9BytesPackedMixedx10DoubleInt32_a11 = a11; + passStruct9BytesPackedMixedx10DoubleInt32x2_a0 = a0; + passStruct9BytesPackedMixedx10DoubleInt32x2_a1 = a1; + passStruct9BytesPackedMixedx10DoubleInt32x2_a2 = a2; + passStruct9BytesPackedMixedx10DoubleInt32x2_a3 = a3; + passStruct9BytesPackedMixedx10DoubleInt32x2_a4 = a4; + passStruct9BytesPackedMixedx10DoubleInt32x2_a5 = a5; + passStruct9BytesPackedMixedx10DoubleInt32x2_a6 = a6; + passStruct9BytesPackedMixedx10DoubleInt32x2_a7 = a7; + passStruct9BytesPackedMixedx10DoubleInt32x2_a8 = a8; + passStruct9BytesPackedMixedx10DoubleInt32x2_a9 = a9; + passStruct9BytesPackedMixedx10DoubleInt32x2_a10 = a10; + passStruct9BytesPackedMixedx10DoubleInt32x2_a11 = a11; + passStruct9BytesPackedMixedx10DoubleInt32x2_a12 = a12; - final result = passStruct9BytesPackedMixedx10DoubleInt32CalculateResult(); + final result = passStruct9BytesPackedMixedx10DoubleInt32x2CalculateResult(); print("result = $result"); return result; } -void passStruct9BytesPackedMixedx10DoubleInt32AfterCallback() { - final result = passStruct9BytesPackedMixedx10DoubleInt32CalculateResult(); +void passStruct9BytesPackedMixedx10DoubleInt32x2AfterCallback() { + final result = passStruct9BytesPackedMixedx10DoubleInt32x2CalculateResult(); print("after callback result = $result"); - Expect.approxEquals(211.0, result); + Expect.approxEquals(188.0, result); } typedef PassStruct5BytesPackedMixedType = Double Function( diff --git a/tests/ffi/function_structs_by_value_generated_test.dart b/tests/ffi/function_structs_by_value_generated_test.dart index 6c970e1734b..9504081ce15 100644 --- a/tests/ffi/function_structs_by_value_generated_test.dart +++ b/tests/ffi/function_structs_by_value_generated_test.dart @@ -72,7 +72,7 @@ void main() { testPassUint8Struct4BytesInlineArrayMultiDimensionalIn(); testPassStruct3BytesPackedIntx10(); testPassStruct8BytesPackedIntx10(); - testPassStruct9BytesPackedMixedx10DoubleInt32(); + testPassStruct9BytesPackedMixedx10DoubleInt32x2(); testPassStruct5BytesPackedMixed(); testPassStructNestedAlignmentStruct5BytesPackedMixed(); testPassStruct6BytesInlineArrayInt(); @@ -185,7 +185,7 @@ void main() { testPassUint8Struct4BytesInlineArrayMultiDimensionalInLeaf(); testPassStruct3BytesPackedIntx10Leaf(); testPassStruct8BytesPackedIntx10Leaf(); - testPassStruct9BytesPackedMixedx10DoubleInt32Leaf(); + testPassStruct9BytesPackedMixedx10DoubleInt32x2Leaf(); testPassStruct5BytesPackedMixedLeaf(); testPassStructNestedAlignmentStruct5BytesPackedMixedLeaf(); testPassStruct6BytesInlineArrayIntLeaf(); @@ -5892,7 +5892,7 @@ void testPassStruct8BytesPackedIntx10() { calloc.free(a9Pointer); } -final passStruct9BytesPackedMixedx10DoubleInt32 = +final passStruct9BytesPackedMixedx10DoubleInt32x2 = ffiTestFunctions.lookupFunction< Double Function( Struct9BytesPackedMixed, @@ -5906,6 +5906,7 @@ final passStruct9BytesPackedMixedx10DoubleInt32 = Struct9BytesPackedMixed, Struct9BytesPackedMixed, Double, + Int32, Int32), double Function( Struct9BytesPackedMixed, @@ -5919,11 +5920,12 @@ final passStruct9BytesPackedMixedx10DoubleInt32 = Struct9BytesPackedMixed, Struct9BytesPackedMixed, double, - int)>("PassStruct9BytesPackedMixedx10DoubleInt32"); + int, + int)>("PassStruct9BytesPackedMixedx10DoubleInt32x2"); /// Struct with mis-aligned member. /// Tests backfilling of CPU and FPU registers. -void testPassStruct9BytesPackedMixedx10DoubleInt32() { +void testPassStruct9BytesPackedMixedx10DoubleInt32x2() { final a0Pointer = calloc(); final Struct9BytesPackedMixed a0 = a0Pointer.ref; final a1Pointer = calloc(); @@ -5946,6 +5948,7 @@ void testPassStruct9BytesPackedMixedx10DoubleInt32() { final Struct9BytesPackedMixed a9 = a9Pointer.ref; double a10; int a11; + int a12; a0.a0 = 1; a0.a1 = 2.0; @@ -5969,13 +5972,14 @@ void testPassStruct9BytesPackedMixedx10DoubleInt32() { a9.a1 = 20.0; a10 = -21.0; a11 = 22; + a12 = -23; - final result = passStruct9BytesPackedMixedx10DoubleInt32( - a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + final result = passStruct9BytesPackedMixedx10DoubleInt32x2( + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); print("result = $result"); - Expect.approxEquals(211.0, result); + Expect.approxEquals(188.0, result); calloc.free(a0Pointer); calloc.free(a1Pointer); @@ -13390,7 +13394,7 @@ void testPassStruct8BytesPackedIntx10Leaf() { calloc.free(a9Pointer); } -final passStruct9BytesPackedMixedx10DoubleInt32Leaf = +final passStruct9BytesPackedMixedx10DoubleInt32x2Leaf = ffiTestFunctions.lookupFunction< Double Function( Struct9BytesPackedMixed, @@ -13404,6 +13408,7 @@ final passStruct9BytesPackedMixedx10DoubleInt32Leaf = Struct9BytesPackedMixed, Struct9BytesPackedMixed, Double, + Int32, Int32), double Function( Struct9BytesPackedMixed, @@ -13417,11 +13422,12 @@ final passStruct9BytesPackedMixedx10DoubleInt32Leaf = Struct9BytesPackedMixed, Struct9BytesPackedMixed, double, - int)>("PassStruct9BytesPackedMixedx10DoubleInt32", isLeaf: true); + int, + int)>("PassStruct9BytesPackedMixedx10DoubleInt32x2", isLeaf: true); /// Struct with mis-aligned member. /// Tests backfilling of CPU and FPU registers. -void testPassStruct9BytesPackedMixedx10DoubleInt32Leaf() { +void testPassStruct9BytesPackedMixedx10DoubleInt32x2Leaf() { final a0Pointer = calloc(); final Struct9BytesPackedMixed a0 = a0Pointer.ref; final a1Pointer = calloc(); @@ -13444,6 +13450,7 @@ void testPassStruct9BytesPackedMixedx10DoubleInt32Leaf() { final Struct9BytesPackedMixed a9 = a9Pointer.ref; double a10; int a11; + int a12; a0.a0 = 1; a0.a1 = 2.0; @@ -13467,13 +13474,14 @@ void testPassStruct9BytesPackedMixedx10DoubleInt32Leaf() { a9.a1 = 20.0; a10 = -21.0; a11 = 22; + a12 = -23; - final result = passStruct9BytesPackedMixedx10DoubleInt32Leaf( - a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + final result = passStruct9BytesPackedMixedx10DoubleInt32x2Leaf( + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); print("result = $result"); - Expect.approxEquals(211.0, result); + Expect.approxEquals(188.0, result); calloc.free(a0Pointer); calloc.free(a1Pointer); diff --git a/tests/ffi/generator/structs_by_value_tests_configuration.dart b/tests/ffi/generator/structs_by_value_tests_configuration.dart index 07b5fd12b44..78c187fcb76 100644 --- a/tests/ffi/generator/structs_by_value_tests_configuration.dart +++ b/tests/ffi/generator/structs_by_value_tests_configuration.dart @@ -339,7 +339,7 @@ Small struct with mis-aligned member."""), FunctionType(List.filled(10, struct8bytesPacked), int64, """ Struct with mis-aligned member."""), FunctionType( - [...List.filled(10, struct9bytesPacked), double_, int32], + [...List.filled(10, struct9bytesPacked), double_, int32, int32], double_, """ Struct with mis-aligned member. diff --git a/tests/ffi/generator/structs_by_value_tests_generator.dart b/tests/ffi/generator/structs_by_value_tests_generator.dart index c624d584e27..72f35859203 100644 --- a/tests/ffi/generator/structs_by_value_tests_generator.dart +++ b/tests/ffi/generator/structs_by_value_tests_generator.dart @@ -856,7 +856,14 @@ const throwExceptionValue = 42; /// Some value between 0 and 127 (works in every native type). const returnNullValue = 84; -const headerDartCallTest = """ +const dart2dot9 = ''' +// @dart = 2.9 +'''; + +headerDartCallTest(bool nnbd) { + final dartVersion = nnbd ? '' : dart2dot9; + + return """ // 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. @@ -869,6 +876,8 @@ const headerDartCallTest = """ // VMOptions=--use-slow-path // VMOptions=--use-slow-path --stacktrace-every=100 +$dartVersion + import 'dart:ffi'; import "package:expect/expect.dart"; @@ -878,11 +887,12 @@ import 'dylib_utils.dart'; final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); """; +} void writeDartCallTest() { for (bool nnbd in [true, false]) { final StringBuffer buffer = StringBuffer(); - buffer.write(headerDartCallTest); + buffer.write(headerDartCallTest(nnbd)); buffer.write(""" void main() { @@ -909,7 +919,10 @@ String callTestPath(bool nnbd) { .path; } -const headerDartCallbackTest = """ +headerDartCallbackTest(bool nnbd) { + final dartVersion = nnbd ? '' : dart2dot9; + + return """ // 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. @@ -922,6 +935,8 @@ const headerDartCallbackTest = """ // VMOptions=--use-slow-path // VMOptions=--use-slow-path --stacktrace-every=100 +$dartVersion + import 'dart:ffi'; import "package:expect/expect.dart"; @@ -942,11 +957,12 @@ void main() { """; +} void writeDartCallbackTest() { for (bool nnbd in [true, false]) { final StringBuffer buffer = StringBuffer(); - buffer.write(headerDartCallbackTest); + buffer.write(headerDartCallbackTest(nnbd)); buffer.write(""" final testCases = [ diff --git a/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart index 8ee78451661..5eb0a63f0d0 100644 --- a/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart +++ b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart @@ -297,10 +297,10 @@ final testCases = [ passStruct8BytesPackedIntx10, 0), passStruct8BytesPackedIntx10AfterCallback), CallbackTest.withCheck( - "PassStruct9BytesPackedMixedx10DoubleInt32", - Pointer.fromFunction( - passStruct9BytesPackedMixedx10DoubleInt32, 0.0), - passStruct9BytesPackedMixedx10DoubleInt32AfterCallback), + "PassStruct9BytesPackedMixedx10DoubleInt32x2", + Pointer.fromFunction( + passStruct9BytesPackedMixedx10DoubleInt32x2, 0.0), + passStruct9BytesPackedMixedx10DoubleInt32x2AfterCallback), CallbackTest.withCheck( "PassStruct5BytesPackedMixed", Pointer.fromFunction( @@ -6755,7 +6755,7 @@ void passStruct8BytesPackedIntx10AfterCallback() { Expect.equals(1275, result); } -typedef PassStruct9BytesPackedMixedx10DoubleInt32Type = Double Function( +typedef PassStruct9BytesPackedMixedx10DoubleInt32x2Type = Double Function( Struct9BytesPackedMixed, Struct9BytesPackedMixed, Struct9BytesPackedMixed, @@ -6767,69 +6767,72 @@ typedef PassStruct9BytesPackedMixedx10DoubleInt32Type = Double Function( Struct9BytesPackedMixed, Struct9BytesPackedMixed, Double, + Int32, Int32); // Global variables to be able to test inputs after callback returned. -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a0 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a0 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a1 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a1 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a2 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a2 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a3 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a3 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a4 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a4 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a5 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a5 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a6 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a6 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a7 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a7 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a8 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a8 = Struct9BytesPackedMixed(); -Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32_a9 = +Struct9BytesPackedMixed passStruct9BytesPackedMixedx10DoubleInt32x2_a9 = Struct9BytesPackedMixed(); -double passStruct9BytesPackedMixedx10DoubleInt32_a10 = 0.0; -int passStruct9BytesPackedMixedx10DoubleInt32_a11 = 0; +double passStruct9BytesPackedMixedx10DoubleInt32x2_a10 = 0.0; +int passStruct9BytesPackedMixedx10DoubleInt32x2_a11 = 0; +int passStruct9BytesPackedMixedx10DoubleInt32x2_a12 = 0; // Result variable also global, so we can delete it after the callback. -double passStruct9BytesPackedMixedx10DoubleInt32Result = 0.0; +double passStruct9BytesPackedMixedx10DoubleInt32x2Result = 0.0; -double passStruct9BytesPackedMixedx10DoubleInt32CalculateResult() { +double passStruct9BytesPackedMixedx10DoubleInt32x2CalculateResult() { double result = 0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a0.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a0.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a1.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a1.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a2.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a2.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a3.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a3.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a4.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a4.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a5.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a5.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a6.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a6.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a7.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a7.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a8.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a8.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a9.a0; - result += passStruct9BytesPackedMixedx10DoubleInt32_a9.a1; - result += passStruct9BytesPackedMixedx10DoubleInt32_a10; - result += passStruct9BytesPackedMixedx10DoubleInt32_a11; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a0.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a0.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a1.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a1.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a2.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a2.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a3.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a3.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a4.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a4.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a5.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a5.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a6.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a6.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a7.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a7.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a8.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a8.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a9.a0; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a9.a1; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a10; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a11; + result += passStruct9BytesPackedMixedx10DoubleInt32x2_a12; - passStruct9BytesPackedMixedx10DoubleInt32Result = result; + passStruct9BytesPackedMixedx10DoubleInt32x2Result = result; return result; } /// Struct with mis-aligned member. /// Tests backfilling of CPU and FPU registers. -double passStruct9BytesPackedMixedx10DoubleInt32( +double passStruct9BytesPackedMixedx10DoubleInt32x2( Struct9BytesPackedMixed a0, Struct9BytesPackedMixed a1, Struct9BytesPackedMixed a2, @@ -6841,9 +6844,10 @@ double passStruct9BytesPackedMixedx10DoubleInt32( Struct9BytesPackedMixed a8, Struct9BytesPackedMixed a9, double a10, - int a11) { + int a11, + int a12) { print( - "passStruct9BytesPackedMixedx10DoubleInt32(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11})"); + "passStruct9BytesPackedMixedx10DoubleInt32x2(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11}, ${a12})"); // In legacy mode, possibly return null. if (a0.a0 == 84) { @@ -6855,35 +6859,36 @@ double passStruct9BytesPackedMixedx10DoubleInt32( if (a0.a0 == 42 || a0.a0 == 84) { print("throwing!"); throw Exception( - "PassStruct9BytesPackedMixedx10DoubleInt32 throwing on purpose!"); + "PassStruct9BytesPackedMixedx10DoubleInt32x2 throwing on purpose!"); } - passStruct9BytesPackedMixedx10DoubleInt32_a0 = a0; - passStruct9BytesPackedMixedx10DoubleInt32_a1 = a1; - passStruct9BytesPackedMixedx10DoubleInt32_a2 = a2; - passStruct9BytesPackedMixedx10DoubleInt32_a3 = a3; - passStruct9BytesPackedMixedx10DoubleInt32_a4 = a4; - passStruct9BytesPackedMixedx10DoubleInt32_a5 = a5; - passStruct9BytesPackedMixedx10DoubleInt32_a6 = a6; - passStruct9BytesPackedMixedx10DoubleInt32_a7 = a7; - passStruct9BytesPackedMixedx10DoubleInt32_a8 = a8; - passStruct9BytesPackedMixedx10DoubleInt32_a9 = a9; - passStruct9BytesPackedMixedx10DoubleInt32_a10 = a10; - passStruct9BytesPackedMixedx10DoubleInt32_a11 = a11; + passStruct9BytesPackedMixedx10DoubleInt32x2_a0 = a0; + passStruct9BytesPackedMixedx10DoubleInt32x2_a1 = a1; + passStruct9BytesPackedMixedx10DoubleInt32x2_a2 = a2; + passStruct9BytesPackedMixedx10DoubleInt32x2_a3 = a3; + passStruct9BytesPackedMixedx10DoubleInt32x2_a4 = a4; + passStruct9BytesPackedMixedx10DoubleInt32x2_a5 = a5; + passStruct9BytesPackedMixedx10DoubleInt32x2_a6 = a6; + passStruct9BytesPackedMixedx10DoubleInt32x2_a7 = a7; + passStruct9BytesPackedMixedx10DoubleInt32x2_a8 = a8; + passStruct9BytesPackedMixedx10DoubleInt32x2_a9 = a9; + passStruct9BytesPackedMixedx10DoubleInt32x2_a10 = a10; + passStruct9BytesPackedMixedx10DoubleInt32x2_a11 = a11; + passStruct9BytesPackedMixedx10DoubleInt32x2_a12 = a12; - final result = passStruct9BytesPackedMixedx10DoubleInt32CalculateResult(); + final result = passStruct9BytesPackedMixedx10DoubleInt32x2CalculateResult(); print("result = $result"); return result; } -void passStruct9BytesPackedMixedx10DoubleInt32AfterCallback() { - final result = passStruct9BytesPackedMixedx10DoubleInt32CalculateResult(); +void passStruct9BytesPackedMixedx10DoubleInt32x2AfterCallback() { + final result = passStruct9BytesPackedMixedx10DoubleInt32x2CalculateResult(); print("after callback result = $result"); - Expect.approxEquals(211.0, result); + Expect.approxEquals(188.0, result); } typedef PassStruct5BytesPackedMixedType = Double Function( diff --git a/tests/ffi_2/function_structs_by_value_generated_test.dart b/tests/ffi_2/function_structs_by_value_generated_test.dart index b1e3f273733..1de965cf18c 100644 --- a/tests/ffi_2/function_structs_by_value_generated_test.dart +++ b/tests/ffi_2/function_structs_by_value_generated_test.dart @@ -74,7 +74,7 @@ void main() { testPassUint8Struct4BytesInlineArrayMultiDimensionalIn(); testPassStruct3BytesPackedIntx10(); testPassStruct8BytesPackedIntx10(); - testPassStruct9BytesPackedMixedx10DoubleInt32(); + testPassStruct9BytesPackedMixedx10DoubleInt32x2(); testPassStruct5BytesPackedMixed(); testPassStructNestedAlignmentStruct5BytesPackedMixed(); testPassStruct6BytesInlineArrayInt(); @@ -187,7 +187,7 @@ void main() { testPassUint8Struct4BytesInlineArrayMultiDimensionalInLeaf(); testPassStruct3BytesPackedIntx10Leaf(); testPassStruct8BytesPackedIntx10Leaf(); - testPassStruct9BytesPackedMixedx10DoubleInt32Leaf(); + testPassStruct9BytesPackedMixedx10DoubleInt32x2Leaf(); testPassStruct5BytesPackedMixedLeaf(); testPassStructNestedAlignmentStruct5BytesPackedMixedLeaf(); testPassStruct6BytesInlineArrayIntLeaf(); @@ -5894,7 +5894,7 @@ void testPassStruct8BytesPackedIntx10() { calloc.free(a9Pointer); } -final passStruct9BytesPackedMixedx10DoubleInt32 = +final passStruct9BytesPackedMixedx10DoubleInt32x2 = ffiTestFunctions.lookupFunction< Double Function( Struct9BytesPackedMixed, @@ -5908,6 +5908,7 @@ final passStruct9BytesPackedMixedx10DoubleInt32 = Struct9BytesPackedMixed, Struct9BytesPackedMixed, Double, + Int32, Int32), double Function( Struct9BytesPackedMixed, @@ -5921,11 +5922,12 @@ final passStruct9BytesPackedMixedx10DoubleInt32 = Struct9BytesPackedMixed, Struct9BytesPackedMixed, double, - int)>("PassStruct9BytesPackedMixedx10DoubleInt32"); + int, + int)>("PassStruct9BytesPackedMixedx10DoubleInt32x2"); /// Struct with mis-aligned member. /// Tests backfilling of CPU and FPU registers. -void testPassStruct9BytesPackedMixedx10DoubleInt32() { +void testPassStruct9BytesPackedMixedx10DoubleInt32x2() { final a0Pointer = calloc(); final Struct9BytesPackedMixed a0 = a0Pointer.ref; final a1Pointer = calloc(); @@ -5948,6 +5950,7 @@ void testPassStruct9BytesPackedMixedx10DoubleInt32() { final Struct9BytesPackedMixed a9 = a9Pointer.ref; double a10; int a11; + int a12; a0.a0 = 1; a0.a1 = 2.0; @@ -5971,13 +5974,14 @@ void testPassStruct9BytesPackedMixedx10DoubleInt32() { a9.a1 = 20.0; a10 = -21.0; a11 = 22; + a12 = -23; - final result = passStruct9BytesPackedMixedx10DoubleInt32( - a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + final result = passStruct9BytesPackedMixedx10DoubleInt32x2( + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); print("result = $result"); - Expect.approxEquals(211.0, result); + Expect.approxEquals(188.0, result); calloc.free(a0Pointer); calloc.free(a1Pointer); @@ -13392,7 +13396,7 @@ void testPassStruct8BytesPackedIntx10Leaf() { calloc.free(a9Pointer); } -final passStruct9BytesPackedMixedx10DoubleInt32Leaf = +final passStruct9BytesPackedMixedx10DoubleInt32x2Leaf = ffiTestFunctions.lookupFunction< Double Function( Struct9BytesPackedMixed, @@ -13406,6 +13410,7 @@ final passStruct9BytesPackedMixedx10DoubleInt32Leaf = Struct9BytesPackedMixed, Struct9BytesPackedMixed, Double, + Int32, Int32), double Function( Struct9BytesPackedMixed, @@ -13419,11 +13424,12 @@ final passStruct9BytesPackedMixedx10DoubleInt32Leaf = Struct9BytesPackedMixed, Struct9BytesPackedMixed, double, - int)>("PassStruct9BytesPackedMixedx10DoubleInt32", isLeaf: true); + int, + int)>("PassStruct9BytesPackedMixedx10DoubleInt32x2", isLeaf: true); /// Struct with mis-aligned member. /// Tests backfilling of CPU and FPU registers. -void testPassStruct9BytesPackedMixedx10DoubleInt32Leaf() { +void testPassStruct9BytesPackedMixedx10DoubleInt32x2Leaf() { final a0Pointer = calloc(); final Struct9BytesPackedMixed a0 = a0Pointer.ref; final a1Pointer = calloc(); @@ -13446,6 +13452,7 @@ void testPassStruct9BytesPackedMixedx10DoubleInt32Leaf() { final Struct9BytesPackedMixed a9 = a9Pointer.ref; double a10; int a11; + int a12; a0.a0 = 1; a0.a1 = 2.0; @@ -13469,13 +13476,14 @@ void testPassStruct9BytesPackedMixedx10DoubleInt32Leaf() { a9.a1 = 20.0; a10 = -21.0; a11 = 22; + a12 = -23; - final result = passStruct9BytesPackedMixedx10DoubleInt32Leaf( - a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + final result = passStruct9BytesPackedMixedx10DoubleInt32x2Leaf( + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); print("result = $result"); - Expect.approxEquals(211.0, result); + Expect.approxEquals(188.0, result); calloc.free(a0Pointer); calloc.free(a1Pointer); diff --git a/tests/ffi_2/generator/c_types.dart b/tests/ffi_2/generator/c_types.dart deleted file mode 100644 index edd670c8548..00000000000 --- a/tests/ffi_2/generator/c_types.dart +++ /dev/null @@ -1,461 +0,0 @@ -// 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. - -// @dart = 2.9 - -import 'dart:math' as math; - -import 'utils.dart'; - -const int8 = FundamentalType(PrimitiveType.int8); -const int16 = FundamentalType(PrimitiveType.int16); -const int32 = FundamentalType(PrimitiveType.int32); -const int64 = FundamentalType(PrimitiveType.int64); -const uint8 = FundamentalType(PrimitiveType.uint8); -const uint16 = FundamentalType(PrimitiveType.uint16); -const uint32 = FundamentalType(PrimitiveType.uint32); -const uint64 = FundamentalType(PrimitiveType.uint64); -const intptr = FundamentalType(PrimitiveType.intptr); -const float = FundamentalType(PrimitiveType.float); -const double_ = FundamentalType(PrimitiveType.double_); - -enum PrimitiveType { - int8, - int16, - int32, - int64, - uint8, - uint16, - uint32, - uint64, - intptr, - float, - double_, -} - -const primitiveNames = [ - "int8", - "int16", - "int32", - "int64", - "uint8", - "uint16", - "uint32", - "uint64", - "intptr", - "float", - "double", -]; - -const intptrSize = -1; -const primitiveSizesInBytes = [1, 2, 4, 8, 1, 2, 4, 8, intptrSize, 4, 8]; - -abstract class CType { - String get cType; - String get dartCType; - String get dartType; - String get dartStructFieldAnnotation; - - /// Has a known [size] that is the same for all architectures. - bool get hasSize; - - /// Get a size in bytes that is the same on all architectures. - int get size; - - /// All members have a floating point type. - bool get isOnlyFloatingPoint; - - /// All members have a integer type. - bool get isOnlyInteger; - - String toString() => dartCType; - - const CType(); -} - -class FundamentalType extends CType { - final PrimitiveType primitive; - - const FundamentalType(this.primitive); - - bool get isFloatingPoint => - primitive == PrimitiveType.float || primitive == PrimitiveType.double_; - bool get isInteger => !isFloatingPoint; - bool get isOnlyFloatingPoint => isFloatingPoint; - bool get isOnlyInteger => isInteger; - bool get isUnsigned => - primitive == PrimitiveType.uint8 || - primitive == PrimitiveType.uint16 || - primitive == PrimitiveType.uint32 || - primitive == PrimitiveType.uint64; - bool get isSigned => !isUnsigned; - - String get name => primitiveNames[primitive.index]; - - String get cType => "${name}${isInteger ? "_t" : ""}"; - String get dartCType => name.upperCaseFirst(); - String get dartType => isInteger ? "int" : "double"; - String get dartStructFieldAnnotation => "@${dartCType}()"; - bool get hasSize => primitive != PrimitiveType.intptr; - int get size { - if (!hasSize) { - throw "Size unknown."; - } - return primitiveSizesInBytes[primitive.index]; - } -} - -class PointerType extends CType { - final CType pointerTo; - - PointerType(this.pointerTo); - - String get cType => "${pointerTo.cType}*"; - String get dartCType => "Pointer<${pointerTo.dartCType}>"; - String get dartType => "Pointer<${pointerTo.dartType}>"; - String get dartStructFieldAnnotation => ""; - bool get hasSize => false; - int get size => throw "Size unknown"; - - bool get isOnlyFloatingPoint => false; - bool get isOnlyInteger => true; -} - -/// Used to give [StructType] fields and [FunctionType] arguments names. -class Member { - final CType type; - final String name; - - Member(this.type, this.name); - - String dartStructField(bool nnbd) { - final modifier = nnbd ? "external" : ""; - return "${type.dartStructFieldAnnotation} $modifier ${type.dartType} $name;"; - } - - String get cStructField { - String postFix = ""; - if (type is FixedLengthArrayType) { - final dimensions = (type as FixedLengthArrayType).dimensions; - postFix = "[${dimensions.join("][")}]"; - } - return "${type.cType} $name$postFix;"; - } - - String toString() => "$type $name"; -} - -List generateMemberNames(List memberTypes) { - int index = 0; - List result = []; - for (final type in memberTypes) { - result.add(Member(type, "a$index")); - index++; - } - return result; -} - -abstract class CompositeType extends CType { - final List members; - - /// To disambiguate same size structs. - final String suffix; - - /// To override names. - final String overrideName; - - CompositeType(List memberTypes) - : this.members = generateMemberNames(memberTypes), - this.suffix = "", - this.overrideName = ""; - CompositeType.disambiguate(List memberTypes, this.suffix) - : this.members = generateMemberNames(memberTypes), - this.overrideName = ""; - CompositeType.override(List memberTypes, this.overrideName) - : this.members = generateMemberNames(memberTypes), - this.suffix = ""; - - List get memberTypes => members.map((a) => a.type).toList(); - - String get name; - - String get cType => name; - String get dartCType => name; - String get dartType => name; - String get dartStructFieldAnnotation => ""; - String get cKeyword; - String get dartSuperClass; - - bool get isOnlyFloatingPoint => - !memberTypes.map((e) => e.isOnlyFloatingPoint).contains(false); - bool get isOnlyInteger => - !memberTypes.map((e) => e.isOnlyInteger).contains(false); - - bool get isMixed => !isOnlyInteger && !isOnlyFloatingPoint; - - bool get hasNestedStructs => - members.map((e) => e.type is StructType).contains(true); - - bool get hasInlineArrays => - members.map((e) => e.type is FixedLengthArrayType).contains(true); - - bool get hasMultiDimensionalInlineArrays => members - .map((e) => e.type) - .whereType() - .where((e) => e.isMulti) - .isNotEmpty; -} - -class StructType extends CompositeType { - final int? packing; - - StructType(List memberTypes, {int? this.packing}) : super(memberTypes); - StructType.disambiguate(List memberTypes, String suffix, - {int? this.packing}) - : super.disambiguate(memberTypes, suffix); - StructType.override(List memberTypes, String overrideName, - {int? this.packing}) - : super.override(memberTypes, overrideName); - - String get cKeyword => "struct"; - String get dartSuperClass => "Struct"; - - bool get hasSize => - !memberTypes.map((e) => e.hasSize).contains(false) && !hasPadding; - int get size => memberTypes.fold(0, (int acc, e) => acc + e.size); - - bool get hasPacking => packing != null; - - bool get hasPadding { - if (members.length < 2) { - return false; - } - if (packing == 1) { - return false; - } - - /// Rough approximation, to not redo all ABI logic here. - return members[0].type.size < members[1].type.size; - } - - /// All members have the same type. - bool get isHomogeneous => memberTypes.toSet().length == 1; - - String get name { - String result = dartSuperClass; - if (overrideName != "") { - return result + overrideName; - } - if (hasSize) { - result += "${size}Byte" + (size != 1 ? "s" : ""); - } - if (hasPacking) { - result += "Packed"; - if (packing! > 1) { - result += "$packing"; - } - } - if (hasNestedStructs) { - result += "Nested"; - } - if (hasInlineArrays) { - result += "InlineArray"; - if (hasMultiDimensionalInlineArrays) { - result += "MultiDimensional"; - } - } - if (members.length == 0) { - // No suffix. - } else if (hasPadding) { - result += "Alignment${memberTypes[1].dartCType}"; - } else if (isHomogeneous && members.length > 1 && !hasNestedStructs) { - result += "Homogeneous${memberTypes.first.dartCType}"; - } else if (isOnlyFloatingPoint) { - result += "Float"; - } else if (isOnlyInteger) { - result += "Int"; - } else { - result += "Mixed"; - } - result += suffix; - return result; - } -} - -class UnionType extends CompositeType { - UnionType(List memberTypes) : super(memberTypes); - - String get cKeyword => "union"; - String get dartSuperClass => "Union"; - - bool get hasSize => !memberTypes.map((e) => e.hasSize).contains(false); - int get size => memberTypes.fold(0, (int acc, e) => math.max(acc, e.size)); - - String get name { - String result = dartSuperClass; - if (overrideName != "") { - return result + overrideName; - } - if (hasSize) { - result += "${size}Byte" + (size != 1 ? "s" : ""); - } - if (hasNestedStructs) { - result += "Nested"; - } - if (hasInlineArrays) { - result += "InlineArray"; - if (hasMultiDimensionalInlineArrays) { - result += "MultiDimensional"; - } - } - if (members.length == 0) { - // No suffix. - } else if (isOnlyFloatingPoint) { - result += "Float"; - } else if (isOnlyInteger) { - result += "Int"; - } else { - result += "Mixed"; - } - result += suffix; - return result; - } -} - -class FixedLengthArrayType extends CType { - final CType elementType; - final int length; - - FixedLengthArrayType(this.elementType, this.length); - - factory FixedLengthArrayType.multi(CType elementType, List dimensions) { - if (dimensions.length == 1) { - return FixedLengthArrayType(elementType, dimensions.single); - } - - final remainingDimensions = dimensions.sublist(1); - final nestedArray = - FixedLengthArrayType.multi(elementType, remainingDimensions); - return FixedLengthArrayType(nestedArray, dimensions.first); - } - - String get cType => elementType.cType; - String get dartCType => "Array<${elementType.dartCType}>"; - String get dartType => "Array<${elementType.dartCType}>"; - - String get dartStructFieldAnnotation { - if (dimensions.length > 5) { - return "@Array.multi([${dimensions.join(", ")}])"; - } - return "@Array(${dimensions.join(", ")})"; - } - - List get dimensions { - final elementType = this.elementType; - if (elementType is FixedLengthArrayType) { - return [length, ...elementType.dimensions]; - } - return [length]; - } - - bool get isMulti => elementType is FixedLengthArrayType; - - bool get hasSize => elementType.hasSize; - int get size => elementType.size * length; - - bool get isOnlyFloatingPoint => elementType.isOnlyFloatingPoint; - bool get isOnlyInteger => elementType.isOnlyInteger; -} - -class FunctionType extends CType { - final List arguments; - final CType returnValue; - final String reason; - - List get argumentTypes => arguments.map((a) => a.type).toList(); - - FunctionType(List argumentTypes, this.returnValue, this.reason) - : this.arguments = generateMemberNames(argumentTypes); - - String get cType => - throw "Are not represented without function or variable name in C."; - - String get dartCType { - final argumentsDartCType = argumentTypes.map((e) => e.dartCType).join(", "); - return "${returnValue.dartCType} Function($argumentsDartCType)"; - } - - String get dartType { - final argumentsDartType = argumentTypes.map((e) => e.dartType).join(", "); - return "${returnValue.dartType} Function($argumentsDartType)"; - } - - String get dartStructFieldAnnotation => throw "No nested function pointers."; - - bool get hasSize => false; - int get size => throw "Unknown size."; - - bool get isOnlyFloatingPoint => throw "Not implemented"; - bool get isOnlyInteger => throw "Not implemented"; - - /// Group consecutive [arguments] by same type. - /// - /// Used for naming. - List> get argumentsGrouped { - List> result = []; - for (final a in arguments) { - if (result.isEmpty) { - result.add([a]); - } else if (result.last.first.type.dartCType == a.type.dartCType) { - result.last.add(a); - } else { - result.add([a]); - } - } - return result; - } - - /// A suitable name based on the signature. - String get cName { - String result = ""; - if (arguments.containsComposites && returnValue is FundamentalType) { - result = "Pass"; - } else if (returnValue is StructType && - argumentTypes.contains(returnValue)) { - result = "ReturnStructArgument"; - } else if (returnValue is UnionType && - argumentTypes.contains(returnValue)) { - result = "ReturnUnionArgument"; - } else if (returnValue is StructType) { - if (arguments.length == (returnValue as StructType).members.length) { - return "Return${returnValue.dartCType}"; - } - } else if (returnValue is UnionType && arguments.length == 1) { - return "Return${returnValue.dartCType}"; - } else { - result = "Uncategorized"; - } - - for (final group in argumentsGrouped) { - result += group.first.type.dartCType; - if (group.length > 1) { - result += "x${group.length}"; - } - } - return result.limitTo(50); - } - - String get dartTestName => "test$cName"; - - String get dartName => cName.lowerCaseFirst(); - - /// Only valid for [TestType.structReturnArgument]. - Member get structReturnArgument => - arguments.firstWhere((a) => a.type == returnValue); -} - -extension MemberList on List { - bool get containsComposites => - map((m) => m.type is CompositeType).contains(true); -} diff --git a/tests/ffi_2/generator/structs_by_value_tests_configuration.dart b/tests/ffi_2/generator/structs_by_value_tests_configuration.dart deleted file mode 100644 index f8fbb1b1287..00000000000 --- a/tests/ffi_2/generator/structs_by_value_tests_configuration.dart +++ /dev/null @@ -1,812 +0,0 @@ -// 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. - -// @dart = 2.9 - -import 'c_types.dart'; - -final functions = [ - ...functionsStructArguments, - ...functionsStructReturn, - ...functionsReturnArgument, -]; - -final functionsStructArguments = [ - FunctionType(List.filled(10, struct1byteInt), int64, """ -Smallest struct with data. -10 struct arguments will exhaust available registers."""), - FunctionType(List.filled(10, struct3bytesInt), int64, """ -Not a multiple of word size, not a power of two. -10 struct arguments will exhaust available registers."""), - FunctionType(List.filled(10, struct3bytesInt2), int64, """ -Not a multiple of word size, not a power of two. -With alignment rules taken into account size is 4 bytes. -10 struct arguments will exhaust available registers."""), - FunctionType(List.filled(10, struct4bytesInt), int64, """ -Exactly word size on 32-bit architectures. -10 struct arguments will exhaust available registers."""), - FunctionType(List.filled(10, struct7bytesInt), int64, """ -Sub word size on 64 bit architectures. -10 struct arguments will exhaust available registers."""), - FunctionType(List.filled(10, struct7bytesInt2), int64, """ -Sub word size on 64 bit architectures. -With alignment rules taken into account size is 8 bytes. -10 struct arguments will exhaust available registers."""), - FunctionType(List.filled(10, struct8bytesInt), int64, """ -Exactly word size struct on 64bit architectures. -10 struct arguments will exhaust available registers."""), - FunctionType(List.filled(10, struct8bytesFloat), float, """ -Arguments passed in FP registers as long as they fit. -10 struct arguments will exhaust available registers."""), - FunctionType(List.filled(10, struct8BytesMixed), float, """ -On x64, arguments go in int registers because it is not only float. -10 struct arguments will exhaust available registers."""), - FunctionType(List.filled(10, struct9bytesInt), int64, """ -Argument is a single byte over a multiple of word size. -10 struct arguments will exhaust available registers. -Struct only has 1-byte aligned fields to test struct alignment itself. -Tests upper bytes in the integer registers that are partly filled. -Tests stack alignment of non word size stack arguments."""), - FunctionType(List.filled(10, struct9bytesInt2), int64, """ -Argument is a single byte over a multiple of word size. -With alignment rules taken into account size is 12 or 16 bytes. -10 struct arguments will exhaust available registers. -"""), - FunctionType(List.filled(6, struct12bytesFloat), float, """ -Arguments in FPU registers on arm hardfp and arm64. -Struct arguments will exhaust available registers, and leave some empty. -The last argument is to test whether arguments are backfilled."""), - FunctionType(List.filled(5, struct16bytesFloat), float, """ -On Linux x64 argument is transferred on stack because it is over 16 bytes. -Arguments in FPU registers on arm hardfp and arm64. -5 struct arguments will exhaust available registers."""), - FunctionType(List.filled(10, struct16bytesMixed), double_, """ -On x64, arguments are split over FP and int registers. -On x64, it will exhaust the integer registers with the 6th argument. -The rest goes on the stack. -On arm, arguments are 8 byte aligned."""), - FunctionType(List.filled(10, struct16bytesMixed2), float, """ -On x64, arguments are split over FP and int registers. -On x64, it will exhaust the integer registers with the 6th argument. -The rest goes on the stack. -On arm, arguments are 4 byte aligned."""), - FunctionType(List.filled(10, struct17bytesInt), int64, """ -Arguments are passed as pointer to copy on arm64. -Tests that the memory allocated for copies are rounded up to word size."""), - FunctionType(List.filled(10, struct19bytesInt), int64, """ -The minimum alignment of this struct is only 1 byte based on its fields. -Test that the memory backing these structs is extended to the right size. -"""), - FunctionType(List.filled(10, struct20bytesInt), int32, """ -Argument too big to go into integer registers on arm64. -The arguments are passed as pointers to copies. -The amount of arguments exhausts the number of integer registers, such that -pointers to copies are also passed on the stack."""), - FunctionType( - [struct20bytesFloat], - float, - """ -Argument too big to go into FPU registers in hardfp and arm64."""), - FunctionType(List.filled(5, struct32bytesDouble), double_, """ -Arguments in FPU registers on arm64. -5 struct arguments will exhaust available registers."""), - FunctionType( - [struct40bytesDouble], - double_, - """ -Argument too big to go into FPU registers in arm64."""), - FunctionType( - [struct1024bytesInt], - uint64, - """ -Test 1kb struct."""), - FunctionType( - [ - float, - struct16bytesFloat, - float, - struct16bytesFloat, - float, - struct16bytesFloat, - float, - struct16bytesFloat, - float - ], - float, - """ -Tests the alignment of structs in FPU registers and backfilling."""), - FunctionType( - [ - float, - struct32bytesDouble, - float, - struct32bytesDouble, - float, - struct32bytesDouble, - float, - struct32bytesDouble, - float - ], - double_, - """ -Tests the alignment of structs in FPU registers and backfilling."""), - FunctionType( - [ - int8, - struct16bytesMixed, - int8, - struct16bytesMixed, - int8, - struct16bytesMixed, - int8, - struct16bytesMixed, - int8 - ], - double_, - """ -Tests the alignment of structs in integers registers and on the stack. -Arm32 aligns this struct at 8. -Also, arm32 allocates the second struct partially in registers, partially -on stack. -Test backfilling of integer registers."""), - FunctionType( - [ - double_, - double_, - double_, - double_, - double_, - double_, - struct16bytesMixed, - struct16bytesMixed, - struct16bytesMixed, - struct16bytesMixed, - int32, - ], - double_, - """ -On Linux x64, it will exhaust xmm registers first, after 6 doubles and 2 -structs. The rest of the structs will go on the stack. -The int will be backfilled into the int register."""), - FunctionType( - [ - int32, - int32, - int32, - int32, - struct16bytesMixed, - struct16bytesMixed, - struct16bytesMixed, - struct16bytesMixed, - double_, - ], - double_, - """ -On Linux x64, it will exhaust int registers first. -The rest of the structs will go on the stack. -The double will be backfilled into the xmm register."""), - FunctionType( - [ - struct40bytesDouble, - struct4bytesInt, - struct8bytesFloat, - ], - double_, - """ -On various architectures, first struct is allocated on stack. -Check that the other two arguments are allocated on registers."""), - FunctionType( - [ - // Exhaust integer registers on all architectures - int32, - int32, - int32, - int32, - int32, - int32, - int32, - int32, - // Exhaust floating point registers on all architectures. - double_, - double_, - double_, - double_, - double_, - double_, - double_, - double_, - // Pass all kinds of structs to exercise stack placement behavior. - // - // For all structs, align stack with int64, then align to 1-byte with - // int8, then pass struct. - int64, - int8, - struct1byteInt, - int64, - int8, - struct4bytesInt, - int64, - int8, - struct8bytesInt, - int64, - int8, - struct8bytesFloat, - int64, - int8, - struct8BytesMixed, - int64, - int8, - structAlignmentInt16, - int64, - int8, - structAlignmentInt32, - int64, - int8, - structAlignmentInt64, - ], - double_, - """ -Test alignment and padding of 16 byte int within struct."""), - FunctionType( - [structAlignmentInt16], - int64, - """ -Test alignment and padding of 16 byte int within struct."""), - FunctionType( - [structAlignmentInt32], - int64, - """ -Test alignment and padding of 32 byte int within struct."""), - FunctionType( - [structAlignmentInt64], - int64, - """ -Test alignment and padding of 64 byte int within struct."""), - FunctionType(List.filled(10, struct8bytesNestedInt), int64, """ -Simple nested struct. No alignment gaps on any architectures. -10 arguments exhaust registers on all platforms."""), - FunctionType(List.filled(10, struct8bytesNestedFloat), float, """ -Simple nested struct. No alignment gaps on any architectures. -10 arguments exhaust fpu registers on all platforms."""), - FunctionType(List.filled(10, struct8bytesNestedFloat2), float, """ -Simple nested struct. No alignment gaps on any architectures. -10 arguments exhaust fpu registers on all platforms. -The nesting is irregular, testing homogenous float rules on arm and arm64, -and the fpu register usage on x64."""), - FunctionType(List.filled(10, struct8bytesNestedMixed), double_, """ -Simple nested struct. No alignment gaps on any architectures. -10 arguments exhaust all registers on all platforms."""), - FunctionType(List.filled(2, struct16bytesNestedInt), int64, """ -Deeper nested struct to test recursive member access."""), - FunctionType(List.filled(2, struct32bytesNestedInt), int64, """ -Even deeper nested struct to test recursive member access."""), - FunctionType( - [structNestedAlignmentInt16], - int64, - """ -Test alignment and padding of nested struct with 16 byte int."""), - FunctionType( - [structNestedAlignmentInt32], - int64, - """ -Test alignment and padding of nested struct with 32 byte int."""), - FunctionType( - [structNestedAlignmentInt64], - int64, - """ -Test alignment and padding of nested struct with 64 byte int."""), - FunctionType(List.filled(4, structNestedEvenBigger), double_, """ -Return big irregular struct as smoke test."""), - FunctionType(List.filled(4, structInlineArray), int32, """ -Simple struct with inline array."""), - FunctionType(List.filled(4, structInlineArrayIrregular), int32, """ -Irregular struct with inline array."""), - FunctionType( - [structInlineArray100Bytes], - int32, - """ -Regular larger struct with inline array."""), - FunctionType(List.filled(5, struct16bytesFloatInlineNested), float, """ -Arguments in FPU registers on arm hardfp and arm64. -5 struct arguments will exhaust available registers."""), - FunctionType(List.filled(5, struct32bytesDoubleInlineNested), double_, """ -Arguments in FPU registers on arm64. -5 struct arguments will exhaust available registers."""), - FunctionType(List.filled(10, struct16bytesMixedInlineNested), float, """ -On x64, arguments are split over FP and int registers. -On x64, it will exhaust the integer registers with the 6th argument. -The rest goes on the stack. -On arm, arguments are 4 byte aligned."""), - FunctionType( - [ - uint8, - struct32bytesInlineArrayMultiDimesional, - uint8, - struct8bytesInlineArrayMultiDimesional, - uint8, - struct8bytesInlineArrayMultiDimesional, - uint8 - ], - uint32, - """ -Test multi dimensional inline array struct as argument."""), - FunctionType( - [uint8, structMultiDimensionalStruct, uint8], - uint32, - """ -Test struct in multi dimensional inline array."""), - FunctionType(List.filled(10, struct3bytesPacked), int64, """ -Small struct with mis-aligned member."""), - FunctionType(List.filled(10, struct8bytesPacked), int64, """ -Struct with mis-aligned member."""), - FunctionType( - [...List.filled(10, struct9bytesPacked), double_, int32], - double_, - """ -Struct with mis-aligned member. -Tests backfilling of CPU and FPU registers."""), - FunctionType( - [struct5bytesPacked], - double_, - """ -This packed struct happens to have only aligned members."""), - FunctionType( - [struct6bytesPacked], - double_, - """ -Check alignment of packed struct in non-packed struct."""), - FunctionType( - [struct6bytesPacked2], - double_, - """ -Check alignment of packed struct array in non-packed struct."""), - FunctionType( - [struct15bytesPacked], - double_, - """ -Check alignment of packed struct array in non-packed struct."""), - FunctionType(List.filled(10, union4bytesMixed), double_, """ -Check placement of mixed integer/float union."""), - FunctionType(List.filled(10, union8bytesFloat), double_, """ -Check placement of mixed floats union."""), - FunctionType(List.filled(10, union12bytesInt), double_, """ -Mixed-size union argument."""), - FunctionType(List.filled(10, union16bytesFloat), double_, """ -Union with homogenous floats."""), - FunctionType(List.filled(10, union16bytesFloat2), double_, """ -Union with homogenous floats."""), -]; - -final functionsStructReturn = [ - FunctionType(struct1byteInt.memberTypes, struct1byteInt, """ -Smallest struct with data."""), - FunctionType(struct3bytesInt.memberTypes, struct3bytesInt, """ -Smaller than word size return value on all architectures."""), - FunctionType(struct3bytesInt2.memberTypes, struct3bytesInt2, """ -Smaller than word size return value on all architectures. -With alignment rules taken into account size is 4 bytes."""), - FunctionType(struct4bytesInt.memberTypes, struct4bytesInt, """ -Word size return value on 32 bit architectures.."""), - FunctionType(struct7bytesInt.memberTypes, struct7bytesInt, """ -Non-wordsize return value."""), - FunctionType(struct7bytesInt2.memberTypes, struct7bytesInt2, """ -Non-wordsize return value. -With alignment rules taken into account size is 8 bytes."""), - FunctionType(struct8bytesInt.memberTypes, struct8bytesInt, """ -Return value in integer registers on many architectures."""), - FunctionType(struct8bytesFloat.memberTypes, struct8bytesFloat, """ -Return value in FP registers on many architectures."""), - FunctionType(struct8BytesMixed.memberTypes, struct8BytesMixed, """ -Return value split over FP and integer register in x64."""), - FunctionType(struct9bytesInt.memberTypes, struct9bytesInt, """ -The minimum alignment of this struct is only 1 byte based on its fields. -Test that the memory backing these structs is the right size and that -dart:ffi trampolines do not write outside this size."""), - FunctionType(struct9bytesInt2.memberTypes, struct9bytesInt2, """ -Return value in two integer registers on x64. -With alignment rules taken into account size is 12 or 16 bytes."""), - FunctionType(struct12bytesFloat.memberTypes, struct12bytesFloat, """ -Return value in FPU registers, but does not use all registers on arm hardfp -and arm64."""), - FunctionType(struct16bytesFloat.memberTypes, struct16bytesFloat, """ -Return value in FPU registers on arm hardfp and arm64."""), - FunctionType(struct16bytesMixed.memberTypes, struct16bytesMixed, """ -Return value split over FP and integer register in x64."""), - FunctionType(struct16bytesMixed2.memberTypes, struct16bytesMixed2, """ -Return value split over FP and integer register in x64. -The integer register contains half float half int."""), - FunctionType(struct17bytesInt.memberTypes, struct17bytesInt, """ -Rerturn value returned in preallocated space passed by pointer on most ABIs. -Is non word size on purpose, to test that structs are rounded up to word size -on all ABIs."""), - FunctionType(struct19bytesInt.memberTypes, struct19bytesInt, """ -The minimum alignment of this struct is only 1 byte based on its fields. -Test that the memory backing these structs is the right size and that -dart:ffi trampolines do not write outside this size."""), - FunctionType(struct20bytesInt.memberTypes, struct20bytesInt, """ -Return value too big to go in cpu registers on arm64."""), - FunctionType(struct20bytesFloat.memberTypes, struct20bytesFloat, """ -Return value too big to go in FPU registers on x64, arm hardfp and arm64."""), - FunctionType(struct32bytesDouble.memberTypes, struct32bytesDouble, """ -Return value in FPU registers on arm64."""), - FunctionType(struct40bytesDouble.memberTypes, struct40bytesDouble, """ -Return value too big to go in FPU registers on arm64."""), - FunctionType(struct1024bytesInt.memberTypes, struct1024bytesInt, """ -Test 1kb struct."""), - FunctionType(struct3bytesPacked.memberTypes, struct3bytesPacked, """ -Small struct with mis-aligned member."""), - FunctionType(struct8bytesPacked.memberTypes, struct8bytesPacked, """ -Struct with mis-aligned member."""), - FunctionType(struct9bytesPacked.memberTypes, struct9bytesPacked, """ -Struct with mis-aligned member. -Tests backfilling of CPU and FPU registers."""), - FunctionType( - [union4bytesMixed.memberTypes.first], - union4bytesMixed, - """ -Returning a mixed integer/float union."""), - FunctionType( - [union8bytesFloat.memberTypes.first], - union8bytesFloat, - """ -Returning a floating point only union."""), - FunctionType( - [union12bytesInt.memberTypes.first], - union12bytesInt, - """ -Returning a mixed-size union."""), - FunctionType( - [union16bytesFloat2.memberTypes.first], - union16bytesFloat2, - """ -Returning union with homogenous floats."""), -]; - -final functionsReturnArgument = [ - FunctionType( - [struct1byteInt], - struct1byteInt, - """ -Test that a struct passed in as argument can be returned. -Especially for ffi callbacks. -Struct is passed in int registers in most ABIs."""), - FunctionType( - [int32, int32, int32, int32, int32, int32, int32, int32, struct1byteInt], - struct1byteInt, - """ -Test that a struct passed in as argument can be returned. -Especially for ffi callbacks. -Struct is passed on stack on all ABIs."""), - FunctionType( - [struct8bytesFloat], - struct8bytesFloat, - """ -Test that a struct passed in as argument can be returned. -Especially for ffi callbacks. -Struct is passed in float registers in most ABIs."""), - FunctionType( - [struct20bytesInt], - struct20bytesInt, - """ -On arm64, both argument and return value are passed in by pointer."""), - FunctionType( - [ - int32, - int32, - int32, - int32, - int32, - int32, - int32, - int32, - struct20bytesInt - ], - struct20bytesInt, - """ -On arm64, both argument and return value are passed in by pointer. -Ints exhaust registers, so that pointer is passed on stack."""), - FunctionType( - [structInlineArray], - structInlineArray, - """ -Test returning struct with inline array."""), - FunctionType( - [struct16bytesFloatInlineNested], - struct16bytesFloatInlineNested, - """ -Return value in FPU registers on arm hardfp and arm64."""), - FunctionType( - [struct32bytesDoubleInlineNested], - struct32bytesDoubleInlineNested, - """ -Return value in FPU registers on arm64."""), - FunctionType( - [struct16bytesMixedInlineNested], - struct16bytesMixedInlineNested, - """ -On x64 Linux, return value is split over FP and int registers."""), - FunctionType(structAlignmentInt16.memberTypes, structAlignmentInt16, """ -Test alignment and padding of 16 byte int within struct."""), - FunctionType(structAlignmentInt32.memberTypes, structAlignmentInt32, """ -Test alignment and padding of 32 byte int within struct."""), - FunctionType(structAlignmentInt64.memberTypes, structAlignmentInt64, """ -Test alignment and padding of 64 byte int within struct."""), - FunctionType(struct8bytesNestedInt.memberTypes, struct8bytesNestedInt, """ -Simple nested struct."""), - FunctionType(struct8bytesNestedFloat.memberTypes, struct8bytesNestedFloat, """ -Simple nested struct with floats."""), - FunctionType( - struct8bytesNestedFloat2.memberTypes, struct8bytesNestedFloat2, """ -The nesting is irregular, testing homogenous float rules on arm and arm64, -and the fpu register usage on x64."""), - FunctionType(struct8bytesNestedMixed.memberTypes, struct8bytesNestedMixed, """ -Simple nested struct with mixed members."""), - FunctionType(struct16bytesNestedInt.memberTypes, struct16bytesNestedInt, """ -Deeper nested struct to test recursive member access."""), - FunctionType(struct32bytesNestedInt.memberTypes, struct32bytesNestedInt, """ -Even deeper nested struct to test recursive member access."""), - FunctionType( - structNestedAlignmentInt16.memberTypes, structNestedAlignmentInt16, """ -Test alignment and padding of nested struct with 16 byte int."""), - FunctionType( - structNestedAlignmentInt32.memberTypes, structNestedAlignmentInt32, """ -Test alignment and padding of nested struct with 32 byte int."""), - FunctionType( - structNestedAlignmentInt64.memberTypes, structNestedAlignmentInt64, """ -Test alignment and padding of nested struct with 64 byte int."""), - FunctionType(structNestedEvenBigger.memberTypes, structNestedEvenBigger, """ -Return big irregular struct as smoke test."""), -]; - -final compounds = [ - struct1byteInt, - struct3bytesInt, - struct3bytesInt2, - struct4bytesInt, - struct4bytesFloat, - struct7bytesInt, - struct7bytesInt2, - struct8bytesInt, - struct8bytesFloat, - struct8bytesFloat2, - struct8BytesMixed, - struct9bytesInt, - struct9bytesInt2, - struct12bytesFloat, - struct16bytesFloat, - struct16bytesMixed, - struct16bytesMixed2, - struct17bytesInt, - struct19bytesInt, - struct20bytesInt, - struct20bytesFloat, - struct32bytesDouble, - struct40bytesDouble, - struct1024bytesInt, - structAlignmentInt16, - structAlignmentInt32, - structAlignmentInt64, - struct8bytesNestedInt, - struct8bytesNestedFloat, - struct8bytesNestedFloat2, - struct8bytesNestedMixed, - struct16bytesNestedInt, - struct32bytesNestedInt, - structNestedAlignmentInt16, - structNestedAlignmentInt32, - structNestedAlignmentInt64, - structNestedBig, - structNestedBigger, - structNestedEvenBigger, - structInlineArray, - structInlineArrayIrregular, - structInlineArray100Bytes, - structInlineArrayBig, - struct16bytesFloatInlineNested, - struct32bytesDoubleInlineNested, - struct16bytesMixedInlineNested, - struct8bytesInlineArrayMultiDimesional, - struct32bytesInlineArrayMultiDimesional, - struct64bytesInlineArrayMultiDimesional, - structMultiDimensionalStruct, - struct3bytesPacked, - struct3bytesPackedMembersAligned, - struct5bytesPacked, - struct6bytesPacked, - struct6bytesPacked2, - struct8bytesPacked, - struct9bytesPacked, - struct15bytesPacked, - union4bytesMixed, - union8bytesFloat, - union12bytesInt, - union16bytesFloat, - union16bytesFloat2, -]; - -final struct1byteInt = StructType([int8]); -final struct3bytesInt = StructType(List.filled(3, uint8)); -final struct3bytesInt2 = StructType.disambiguate([int16, int8], "2ByteAligned"); -final struct4bytesInt = StructType([int16, int16]); -final struct4bytesFloat = StructType([float]); -final struct7bytesInt = StructType(List.filled(7, uint8)); -final struct7bytesInt2 = - StructType.disambiguate([int32, int16, int8], "4ByteAligned"); -final struct8bytesInt = StructType([int16, int16, int32]); -final struct8bytesFloat = StructType([float, float]); -final struct8bytesFloat2 = StructType([double_]); -final struct8BytesMixed = StructType([float, int16, int16]); -final struct9bytesInt = StructType(List.filled(9, uint8)); -final struct9bytesInt2 = - StructType.disambiguate([int64, int8], "4Or8ByteAligned"); -final struct12bytesFloat = StructType([float, float, float]); - -/// The largest homogenous float that goes into FPU registers on softfp and -/// arm64. -final struct16bytesFloat = StructType([float, float, float, float]); - -/// This struct will be 8 byte aligned on arm. -final struct16bytesMixed = StructType([double_, int64]); - -/// This struct will be 4 byte aligned on arm. -final struct16bytesMixed2 = - StructType.disambiguate([float, float, float, int32], "2"); - -final struct17bytesInt = StructType([int64, int64, int8]); - -/// This struct has only 1 byte field-alignmnent requirements. -final struct19bytesInt = StructType(List.filled(19, uint8)); - -/// The first homogenous integer struct that does not go into registers -/// anymore on arm64. -final struct20bytesInt = StructType([int32, int32, int32, int32, int32]); - -/// The first homogenous float that does not go into FPU registers anymore on -/// softfp and arm64. -final struct20bytesFloat = StructType([float, float, float, float, float]); - -/// Largest homogenous doubles in arm64 that goes into FPU registers. -final struct32bytesDouble = StructType([double_, double_, double_, double_]); - -/// The first homogenous doubles that does not go into FPU registers anymore on -/// arm64. -final struct40bytesDouble = - StructType([double_, double_, double_, double_, double_]); - -final struct1024bytesInt = StructType(List.filled(128, uint64)); - -final structAlignmentInt16 = StructType([int8, int16, int8]); -final structAlignmentInt32 = StructType([int8, int32, int8]); -final structAlignmentInt64 = StructType([int8, int64, int8]); - -final struct8bytesNestedInt = StructType([struct4bytesInt, struct4bytesInt]); -final struct8bytesNestedFloat = - StructType([struct4bytesFloat, struct4bytesFloat]); -final struct8bytesNestedFloat2 = - StructType.disambiguate([struct4bytesFloat, float], "2"); -final struct8bytesNestedMixed = - StructType([struct4bytesInt, struct4bytesFloat]); - -final struct16bytesNestedInt = - StructType([struct8bytesNestedInt, struct8bytesNestedInt]); -final struct32bytesNestedInt = - StructType([struct16bytesNestedInt, struct16bytesNestedInt]); - -final structNestedAlignmentInt16 = StructType.disambiguate( - List.filled(2, structAlignmentInt16), structAlignmentInt16.name); -final structNestedAlignmentInt32 = StructType.disambiguate( - List.filled(2, structAlignmentInt32), structAlignmentInt32.name); -final structNestedAlignmentInt64 = StructType.disambiguate( - List.filled(2, structAlignmentInt64), structAlignmentInt64.name); - -final structNestedBig = StructType.override([ - uint16, - struct8bytesNestedMixed, - uint16, - struct8bytesNestedFloat2, - uint16, - struct8bytesNestedFloat, - uint16 -], "NestedIrregularBig"); -final structNestedBigger = StructType.override( - [structNestedBig, struct8bytesNestedMixed, float, double_], - "NestedIrregularBigger"); -final structNestedEvenBigger = StructType.override( - [uint64, structNestedBigger, structNestedBigger, double_], - "NestedIrregularEvenBigger"); - -final structInlineArray = StructType([FixedLengthArrayType(uint8, 8)]); - -final structInlineArrayIrregular = StructType.override( - [FixedLengthArrayType(struct3bytesInt2, 2), uint8], "InlineArrayIrregular"); - -final structInlineArray100Bytes = StructType.override( - [FixedLengthArrayType(uint8, 100)], "InlineArray100Bytes"); - -final structInlineArrayBig = StructType.override( - [uint32, uint32, FixedLengthArrayType(uint8, 4000)], "InlineArrayBig"); - -/// The largest homogenous float that goes into FPU registers on softfp and -/// arm64. This time with nested structs and inline arrays. -final struct16bytesFloatInlineNested = StructType.override([ - StructType([float]), - FixedLengthArrayType(StructType([float]), 2), - float, -], "Struct16BytesHomogeneousFloat2"); - -/// The largest homogenous float that goes into FPU registers on arm64. -/// This time with nested structs and inline arrays. -final struct32bytesDoubleInlineNested = StructType.override([ - StructType([double_]), - FixedLengthArrayType(StructType([double_]), 2), - double_, -], "Struct32BytesHomogeneousDouble2"); - -/// This struct is split over a CPU and FPU register in x64 Linux. -/// This time with nested structs and inline arrays. -final struct16bytesMixedInlineNested = StructType.override([ - StructType([float]), - FixedLengthArrayType(StructType([float, int16, int16]), 1), - FixedLengthArrayType(int16, 2), -], "Struct16BytesMixed3"); - -final struct8bytesInlineArrayMultiDimesional = StructType([ - FixedLengthArrayType.multi(uint8, [2, 2, 2]) -]); - -final struct32bytesInlineArrayMultiDimesional = StructType([ - FixedLengthArrayType.multi(uint8, [2, 2, 2, 2, 2]) -]); - -final struct64bytesInlineArrayMultiDimesional = StructType([ - FixedLengthArrayType.multi(uint8, [2, 2, 2, 2, 2, 2]) -]); - -final structMultiDimensionalStruct = StructType([ - FixedLengthArrayType.multi(struct1byteInt, [2, 2]) -]); - -final struct3bytesPacked = StructType([int8, int16], packing: 1); - -final struct3bytesPackedMembersAligned = - StructType.disambiguate([int8, int16], "MembersAligned", packing: 1); - -final struct5bytesPacked = StructType([float, uint8], packing: 1); - -/// The float in the nested struct is not aligned. -final struct6bytesPacked = StructType([uint8, struct5bytesPacked]); - -/// The second element in the array has a nested misaligned int16. -final struct6bytesPacked2 = - StructType([FixedLengthArrayType(struct3bytesPackedMembersAligned, 2)]); - -final struct8bytesPacked = - StructType([uint8, uint32, uint8, uint8, uint8], packing: 1); - -final struct9bytesPacked = StructType([uint8, double_], packing: 1); - -/// The float in the nested struct is aligned in the first element in the -/// inline array, but not in the subsequent ones. -final struct15bytesPacked = - StructType([FixedLengthArrayType(struct5bytesPacked, 3)]); - -/// Mixed integer and float. Tests whether calling conventions put this in -/// integer registers or not. -final union4bytesMixed = UnionType([uint32, float]); - -/// Different types of float. Tests whether calling conventions put this in -/// FPU registers or not. -final union8bytesFloat = UnionType([double_, struct8bytesFloat]); - -/// This union has a size of 12, because of the 4-byte alignment of the first -/// member. -final union12bytesInt = UnionType([struct8bytesInt, struct9bytesInt]); - -/// This union has homogenous floats of the same sizes. -final union16bytesFloat = - UnionType([FixedLengthArrayType(float, 4), struct16bytesFloat]); - -/// This union has homogenous floats of different sizes. -final union16bytesFloat2 = - UnionType([struct8bytesFloat, struct12bytesFloat, struct16bytesFloat]); diff --git a/tests/ffi_2/generator/structs_by_value_tests_generator.dart b/tests/ffi_2/generator/structs_by_value_tests_generator.dart deleted file mode 100644 index 39d8f7f19c5..00000000000 --- a/tests/ffi_2/generator/structs_by_value_tests_generator.dart +++ /dev/null @@ -1,1059 +0,0 @@ -// 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. - -// @dart = 2.9 - -import 'dart:io'; - -import 'c_types.dart'; -import 'structs_by_value_tests_configuration.dart'; -import 'utils.dart'; - -/// The test type determines how to convert the arguments into return values -/// such that the caller knows what to check. -enum TestType { - /// Tested by getting all the individual fields out of the structs and - /// summing their values. - structArguments, - - /// Tested by passing assigning the arguments to the struct fields. - structReturn, - - /// Tested by returning the struct passed in. - structReturnArgument, -} - -extension on FunctionType { - TestType get testType { - if (arguments.containsComposites && returnValue is FundamentalType) { - return TestType.structArguments; - } - if (returnValue is CompositeType && argumentTypes.contains(returnValue)) { - return TestType.structReturnArgument; - } - if (returnValue is StructType) { - if (arguments.length == (returnValue as CompositeType).members.length) { - return TestType.structReturn; - } - } - if (returnValue is UnionType) { - if (arguments.length == 1) { - return TestType.structReturn; - } - } - throw Exception("Unknown test type: $this"); - } -} - -/// We use the class structure as an algebraic data type in order to keep the -/// relevant parts of the code generation closer together. -extension on CType { - /// The part of the cout expression after `std::cout` and before the `;`. - String coutExpression(String variableName) { - switch (this.runtimeType) { - case FundamentalType: - if (this == uint8 || this == int8) { - return "<< static_cast($variableName)"; - } - return "<< $variableName"; - - case StructType: - case UnionType: - final this_ = this as CompositeType; - return this_.members.coutExpression("$variableName."); - - case FixedLengthArrayType: - final this_ = this as FixedLengthArrayType; - final indices = [for (var i = 0; i < this_.length; i += 1) i]; - - String result = '<< "["'; - result += indices - .map((i) => this_.elementType.coutExpression("$variableName[$i]")) - .join('<< ", "'); - result += '<< "]"'; - return result.trimCouts(); - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } - - /// A statement recursively outputting all members. - String coutStatement(String variableName) { - final coutExpr = this.coutExpression(variableName); - return 'std::cout << "$variableName = " $coutExpr << "\\n";'; - } -} - -extension on List { - /// The part of the cout expression after `std::cout` and before the `;`. - String coutExpression([String namePrefix = ""]) { - String result = '<< "("'; - result += this - .map((m) => m.type.coutExpression("$namePrefix${m.name}")) - .join('<< ", "'); - result += '<< ")"'; - return result.trimCouts(); - } -} - -extension on CType { - /// A list of statements adding all members recurisvely to `result`. - /// - /// Both valid in Dart and C. - String addToResultStatements(String variableName) { - switch (this.runtimeType) { - case FundamentalType: - return "result += $variableName;\n"; - - case StructType: - final this_ = this as StructType; - return this_.members.addToResultStatements("$variableName."); - - case UnionType: - final this_ = this as UnionType; - final member = this_.members.first; - return member.type - .addToResultStatements("$variableName.${member.name}"); - - case FixedLengthArrayType: - final this_ = this as FixedLengthArrayType; - final indices = [for (var i = 0; i < this_.length; i += 1) i]; - return indices - .map((i) => - this_.elementType.addToResultStatements("$variableName[$i]")) - .join(); - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } -} - -extension on List { - /// A list of statements adding all members recurisvely to `result`. - /// - /// Both valid in Dart and C. - String addToResultStatements([String namePrefix = ""]) { - return map((m) => m.type.addToResultStatements("$namePrefix${m.name}")) - .join(); - } -} - -extension on CType { - /// A list of statements recursively assigning all members with [a]. - /// - /// Both valid in Dart and C. - String assignValueStatements(ArgumentValueAssigner a, String variableName) { - switch (this.runtimeType) { - case FundamentalType: - final this_ = this as FundamentalType; - return "$variableName = ${a.nextValue(this_)};\n"; - - case StructType: - final this_ = this as StructType; - return this_.members.assignValueStatements(a, "$variableName."); - - case UnionType: - final this_ = this as UnionType; - final member = this_.members.first; - return member.type - .assignValueStatements(a, "$variableName.${member.name}"); - - case FixedLengthArrayType: - final this_ = this as FixedLengthArrayType; - final indices = [for (var i = 0; i < this_.length; i += 1) i]; - return indices - .map((i) => - this_.elementType.assignValueStatements(a, "$variableName[$i]")) - .join(); - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } - - /// A list of statements recursively coping all members from [source]. - /// - /// Both valid in Dart and C. - String copyValueStatements(String source, String destination) { - switch (this.runtimeType) { - case FundamentalType: - return "$destination = $source;\n"; - - case StructType: - final this_ = this as StructType; - return this_.members.copyValueStatements("$source.", "$destination."); - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } -} - -extension on List { - /// A list of statements recursively assigning all members with [a]. - /// - /// Both valid in Dart and C. - String assignValueStatements(ArgumentValueAssigner a, - [String namePrefix = ""]) { - return map((m) => m.type.assignValueStatements(a, "$namePrefix${m.name}")) - .join(); - } - - /// A list of statements recursively coping all members from [source]. - /// - /// Both valid in Dart and C. - String copyValueStatements([sourcePrefix = "", destinationPrefix = ""]) { - return map((m) => m.type.copyValueStatements( - "$sourcePrefix${m.name}", "$destinationPrefix${m.name}")).join(); - } -} - -/// A helper class that assigns values to fundamental types. -/// -/// Also keeps track of a sum of all values, to be used for testing the result. -class ArgumentValueAssigner { - int i = 1; - int sum = 0; - String nextValue(FundamentalType type) { - int argumentValue = i; - i++; - if (type.isSigned && i % 2 == 0) { - argumentValue = -argumentValue; - } - sum += argumentValue; - if (type.isFloatingPoint) { - return argumentValue.toDouble().toString(); - } else { - return argumentValue.toString(); - } - } - - String sumValue(FundamentalType type) { - if (type.isFloatingPoint) { - return sum.toDouble().toString(); - } else { - return sum.toString(); - } - } -} - -extension on CType { - /// A list of Dart statements recursively allocating all members. - String dartAllocateStatements(String variableName) { - switch (this.runtimeType) { - case FundamentalType: - return "${dartType} ${variableName};\n"; - - case StructType: - case UnionType: - return """ -final ${variableName}Pointer = calloc<$dartType>(); -final ${dartType} ${variableName} = ${variableName}Pointer.ref; -"""; - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } - - /// A list of Dart statements allocating as zero or nullptr. - String dartAllocateZeroStatements(String variableName, - {bool structsAsPointers = false}) { - switch (this.runtimeType) { - case FundamentalType: - final this_ = this as FundamentalType; - if (this_.isInteger) { - return "${dartType} ${variableName} = 0;\n"; - } - return "${dartType} ${variableName} = 0.0;\n"; - - case StructType: - case UnionType: - if (structsAsPointers) { - return "Pointer<${dartType}> ${variableName}Pointer = nullptr;\n"; - } else { - return "${dartType} ${variableName} = ${dartType}();\n"; - } - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } -} - -extension on List { - /// A list of Dart statements recursively allocating all members. - String dartAllocateStatements([String namePrefix = ""]) { - return map((m) => m.type.dartAllocateStatements("$namePrefix${m.name}")) - .join(); - } - - /// A list of Dart statements as zero or nullptr. - String dartAllocateZeroStatements(String namePrefix) { - return map((m) => m.type.dartAllocateZeroStatements("$namePrefix${m.name}")) - .join(); - } -} - -extension on CType { - /// A list of Dart statements recursively freeing all members. - String dartFreeStatements(String variableName) { - switch (this.runtimeType) { - case FundamentalType: - return ""; - - case StructType: - case UnionType: - return "calloc.free(${variableName}Pointer);\n"; - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } -} - -extension on List { - /// A list of Dart statements recursively freeing all members. - String dartFreeStatements([String namePrefix = ""]) { - return map((m) => m.type.dartFreeStatements("$namePrefix${m.name}")).join(); - } -} - -extension on CType { - /// A list of C statements recursively allocating all members. - String cAllocateStatements(String variableName) { - switch (this.runtimeType) { - case FundamentalType: - case StructType: - case UnionType: - return "${cType} ${variableName};\n"; - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } -} - -extension on List { - /// A list of C statements recursively allocating all members. - String cAllocateStatements([String namePrefix = ""]) { - return map((m) => m.type.cAllocateStatements("$namePrefix${m.name}")) - .join(); - } -} - -extension on CType { - /// A list of Dart statements recursively checking all members. - String dartExpectsStatements(String expected, String actual) { - switch (this.runtimeType) { - case FundamentalType: - final this_ = this as FundamentalType; - if (this_.isInteger) { - return "Expect.equals(${expected}, ${actual});"; - } - assert(this_.isFloatingPoint); - return "Expect.approxEquals(${expected}, ${actual});"; - - case StructType: - final this_ = this as StructType; - return this_.members.dartExpectsStatements("$expected.", "$actual."); - - case FixedLengthArrayType: - final this_ = this as FixedLengthArrayType; - return """ -for (int i = 0; i < ${this_.length}; i++){ - ${this_.elementType.dartExpectsStatements("$expected[i]", "$actual[i]")} -} -"""; - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } -} - -extension on List { - /// A list of Dart statements recursively checking all members. - String dartExpectsStatements( - [String expectedPrefix = "", String actualPrefix = ""]) { - return map((m) => m.type.dartExpectsStatements( - "$expectedPrefix${m.name}", "$actualPrefix${m.name}")).join(); - } -} - -extension on CType { - /// A list of C statements recursively checking all members. - String cExpectsStatements(String expected, String actual) { - switch (this.runtimeType) { - case FundamentalType: - final this_ = this as FundamentalType; - if (this_.isInteger) { - return "CHECK_EQ(${expected}, ${actual});"; - } - assert(this_.isFloatingPoint); - return "CHECK_APPROX(${expected}, ${actual});"; - - case StructType: - final this_ = this as StructType; - return this_.members.cExpectsStatements("$expected.", "$actual."); - - case FixedLengthArrayType: - final this_ = this as FixedLengthArrayType; - return """ -for (intptr_t i = 0; i < ${this_.length}; i++){ - ${this_.elementType.cExpectsStatements("$expected[i]", "$actual[i]")} -} -"""; - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } - - /// A list of C statements recursively checking all members for zero. - String cExpectsZeroStatements(String actual) { - switch (this.runtimeType) { - case FundamentalType: - final this_ = this as FundamentalType; - if (this_.isInteger) { - return "CHECK_EQ(0, ${actual});"; - } - assert(this_.isFloatingPoint); - return "CHECK_APPROX(0.0, ${actual});"; - - case StructType: - final this_ = this as StructType; - return this_.members.cExpectsZeroStatements("$actual."); - - case FixedLengthArrayType: - final this_ = this as FixedLengthArrayType; - return """ -for (intptr_t i = 0; i < ${this_.length}; i++){ - ${this_.elementType.cExpectsZeroStatements("$actual[i]")} -} -"""; - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } -} - -extension on List { - /// A list of C statements recursively checking all members. - String cExpectsStatements( - [String expectedPrefix = "", String actualPrefix = ""]) { - return map((m) => m.type.cExpectsStatements( - "$expectedPrefix${m.name}", "$actualPrefix${m.name}")).join(); - } - - /// A list of C statements recursively checking all members for zero. - String cExpectsZeroStatements([String actualPrefix = ""]) { - return map((m) => m.type.cExpectsZeroStatements("$actualPrefix${m.name}")) - .join(); - } -} - -extension on CType { - /// Expression denoting the first FundamentalType field. - /// - /// Both valid in Dart and C. - String firstArgumentName(String variableName) { - switch (this.runtimeType) { - case FundamentalType: - return variableName; - - case StructType: - case UnionType: - final this_ = this as CompositeType; - return this_.members.firstArgumentName("$variableName."); - - case FixedLengthArrayType: - final this_ = this as FixedLengthArrayType; - return this_.elementType.firstArgumentName("$variableName[0]"); - } - - throw Exception("Not implemented for ${this.runtimeType}"); - } -} - -extension on List { - /// Expression denoting the first FundamentalType field. - /// - /// Both valid in Dart and C. - String firstArgumentName([String prefix = ""]) { - return this[0].type.firstArgumentName("$prefix${this[0].name}"); - } -} - -extension on CompositeType { - String dartClass(bool nnbd) { - final self = this; - final packingAnnotation = (self is StructType) && self.hasPacking - ? "@Packed(${self.packing})" - : ""; - String dartFields = ""; - for (final member in members) { - dartFields += "${member.dartStructField(nnbd)}\n\n"; - } - String toStringBody = members.map((m) { - if (m.type is FixedLengthArrayType) { - int dimensionNumber = 0; - String inlineFor = ""; - String read = m.name; - String closing = ""; - for (final dimension in (m.type as FixedLengthArrayType).dimensions) { - final i = "i$dimensionNumber"; - inlineFor += "[for (var $i = 0; $i < $dimension; $i += 1)"; - read += "[$i]"; - closing += "]"; - dimensionNumber++; - } - return "\$\{$inlineFor $read $closing\}"; - } - return "\$\{${m.name}\}"; - }).join(", "); - return """ - $packingAnnotation - class $name extends $dartSuperClass { - $dartFields - - String toString() => "($toStringBody)"; - } - """; - } - - String get cDefinition { - final self = this; - final packingPragmaPush = (self is StructType) && self.hasPacking - ? "#pragma pack(push, ${self.packing})" - : ""; - final packingPragmaPop = - (self is StructType) && self.hasPacking ? "#pragma pack(pop)" : ""; - - String cFields = ""; - for (final member in members) { - cFields += " ${member.cStructField}\n"; - } - return """ - $packingPragmaPush - $cKeyword $name { - $cFields - }; - $packingPragmaPop - - """; - } -} - -extension on FunctionType { - String dartCallCode({bool isLeaf: false}) { - final a = ArgumentValueAssigner(); - final assignValues = arguments.assignValueStatements(a); - final argumentFrees = arguments.dartFreeStatements(); - - final argumentNames = arguments.map((e) => e.name).join(", "); - - String expects; - switch (testType) { - case TestType.structArguments: - // Check against sum value. - final expectedResult = a.sumValue(returnValue as FundamentalType); - expects = returnValue.dartExpectsStatements(expectedResult, "result"); - break; - case TestType.structReturn: - // Check against input arguments. - expects = arguments.dartExpectsStatements("", "result."); - break; - case TestType.structReturnArgument: - expects = returnValue.dartExpectsStatements( - structReturnArgument.name, "result"); - break; - } - - final namePostfix = isLeaf ? "Leaf" : ""; - return """ - final ${dartName}$namePostfix = - ffiTestFunctions.lookupFunction<$dartCType, $dartType>( - "$cName"${isLeaf ? ", isLeaf:true" : ""}); - - ${reason.makeDartDocComment()} - void ${dartTestName}$namePostfix() { - ${arguments.dartAllocateStatements()} - - ${assignValues} - - final result = ${dartName}$namePostfix($argumentNames); - - print("result = \$result"); - - $expects - - $argumentFrees - } - """; - } - - String dartCallbackCode(bool nnbd) { - final argumentss = - arguments.map((a) => "${a.type.dartType} ${a.name}").join(", "); - - final prints = arguments.map((a) => "\$\{${a.name}\}").join(", "); - - bool structsAsPointers = false; - String assignReturnGlobal = ""; - String buildReturnValue = ""; - switch (testType) { - case TestType.structArguments: - // Sum all input values. - buildReturnValue = """ - ${returnValue.dartType} result = 0; - - ${arguments.addToResultStatements('${dartName}_')} - """; - assignReturnGlobal = "${dartName}Result = result;"; - break; - case TestType.structReturn: - // Allocate a struct. - buildReturnValue = """ - final resultPointer = calloc<${returnValue.dartType}>(); - final result = resultPointer.ref; - - ${arguments.copyValueStatements("${dartName}_", "result.")} - """; - assignReturnGlobal = "${dartName}ResultPointer = resultPointer;"; - structsAsPointers = true; - break; - case TestType.structReturnArgument: - buildReturnValue = """ - ${returnValue.cType} result = ${dartName}_${structReturnArgument.name}; - """; - assignReturnGlobal = "${dartName}Result = result;"; - break; - } - - final globals = arguments.dartAllocateZeroStatements("${dartName}_"); - - final copyToGlobals = - arguments.map((a) => '${dartName}_${a.name} = ${a.name};').join("\n"); - - // Simulate assigning values the same way as in C, so that we know what the - // final return value should be. - final a = ArgumentValueAssigner(); - arguments.assignValueStatements(a); - String afterCallbackExpects = ""; - String afterCallbackFrees = ""; - switch (testType) { - case TestType.structArguments: - // Check that the input structs are still available. - // Check against sum value. - final expectedResult = a.sumValue(returnValue as FundamentalType); - afterCallbackExpects = - returnValue.dartExpectsStatements(expectedResult, "result"); - break; - case TestType.structReturn: - // We're passing allocating structs in [buildReturnValue]. - afterCallbackFrees = - returnValue.dartFreeStatements("${dartName}Result"); - break; - case TestType.structReturnArgument: - break; - } - - String returnNull = ""; - if (!nnbd) { - returnNull = """ - if (${arguments.firstArgumentName()} == $returnNullValue) { - print("returning null!"); - return null; - } - """; - } - - return """ - typedef ${cName}Type = $dartCType; - - // Global variables to be able to test inputs after callback returned. - $globals - - // Result variable also global, so we can delete it after the callback. - ${returnValue.dartAllocateZeroStatements("${dartName}Result", structsAsPointers: structsAsPointers)} - - ${returnValue.dartType} ${dartName}CalculateResult() { - $buildReturnValue - - $assignReturnGlobal - - return result; - } - - ${reason.makeDartDocComment()} - ${returnValue.dartType} $dartName($argumentss) { - print("$dartName($prints)"); - - // In legacy mode, possibly return null. - $returnNull - - // In both nnbd and legacy mode, possibly throw. - if (${arguments.firstArgumentName()} == $throwExceptionValue || - ${arguments.firstArgumentName()} == $returnNullValue) { - print("throwing!"); - throw Exception("$cName throwing on purpose!"); - } - - $copyToGlobals - - final result = ${dartName}CalculateResult(); - - print(\"result = \$result\"); - - return result; - } - - void ${dartName}AfterCallback() { - $afterCallbackFrees - - final result = ${dartName}CalculateResult(); - - print(\"after callback result = \$result\"); - - $afterCallbackExpects - - $afterCallbackFrees - } - - """; - } - - String get dartCallbackTestConstructor { - String exceptionalReturn = ""; - if (returnValue is FundamentalType) { - if ((returnValue as FundamentalType).isFloatingPoint) { - exceptionalReturn = ", 0.0"; - } else { - exceptionalReturn = ", 0"; - } - } - return """ - CallbackTest.withCheck("$cName", - Pointer.fromFunction<${cName}Type>($dartName$exceptionalReturn), - ${dartName}AfterCallback), - """; - } - - String get cCallCode { - String body = ""; - switch (testType) { - case TestType.structArguments: - body = """ - ${returnValue.cType} result = 0; - - ${arguments.addToResultStatements()} - """; - break; - case TestType.structReturn: - body = """ - ${returnValue.cType} result; - - ${arguments.copyValueStatements("", "result.")} - """; - break; - case TestType.structReturnArgument: - body = """ - ${returnValue.cType} result = ${structReturnArgument.name}; - """; - break; - } - - final argumentss = - arguments.map((e) => "${e.type.cType} ${e.name}").join(", "); - - return """ - // Used for testing structs and unions by value. - ${reason.makeCComment()} - DART_EXPORT ${returnValue.cType} $cName($argumentss) { - std::cout << \"$cName\" ${arguments.coutExpression()} << \"\\n\"; - - $body - - ${returnValue.coutStatement("result")} - - return result; - } - - """; - } - - String get cCallbackCode { - final a = ArgumentValueAssigner(); - final argumentAllocations = arguments.cAllocateStatements(); - final assignValues = arguments.assignValueStatements(a); - - final argumentss = - arguments.map((e) => "${e.type.cType} ${e.name}").join(", "); - - final argumentNames = arguments.map((e) => e.name).join(", "); - - String expects = ""; - String expectsZero = ""; - switch (testType) { - case TestType.structArguments: - // Check against sum value. - final returnValue_ = returnValue as FundamentalType; - final expectedResult = a.sumValue(returnValue_); - expects = returnValue.cExpectsStatements(expectedResult, "result"); - - expectsZero = returnValue.cExpectsZeroStatements("result"); - break; - case TestType.structReturn: - // Check against input statements. - expects = arguments.cExpectsStatements("", "result."); - - expectsZero = arguments.cExpectsZeroStatements("result."); - break; - case TestType.structReturnArgument: - // Check against input struct fields. - expects = - returnValue.cExpectsStatements(structReturnArgument.name, "result"); - - expectsZero = returnValue.cExpectsZeroStatements("result"); - break; - } - - return """ - // Used for testing structs and unions by value. - ${reason.makeCComment()} - DART_EXPORT intptr_t - Test$cName( - // NOLINTNEXTLINE(whitespace/parens) - ${returnValue.cType} (*f)($argumentss)) { - $argumentAllocations - - $assignValues - - std::cout << \"Calling Test$cName(\" ${arguments.coutExpression()} << \")\\n\"; - - ${returnValue.cType} result = f($argumentNames); - - ${returnValue.coutStatement("result")} - - $expects - - // Pass argument that will make the Dart callback throw. - ${arguments.firstArgumentName()} = $throwExceptionValue; - - result = f($argumentNames); - - $expectsZero - - // Pass argument that will make the Dart callback return null. - ${arguments.firstArgumentName()} = $returnNullValue; - - result = f($argumentNames); - - $expectsZero - - return 0; - } - - """; - } -} - -/// Some value between 0 and 127 (works in every native type). -const throwExceptionValue = 42; - -/// Some value between 0 and 127 (works in every native type). -const returnNullValue = 84; - -const headerDartCallTest = """ -// 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. -// -// This file has been automatically generated. Please do not edit it manually. -// -// SharedObjects=ffi_test_functions -// VMOptions= -// VMOptions=--deterministic --optimization-counter-threshold=5 -// VMOptions=--use-slow-path -// VMOptions=--use-slow-path --stacktrace-every=100 - -import 'dart:ffi'; - -import "package:expect/expect.dart"; -import "package:ffi/ffi.dart"; - -import 'dylib_utils.dart'; - -final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); -"""; - -void writeDartCallTest() { - for (bool nnbd in [true, false]) { - final StringBuffer buffer = StringBuffer(); - buffer.write(headerDartCallTest); - - buffer.write(""" - void main() { - for (int i = 0; i < 10; ++i) { - ${functions.map((e) => "${e.dartTestName}();").join("\n")} - ${functions.map((e) => "${e.dartTestName}Leaf();").join("\n")} - } - } - """); - buffer.writeAll(compounds.map((e) => e.dartClass(nnbd))); - buffer.writeAll(functions.map((e) => e.dartCallCode(isLeaf: false))); - buffer.writeAll(functions.map((e) => e.dartCallCode(isLeaf: true))); - - final path = callTestPath(nnbd); - File(path).writeAsStringSync(buffer.toString()); - Process.runSync("dartfmt", ["-w", path]); - } -} - -String callTestPath(bool nnbd) { - final folder = nnbd ? "ffi" : "ffi_2"; - return Platform.script - .resolve("../../$folder/function_structs_by_value_generated_test.dart") - .path; -} - -const headerDartCallbackTest = """ -// 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. -// -// This file has been automatically generated. Please do not edit it manually. -// -// SharedObjects=ffi_test_functions -// VMOptions= -// VMOptions=--deterministic --optimization-counter-threshold=10 -// VMOptions=--use-slow-path -// VMOptions=--use-slow-path --stacktrace-every=100 - -import 'dart:ffi'; - -import "package:expect/expect.dart"; -import "package:ffi/ffi.dart"; - -import 'callback_tests_utils.dart'; - -// Reuse the struct classes. -import 'function_structs_by_value_generated_test.dart'; - - -void main() { - testCases.forEach((t) { - print("==== Running " + t.name); - t.run(); - }); -} - - -"""; - -void writeDartCallbackTest() { - for (bool nnbd in [true, false]) { - final StringBuffer buffer = StringBuffer(); - buffer.write(headerDartCallbackTest); - - buffer.write(""" - final testCases = [ - ${functions.map((e) => e.dartCallbackTestConstructor).join("\n")} - ]; - """); - - buffer.writeAll(functions.map((e) => e.dartCallbackCode(nnbd))); - - final path = callbackTestPath(nnbd); - File(path).writeAsStringSync(buffer.toString()); - Process.runSync("dartfmt", ["-w", path]); - } -} - -String callbackTestPath(bool nnbd) { - final folder = nnbd ? "ffi" : "ffi_2"; - return Platform.script - .resolve( - "../../$folder/function_callbacks_structs_by_value_generated_test.dart") - .path; -} - -const headerC = """ -// 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. -// -// This file has been automatically generated. Please do not edit it manually. - -#include -#include -#include - -#include -#include -#include - -#if defined(_WIN32) -#define DART_EXPORT extern "C" __declspec(dllexport) -#else -#define DART_EXPORT \\ - extern "C" __attribute__((visibility("default"))) __attribute((used)) -#endif - -namespace dart { - -#define CHECK(X) \\ - if (!(X)) { \\ - fprintf(stderr, "%s\\n", "Check failed: " #X); \\ - return 1; \\ - } - -#define CHECK_EQ(X, Y) CHECK((X) == (Y)) - -// Works for positive, negative and zero. -#define CHECK_APPROX(EXPECTED, ACTUAL) \\ - CHECK(((EXPECTED * 0.99) <= (ACTUAL) && (EXPECTED * 1.01) >= (ACTUAL)) || \\ - ((EXPECTED * 0.99) >= (ACTUAL) && (EXPECTED * 1.01) <= (ACTUAL))) - -"""; - -const footerC = """ - -} // namespace dart -"""; - -void writeC() { - final StringBuffer buffer = StringBuffer(); - buffer.write(headerC); - - buffer.writeAll(compounds.map((e) => e.cDefinition)); - buffer.writeAll(functions.map((e) => e.cCallCode)); - buffer.writeAll(functions.map((e) => e.cCallbackCode)); - - buffer.write(footerC); - - File(ccPath).writeAsStringSync(buffer.toString()); - Process.runSync("clang-format", ["-i", ccPath]); -} - -final ccPath = Platform.script - .resolve("../../../runtime/bin/ffi_test/ffi_test_functions_generated.cc") - .path; - -void printUsage() { - print(""" -Generates structs by value tests. - -Generates: -- $ccPath -- ${callbackTestPath(true)} -- ${callTestPath(true)} -- ${callbackTestPath(false)} -- ${callTestPath(false)} -"""); -} - -void main(List arguments) { - if (arguments.length != 0) { - printUsage(); - return; - } - - writeDartCallTest(); - writeDartCallbackTest(); - writeC(); -} diff --git a/tests/ffi_2/generator/utils.dart b/tests/ffi_2/generator/utils.dart deleted file mode 100644 index a1130cc1289..00000000000 --- a/tests/ffi_2/generator/utils.dart +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -// @dart = 2.9 - -extension TestGeneratorStringExtension on String { - String upperCaseFirst() => "${this[0].toUpperCase()}${this.substring(1)}"; - - String lowerCaseFirst() => "${this[0].toLowerCase()}${this.substring(1)}"; - - String makeCComment() => "// " + split("\n").join("\n// "); - - String makeDartDocComment() => "/// " + split("\n").join("\n/// "); - - String limitTo(int lenght) { - if (this.length > lenght) { - return substring(0, lenght); - } - return this; - } - - String trimCouts() => replaceAll('" << "', '').replaceAll('"<< "', ''); -}