[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 <sstrickl@google.com>
This commit is contained in:
Daco Harkes 2021-06-11 12:00:26 +00:00 committed by commit-bot@chromium.org
parent a9f08a75a2
commit ddafaa0775
27 changed files with 401 additions and 2575 deletions

View file

@ -170,8 +170,7 @@ DART_EXPORT intptr_t TakeMaxUint8x10(uint8_t a,
<< static_cast<int>(d) << ", " << static_cast<int>(e) << ", "
<< static_cast<int>(f) << ", " << static_cast<int>(g) << ", "
<< static_cast<int>(h) << ", " << static_cast<int>(i) << ", "
<< static_cast<int>(j) << ", "
<< ")\n";
<< static_cast<int>(j) << ")\n";
return (a == 0xff && b == 0xff && c == 0xff && d == 0xff && e == 0xff &&
f == 0xff && g == 0xff && h == 0xff && i == 0xff && j == 0xff)
? 1

View file

@ -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<int>(a0.a0) << ", " << a0.a1 << "), ("
<< static_cast<int>(a1.a0) << ", " << a1.a1 << "), ("
<< static_cast<int>(a2.a0) << ", " << a2.a1 << "), ("
@ -4255,7 +4256,7 @@ DART_EXPORT double PassStruct9BytesPackedMixedx10DoubleInt32(
<< static_cast<int>(a7.a0) << ", " << a7.a1 << "), ("
<< static_cast<int>(a8.a0) << ", " << a8.a1 << "), ("
<< static_cast<int>(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<int>(a0.a0) << ", " << a0.a1 << "), ("
<< static_cast<int>(a1.a0) << ", " << a1.a1 << "), ("
<< static_cast<int>(a2.a0) << ", " << a2.a1 << "), ("
@ -11553,26 +11558,26 @@ DART_EXPORT intptr_t TestPassStruct9BytesPackedMixedx10DoubleInt32(
<< static_cast<int>(a7.a0) << ", " << a7.a1 << "), ("
<< static_cast<int>(a8.a0) << ", " << a8.a1 << "), ("
<< static_cast<int>(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);

View file

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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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]

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -295,10 +295,10 @@ final testCases = [
passStruct8BytesPackedIntx10, 0),
passStruct8BytesPackedIntx10AfterCallback),
CallbackTest.withCheck(
"PassStruct9BytesPackedMixedx10DoubleInt32",
Pointer.fromFunction<PassStruct9BytesPackedMixedx10DoubleInt32Type>(
passStruct9BytesPackedMixedx10DoubleInt32, 0.0),
passStruct9BytesPackedMixedx10DoubleInt32AfterCallback),
"PassStruct9BytesPackedMixedx10DoubleInt32x2",
Pointer.fromFunction<PassStruct9BytesPackedMixedx10DoubleInt32x2Type>(
passStruct9BytesPackedMixedx10DoubleInt32x2, 0.0),
passStruct9BytesPackedMixedx10DoubleInt32x2AfterCallback),
CallbackTest.withCheck(
"PassStruct5BytesPackedMixed",
Pointer.fromFunction<PassStruct5BytesPackedMixedType>(
@ -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(

View file

@ -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<Struct9BytesPackedMixed>();
final Struct9BytesPackedMixed a0 = a0Pointer.ref;
final a1Pointer = calloc<Struct9BytesPackedMixed>();
@ -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<Struct9BytesPackedMixed>();
final Struct9BytesPackedMixed a0 = a0Pointer.ref;
final a1Pointer = calloc<Struct9BytesPackedMixed>();
@ -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);

View file

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

View file

@ -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 = [

View file

@ -297,10 +297,10 @@ final testCases = [
passStruct8BytesPackedIntx10, 0),
passStruct8BytesPackedIntx10AfterCallback),
CallbackTest.withCheck(
"PassStruct9BytesPackedMixedx10DoubleInt32",
Pointer.fromFunction<PassStruct9BytesPackedMixedx10DoubleInt32Type>(
passStruct9BytesPackedMixedx10DoubleInt32, 0.0),
passStruct9BytesPackedMixedx10DoubleInt32AfterCallback),
"PassStruct9BytesPackedMixedx10DoubleInt32x2",
Pointer.fromFunction<PassStruct9BytesPackedMixedx10DoubleInt32x2Type>(
passStruct9BytesPackedMixedx10DoubleInt32x2, 0.0),
passStruct9BytesPackedMixedx10DoubleInt32x2AfterCallback),
CallbackTest.withCheck(
"PassStruct5BytesPackedMixed",
Pointer.fromFunction<PassStruct5BytesPackedMixedType>(
@ -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(

View file

@ -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<Struct9BytesPackedMixed>();
final Struct9BytesPackedMixed a0 = a0Pointer.ref;
final a1Pointer = calloc<Struct9BytesPackedMixed>();
@ -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<Struct9BytesPackedMixed>();
final Struct9BytesPackedMixed a0 = a0Pointer.ref;
final a1Pointer = calloc<Struct9BytesPackedMixed>();
@ -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);

View file

@ -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<Member> generateMemberNames(List<CType> memberTypes) {
int index = 0;
List<Member> result = [];
for (final type in memberTypes) {
result.add(Member(type, "a$index"));
index++;
}
return result;
}
abstract class CompositeType extends CType {
final List<Member> members;
/// To disambiguate same size structs.
final String suffix;
/// To override names.
final String overrideName;
CompositeType(List<CType> memberTypes)
: this.members = generateMemberNames(memberTypes),
this.suffix = "",
this.overrideName = "";
CompositeType.disambiguate(List<CType> memberTypes, this.suffix)
: this.members = generateMemberNames(memberTypes),
this.overrideName = "";
CompositeType.override(List<CType> memberTypes, this.overrideName)
: this.members = generateMemberNames(memberTypes),
this.suffix = "";
List<CType> 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<FixedLengthArrayType>()
.where((e) => e.isMulti)
.isNotEmpty;
}
class StructType extends CompositeType {
final int? packing;
StructType(List<CType> memberTypes, {int? this.packing}) : super(memberTypes);
StructType.disambiguate(List<CType> memberTypes, String suffix,
{int? this.packing})
: super.disambiguate(memberTypes, suffix);
StructType.override(List<CType> 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<CType> 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<int> 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<int> 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<Member> arguments;
final CType returnValue;
final String reason;
List<CType> get argumentTypes => arguments.map((a) => a.type).toList();
FunctionType(List<CType> 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<List<Member>> get argumentsGrouped {
List<List<Member>> 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<Member> {
bool get containsComposites =>
map((m) => m.type is CompositeType).contains(true);
}

View file

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

File diff suppressed because it is too large Load diff

View file

@ -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('"<< "', '');
}