// 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))) struct Struct1ByteInt { int8_t a0; }; struct Struct3BytesHomogeneousUint8 { uint8_t a0; uint8_t a1; uint8_t a2; }; struct Struct3BytesInt2ByteAligned { int16_t a0; int8_t a1; }; struct Struct4BytesHomogeneousInt16 { int16_t a0; int16_t a1; }; struct Struct4BytesFloat { float a0; }; struct Struct7BytesHomogeneousUint8 { uint8_t a0; uint8_t a1; uint8_t a2; uint8_t a3; uint8_t a4; uint8_t a5; uint8_t a6; }; struct Struct7BytesInt4ByteAligned { int32_t a0; int16_t a1; int8_t a2; }; struct Struct8BytesInt { int16_t a0; int16_t a1; int32_t a2; }; struct Struct8BytesHomogeneousFloat { float a0; float a1; }; struct Struct8BytesFloat { double a0; }; struct Struct8BytesMixed { float a0; int16_t a1; int16_t a2; }; struct Struct9BytesHomogeneousUint8 { uint8_t a0; uint8_t a1; uint8_t a2; uint8_t a3; uint8_t a4; uint8_t a5; uint8_t a6; uint8_t a7; uint8_t a8; }; struct Struct9BytesInt4Or8ByteAligned { int64_t a0; int8_t a1; }; struct Struct12BytesHomogeneousFloat { float a0; float a1; float a2; }; struct Struct16BytesHomogeneousFloat { float a0; float a1; float a2; float a3; }; struct Struct16BytesMixed { double a0; int64_t a1; }; struct Struct16BytesMixed2 { float a0; float a1; float a2; int32_t a3; }; struct Struct17BytesInt { int64_t a0; int64_t a1; int8_t a2; }; struct Struct19BytesHomogeneousUint8 { uint8_t a0; uint8_t a1; uint8_t a2; uint8_t a3; uint8_t a4; uint8_t a5; uint8_t a6; uint8_t a7; uint8_t a8; uint8_t a9; uint8_t a10; uint8_t a11; uint8_t a12; uint8_t a13; uint8_t a14; uint8_t a15; uint8_t a16; uint8_t a17; uint8_t a18; }; struct Struct20BytesHomogeneousInt32 { int32_t a0; int32_t a1; int32_t a2; int32_t a3; int32_t a4; }; struct Struct20BytesHomogeneousFloat { float a0; float a1; float a2; float a3; float a4; }; struct Struct32BytesHomogeneousDouble { double a0; double a1; double a2; double a3; }; struct Struct40BytesHomogeneousDouble { double a0; double a1; double a2; double a3; double a4; }; struct Struct1024BytesHomogeneousUint64 { uint64_t a0; uint64_t a1; uint64_t a2; uint64_t a3; uint64_t a4; uint64_t a5; uint64_t a6; uint64_t a7; uint64_t a8; uint64_t a9; uint64_t a10; uint64_t a11; uint64_t a12; uint64_t a13; uint64_t a14; uint64_t a15; uint64_t a16; uint64_t a17; uint64_t a18; uint64_t a19; uint64_t a20; uint64_t a21; uint64_t a22; uint64_t a23; uint64_t a24; uint64_t a25; uint64_t a26; uint64_t a27; uint64_t a28; uint64_t a29; uint64_t a30; uint64_t a31; uint64_t a32; uint64_t a33; uint64_t a34; uint64_t a35; uint64_t a36; uint64_t a37; uint64_t a38; uint64_t a39; uint64_t a40; uint64_t a41; uint64_t a42; uint64_t a43; uint64_t a44; uint64_t a45; uint64_t a46; uint64_t a47; uint64_t a48; uint64_t a49; uint64_t a50; uint64_t a51; uint64_t a52; uint64_t a53; uint64_t a54; uint64_t a55; uint64_t a56; uint64_t a57; uint64_t a58; uint64_t a59; uint64_t a60; uint64_t a61; uint64_t a62; uint64_t a63; uint64_t a64; uint64_t a65; uint64_t a66; uint64_t a67; uint64_t a68; uint64_t a69; uint64_t a70; uint64_t a71; uint64_t a72; uint64_t a73; uint64_t a74; uint64_t a75; uint64_t a76; uint64_t a77; uint64_t a78; uint64_t a79; uint64_t a80; uint64_t a81; uint64_t a82; uint64_t a83; uint64_t a84; uint64_t a85; uint64_t a86; uint64_t a87; uint64_t a88; uint64_t a89; uint64_t a90; uint64_t a91; uint64_t a92; uint64_t a93; uint64_t a94; uint64_t a95; uint64_t a96; uint64_t a97; uint64_t a98; uint64_t a99; uint64_t a100; uint64_t a101; uint64_t a102; uint64_t a103; uint64_t a104; uint64_t a105; uint64_t a106; uint64_t a107; uint64_t a108; uint64_t a109; uint64_t a110; uint64_t a111; uint64_t a112; uint64_t a113; uint64_t a114; uint64_t a115; uint64_t a116; uint64_t a117; uint64_t a118; uint64_t a119; uint64_t a120; uint64_t a121; uint64_t a122; uint64_t a123; uint64_t a124; uint64_t a125; uint64_t a126; uint64_t a127; }; struct StructAlignmentInt16 { int8_t a0; int16_t a1; int8_t a2; }; struct StructAlignmentInt32 { int8_t a0; int32_t a1; int8_t a2; }; struct StructAlignmentInt64 { int8_t a0; int64_t a1; int8_t a2; }; struct Struct8BytesNestedInt { Struct4BytesHomogeneousInt16 a0; Struct4BytesHomogeneousInt16 a1; }; struct Struct8BytesNestedFloat { Struct4BytesFloat a0; Struct4BytesFloat a1; }; struct Struct8BytesNestedFloat2 { Struct4BytesFloat a0; float a1; }; struct Struct8BytesNestedMixed { Struct4BytesHomogeneousInt16 a0; Struct4BytesFloat a1; }; struct Struct16BytesNestedInt { Struct8BytesNestedInt a0; Struct8BytesNestedInt a1; }; struct Struct32BytesNestedInt { Struct16BytesNestedInt a0; Struct16BytesNestedInt a1; }; struct StructNestedIntStructAlignmentInt16 { StructAlignmentInt16 a0; StructAlignmentInt16 a1; }; struct StructNestedIntStructAlignmentInt32 { StructAlignmentInt32 a0; StructAlignmentInt32 a1; }; struct StructNestedIntStructAlignmentInt64 { StructAlignmentInt64 a0; StructAlignmentInt64 a1; }; struct StructNestedIrregularBig { uint16_t a0; Struct8BytesNestedMixed a1; uint16_t a2; Struct8BytesNestedFloat2 a3; uint16_t a4; Struct8BytesNestedFloat a5; uint16_t a6; }; struct StructNestedIrregularBigger { StructNestedIrregularBig a0; Struct8BytesNestedMixed a1; float a2; double a3; }; struct StructNestedIrregularEvenBigger { uint64_t a0; StructNestedIrregularBigger a1; StructNestedIrregularBigger a2; double a3; }; struct Struct8BytesInlineArrayInt { uint8_t a0[8]; }; struct StructInlineArrayIrregular { Struct3BytesInt2ByteAligned a0[2]; uint8_t a1; }; struct StructInlineArray100Bytes { uint8_t a0[100]; }; struct StructInlineArrayBig { uint32_t a0; uint32_t a1; uint8_t a2[4000]; }; struct StructStruct16BytesHomogeneousFloat2 { Struct4BytesFloat a0; Struct4BytesFloat a1[2]; float a2; }; struct StructStruct32BytesHomogeneousDouble2 { Struct8BytesFloat a0; Struct8BytesFloat a1[2]; double a2; }; struct StructStruct16BytesMixed3 { Struct4BytesFloat a0; Struct8BytesMixed a1[1]; int16_t a2[2]; }; struct Struct8BytesInlineArrayMultiDimensionalInt { uint8_t a0[2][2][2]; }; struct Struct32BytesInlineArrayMultiDimensionalInt { uint8_t a0[2][2][2][2][2]; }; struct Struct64BytesInlineArrayMultiDimensionalInt { uint8_t a0[2][2][2][2][2][2]; }; struct Struct4BytesInlineArrayMultiDimensionalInt { Struct1ByteInt a0[2][2]; }; #pragma pack(push, 1) struct Struct3BytesPackedInt { int8_t a0; int16_t a1; }; #pragma pack(pop) #pragma pack(push, 1) struct Struct3BytesPackedIntMembersAligned { int8_t a0; int16_t a1; }; #pragma pack(pop) #pragma pack(push, 1) struct Struct5BytesPackedMixed { float a0; uint8_t a1; }; #pragma pack(pop) struct StructNestedAlignmentStruct5BytesPackedMixed { uint8_t a0; Struct5BytesPackedMixed a1; }; struct Struct6BytesInlineArrayInt { Struct3BytesPackedIntMembersAligned a0[2]; }; #pragma pack(push, 1) struct Struct8BytesPackedInt { uint8_t a0; uint32_t a1; uint8_t a2; uint8_t a3; uint8_t a4; }; #pragma pack(pop) #pragma pack(push, 1) struct Struct9BytesPackedMixed { uint8_t a0; double a1; }; #pragma pack(pop) struct Struct15BytesInlineArrayMixed { Struct5BytesPackedMixed a0[3]; }; union Union4BytesMixed { uint32_t a0; float a1; }; union Union8BytesNestedFloat { double a0; Struct8BytesHomogeneousFloat a1; }; union Union9BytesNestedInt { Struct8BytesInt a0; Struct9BytesHomogeneousUint8 a1; }; union Union16BytesNestedInlineArrayFloat { float a0[4]; Struct16BytesHomogeneousFloat a1; }; union Union16BytesNestedFloat { Struct8BytesHomogeneousFloat a0; Struct12BytesHomogeneousFloat a1; Struct16BytesHomogeneousFloat a2; }; // Used for testing structs and unions by value. // Smallest struct with data. // 10 struct arguments will exhaust available registers. DART_EXPORT int64_t PassStruct1ByteIntx10(Struct1ByteInt a0, Struct1ByteInt a1, Struct1ByteInt a2, Struct1ByteInt a3, Struct1ByteInt a4, Struct1ByteInt a5, Struct1ByteInt a6, Struct1ByteInt a7, Struct1ByteInt a8, Struct1ByteInt a9) { std::cout << "PassStruct1ByteIntx10" << "((" << static_cast(a0.a0) << "), (" << static_cast(a1.a0) << "), (" << static_cast(a2.a0) << "), (" << static_cast(a3.a0) << "), (" << static_cast(a4.a0) << "), (" << static_cast(a5.a0) << "), (" << static_cast(a6.a0) << "), (" << static_cast(a7.a0) << "), (" << static_cast(a8.a0) << "), (" << static_cast(a9.a0) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a1.a0; result += a2.a0; result += a3.a0; result += a4.a0; result += a5.a0; result += a6.a0; result += a7.a0; result += a8.a0; result += a9.a0; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Not a multiple of word size, not a power of two. // 10 struct arguments will exhaust available registers. DART_EXPORT int64_t PassStruct3BytesHomogeneousUint8x10(Struct3BytesHomogeneousUint8 a0, Struct3BytesHomogeneousUint8 a1, Struct3BytesHomogeneousUint8 a2, Struct3BytesHomogeneousUint8 a3, Struct3BytesHomogeneousUint8 a4, Struct3BytesHomogeneousUint8 a5, Struct3BytesHomogeneousUint8 a6, Struct3BytesHomogeneousUint8 a7, Struct3BytesHomogeneousUint8 a8, Struct3BytesHomogeneousUint8 a9) { std::cout << "PassStruct3BytesHomogeneousUint8x10" << "((" << static_cast(a0.a0) << ", " << static_cast(a0.a1) << ", " << static_cast(a0.a2) << "), (" << static_cast(a1.a0) << ", " << static_cast(a1.a1) << ", " << static_cast(a1.a2) << "), (" << static_cast(a2.a0) << ", " << static_cast(a2.a1) << ", " << static_cast(a2.a2) << "), (" << static_cast(a3.a0) << ", " << static_cast(a3.a1) << ", " << static_cast(a3.a2) << "), (" << static_cast(a4.a0) << ", " << static_cast(a4.a1) << ", " << static_cast(a4.a2) << "), (" << static_cast(a5.a0) << ", " << static_cast(a5.a1) << ", " << static_cast(a5.a2) << "), (" << static_cast(a6.a0) << ", " << static_cast(a6.a1) << ", " << static_cast(a6.a2) << "), (" << static_cast(a7.a0) << ", " << static_cast(a7.a1) << ", " << static_cast(a7.a2) << "), (" << static_cast(a8.a0) << ", " << static_cast(a8.a1) << ", " << static_cast(a8.a2) << "), (" << static_cast(a9.a0) << ", " << static_cast(a9.a1) << ", " << static_cast(a9.a2) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a1.a0; result += a1.a1; result += a1.a2; result += a2.a0; result += a2.a1; result += a2.a2; result += a3.a0; result += a3.a1; result += a3.a2; result += a4.a0; result += a4.a1; result += a4.a2; result += a5.a0; result += a5.a1; result += a5.a2; result += a6.a0; result += a6.a1; result += a6.a2; result += a7.a0; result += a7.a1; result += a7.a2; result += a8.a0; result += a8.a1; result += a8.a2; result += a9.a0; result += a9.a1; result += a9.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT int64_t PassStruct3BytesInt2ByteAlignedx10(Struct3BytesInt2ByteAligned a0, Struct3BytesInt2ByteAligned a1, Struct3BytesInt2ByteAligned a2, Struct3BytesInt2ByteAligned a3, Struct3BytesInt2ByteAligned a4, Struct3BytesInt2ByteAligned a5, Struct3BytesInt2ByteAligned a6, Struct3BytesInt2ByteAligned a7, Struct3BytesInt2ByteAligned a8, Struct3BytesInt2ByteAligned a9) { std::cout << "PassStruct3BytesInt2ByteAlignedx10" << "((" << a0.a0 << ", " << static_cast(a0.a1) << "), (" << a1.a0 << ", " << static_cast(a1.a1) << "), (" << a2.a0 << ", " << static_cast(a2.a1) << "), (" << a3.a0 << ", " << static_cast(a3.a1) << "), (" << a4.a0 << ", " << static_cast(a4.a1) << "), (" << a5.a0 << ", " << static_cast(a5.a1) << "), (" << a6.a0 << ", " << static_cast(a6.a1) << "), (" << a7.a0 << ", " << static_cast(a7.a1) << "), (" << a8.a0 << ", " << static_cast(a8.a1) << "), (" << a9.a0 << ", " << static_cast(a9.a1) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a1.a0; result += a1.a1; result += a2.a0; result += a2.a1; result += a3.a0; result += a3.a1; result += a4.a0; result += a4.a1; result += a5.a0; result += a5.a1; result += a6.a0; result += a6.a1; result += a7.a0; result += a7.a1; result += a8.a0; result += a8.a1; result += a9.a0; result += a9.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Exactly word size on 32-bit architectures. // 10 struct arguments will exhaust available registers. DART_EXPORT int64_t PassStruct4BytesHomogeneousInt16x10(Struct4BytesHomogeneousInt16 a0, Struct4BytesHomogeneousInt16 a1, Struct4BytesHomogeneousInt16 a2, Struct4BytesHomogeneousInt16 a3, Struct4BytesHomogeneousInt16 a4, Struct4BytesHomogeneousInt16 a5, Struct4BytesHomogeneousInt16 a6, Struct4BytesHomogeneousInt16 a7, Struct4BytesHomogeneousInt16 a8, Struct4BytesHomogeneousInt16 a9) { std::cout << "PassStruct4BytesHomogeneousInt16x10" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", " << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0 << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a1.a0; result += a1.a1; result += a2.a0; result += a2.a1; result += a3.a0; result += a3.a1; result += a4.a0; result += a4.a1; result += a5.a0; result += a5.a1; result += a6.a0; result += a6.a1; result += a7.a0; result += a7.a1; result += a8.a0; result += a8.a1; result += a9.a0; result += a9.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Sub word size on 64 bit architectures. // 10 struct arguments will exhaust available registers. DART_EXPORT int64_t PassStruct7BytesHomogeneousUint8x10(Struct7BytesHomogeneousUint8 a0, Struct7BytesHomogeneousUint8 a1, Struct7BytesHomogeneousUint8 a2, Struct7BytesHomogeneousUint8 a3, Struct7BytesHomogeneousUint8 a4, Struct7BytesHomogeneousUint8 a5, Struct7BytesHomogeneousUint8 a6, Struct7BytesHomogeneousUint8 a7, Struct7BytesHomogeneousUint8 a8, Struct7BytesHomogeneousUint8 a9) { std::cout << "PassStruct7BytesHomogeneousUint8x10" << "((" << static_cast(a0.a0) << ", " << static_cast(a0.a1) << ", " << static_cast(a0.a2) << ", " << static_cast(a0.a3) << ", " << static_cast(a0.a4) << ", " << static_cast(a0.a5) << ", " << static_cast(a0.a6) << "), (" << static_cast(a1.a0) << ", " << static_cast(a1.a1) << ", " << static_cast(a1.a2) << ", " << static_cast(a1.a3) << ", " << static_cast(a1.a4) << ", " << static_cast(a1.a5) << ", " << static_cast(a1.a6) << "), (" << static_cast(a2.a0) << ", " << static_cast(a2.a1) << ", " << static_cast(a2.a2) << ", " << static_cast(a2.a3) << ", " << static_cast(a2.a4) << ", " << static_cast(a2.a5) << ", " << static_cast(a2.a6) << "), (" << static_cast(a3.a0) << ", " << static_cast(a3.a1) << ", " << static_cast(a3.a2) << ", " << static_cast(a3.a3) << ", " << static_cast(a3.a4) << ", " << static_cast(a3.a5) << ", " << static_cast(a3.a6) << "), (" << static_cast(a4.a0) << ", " << static_cast(a4.a1) << ", " << static_cast(a4.a2) << ", " << static_cast(a4.a3) << ", " << static_cast(a4.a4) << ", " << static_cast(a4.a5) << ", " << static_cast(a4.a6) << "), (" << static_cast(a5.a0) << ", " << static_cast(a5.a1) << ", " << static_cast(a5.a2) << ", " << static_cast(a5.a3) << ", " << static_cast(a5.a4) << ", " << static_cast(a5.a5) << ", " << static_cast(a5.a6) << "), (" << static_cast(a6.a0) << ", " << static_cast(a6.a1) << ", " << static_cast(a6.a2) << ", " << static_cast(a6.a3) << ", " << static_cast(a6.a4) << ", " << static_cast(a6.a5) << ", " << static_cast(a6.a6) << "), (" << static_cast(a7.a0) << ", " << static_cast(a7.a1) << ", " << static_cast(a7.a2) << ", " << static_cast(a7.a3) << ", " << static_cast(a7.a4) << ", " << static_cast(a7.a5) << ", " << static_cast(a7.a6) << "), (" << static_cast(a8.a0) << ", " << static_cast(a8.a1) << ", " << static_cast(a8.a2) << ", " << static_cast(a8.a3) << ", " << static_cast(a8.a4) << ", " << static_cast(a8.a5) << ", " << static_cast(a8.a6) << "), (" << static_cast(a9.a0) << ", " << static_cast(a9.a1) << ", " << static_cast(a9.a2) << ", " << static_cast(a9.a3) << ", " << static_cast(a9.a4) << ", " << static_cast(a9.a5) << ", " << static_cast(a9.a6) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a0.a4; result += a0.a5; result += a0.a6; result += a1.a0; result += a1.a1; result += a1.a2; result += a1.a3; result += a1.a4; result += a1.a5; result += a1.a6; result += a2.a0; result += a2.a1; result += a2.a2; result += a2.a3; result += a2.a4; result += a2.a5; result += a2.a6; result += a3.a0; result += a3.a1; result += a3.a2; result += a3.a3; result += a3.a4; result += a3.a5; result += a3.a6; result += a4.a0; result += a4.a1; result += a4.a2; result += a4.a3; result += a4.a4; result += a4.a5; result += a4.a6; result += a5.a0; result += a5.a1; result += a5.a2; result += a5.a3; result += a5.a4; result += a5.a5; result += a5.a6; result += a6.a0; result += a6.a1; result += a6.a2; result += a6.a3; result += a6.a4; result += a6.a5; result += a6.a6; result += a7.a0; result += a7.a1; result += a7.a2; result += a7.a3; result += a7.a4; result += a7.a5; result += a7.a6; result += a8.a0; result += a8.a1; result += a8.a2; result += a8.a3; result += a8.a4; result += a8.a5; result += a8.a6; result += a9.a0; result += a9.a1; result += a9.a2; result += a9.a3; result += a9.a4; result += a9.a5; result += a9.a6; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Sub word size on 64 bit architectures. // With alignment rules taken into account size is 8 bytes. // 10 struct arguments will exhaust available registers. DART_EXPORT int64_t PassStruct7BytesInt4ByteAlignedx10(Struct7BytesInt4ByteAligned a0, Struct7BytesInt4ByteAligned a1, Struct7BytesInt4ByteAligned a2, Struct7BytesInt4ByteAligned a3, Struct7BytesInt4ByteAligned a4, Struct7BytesInt4ByteAligned a5, Struct7BytesInt4ByteAligned a6, Struct7BytesInt4ByteAligned a7, Struct7BytesInt4ByteAligned a8, Struct7BytesInt4ByteAligned a9) { std::cout << "PassStruct7BytesInt4ByteAlignedx10" << "((" << a0.a0 << ", " << a0.a1 << ", " << static_cast(a0.a2) << "), (" << a1.a0 << ", " << a1.a1 << ", " << static_cast(a1.a2) << "), (" << a2.a0 << ", " << a2.a1 << ", " << static_cast(a2.a2) << "), (" << a3.a0 << ", " << a3.a1 << ", " << static_cast(a3.a2) << "), (" << a4.a0 << ", " << a4.a1 << ", " << static_cast(a4.a2) << "), (" << a5.a0 << ", " << a5.a1 << ", " << static_cast(a5.a2) << "), (" << a6.a0 << ", " << a6.a1 << ", " << static_cast(a6.a2) << "), (" << a7.a0 << ", " << a7.a1 << ", " << static_cast(a7.a2) << "), (" << a8.a0 << ", " << a8.a1 << ", " << static_cast(a8.a2) << "), (" << a9.a0 << ", " << a9.a1 << ", " << static_cast(a9.a2) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a1.a0; result += a1.a1; result += a1.a2; result += a2.a0; result += a2.a1; result += a2.a2; result += a3.a0; result += a3.a1; result += a3.a2; result += a4.a0; result += a4.a1; result += a4.a2; result += a5.a0; result += a5.a1; result += a5.a2; result += a6.a0; result += a6.a1; result += a6.a2; result += a7.a0; result += a7.a1; result += a7.a2; result += a8.a0; result += a8.a1; result += a8.a2; result += a9.a0; result += a9.a1; result += a9.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Exactly word size struct on 64bit architectures. // 10 struct arguments will exhaust available registers. DART_EXPORT int64_t PassStruct8BytesIntx10(Struct8BytesInt a0, Struct8BytesInt a1, Struct8BytesInt a2, Struct8BytesInt a3, Struct8BytesInt a4, Struct8BytesInt a5, Struct8BytesInt a6, Struct8BytesInt a7, Struct8BytesInt a8, Struct8BytesInt a9) { std::cout << "PassStruct8BytesIntx10" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2 << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << "), (" << a9.a0 << ", " << a9.a1 << ", " << a9.a2 << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a1.a0; result += a1.a1; result += a1.a2; result += a2.a0; result += a2.a1; result += a2.a2; result += a3.a0; result += a3.a1; result += a3.a2; result += a4.a0; result += a4.a1; result += a4.a2; result += a5.a0; result += a5.a1; result += a5.a2; result += a6.a0; result += a6.a1; result += a6.a2; result += a7.a0; result += a7.a1; result += a7.a2; result += a8.a0; result += a8.a1; result += a8.a2; result += a9.a0; result += a9.a1; result += a9.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Arguments passed in FP registers as long as they fit. // 10 struct arguments will exhaust available registers. DART_EXPORT float PassStruct8BytesHomogeneousFloatx10( Struct8BytesHomogeneousFloat a0, Struct8BytesHomogeneousFloat a1, Struct8BytesHomogeneousFloat a2, Struct8BytesHomogeneousFloat a3, Struct8BytesHomogeneousFloat a4, Struct8BytesHomogeneousFloat a5, Struct8BytesHomogeneousFloat a6, Struct8BytesHomogeneousFloat a7, Struct8BytesHomogeneousFloat a8, Struct8BytesHomogeneousFloat a9) { std::cout << "PassStruct8BytesHomogeneousFloatx10" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", " << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0 << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))" << "\n"; float result = 0; result += a0.a0; result += a0.a1; result += a1.a0; result += a1.a1; result += a2.a0; result += a2.a1; result += a3.a0; result += a3.a1; result += a4.a0; result += a4.a1; result += a5.a0; result += a5.a1; result += a6.a0; result += a6.a1; result += a7.a0; result += a7.a1; result += a8.a0; result += a8.a1; result += a9.a0; result += a9.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // On x64, arguments go in int registers because it is not only float. // 10 struct arguments will exhaust available registers. DART_EXPORT float PassStruct8BytesMixedx10(Struct8BytesMixed a0, Struct8BytesMixed a1, Struct8BytesMixed a2, Struct8BytesMixed a3, Struct8BytesMixed a4, Struct8BytesMixed a5, Struct8BytesMixed a6, Struct8BytesMixed a7, Struct8BytesMixed a8, Struct8BytesMixed a9) { std::cout << "PassStruct8BytesMixedx10" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2 << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << "), (" << a9.a0 << ", " << a9.a1 << ", " << a9.a2 << "))" << "\n"; float result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a1.a0; result += a1.a1; result += a1.a2; result += a2.a0; result += a2.a1; result += a2.a2; result += a3.a0; result += a3.a1; result += a3.a2; result += a4.a0; result += a4.a1; result += a4.a2; result += a5.a0; result += a5.a1; result += a5.a2; result += a6.a0; result += a6.a1; result += a6.a2; result += a7.a0; result += a7.a1; result += a7.a2; result += a8.a0; result += a8.a1; result += a8.a2; result += a9.a0; result += a9.a1; result += a9.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT int64_t PassStruct9BytesHomogeneousUint8x10(Struct9BytesHomogeneousUint8 a0, Struct9BytesHomogeneousUint8 a1, Struct9BytesHomogeneousUint8 a2, Struct9BytesHomogeneousUint8 a3, Struct9BytesHomogeneousUint8 a4, Struct9BytesHomogeneousUint8 a5, Struct9BytesHomogeneousUint8 a6, Struct9BytesHomogeneousUint8 a7, Struct9BytesHomogeneousUint8 a8, Struct9BytesHomogeneousUint8 a9) { std::cout << "PassStruct9BytesHomogeneousUint8x10" << "((" << static_cast(a0.a0) << ", " << static_cast(a0.a1) << ", " << static_cast(a0.a2) << ", " << static_cast(a0.a3) << ", " << static_cast(a0.a4) << ", " << static_cast(a0.a5) << ", " << static_cast(a0.a6) << ", " << static_cast(a0.a7) << ", " << static_cast(a0.a8) << "), (" << static_cast(a1.a0) << ", " << static_cast(a1.a1) << ", " << static_cast(a1.a2) << ", " << static_cast(a1.a3) << ", " << static_cast(a1.a4) << ", " << static_cast(a1.a5) << ", " << static_cast(a1.a6) << ", " << static_cast(a1.a7) << ", " << static_cast(a1.a8) << "), (" << static_cast(a2.a0) << ", " << static_cast(a2.a1) << ", " << static_cast(a2.a2) << ", " << static_cast(a2.a3) << ", " << static_cast(a2.a4) << ", " << static_cast(a2.a5) << ", " << static_cast(a2.a6) << ", " << static_cast(a2.a7) << ", " << static_cast(a2.a8) << "), (" << static_cast(a3.a0) << ", " << static_cast(a3.a1) << ", " << static_cast(a3.a2) << ", " << static_cast(a3.a3) << ", " << static_cast(a3.a4) << ", " << static_cast(a3.a5) << ", " << static_cast(a3.a6) << ", " << static_cast(a3.a7) << ", " << static_cast(a3.a8) << "), (" << static_cast(a4.a0) << ", " << static_cast(a4.a1) << ", " << static_cast(a4.a2) << ", " << static_cast(a4.a3) << ", " << static_cast(a4.a4) << ", " << static_cast(a4.a5) << ", " << static_cast(a4.a6) << ", " << static_cast(a4.a7) << ", " << static_cast(a4.a8) << "), (" << static_cast(a5.a0) << ", " << static_cast(a5.a1) << ", " << static_cast(a5.a2) << ", " << static_cast(a5.a3) << ", " << static_cast(a5.a4) << ", " << static_cast(a5.a5) << ", " << static_cast(a5.a6) << ", " << static_cast(a5.a7) << ", " << static_cast(a5.a8) << "), (" << static_cast(a6.a0) << ", " << static_cast(a6.a1) << ", " << static_cast(a6.a2) << ", " << static_cast(a6.a3) << ", " << static_cast(a6.a4) << ", " << static_cast(a6.a5) << ", " << static_cast(a6.a6) << ", " << static_cast(a6.a7) << ", " << static_cast(a6.a8) << "), (" << static_cast(a7.a0) << ", " << static_cast(a7.a1) << ", " << static_cast(a7.a2) << ", " << static_cast(a7.a3) << ", " << static_cast(a7.a4) << ", " << static_cast(a7.a5) << ", " << static_cast(a7.a6) << ", " << static_cast(a7.a7) << ", " << static_cast(a7.a8) << "), (" << static_cast(a8.a0) << ", " << static_cast(a8.a1) << ", " << static_cast(a8.a2) << ", " << static_cast(a8.a3) << ", " << static_cast(a8.a4) << ", " << static_cast(a8.a5) << ", " << static_cast(a8.a6) << ", " << static_cast(a8.a7) << ", " << static_cast(a8.a8) << "), (" << static_cast(a9.a0) << ", " << static_cast(a9.a1) << ", " << static_cast(a9.a2) << ", " << static_cast(a9.a3) << ", " << static_cast(a9.a4) << ", " << static_cast(a9.a5) << ", " << static_cast(a9.a6) << ", " << static_cast(a9.a7) << ", " << static_cast(a9.a8) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a0.a4; result += a0.a5; result += a0.a6; result += a0.a7; result += a0.a8; result += a1.a0; result += a1.a1; result += a1.a2; result += a1.a3; result += a1.a4; result += a1.a5; result += a1.a6; result += a1.a7; result += a1.a8; result += a2.a0; result += a2.a1; result += a2.a2; result += a2.a3; result += a2.a4; result += a2.a5; result += a2.a6; result += a2.a7; result += a2.a8; result += a3.a0; result += a3.a1; result += a3.a2; result += a3.a3; result += a3.a4; result += a3.a5; result += a3.a6; result += a3.a7; result += a3.a8; result += a4.a0; result += a4.a1; result += a4.a2; result += a4.a3; result += a4.a4; result += a4.a5; result += a4.a6; result += a4.a7; result += a4.a8; result += a5.a0; result += a5.a1; result += a5.a2; result += a5.a3; result += a5.a4; result += a5.a5; result += a5.a6; result += a5.a7; result += a5.a8; result += a6.a0; result += a6.a1; result += a6.a2; result += a6.a3; result += a6.a4; result += a6.a5; result += a6.a6; result += a6.a7; result += a6.a8; result += a7.a0; result += a7.a1; result += a7.a2; result += a7.a3; result += a7.a4; result += a7.a5; result += a7.a6; result += a7.a7; result += a7.a8; result += a8.a0; result += a8.a1; result += a8.a2; result += a8.a3; result += a8.a4; result += a8.a5; result += a8.a6; result += a8.a7; result += a8.a8; result += a9.a0; result += a9.a1; result += a9.a2; result += a9.a3; result += a9.a4; result += a9.a5; result += a9.a6; result += a9.a7; result += a9.a8; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. // DART_EXPORT int64_t PassStruct9BytesInt4Or8ByteAlignedx10(Struct9BytesInt4Or8ByteAligned a0, Struct9BytesInt4Or8ByteAligned a1, Struct9BytesInt4Or8ByteAligned a2, Struct9BytesInt4Or8ByteAligned a3, Struct9BytesInt4Or8ByteAligned a4, Struct9BytesInt4Or8ByteAligned a5, Struct9BytesInt4Or8ByteAligned a6, Struct9BytesInt4Or8ByteAligned a7, Struct9BytesInt4Or8ByteAligned a8, Struct9BytesInt4Or8ByteAligned a9) { std::cout << "PassStruct9BytesInt4Or8ByteAlignedx10" << "((" << a0.a0 << ", " << static_cast(a0.a1) << "), (" << a1.a0 << ", " << static_cast(a1.a1) << "), (" << a2.a0 << ", " << static_cast(a2.a1) << "), (" << a3.a0 << ", " << static_cast(a3.a1) << "), (" << a4.a0 << ", " << static_cast(a4.a1) << "), (" << a5.a0 << ", " << static_cast(a5.a1) << "), (" << a6.a0 << ", " << static_cast(a6.a1) << "), (" << a7.a0 << ", " << static_cast(a7.a1) << "), (" << a8.a0 << ", " << static_cast(a8.a1) << "), (" << a9.a0 << ", " << static_cast(a9.a1) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a1.a0; result += a1.a1; result += a2.a0; result += a2.a1; result += a3.a0; result += a3.a1; result += a4.a0; result += a4.a1; result += a5.a0; result += a5.a1; result += a6.a0; result += a6.a1; result += a7.a0; result += a7.a1; result += a8.a0; result += a8.a1; result += a9.a0; result += a9.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT float PassStruct12BytesHomogeneousFloatx6( Struct12BytesHomogeneousFloat a0, Struct12BytesHomogeneousFloat a1, Struct12BytesHomogeneousFloat a2, Struct12BytesHomogeneousFloat a3, Struct12BytesHomogeneousFloat a4, Struct12BytesHomogeneousFloat a5) { std::cout << "PassStruct12BytesHomogeneousFloatx6" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << "))" << "\n"; float result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a1.a0; result += a1.a1; result += a1.a2; result += a2.a0; result += a2.a1; result += a2.a2; result += a3.a0; result += a3.a1; result += a3.a2; result += a4.a0; result += a4.a1; result += a4.a2; result += a5.a0; result += a5.a1; result += a5.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT float PassStruct16BytesHomogeneousFloatx5( Struct16BytesHomogeneousFloat a0, Struct16BytesHomogeneousFloat a1, Struct16BytesHomogeneousFloat a2, Struct16BytesHomogeneousFloat a3, Struct16BytesHomogeneousFloat a4) { std::cout << "PassStruct16BytesHomogeneousFloatx5" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << ", " << a4.a3 << "))" << "\n"; float result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a1.a0; result += a1.a1; result += a1.a2; result += a1.a3; result += a2.a0; result += a2.a1; result += a2.a2; result += a2.a3; result += a3.a0; result += a3.a1; result += a3.a2; result += a3.a3; result += a4.a0; result += a4.a1; result += a4.a2; result += a4.a3; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT double PassStruct16BytesMixedx10(Struct16BytesMixed a0, Struct16BytesMixed a1, Struct16BytesMixed a2, Struct16BytesMixed a3, Struct16BytesMixed a4, Struct16BytesMixed a5, Struct16BytesMixed a6, Struct16BytesMixed a7, Struct16BytesMixed a8, Struct16BytesMixed a9) { std::cout << "PassStruct16BytesMixedx10" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", " << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0 << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))" << "\n"; double result = 0; result += a0.a0; result += a0.a1; result += a1.a0; result += a1.a1; result += a2.a0; result += a2.a1; result += a3.a0; result += a3.a1; result += a4.a0; result += a4.a1; result += a5.a0; result += a5.a1; result += a6.a0; result += a6.a1; result += a7.a0; result += a7.a1; result += a8.a0; result += a8.a1; result += a9.a0; result += a9.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT float PassStruct16BytesMixed2x10(Struct16BytesMixed2 a0, Struct16BytesMixed2 a1, Struct16BytesMixed2 a2, Struct16BytesMixed2 a3, Struct16BytesMixed2 a4, Struct16BytesMixed2 a5, Struct16BytesMixed2 a6, Struct16BytesMixed2 a7, Struct16BytesMixed2 a8, Struct16BytesMixed2 a9) { std::cout << "PassStruct16BytesMixed2x10" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << ", " << a4.a3 << "), (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2 << ", " << a6.a3 << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3 << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << ", " << a8.a3 << "), (" << a9.a0 << ", " << a9.a1 << ", " << a9.a2 << ", " << a9.a3 << "))" << "\n"; float result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a1.a0; result += a1.a1; result += a1.a2; result += a1.a3; result += a2.a0; result += a2.a1; result += a2.a2; result += a2.a3; result += a3.a0; result += a3.a1; result += a3.a2; result += a3.a3; result += a4.a0; result += a4.a1; result += a4.a2; result += a4.a3; result += a5.a0; result += a5.a1; result += a5.a2; result += a5.a3; result += a6.a0; result += a6.a1; result += a6.a2; result += a6.a3; result += a7.a0; result += a7.a1; result += a7.a2; result += a7.a3; result += a8.a0; result += a8.a1; result += a8.a2; result += a8.a3; result += a9.a0; result += a9.a1; result += a9.a2; result += a9.a3; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Arguments are passed as pointer to copy on arm64. // Tests that the memory allocated for copies are rounded up to word size. DART_EXPORT int64_t PassStruct17BytesIntx10(Struct17BytesInt a0, Struct17BytesInt a1, Struct17BytesInt a2, Struct17BytesInt a3, Struct17BytesInt a4, Struct17BytesInt a5, Struct17BytesInt a6, Struct17BytesInt a7, Struct17BytesInt a8, Struct17BytesInt a9) { std::cout << "PassStruct17BytesIntx10" << "((" << a0.a0 << ", " << a0.a1 << ", " << static_cast(a0.a2) << "), (" << a1.a0 << ", " << a1.a1 << ", " << static_cast(a1.a2) << "), (" << a2.a0 << ", " << a2.a1 << ", " << static_cast(a2.a2) << "), (" << a3.a0 << ", " << a3.a1 << ", " << static_cast(a3.a2) << "), (" << a4.a0 << ", " << a4.a1 << ", " << static_cast(a4.a2) << "), (" << a5.a0 << ", " << a5.a1 << ", " << static_cast(a5.a2) << "), (" << a6.a0 << ", " << a6.a1 << ", " << static_cast(a6.a2) << "), (" << a7.a0 << ", " << a7.a1 << ", " << static_cast(a7.a2) << "), (" << a8.a0 << ", " << a8.a1 << ", " << static_cast(a8.a2) << "), (" << a9.a0 << ", " << a9.a1 << ", " << static_cast(a9.a2) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a1.a0; result += a1.a1; result += a1.a2; result += a2.a0; result += a2.a1; result += a2.a2; result += a3.a0; result += a3.a1; result += a3.a2; result += a4.a0; result += a4.a1; result += a4.a2; result += a5.a0; result += a5.a1; result += a5.a2; result += a6.a0; result += a6.a1; result += a6.a2; result += a7.a0; result += a7.a1; result += a7.a2; result += a8.a0; result += a8.a1; result += a8.a2; result += a9.a0; result += a9.a1; result += a9.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. // DART_EXPORT int64_t PassStruct19BytesHomogeneousUint8x10(Struct19BytesHomogeneousUint8 a0, Struct19BytesHomogeneousUint8 a1, Struct19BytesHomogeneousUint8 a2, Struct19BytesHomogeneousUint8 a3, Struct19BytesHomogeneousUint8 a4, Struct19BytesHomogeneousUint8 a5, Struct19BytesHomogeneousUint8 a6, Struct19BytesHomogeneousUint8 a7, Struct19BytesHomogeneousUint8 a8, Struct19BytesHomogeneousUint8 a9) { std::cout << "PassStruct19BytesHomogeneousUint8x10" << "((" << static_cast(a0.a0) << ", " << static_cast(a0.a1) << ", " << static_cast(a0.a2) << ", " << static_cast(a0.a3) << ", " << static_cast(a0.a4) << ", " << static_cast(a0.a5) << ", " << static_cast(a0.a6) << ", " << static_cast(a0.a7) << ", " << static_cast(a0.a8) << ", " << static_cast(a0.a9) << ", " << static_cast(a0.a10) << ", " << static_cast(a0.a11) << ", " << static_cast(a0.a12) << ", " << static_cast(a0.a13) << ", " << static_cast(a0.a14) << ", " << static_cast(a0.a15) << ", " << static_cast(a0.a16) << ", " << static_cast(a0.a17) << ", " << static_cast(a0.a18) << "), (" << static_cast(a1.a0) << ", " << static_cast(a1.a1) << ", " << static_cast(a1.a2) << ", " << static_cast(a1.a3) << ", " << static_cast(a1.a4) << ", " << static_cast(a1.a5) << ", " << static_cast(a1.a6) << ", " << static_cast(a1.a7) << ", " << static_cast(a1.a8) << ", " << static_cast(a1.a9) << ", " << static_cast(a1.a10) << ", " << static_cast(a1.a11) << ", " << static_cast(a1.a12) << ", " << static_cast(a1.a13) << ", " << static_cast(a1.a14) << ", " << static_cast(a1.a15) << ", " << static_cast(a1.a16) << ", " << static_cast(a1.a17) << ", " << static_cast(a1.a18) << "), (" << static_cast(a2.a0) << ", " << static_cast(a2.a1) << ", " << static_cast(a2.a2) << ", " << static_cast(a2.a3) << ", " << static_cast(a2.a4) << ", " << static_cast(a2.a5) << ", " << static_cast(a2.a6) << ", " << static_cast(a2.a7) << ", " << static_cast(a2.a8) << ", " << static_cast(a2.a9) << ", " << static_cast(a2.a10) << ", " << static_cast(a2.a11) << ", " << static_cast(a2.a12) << ", " << static_cast(a2.a13) << ", " << static_cast(a2.a14) << ", " << static_cast(a2.a15) << ", " << static_cast(a2.a16) << ", " << static_cast(a2.a17) << ", " << static_cast(a2.a18) << "), (" << static_cast(a3.a0) << ", " << static_cast(a3.a1) << ", " << static_cast(a3.a2) << ", " << static_cast(a3.a3) << ", " << static_cast(a3.a4) << ", " << static_cast(a3.a5) << ", " << static_cast(a3.a6) << ", " << static_cast(a3.a7) << ", " << static_cast(a3.a8) << ", " << static_cast(a3.a9) << ", " << static_cast(a3.a10) << ", " << static_cast(a3.a11) << ", " << static_cast(a3.a12) << ", " << static_cast(a3.a13) << ", " << static_cast(a3.a14) << ", " << static_cast(a3.a15) << ", " << static_cast(a3.a16) << ", " << static_cast(a3.a17) << ", " << static_cast(a3.a18) << "), (" << static_cast(a4.a0) << ", " << static_cast(a4.a1) << ", " << static_cast(a4.a2) << ", " << static_cast(a4.a3) << ", " << static_cast(a4.a4) << ", " << static_cast(a4.a5) << ", " << static_cast(a4.a6) << ", " << static_cast(a4.a7) << ", " << static_cast(a4.a8) << ", " << static_cast(a4.a9) << ", " << static_cast(a4.a10) << ", " << static_cast(a4.a11) << ", " << static_cast(a4.a12) << ", " << static_cast(a4.a13) << ", " << static_cast(a4.a14) << ", " << static_cast(a4.a15) << ", " << static_cast(a4.a16) << ", " << static_cast(a4.a17) << ", " << static_cast(a4.a18) << "), (" << static_cast(a5.a0) << ", " << static_cast(a5.a1) << ", " << static_cast(a5.a2) << ", " << static_cast(a5.a3) << ", " << static_cast(a5.a4) << ", " << static_cast(a5.a5) << ", " << static_cast(a5.a6) << ", " << static_cast(a5.a7) << ", " << static_cast(a5.a8) << ", " << static_cast(a5.a9) << ", " << static_cast(a5.a10) << ", " << static_cast(a5.a11) << ", " << static_cast(a5.a12) << ", " << static_cast(a5.a13) << ", " << static_cast(a5.a14) << ", " << static_cast(a5.a15) << ", " << static_cast(a5.a16) << ", " << static_cast(a5.a17) << ", " << static_cast(a5.a18) << "), (" << static_cast(a6.a0) << ", " << static_cast(a6.a1) << ", " << static_cast(a6.a2) << ", " << static_cast(a6.a3) << ", " << static_cast(a6.a4) << ", " << static_cast(a6.a5) << ", " << static_cast(a6.a6) << ", " << static_cast(a6.a7) << ", " << static_cast(a6.a8) << ", " << static_cast(a6.a9) << ", " << static_cast(a6.a10) << ", " << static_cast(a6.a11) << ", " << static_cast(a6.a12) << ", " << static_cast(a6.a13) << ", " << static_cast(a6.a14) << ", " << static_cast(a6.a15) << ", " << static_cast(a6.a16) << ", " << static_cast(a6.a17) << ", " << static_cast(a6.a18) << "), (" << static_cast(a7.a0) << ", " << static_cast(a7.a1) << ", " << static_cast(a7.a2) << ", " << static_cast(a7.a3) << ", " << static_cast(a7.a4) << ", " << static_cast(a7.a5) << ", " << static_cast(a7.a6) << ", " << static_cast(a7.a7) << ", " << static_cast(a7.a8) << ", " << static_cast(a7.a9) << ", " << static_cast(a7.a10) << ", " << static_cast(a7.a11) << ", " << static_cast(a7.a12) << ", " << static_cast(a7.a13) << ", " << static_cast(a7.a14) << ", " << static_cast(a7.a15) << ", " << static_cast(a7.a16) << ", " << static_cast(a7.a17) << ", " << static_cast(a7.a18) << "), (" << static_cast(a8.a0) << ", " << static_cast(a8.a1) << ", " << static_cast(a8.a2) << ", " << static_cast(a8.a3) << ", " << static_cast(a8.a4) << ", " << static_cast(a8.a5) << ", " << static_cast(a8.a6) << ", " << static_cast(a8.a7) << ", " << static_cast(a8.a8) << ", " << static_cast(a8.a9) << ", " << static_cast(a8.a10) << ", " << static_cast(a8.a11) << ", " << static_cast(a8.a12) << ", " << static_cast(a8.a13) << ", " << static_cast(a8.a14) << ", " << static_cast(a8.a15) << ", " << static_cast(a8.a16) << ", " << static_cast(a8.a17) << ", " << static_cast(a8.a18) << "), (" << static_cast(a9.a0) << ", " << static_cast(a9.a1) << ", " << static_cast(a9.a2) << ", " << static_cast(a9.a3) << ", " << static_cast(a9.a4) << ", " << static_cast(a9.a5) << ", " << static_cast(a9.a6) << ", " << static_cast(a9.a7) << ", " << static_cast(a9.a8) << ", " << static_cast(a9.a9) << ", " << static_cast(a9.a10) << ", " << static_cast(a9.a11) << ", " << static_cast(a9.a12) << ", " << static_cast(a9.a13) << ", " << static_cast(a9.a14) << ", " << static_cast(a9.a15) << ", " << static_cast(a9.a16) << ", " << static_cast(a9.a17) << ", " << static_cast(a9.a18) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a0.a4; result += a0.a5; result += a0.a6; result += a0.a7; result += a0.a8; result += a0.a9; result += a0.a10; result += a0.a11; result += a0.a12; result += a0.a13; result += a0.a14; result += a0.a15; result += a0.a16; result += a0.a17; result += a0.a18; result += a1.a0; result += a1.a1; result += a1.a2; result += a1.a3; result += a1.a4; result += a1.a5; result += a1.a6; result += a1.a7; result += a1.a8; result += a1.a9; result += a1.a10; result += a1.a11; result += a1.a12; result += a1.a13; result += a1.a14; result += a1.a15; result += a1.a16; result += a1.a17; result += a1.a18; result += a2.a0; result += a2.a1; result += a2.a2; result += a2.a3; result += a2.a4; result += a2.a5; result += a2.a6; result += a2.a7; result += a2.a8; result += a2.a9; result += a2.a10; result += a2.a11; result += a2.a12; result += a2.a13; result += a2.a14; result += a2.a15; result += a2.a16; result += a2.a17; result += a2.a18; result += a3.a0; result += a3.a1; result += a3.a2; result += a3.a3; result += a3.a4; result += a3.a5; result += a3.a6; result += a3.a7; result += a3.a8; result += a3.a9; result += a3.a10; result += a3.a11; result += a3.a12; result += a3.a13; result += a3.a14; result += a3.a15; result += a3.a16; result += a3.a17; result += a3.a18; result += a4.a0; result += a4.a1; result += a4.a2; result += a4.a3; result += a4.a4; result += a4.a5; result += a4.a6; result += a4.a7; result += a4.a8; result += a4.a9; result += a4.a10; result += a4.a11; result += a4.a12; result += a4.a13; result += a4.a14; result += a4.a15; result += a4.a16; result += a4.a17; result += a4.a18; result += a5.a0; result += a5.a1; result += a5.a2; result += a5.a3; result += a5.a4; result += a5.a5; result += a5.a6; result += a5.a7; result += a5.a8; result += a5.a9; result += a5.a10; result += a5.a11; result += a5.a12; result += a5.a13; result += a5.a14; result += a5.a15; result += a5.a16; result += a5.a17; result += a5.a18; result += a6.a0; result += a6.a1; result += a6.a2; result += a6.a3; result += a6.a4; result += a6.a5; result += a6.a6; result += a6.a7; result += a6.a8; result += a6.a9; result += a6.a10; result += a6.a11; result += a6.a12; result += a6.a13; result += a6.a14; result += a6.a15; result += a6.a16; result += a6.a17; result += a6.a18; result += a7.a0; result += a7.a1; result += a7.a2; result += a7.a3; result += a7.a4; result += a7.a5; result += a7.a6; result += a7.a7; result += a7.a8; result += a7.a9; result += a7.a10; result += a7.a11; result += a7.a12; result += a7.a13; result += a7.a14; result += a7.a15; result += a7.a16; result += a7.a17; result += a7.a18; result += a8.a0; result += a8.a1; result += a8.a2; result += a8.a3; result += a8.a4; result += a8.a5; result += a8.a6; result += a8.a7; result += a8.a8; result += a8.a9; result += a8.a10; result += a8.a11; result += a8.a12; result += a8.a13; result += a8.a14; result += a8.a15; result += a8.a16; result += a8.a17; result += a8.a18; result += a9.a0; result += a9.a1; result += a9.a2; result += a9.a3; result += a9.a4; result += a9.a5; result += a9.a6; result += a9.a7; result += a9.a8; result += a9.a9; result += a9.a10; result += a9.a11; result += a9.a12; result += a9.a13; result += a9.a14; result += a9.a15; result += a9.a16; result += a9.a17; result += a9.a18; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT int32_t PassStruct20BytesHomogeneousInt32x10(Struct20BytesHomogeneousInt32 a0, Struct20BytesHomogeneousInt32 a1, Struct20BytesHomogeneousInt32 a2, Struct20BytesHomogeneousInt32 a3, Struct20BytesHomogeneousInt32 a4, Struct20BytesHomogeneousInt32 a5, Struct20BytesHomogeneousInt32 a6, Struct20BytesHomogeneousInt32 a7, Struct20BytesHomogeneousInt32 a8, Struct20BytesHomogeneousInt32 a9) { std::cout << "PassStruct20BytesHomogeneousInt32x10" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << ", " << a1.a4 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << ", " << a2.a3 << ", " << a2.a4 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << ", " << a3.a4 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << ", " << a4.a3 << ", " << a4.a4 << "), (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << ", " << a5.a4 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2 << ", " << a6.a3 << ", " << a6.a4 << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3 << ", " << a7.a4 << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << ", " << a8.a3 << ", " << a8.a4 << "), (" << a9.a0 << ", " << a9.a1 << ", " << a9.a2 << ", " << a9.a3 << ", " << a9.a4 << "))" << "\n"; int32_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a0.a4; result += a1.a0; result += a1.a1; result += a1.a2; result += a1.a3; result += a1.a4; result += a2.a0; result += a2.a1; result += a2.a2; result += a2.a3; result += a2.a4; result += a3.a0; result += a3.a1; result += a3.a2; result += a3.a3; result += a3.a4; result += a4.a0; result += a4.a1; result += a4.a2; result += a4.a3; result += a4.a4; result += a5.a0; result += a5.a1; result += a5.a2; result += a5.a3; result += a5.a4; result += a6.a0; result += a6.a1; result += a6.a2; result += a6.a3; result += a6.a4; result += a7.a0; result += a7.a1; result += a7.a2; result += a7.a3; result += a7.a4; result += a8.a0; result += a8.a1; result += a8.a2; result += a8.a3; result += a8.a4; result += a9.a0; result += a9.a1; result += a9.a2; result += a9.a3; result += a9.a4; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Argument too big to go into FPU registers in hardfp and arm64. DART_EXPORT float PassStruct20BytesHomogeneousFloat( Struct20BytesHomogeneousFloat a0) { std::cout << "PassStruct20BytesHomogeneousFloat" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << "))" << "\n"; float result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a0.a4; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Arguments in FPU registers on arm64. // 5 struct arguments will exhaust available registers. DART_EXPORT double PassStruct32BytesHomogeneousDoublex5( Struct32BytesHomogeneousDouble a0, Struct32BytesHomogeneousDouble a1, Struct32BytesHomogeneousDouble a2, Struct32BytesHomogeneousDouble a3, Struct32BytesHomogeneousDouble a4) { std::cout << "PassStruct32BytesHomogeneousDoublex5" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << ", " << a4.a3 << "))" << "\n"; double result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a1.a0; result += a1.a1; result += a1.a2; result += a1.a3; result += a2.a0; result += a2.a1; result += a2.a2; result += a2.a3; result += a3.a0; result += a3.a1; result += a3.a2; result += a3.a3; result += a4.a0; result += a4.a1; result += a4.a2; result += a4.a3; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Argument too big to go into FPU registers in arm64. DART_EXPORT double PassStruct40BytesHomogeneousDouble( Struct40BytesHomogeneousDouble a0) { std::cout << "PassStruct40BytesHomogeneousDouble" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << "))" << "\n"; double result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a0.a4; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Test 1kb struct. DART_EXPORT uint64_t PassStruct1024BytesHomogeneousUint64(Struct1024BytesHomogeneousUint64 a0) { std::cout << "PassStruct1024BytesHomogeneousUint64" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << ", " << a0.a5 << ", " << a0.a6 << ", " << a0.a7 << ", " << a0.a8 << ", " << a0.a9 << ", " << a0.a10 << ", " << a0.a11 << ", " << a0.a12 << ", " << a0.a13 << ", " << a0.a14 << ", " << a0.a15 << ", " << a0.a16 << ", " << a0.a17 << ", " << a0.a18 << ", " << a0.a19 << ", " << a0.a20 << ", " << a0.a21 << ", " << a0.a22 << ", " << a0.a23 << ", " << a0.a24 << ", " << a0.a25 << ", " << a0.a26 << ", " << a0.a27 << ", " << a0.a28 << ", " << a0.a29 << ", " << a0.a30 << ", " << a0.a31 << ", " << a0.a32 << ", " << a0.a33 << ", " << a0.a34 << ", " << a0.a35 << ", " << a0.a36 << ", " << a0.a37 << ", " << a0.a38 << ", " << a0.a39 << ", " << a0.a40 << ", " << a0.a41 << ", " << a0.a42 << ", " << a0.a43 << ", " << a0.a44 << ", " << a0.a45 << ", " << a0.a46 << ", " << a0.a47 << ", " << a0.a48 << ", " << a0.a49 << ", " << a0.a50 << ", " << a0.a51 << ", " << a0.a52 << ", " << a0.a53 << ", " << a0.a54 << ", " << a0.a55 << ", " << a0.a56 << ", " << a0.a57 << ", " << a0.a58 << ", " << a0.a59 << ", " << a0.a60 << ", " << a0.a61 << ", " << a0.a62 << ", " << a0.a63 << ", " << a0.a64 << ", " << a0.a65 << ", " << a0.a66 << ", " << a0.a67 << ", " << a0.a68 << ", " << a0.a69 << ", " << a0.a70 << ", " << a0.a71 << ", " << a0.a72 << ", " << a0.a73 << ", " << a0.a74 << ", " << a0.a75 << ", " << a0.a76 << ", " << a0.a77 << ", " << a0.a78 << ", " << a0.a79 << ", " << a0.a80 << ", " << a0.a81 << ", " << a0.a82 << ", " << a0.a83 << ", " << a0.a84 << ", " << a0.a85 << ", " << a0.a86 << ", " << a0.a87 << ", " << a0.a88 << ", " << a0.a89 << ", " << a0.a90 << ", " << a0.a91 << ", " << a0.a92 << ", " << a0.a93 << ", " << a0.a94 << ", " << a0.a95 << ", " << a0.a96 << ", " << a0.a97 << ", " << a0.a98 << ", " << a0.a99 << ", " << a0.a100 << ", " << a0.a101 << ", " << a0.a102 << ", " << a0.a103 << ", " << a0.a104 << ", " << a0.a105 << ", " << a0.a106 << ", " << a0.a107 << ", " << a0.a108 << ", " << a0.a109 << ", " << a0.a110 << ", " << a0.a111 << ", " << a0.a112 << ", " << a0.a113 << ", " << a0.a114 << ", " << a0.a115 << ", " << a0.a116 << ", " << a0.a117 << ", " << a0.a118 << ", " << a0.a119 << ", " << a0.a120 << ", " << a0.a121 << ", " << a0.a122 << ", " << a0.a123 << ", " << a0.a124 << ", " << a0.a125 << ", " << a0.a126 << ", " << a0.a127 << "))" << "\n"; uint64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a0.a4; result += a0.a5; result += a0.a6; result += a0.a7; result += a0.a8; result += a0.a9; result += a0.a10; result += a0.a11; result += a0.a12; result += a0.a13; result += a0.a14; result += a0.a15; result += a0.a16; result += a0.a17; result += a0.a18; result += a0.a19; result += a0.a20; result += a0.a21; result += a0.a22; result += a0.a23; result += a0.a24; result += a0.a25; result += a0.a26; result += a0.a27; result += a0.a28; result += a0.a29; result += a0.a30; result += a0.a31; result += a0.a32; result += a0.a33; result += a0.a34; result += a0.a35; result += a0.a36; result += a0.a37; result += a0.a38; result += a0.a39; result += a0.a40; result += a0.a41; result += a0.a42; result += a0.a43; result += a0.a44; result += a0.a45; result += a0.a46; result += a0.a47; result += a0.a48; result += a0.a49; result += a0.a50; result += a0.a51; result += a0.a52; result += a0.a53; result += a0.a54; result += a0.a55; result += a0.a56; result += a0.a57; result += a0.a58; result += a0.a59; result += a0.a60; result += a0.a61; result += a0.a62; result += a0.a63; result += a0.a64; result += a0.a65; result += a0.a66; result += a0.a67; result += a0.a68; result += a0.a69; result += a0.a70; result += a0.a71; result += a0.a72; result += a0.a73; result += a0.a74; result += a0.a75; result += a0.a76; result += a0.a77; result += a0.a78; result += a0.a79; result += a0.a80; result += a0.a81; result += a0.a82; result += a0.a83; result += a0.a84; result += a0.a85; result += a0.a86; result += a0.a87; result += a0.a88; result += a0.a89; result += a0.a90; result += a0.a91; result += a0.a92; result += a0.a93; result += a0.a94; result += a0.a95; result += a0.a96; result += a0.a97; result += a0.a98; result += a0.a99; result += a0.a100; result += a0.a101; result += a0.a102; result += a0.a103; result += a0.a104; result += a0.a105; result += a0.a106; result += a0.a107; result += a0.a108; result += a0.a109; result += a0.a110; result += a0.a111; result += a0.a112; result += a0.a113; result += a0.a114; result += a0.a115; result += a0.a116; result += a0.a117; result += a0.a118; result += a0.a119; result += a0.a120; result += a0.a121; result += a0.a122; result += a0.a123; result += a0.a124; result += a0.a125; result += a0.a126; result += a0.a127; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Tests the alignment of structs in FPU registers and backfilling. DART_EXPORT float PassFloatStruct16BytesHomogeneousFloatFloatStruct1( float a0, Struct16BytesHomogeneousFloat a1, float a2, Struct16BytesHomogeneousFloat a3, float a4, Struct16BytesHomogeneousFloat a5, float a6, Struct16BytesHomogeneousFloat a7, float a8) { std::cout << "PassFloatStruct16BytesHomogeneousFloatFloatStruct1" << "(" << a0 << ", (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << "), " << a2 << ", (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << "), " << a4 << ", (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), " << a6 << ", (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3 << "), " << a8 << ")" << "\n"; float result = 0; result += a0; result += a1.a0; result += a1.a1; result += a1.a2; result += a1.a3; result += a2; result += a3.a0; result += a3.a1; result += a3.a2; result += a3.a3; result += a4; result += a5.a0; result += a5.a1; result += a5.a2; result += a5.a3; result += a6; result += a7.a0; result += a7.a1; result += a7.a2; result += a7.a3; result += a8; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Tests the alignment of structs in FPU registers and backfilling. DART_EXPORT double PassFloatStruct32BytesHomogeneousDoubleFloatStruct( float a0, Struct32BytesHomogeneousDouble a1, float a2, Struct32BytesHomogeneousDouble a3, float a4, Struct32BytesHomogeneousDouble a5, float a6, Struct32BytesHomogeneousDouble a7, float a8) { std::cout << "PassFloatStruct32BytesHomogeneousDoubleFloatStruct" << "(" << a0 << ", (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << "), " << a2 << ", (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << "), " << a4 << ", (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), " << a6 << ", (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3 << "), " << a8 << ")" << "\n"; double result = 0; result += a0; result += a1.a0; result += a1.a1; result += a1.a2; result += a1.a3; result += a2; result += a3.a0; result += a3.a1; result += a3.a2; result += a3.a3; result += a4; result += a5.a0; result += a5.a1; result += a5.a2; result += a5.a3; result += a6; result += a7.a0; result += a7.a1; result += a7.a2; result += a7.a3; result += a8; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT double PassInt8Struct16BytesMixedInt8Struct16BytesMixedIn( int8_t a0, Struct16BytesMixed a1, int8_t a2, Struct16BytesMixed a3, int8_t a4, Struct16BytesMixed a5, int8_t a6, Struct16BytesMixed a7, int8_t a8) { std::cout << "PassInt8Struct16BytesMixedInt8Struct16BytesMixedIn" << "(" << static_cast(a0) << ", (" << a1.a0 << ", " << a1.a1 << "), " << static_cast(a2) << ", (" << a3.a0 << ", " << a3.a1 << "), " << static_cast(a4) << ", (" << a5.a0 << ", " << a5.a1 << "), " << static_cast(a6) << ", (" << a7.a0 << ", " << a7.a1 << "), " << static_cast(a8) << ")" << "\n"; double result = 0; result += a0; result += a1.a0; result += a1.a1; result += a2; result += a3.a0; result += a3.a1; result += a4; result += a5.a0; result += a5.a1; result += a6; result += a7.a0; result += a7.a1; result += a8; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT double PassDoublex6Struct16BytesMixedx4Int32(double a0, double a1, double a2, double a3, double a4, double a5, Struct16BytesMixed a6, Struct16BytesMixed a7, Struct16BytesMixed a8, Struct16BytesMixed a9, int32_t a10) { std::cout << "PassDoublex6Struct16BytesMixedx4Int32" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ", " << a5 << ", (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "), " << a10 << ")" << "\n"; double result = 0; result += a0; result += a1; result += a2; result += a3; result += a4; result += a5; result += a6.a0; result += a6.a1; result += a7.a0; result += a7.a1; result += a8.a0; result += a8.a1; result += a9.a0; result += a9.a1; result += a10; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT double PassInt32x4Struct16BytesMixedx4Double(int32_t a0, int32_t a1, int32_t a2, int32_t a3, Struct16BytesMixed a4, Struct16BytesMixed a5, Struct16BytesMixed a6, Struct16BytesMixed a7, double a8) { std::cout << "PassInt32x4Struct16BytesMixedx4Double" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", (" << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), " << a8 << ")" << "\n"; double result = 0; result += a0; result += a1; result += a2; result += a3; result += a4.a0; result += a4.a1; result += a5.a0; result += a5.a1; result += a6.a0; result += a6.a1; result += a7.a0; result += a7.a1; result += a8; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // On various architectures, first struct is allocated on stack. // Check that the other two arguments are allocated on registers. DART_EXPORT double PassStruct40BytesHomogeneousDoubleStruct4BytesHomo( Struct40BytesHomogeneousDouble a0, Struct4BytesHomogeneousInt16 a1, Struct8BytesHomogeneousFloat a2) { std::cout << "PassStruct40BytesHomogeneousDoubleStruct4BytesHomo" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << "), (" << a1.a0 << ", " << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "))" << "\n"; double result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a0.a4; result += a1.a0; result += a1.a1; result += a2.a0; result += a2.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of 16 byte int within struct. DART_EXPORT double PassInt32x8Doublex8Int64Int8Struct1ByteIntInt64Int( int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, double a8, double a9, double a10, double a11, double a12, double a13, double a14, double a15, int64_t a16, int8_t a17, Struct1ByteInt a18, int64_t a19, int8_t a20, Struct4BytesHomogeneousInt16 a21, int64_t a22, int8_t a23, Struct8BytesInt a24, int64_t a25, int8_t a26, Struct8BytesHomogeneousFloat a27, int64_t a28, int8_t a29, Struct8BytesMixed a30, int64_t a31, int8_t a32, StructAlignmentInt16 a33, int64_t a34, int8_t a35, StructAlignmentInt32 a36, int64_t a37, int8_t a38, StructAlignmentInt64 a39) { std::cout << "PassInt32x8Doublex8Int64Int8Struct1ByteIntInt64Int" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7 << ", " << a8 << ", " << a9 << ", " << a10 << ", " << a11 << ", " << a12 << ", " << a13 << ", " << a14 << ", " << a15 << ", " << a16 << ", " << static_cast(a17) << ", (" << static_cast(a18.a0) << "), " << a19 << ", " << static_cast(a20) << ", (" << a21.a0 << ", " << a21.a1 << "), " << a22 << ", " << static_cast(a23) << ", (" << a24.a0 << ", " << a24.a1 << ", " << a24.a2 << "), " << a25 << ", " << static_cast(a26) << ", (" << a27.a0 << ", " << a27.a1 << "), " << a28 << ", " << static_cast(a29) << ", (" << a30.a0 << ", " << a30.a1 << ", " << a30.a2 << "), " << a31 << ", " << static_cast(a32) << ", (" << static_cast(a33.a0) << ", " << a33.a1 << ", " << static_cast(a33.a2) << "), " << a34 << ", " << static_cast(a35) << ", (" << static_cast(a36.a0) << ", " << a36.a1 << ", " << static_cast(a36.a2) << "), " << a37 << ", " << static_cast(a38) << ", (" << static_cast(a39.a0) << ", " << a39.a1 << ", " << static_cast(a39.a2) << "))" << "\n"; double result = 0; result += a0; result += a1; result += a2; result += a3; result += a4; result += a5; result += a6; result += a7; result += a8; result += a9; result += a10; result += a11; result += a12; result += a13; result += a14; result += a15; result += a16; result += a17; result += a18.a0; result += a19; result += a20; result += a21.a0; result += a21.a1; result += a22; result += a23; result += a24.a0; result += a24.a1; result += a24.a2; result += a25; result += a26; result += a27.a0; result += a27.a1; result += a28; result += a29; result += a30.a0; result += a30.a1; result += a30.a2; result += a31; result += a32; result += a33.a0; result += a33.a1; result += a33.a2; result += a34; result += a35; result += a36.a0; result += a36.a1; result += a36.a2; result += a37; result += a38; result += a39.a0; result += a39.a1; result += a39.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of 16 byte int within struct. DART_EXPORT int64_t PassStructAlignmentInt16(StructAlignmentInt16 a0) { std::cout << "PassStructAlignmentInt16" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of 32 byte int within struct. DART_EXPORT int64_t PassStructAlignmentInt32(StructAlignmentInt32 a0) { std::cout << "PassStructAlignmentInt32" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of 64 byte int within struct. DART_EXPORT int64_t PassStructAlignmentInt64(StructAlignmentInt64 a0) { std::cout << "PassStructAlignmentInt64" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Simple nested struct. No alignment gaps on any architectures. // 10 arguments exhaust registers on all platforms. DART_EXPORT int64_t PassStruct8BytesNestedIntx10(Struct8BytesNestedInt a0, Struct8BytesNestedInt a1, Struct8BytesNestedInt a2, Struct8BytesNestedInt a3, Struct8BytesNestedInt a4, Struct8BytesNestedInt a5, Struct8BytesNestedInt a6, Struct8BytesNestedInt a7, Struct8BytesNestedInt a8, Struct8BytesNestedInt a9) { std::cout << "PassStruct8BytesNestedIntx10" << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0 << ", " << a0.a1.a1 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << "), (" << a1.a1.a0 << ", " << a1.a1.a1 << ")), ((" << a2.a0.a0 << ", " << a2.a0.a1 << "), (" << a2.a1.a0 << ", " << a2.a1.a1 << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << "), (" << a3.a1.a0 << ", " << a3.a1.a1 << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1 << "), (" << a4.a1.a0 << ", " << a4.a1.a1 << ")), ((" << a5.a0.a0 << ", " << a5.a0.a1 << "), (" << a5.a1.a0 << ", " << a5.a1.a1 << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << "), (" << a6.a1.a0 << ", " << a6.a1.a1 << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1 << "), (" << a7.a1.a0 << ", " << a7.a1.a1 << ")), ((" << a8.a0.a0 << ", " << a8.a0.a1 << "), (" << a8.a1.a0 << ", " << a8.a1.a1 << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << "), (" << a9.a1.a0 << ", " << a9.a1.a1 << ")))" << "\n"; int64_t result = 0; result += a0.a0.a0; result += a0.a0.a1; result += a0.a1.a0; result += a0.a1.a1; result += a1.a0.a0; result += a1.a0.a1; result += a1.a1.a0; result += a1.a1.a1; result += a2.a0.a0; result += a2.a0.a1; result += a2.a1.a0; result += a2.a1.a1; result += a3.a0.a0; result += a3.a0.a1; result += a3.a1.a0; result += a3.a1.a1; result += a4.a0.a0; result += a4.a0.a1; result += a4.a1.a0; result += a4.a1.a1; result += a5.a0.a0; result += a5.a0.a1; result += a5.a1.a0; result += a5.a1.a1; result += a6.a0.a0; result += a6.a0.a1; result += a6.a1.a0; result += a6.a1.a1; result += a7.a0.a0; result += a7.a0.a1; result += a7.a1.a0; result += a7.a1.a1; result += a8.a0.a0; result += a8.a0.a1; result += a8.a1.a0; result += a8.a1.a1; result += a9.a0.a0; result += a9.a0.a1; result += a9.a1.a0; result += a9.a1.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Simple nested struct. No alignment gaps on any architectures. // 10 arguments exhaust fpu registers on all platforms. DART_EXPORT float PassStruct8BytesNestedFloatx10(Struct8BytesNestedFloat a0, Struct8BytesNestedFloat a1, Struct8BytesNestedFloat a2, Struct8BytesNestedFloat a3, Struct8BytesNestedFloat a4, Struct8BytesNestedFloat a5, Struct8BytesNestedFloat a6, Struct8BytesNestedFloat a7, Struct8BytesNestedFloat a8, Struct8BytesNestedFloat a9) { std::cout << "PassStruct8BytesNestedFloatx10" << "(((" << a0.a0.a0 << "), (" << a0.a1.a0 << ")), ((" << a1.a0.a0 << "), (" << a1.a1.a0 << ")), ((" << a2.a0.a0 << "), (" << a2.a1.a0 << ")), ((" << a3.a0.a0 << "), (" << a3.a1.a0 << ")), ((" << a4.a0.a0 << "), (" << a4.a1.a0 << ")), ((" << a5.a0.a0 << "), (" << a5.a1.a0 << ")), ((" << a6.a0.a0 << "), (" << a6.a1.a0 << ")), ((" << a7.a0.a0 << "), (" << a7.a1.a0 << ")), ((" << a8.a0.a0 << "), (" << a8.a1.a0 << ")), ((" << a9.a0.a0 << "), (" << a9.a1.a0 << ")))" << "\n"; float result = 0; result += a0.a0.a0; result += a0.a1.a0; result += a1.a0.a0; result += a1.a1.a0; result += a2.a0.a0; result += a2.a1.a0; result += a3.a0.a0; result += a3.a1.a0; result += a4.a0.a0; result += a4.a1.a0; result += a5.a0.a0; result += a5.a1.a0; result += a6.a0.a0; result += a6.a1.a0; result += a7.a0.a0; result += a7.a1.a0; result += a8.a0.a0; result += a8.a1.a0; result += a9.a0.a0; result += a9.a1.a0; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT float PassStruct8BytesNestedFloat2x10(Struct8BytesNestedFloat2 a0, Struct8BytesNestedFloat2 a1, Struct8BytesNestedFloat2 a2, Struct8BytesNestedFloat2 a3, Struct8BytesNestedFloat2 a4, Struct8BytesNestedFloat2 a5, Struct8BytesNestedFloat2 a6, Struct8BytesNestedFloat2 a7, Struct8BytesNestedFloat2 a8, Struct8BytesNestedFloat2 a9) { std::cout << "PassStruct8BytesNestedFloat2x10" << "(((" << a0.a0.a0 << "), " << a0.a1 << "), ((" << a1.a0.a0 << "), " << a1.a1 << "), ((" << a2.a0.a0 << "), " << a2.a1 << "), ((" << a3.a0.a0 << "), " << a3.a1 << "), ((" << a4.a0.a0 << "), " << a4.a1 << "), ((" << a5.a0.a0 << "), " << a5.a1 << "), ((" << a6.a0.a0 << "), " << a6.a1 << "), ((" << a7.a0.a0 << "), " << a7.a1 << "), ((" << a8.a0.a0 << "), " << a8.a1 << "), ((" << a9.a0.a0 << "), " << a9.a1 << "))" << "\n"; float result = 0; result += a0.a0.a0; result += a0.a1; result += a1.a0.a0; result += a1.a1; result += a2.a0.a0; result += a2.a1; result += a3.a0.a0; result += a3.a1; result += a4.a0.a0; result += a4.a1; result += a5.a0.a0; result += a5.a1; result += a6.a0.a0; result += a6.a1; result += a7.a0.a0; result += a7.a1; result += a8.a0.a0; result += a8.a1; result += a9.a0.a0; result += a9.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Simple nested struct. No alignment gaps on any architectures. // 10 arguments exhaust all registers on all platforms. DART_EXPORT double PassStruct8BytesNestedMixedx10(Struct8BytesNestedMixed a0, Struct8BytesNestedMixed a1, Struct8BytesNestedMixed a2, Struct8BytesNestedMixed a3, Struct8BytesNestedMixed a4, Struct8BytesNestedMixed a5, Struct8BytesNestedMixed a6, Struct8BytesNestedMixed a7, Struct8BytesNestedMixed a8, Struct8BytesNestedMixed a9) { std::cout << "PassStruct8BytesNestedMixedx10" << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << "), (" << a1.a1.a0 << ")), ((" << a2.a0.a0 << ", " << a2.a0.a1 << "), (" << a2.a1.a0 << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << "), (" << a3.a1.a0 << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1 << "), (" << a4.a1.a0 << ")), ((" << a5.a0.a0 << ", " << a5.a0.a1 << "), (" << a5.a1.a0 << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << "), (" << a6.a1.a0 << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1 << "), (" << a7.a1.a0 << ")), ((" << a8.a0.a0 << ", " << a8.a0.a1 << "), (" << a8.a1.a0 << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << "), (" << a9.a1.a0 << ")))" << "\n"; double result = 0; result += a0.a0.a0; result += a0.a0.a1; result += a0.a1.a0; result += a1.a0.a0; result += a1.a0.a1; result += a1.a1.a0; result += a2.a0.a0; result += a2.a0.a1; result += a2.a1.a0; result += a3.a0.a0; result += a3.a0.a1; result += a3.a1.a0; result += a4.a0.a0; result += a4.a0.a1; result += a4.a1.a0; result += a5.a0.a0; result += a5.a0.a1; result += a5.a1.a0; result += a6.a0.a0; result += a6.a0.a1; result += a6.a1.a0; result += a7.a0.a0; result += a7.a0.a1; result += a7.a1.a0; result += a8.a0.a0; result += a8.a0.a1; result += a8.a1.a0; result += a9.a0.a0; result += a9.a0.a1; result += a9.a1.a0; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Deeper nested struct to test recursive member access. DART_EXPORT int64_t PassStruct16BytesNestedIntx2(Struct16BytesNestedInt a0, Struct16BytesNestedInt a1) { std::cout << "PassStruct16BytesNestedIntx2" << "((((" << a0.a0.a0.a0 << ", " << a0.a0.a0.a1 << "), (" << a0.a0.a1.a0 << ", " << a0.a0.a1.a1 << ")), ((" << a0.a1.a0.a0 << ", " << a0.a1.a0.a1 << "), (" << a0.a1.a1.a0 << ", " << a0.a1.a1.a1 << "))), (((" << a1.a0.a0.a0 << ", " << a1.a0.a0.a1 << "), (" << a1.a0.a1.a0 << ", " << a1.a0.a1.a1 << ")), ((" << a1.a1.a0.a0 << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0 << ", " << a1.a1.a1.a1 << "))))" << "\n"; int64_t result = 0; result += a0.a0.a0.a0; result += a0.a0.a0.a1; result += a0.a0.a1.a0; result += a0.a0.a1.a1; result += a0.a1.a0.a0; result += a0.a1.a0.a1; result += a0.a1.a1.a0; result += a0.a1.a1.a1; result += a1.a0.a0.a0; result += a1.a0.a0.a1; result += a1.a0.a1.a0; result += a1.a0.a1.a1; result += a1.a1.a0.a0; result += a1.a1.a0.a1; result += a1.a1.a1.a0; result += a1.a1.a1.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Even deeper nested struct to test recursive member access. DART_EXPORT int64_t PassStruct32BytesNestedIntx2(Struct32BytesNestedInt a0, Struct32BytesNestedInt a1) { std::cout << "PassStruct32BytesNestedIntx2" << "(((((" << a0.a0.a0.a0.a0 << ", " << a0.a0.a0.a0.a1 << "), (" << a0.a0.a0.a1.a0 << ", " << a0.a0.a0.a1.a1 << ")), ((" << a0.a0.a1.a0.a0 << ", " << a0.a0.a1.a0.a1 << "), (" << a0.a0.a1.a1.a0 << ", " << a0.a0.a1.a1.a1 << "))), (((" << a0.a1.a0.a0.a0 << ", " << a0.a1.a0.a0.a1 << "), (" << a0.a1.a0.a1.a0 << ", " << a0.a1.a0.a1.a1 << ")), ((" << a0.a1.a1.a0.a0 << ", " << a0.a1.a1.a0.a1 << "), (" << a0.a1.a1.a1.a0 << ", " << a0.a1.a1.a1.a1 << ")))), ((((" << a1.a0.a0.a0.a0 << ", " << a1.a0.a0.a0.a1 << "), (" << a1.a0.a0.a1.a0 << ", " << a1.a0.a0.a1.a1 << ")), ((" << a1.a0.a1.a0.a0 << ", " << a1.a0.a1.a0.a1 << "), (" << a1.a0.a1.a1.a0 << ", " << a1.a0.a1.a1.a1 << "))), (((" << a1.a1.a0.a0.a0 << ", " << a1.a1.a0.a0.a1 << "), (" << a1.a1.a0.a1.a0 << ", " << a1.a1.a0.a1.a1 << ")), ((" << a1.a1.a1.a0.a0 << ", " << a1.a1.a1.a0.a1 << "), (" << a1.a1.a1.a1.a0 << ", " << a1.a1.a1.a1.a1 << ")))))" << "\n"; int64_t result = 0; result += a0.a0.a0.a0.a0; result += a0.a0.a0.a0.a1; result += a0.a0.a0.a1.a0; result += a0.a0.a0.a1.a1; result += a0.a0.a1.a0.a0; result += a0.a0.a1.a0.a1; result += a0.a0.a1.a1.a0; result += a0.a0.a1.a1.a1; result += a0.a1.a0.a0.a0; result += a0.a1.a0.a0.a1; result += a0.a1.a0.a1.a0; result += a0.a1.a0.a1.a1; result += a0.a1.a1.a0.a0; result += a0.a1.a1.a0.a1; result += a0.a1.a1.a1.a0; result += a0.a1.a1.a1.a1; result += a1.a0.a0.a0.a0; result += a1.a0.a0.a0.a1; result += a1.a0.a0.a1.a0; result += a1.a0.a0.a1.a1; result += a1.a0.a1.a0.a0; result += a1.a0.a1.a0.a1; result += a1.a0.a1.a1.a0; result += a1.a0.a1.a1.a1; result += a1.a1.a0.a0.a0; result += a1.a1.a0.a0.a1; result += a1.a1.a0.a1.a0; result += a1.a1.a0.a1.a1; result += a1.a1.a1.a0.a0; result += a1.a1.a1.a0.a1; result += a1.a1.a1.a1.a0; result += a1.a1.a1.a1.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 16 byte int. DART_EXPORT int64_t PassStructNestedIntStructAlignmentInt16( StructNestedIntStructAlignmentInt16 a0) { std::cout << "PassStructNestedIntStructAlignmentInt16" << "(((" << static_cast(a0.a0.a0) << ", " << a0.a0.a1 << ", " << static_cast(a0.a0.a2) << "), (" << static_cast(a0.a1.a0) << ", " << a0.a1.a1 << ", " << static_cast(a0.a1.a2) << ")))" << "\n"; int64_t result = 0; result += a0.a0.a0; result += a0.a0.a1; result += a0.a0.a2; result += a0.a1.a0; result += a0.a1.a1; result += a0.a1.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 32 byte int. DART_EXPORT int64_t PassStructNestedIntStructAlignmentInt32( StructNestedIntStructAlignmentInt32 a0) { std::cout << "PassStructNestedIntStructAlignmentInt32" << "(((" << static_cast(a0.a0.a0) << ", " << a0.a0.a1 << ", " << static_cast(a0.a0.a2) << "), (" << static_cast(a0.a1.a0) << ", " << a0.a1.a1 << ", " << static_cast(a0.a1.a2) << ")))" << "\n"; int64_t result = 0; result += a0.a0.a0; result += a0.a0.a1; result += a0.a0.a2; result += a0.a1.a0; result += a0.a1.a1; result += a0.a1.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 64 byte int. DART_EXPORT int64_t PassStructNestedIntStructAlignmentInt64( StructNestedIntStructAlignmentInt64 a0) { std::cout << "PassStructNestedIntStructAlignmentInt64" << "(((" << static_cast(a0.a0.a0) << ", " << a0.a0.a1 << ", " << static_cast(a0.a0.a2) << "), (" << static_cast(a0.a1.a0) << ", " << a0.a1.a1 << ", " << static_cast(a0.a1.a2) << ")))" << "\n"; int64_t result = 0; result += a0.a0.a0; result += a0.a0.a1; result += a0.a0.a2; result += a0.a1.a0; result += a0.a1.a1; result += a0.a1.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Return big irregular struct as smoke test. DART_EXPORT double PassStructNestedIrregularEvenBiggerx4( StructNestedIrregularEvenBigger a0, StructNestedIrregularEvenBigger a1, StructNestedIrregularEvenBigger a2, StructNestedIrregularEvenBigger a3) { std::cout << "PassStructNestedIrregularEvenBiggerx4" << "((" << a0.a0 << ", ((" << a0.a1.a0.a0 << ", ((" << a0.a1.a0.a1.a0.a0 << ", " << a0.a1.a0.a1.a0.a1 << "), (" << a0.a1.a0.a1.a1.a0 << ")), " << a0.a1.a0.a2 << ", ((" << a0.a1.a0.a3.a0.a0 << "), " << a0.a1.a0.a3.a1 << "), " << a0.a1.a0.a4 << ", ((" << a0.a1.a0.a5.a0.a0 << "), (" << a0.a1.a0.a5.a1.a0 << ")), " << a0.a1.a0.a6 << "), ((" << a0.a1.a1.a0.a0 << ", " << a0.a1.a1.a0.a1 << "), (" << a0.a1.a1.a1.a0 << ")), " << a0.a1.a2 << ", " << a0.a1.a3 << "), ((" << a0.a2.a0.a0 << ", ((" << a0.a2.a0.a1.a0.a0 << ", " << a0.a2.a0.a1.a0.a1 << "), (" << a0.a2.a0.a1.a1.a0 << ")), " << a0.a2.a0.a2 << ", ((" << a0.a2.a0.a3.a0.a0 << "), " << a0.a2.a0.a3.a1 << "), " << a0.a2.a0.a4 << ", ((" << a0.a2.a0.a5.a0.a0 << "), (" << a0.a2.a0.a5.a1.a0 << ")), " << a0.a2.a0.a6 << "), ((" << a0.a2.a1.a0.a0 << ", " << a0.a2.a1.a0.a1 << "), (" << a0.a2.a1.a1.a0 << ")), " << a0.a2.a2 << ", " << a0.a2.a3 << "), " << a0.a3 << "), (" << a1.a0 << ", ((" << a1.a1.a0.a0 << ", ((" << a1.a1.a0.a1.a0.a0 << ", " << a1.a1.a0.a1.a0.a1 << "), (" << a1.a1.a0.a1.a1.a0 << ")), " << a1.a1.a0.a2 << ", ((" << a1.a1.a0.a3.a0.a0 << "), " << a1.a1.a0.a3.a1 << "), " << a1.a1.a0.a4 << ", ((" << a1.a1.a0.a5.a0.a0 << "), (" << a1.a1.a0.a5.a1.a0 << ")), " << a1.a1.a0.a6 << "), ((" << a1.a1.a1.a0.a0 << ", " << a1.a1.a1.a0.a1 << "), (" << a1.a1.a1.a1.a0 << ")), " << a1.a1.a2 << ", " << a1.a1.a3 << "), ((" << a1.a2.a0.a0 << ", ((" << a1.a2.a0.a1.a0.a0 << ", " << a1.a2.a0.a1.a0.a1 << "), (" << a1.a2.a0.a1.a1.a0 << ")), " << a1.a2.a0.a2 << ", ((" << a1.a2.a0.a3.a0.a0 << "), " << a1.a2.a0.a3.a1 << "), " << a1.a2.a0.a4 << ", ((" << a1.a2.a0.a5.a0.a0 << "), (" << a1.a2.a0.a5.a1.a0 << ")), " << a1.a2.a0.a6 << "), ((" << a1.a2.a1.a0.a0 << ", " << a1.a2.a1.a0.a1 << "), (" << a1.a2.a1.a1.a0 << ")), " << a1.a2.a2 << ", " << a1.a2.a3 << "), " << a1.a3 << "), (" << a2.a0 << ", ((" << a2.a1.a0.a0 << ", ((" << a2.a1.a0.a1.a0.a0 << ", " << a2.a1.a0.a1.a0.a1 << "), (" << a2.a1.a0.a1.a1.a0 << ")), " << a2.a1.a0.a2 << ", ((" << a2.a1.a0.a3.a0.a0 << "), " << a2.a1.a0.a3.a1 << "), " << a2.a1.a0.a4 << ", ((" << a2.a1.a0.a5.a0.a0 << "), (" << a2.a1.a0.a5.a1.a0 << ")), " << a2.a1.a0.a6 << "), ((" << a2.a1.a1.a0.a0 << ", " << a2.a1.a1.a0.a1 << "), (" << a2.a1.a1.a1.a0 << ")), " << a2.a1.a2 << ", " << a2.a1.a3 << "), ((" << a2.a2.a0.a0 << ", ((" << a2.a2.a0.a1.a0.a0 << ", " << a2.a2.a0.a1.a0.a1 << "), (" << a2.a2.a0.a1.a1.a0 << ")), " << a2.a2.a0.a2 << ", ((" << a2.a2.a0.a3.a0.a0 << "), " << a2.a2.a0.a3.a1 << "), " << a2.a2.a0.a4 << ", ((" << a2.a2.a0.a5.a0.a0 << "), (" << a2.a2.a0.a5.a1.a0 << ")), " << a2.a2.a0.a6 << "), ((" << a2.a2.a1.a0.a0 << ", " << a2.a2.a1.a0.a1 << "), (" << a2.a2.a1.a1.a0 << ")), " << a2.a2.a2 << ", " << a2.a2.a3 << "), " << a2.a3 << "), (" << a3.a0 << ", ((" << a3.a1.a0.a0 << ", ((" << a3.a1.a0.a1.a0.a0 << ", " << a3.a1.a0.a1.a0.a1 << "), (" << a3.a1.a0.a1.a1.a0 << ")), " << a3.a1.a0.a2 << ", ((" << a3.a1.a0.a3.a0.a0 << "), " << a3.a1.a0.a3.a1 << "), " << a3.a1.a0.a4 << ", ((" << a3.a1.a0.a5.a0.a0 << "), (" << a3.a1.a0.a5.a1.a0 << ")), " << a3.a1.a0.a6 << "), ((" << a3.a1.a1.a0.a0 << ", " << a3.a1.a1.a0.a1 << "), (" << a3.a1.a1.a1.a0 << ")), " << a3.a1.a2 << ", " << a3.a1.a3 << "), ((" << a3.a2.a0.a0 << ", ((" << a3.a2.a0.a1.a0.a0 << ", " << a3.a2.a0.a1.a0.a1 << "), (" << a3.a2.a0.a1.a1.a0 << ")), " << a3.a2.a0.a2 << ", ((" << a3.a2.a0.a3.a0.a0 << "), " << a3.a2.a0.a3.a1 << "), " << a3.a2.a0.a4 << ", ((" << a3.a2.a0.a5.a0.a0 << "), (" << a3.a2.a0.a5.a1.a0 << ")), " << a3.a2.a0.a6 << "), ((" << a3.a2.a1.a0.a0 << ", " << a3.a2.a1.a0.a1 << "), (" << a3.a2.a1.a1.a0 << ")), " << a3.a2.a2 << ", " << a3.a2.a3 << "), " << a3.a3 << "))" << "\n"; double result = 0; result += a0.a0; result += a0.a1.a0.a0; result += a0.a1.a0.a1.a0.a0; result += a0.a1.a0.a1.a0.a1; result += a0.a1.a0.a1.a1.a0; result += a0.a1.a0.a2; result += a0.a1.a0.a3.a0.a0; result += a0.a1.a0.a3.a1; result += a0.a1.a0.a4; result += a0.a1.a0.a5.a0.a0; result += a0.a1.a0.a5.a1.a0; result += a0.a1.a0.a6; result += a0.a1.a1.a0.a0; result += a0.a1.a1.a0.a1; result += a0.a1.a1.a1.a0; result += a0.a1.a2; result += a0.a1.a3; result += a0.a2.a0.a0; result += a0.a2.a0.a1.a0.a0; result += a0.a2.a0.a1.a0.a1; result += a0.a2.a0.a1.a1.a0; result += a0.a2.a0.a2; result += a0.a2.a0.a3.a0.a0; result += a0.a2.a0.a3.a1; result += a0.a2.a0.a4; result += a0.a2.a0.a5.a0.a0; result += a0.a2.a0.a5.a1.a0; result += a0.a2.a0.a6; result += a0.a2.a1.a0.a0; result += a0.a2.a1.a0.a1; result += a0.a2.a1.a1.a0; result += a0.a2.a2; result += a0.a2.a3; result += a0.a3; result += a1.a0; result += a1.a1.a0.a0; result += a1.a1.a0.a1.a0.a0; result += a1.a1.a0.a1.a0.a1; result += a1.a1.a0.a1.a1.a0; result += a1.a1.a0.a2; result += a1.a1.a0.a3.a0.a0; result += a1.a1.a0.a3.a1; result += a1.a1.a0.a4; result += a1.a1.a0.a5.a0.a0; result += a1.a1.a0.a5.a1.a0; result += a1.a1.a0.a6; result += a1.a1.a1.a0.a0; result += a1.a1.a1.a0.a1; result += a1.a1.a1.a1.a0; result += a1.a1.a2; result += a1.a1.a3; result += a1.a2.a0.a0; result += a1.a2.a0.a1.a0.a0; result += a1.a2.a0.a1.a0.a1; result += a1.a2.a0.a1.a1.a0; result += a1.a2.a0.a2; result += a1.a2.a0.a3.a0.a0; result += a1.a2.a0.a3.a1; result += a1.a2.a0.a4; result += a1.a2.a0.a5.a0.a0; result += a1.a2.a0.a5.a1.a0; result += a1.a2.a0.a6; result += a1.a2.a1.a0.a0; result += a1.a2.a1.a0.a1; result += a1.a2.a1.a1.a0; result += a1.a2.a2; result += a1.a2.a3; result += a1.a3; result += a2.a0; result += a2.a1.a0.a0; result += a2.a1.a0.a1.a0.a0; result += a2.a1.a0.a1.a0.a1; result += a2.a1.a0.a1.a1.a0; result += a2.a1.a0.a2; result += a2.a1.a0.a3.a0.a0; result += a2.a1.a0.a3.a1; result += a2.a1.a0.a4; result += a2.a1.a0.a5.a0.a0; result += a2.a1.a0.a5.a1.a0; result += a2.a1.a0.a6; result += a2.a1.a1.a0.a0; result += a2.a1.a1.a0.a1; result += a2.a1.a1.a1.a0; result += a2.a1.a2; result += a2.a1.a3; result += a2.a2.a0.a0; result += a2.a2.a0.a1.a0.a0; result += a2.a2.a0.a1.a0.a1; result += a2.a2.a0.a1.a1.a0; result += a2.a2.a0.a2; result += a2.a2.a0.a3.a0.a0; result += a2.a2.a0.a3.a1; result += a2.a2.a0.a4; result += a2.a2.a0.a5.a0.a0; result += a2.a2.a0.a5.a1.a0; result += a2.a2.a0.a6; result += a2.a2.a1.a0.a0; result += a2.a2.a1.a0.a1; result += a2.a2.a1.a1.a0; result += a2.a2.a2; result += a2.a2.a3; result += a2.a3; result += a3.a0; result += a3.a1.a0.a0; result += a3.a1.a0.a1.a0.a0; result += a3.a1.a0.a1.a0.a1; result += a3.a1.a0.a1.a1.a0; result += a3.a1.a0.a2; result += a3.a1.a0.a3.a0.a0; result += a3.a1.a0.a3.a1; result += a3.a1.a0.a4; result += a3.a1.a0.a5.a0.a0; result += a3.a1.a0.a5.a1.a0; result += a3.a1.a0.a6; result += a3.a1.a1.a0.a0; result += a3.a1.a1.a0.a1; result += a3.a1.a1.a1.a0; result += a3.a1.a2; result += a3.a1.a3; result += a3.a2.a0.a0; result += a3.a2.a0.a1.a0.a0; result += a3.a2.a0.a1.a0.a1; result += a3.a2.a0.a1.a1.a0; result += a3.a2.a0.a2; result += a3.a2.a0.a3.a0.a0; result += a3.a2.a0.a3.a1; result += a3.a2.a0.a4; result += a3.a2.a0.a5.a0.a0; result += a3.a2.a0.a5.a1.a0; result += a3.a2.a0.a6; result += a3.a2.a1.a0.a0; result += a3.a2.a1.a0.a1; result += a3.a2.a1.a1.a0; result += a3.a2.a2; result += a3.a2.a3; result += a3.a3; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Simple struct with inline array. DART_EXPORT int32_t PassStruct8BytesInlineArrayIntx4(Struct8BytesInlineArrayInt a0, Struct8BytesInlineArrayInt a1, Struct8BytesInlineArrayInt a2, Struct8BytesInlineArrayInt a3) { std::cout << "PassStruct8BytesInlineArrayIntx4" << "(([" << static_cast(a0.a0[0]) << ", " << static_cast(a0.a0[1]) << ", " << static_cast(a0.a0[2]) << ", " << static_cast(a0.a0[3]) << ", " << static_cast(a0.a0[4]) << ", " << static_cast(a0.a0[5]) << ", " << static_cast(a0.a0[6]) << ", " << static_cast(a0.a0[7]) << "]), ([" << static_cast(a1.a0[0]) << ", " << static_cast(a1.a0[1]) << ", " << static_cast(a1.a0[2]) << ", " << static_cast(a1.a0[3]) << ", " << static_cast(a1.a0[4]) << ", " << static_cast(a1.a0[5]) << ", " << static_cast(a1.a0[6]) << ", " << static_cast(a1.a0[7]) << "]), ([" << static_cast(a2.a0[0]) << ", " << static_cast(a2.a0[1]) << ", " << static_cast(a2.a0[2]) << ", " << static_cast(a2.a0[3]) << ", " << static_cast(a2.a0[4]) << ", " << static_cast(a2.a0[5]) << ", " << static_cast(a2.a0[6]) << ", " << static_cast(a2.a0[7]) << "]), ([" << static_cast(a3.a0[0]) << ", " << static_cast(a3.a0[1]) << ", " << static_cast(a3.a0[2]) << ", " << static_cast(a3.a0[3]) << ", " << static_cast(a3.a0[4]) << ", " << static_cast(a3.a0[5]) << ", " << static_cast(a3.a0[6]) << ", " << static_cast(a3.a0[7]) << "]))" << "\n"; int32_t result = 0; result += a0.a0[0]; result += a0.a0[1]; result += a0.a0[2]; result += a0.a0[3]; result += a0.a0[4]; result += a0.a0[5]; result += a0.a0[6]; result += a0.a0[7]; result += a1.a0[0]; result += a1.a0[1]; result += a1.a0[2]; result += a1.a0[3]; result += a1.a0[4]; result += a1.a0[5]; result += a1.a0[6]; result += a1.a0[7]; result += a2.a0[0]; result += a2.a0[1]; result += a2.a0[2]; result += a2.a0[3]; result += a2.a0[4]; result += a2.a0[5]; result += a2.a0[6]; result += a2.a0[7]; result += a3.a0[0]; result += a3.a0[1]; result += a3.a0[2]; result += a3.a0[3]; result += a3.a0[4]; result += a3.a0[5]; result += a3.a0[6]; result += a3.a0[7]; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Irregular struct with inline array. DART_EXPORT int32_t PassStructInlineArrayIrregularx4(StructInlineArrayIrregular a0, StructInlineArrayIrregular a1, StructInlineArrayIrregular a2, StructInlineArrayIrregular a3) { std::cout << "PassStructInlineArrayIrregularx4" << "(([(" << a0.a0[0].a0 << ", " << static_cast(a0.a0[0].a1) << "), (" << a0.a0[1].a0 << ", " << static_cast(a0.a0[1].a1) << ")], " << static_cast(a0.a1) << "), ([(" << a1.a0[0].a0 << ", " << static_cast(a1.a0[0].a1) << "), (" << a1.a0[1].a0 << ", " << static_cast(a1.a0[1].a1) << ")], " << static_cast(a1.a1) << "), ([(" << a2.a0[0].a0 << ", " << static_cast(a2.a0[0].a1) << "), (" << a2.a0[1].a0 << ", " << static_cast(a2.a0[1].a1) << ")], " << static_cast(a2.a1) << "), ([(" << a3.a0[0].a0 << ", " << static_cast(a3.a0[0].a1) << "), (" << a3.a0[1].a0 << ", " << static_cast(a3.a0[1].a1) << ")], " << static_cast(a3.a1) << "))" << "\n"; int32_t result = 0; result += a0.a0[0].a0; result += a0.a0[0].a1; result += a0.a0[1].a0; result += a0.a0[1].a1; result += a0.a1; result += a1.a0[0].a0; result += a1.a0[0].a1; result += a1.a0[1].a0; result += a1.a0[1].a1; result += a1.a1; result += a2.a0[0].a0; result += a2.a0[0].a1; result += a2.a0[1].a0; result += a2.a0[1].a1; result += a2.a1; result += a3.a0[0].a0; result += a3.a0[0].a1; result += a3.a0[1].a0; result += a3.a0[1].a1; result += a3.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Regular larger struct with inline array. DART_EXPORT int32_t PassStructInlineArray100Bytes(StructInlineArray100Bytes a0) { std::cout << "PassStructInlineArray100Bytes" << "(([" << static_cast(a0.a0[0]) << ", " << static_cast(a0.a0[1]) << ", " << static_cast(a0.a0[2]) << ", " << static_cast(a0.a0[3]) << ", " << static_cast(a0.a0[4]) << ", " << static_cast(a0.a0[5]) << ", " << static_cast(a0.a0[6]) << ", " << static_cast(a0.a0[7]) << ", " << static_cast(a0.a0[8]) << ", " << static_cast(a0.a0[9]) << ", " << static_cast(a0.a0[10]) << ", " << static_cast(a0.a0[11]) << ", " << static_cast(a0.a0[12]) << ", " << static_cast(a0.a0[13]) << ", " << static_cast(a0.a0[14]) << ", " << static_cast(a0.a0[15]) << ", " << static_cast(a0.a0[16]) << ", " << static_cast(a0.a0[17]) << ", " << static_cast(a0.a0[18]) << ", " << static_cast(a0.a0[19]) << ", " << static_cast(a0.a0[20]) << ", " << static_cast(a0.a0[21]) << ", " << static_cast(a0.a0[22]) << ", " << static_cast(a0.a0[23]) << ", " << static_cast(a0.a0[24]) << ", " << static_cast(a0.a0[25]) << ", " << static_cast(a0.a0[26]) << ", " << static_cast(a0.a0[27]) << ", " << static_cast(a0.a0[28]) << ", " << static_cast(a0.a0[29]) << ", " << static_cast(a0.a0[30]) << ", " << static_cast(a0.a0[31]) << ", " << static_cast(a0.a0[32]) << ", " << static_cast(a0.a0[33]) << ", " << static_cast(a0.a0[34]) << ", " << static_cast(a0.a0[35]) << ", " << static_cast(a0.a0[36]) << ", " << static_cast(a0.a0[37]) << ", " << static_cast(a0.a0[38]) << ", " << static_cast(a0.a0[39]) << ", " << static_cast(a0.a0[40]) << ", " << static_cast(a0.a0[41]) << ", " << static_cast(a0.a0[42]) << ", " << static_cast(a0.a0[43]) << ", " << static_cast(a0.a0[44]) << ", " << static_cast(a0.a0[45]) << ", " << static_cast(a0.a0[46]) << ", " << static_cast(a0.a0[47]) << ", " << static_cast(a0.a0[48]) << ", " << static_cast(a0.a0[49]) << ", " << static_cast(a0.a0[50]) << ", " << static_cast(a0.a0[51]) << ", " << static_cast(a0.a0[52]) << ", " << static_cast(a0.a0[53]) << ", " << static_cast(a0.a0[54]) << ", " << static_cast(a0.a0[55]) << ", " << static_cast(a0.a0[56]) << ", " << static_cast(a0.a0[57]) << ", " << static_cast(a0.a0[58]) << ", " << static_cast(a0.a0[59]) << ", " << static_cast(a0.a0[60]) << ", " << static_cast(a0.a0[61]) << ", " << static_cast(a0.a0[62]) << ", " << static_cast(a0.a0[63]) << ", " << static_cast(a0.a0[64]) << ", " << static_cast(a0.a0[65]) << ", " << static_cast(a0.a0[66]) << ", " << static_cast(a0.a0[67]) << ", " << static_cast(a0.a0[68]) << ", " << static_cast(a0.a0[69]) << ", " << static_cast(a0.a0[70]) << ", " << static_cast(a0.a0[71]) << ", " << static_cast(a0.a0[72]) << ", " << static_cast(a0.a0[73]) << ", " << static_cast(a0.a0[74]) << ", " << static_cast(a0.a0[75]) << ", " << static_cast(a0.a0[76]) << ", " << static_cast(a0.a0[77]) << ", " << static_cast(a0.a0[78]) << ", " << static_cast(a0.a0[79]) << ", " << static_cast(a0.a0[80]) << ", " << static_cast(a0.a0[81]) << ", " << static_cast(a0.a0[82]) << ", " << static_cast(a0.a0[83]) << ", " << static_cast(a0.a0[84]) << ", " << static_cast(a0.a0[85]) << ", " << static_cast(a0.a0[86]) << ", " << static_cast(a0.a0[87]) << ", " << static_cast(a0.a0[88]) << ", " << static_cast(a0.a0[89]) << ", " << static_cast(a0.a0[90]) << ", " << static_cast(a0.a0[91]) << ", " << static_cast(a0.a0[92]) << ", " << static_cast(a0.a0[93]) << ", " << static_cast(a0.a0[94]) << ", " << static_cast(a0.a0[95]) << ", " << static_cast(a0.a0[96]) << ", " << static_cast(a0.a0[97]) << ", " << static_cast(a0.a0[98]) << ", " << static_cast(a0.a0[99]) << "]))" << "\n"; int32_t result = 0; result += a0.a0[0]; result += a0.a0[1]; result += a0.a0[2]; result += a0.a0[3]; result += a0.a0[4]; result += a0.a0[5]; result += a0.a0[6]; result += a0.a0[7]; result += a0.a0[8]; result += a0.a0[9]; result += a0.a0[10]; result += a0.a0[11]; result += a0.a0[12]; result += a0.a0[13]; result += a0.a0[14]; result += a0.a0[15]; result += a0.a0[16]; result += a0.a0[17]; result += a0.a0[18]; result += a0.a0[19]; result += a0.a0[20]; result += a0.a0[21]; result += a0.a0[22]; result += a0.a0[23]; result += a0.a0[24]; result += a0.a0[25]; result += a0.a0[26]; result += a0.a0[27]; result += a0.a0[28]; result += a0.a0[29]; result += a0.a0[30]; result += a0.a0[31]; result += a0.a0[32]; result += a0.a0[33]; result += a0.a0[34]; result += a0.a0[35]; result += a0.a0[36]; result += a0.a0[37]; result += a0.a0[38]; result += a0.a0[39]; result += a0.a0[40]; result += a0.a0[41]; result += a0.a0[42]; result += a0.a0[43]; result += a0.a0[44]; result += a0.a0[45]; result += a0.a0[46]; result += a0.a0[47]; result += a0.a0[48]; result += a0.a0[49]; result += a0.a0[50]; result += a0.a0[51]; result += a0.a0[52]; result += a0.a0[53]; result += a0.a0[54]; result += a0.a0[55]; result += a0.a0[56]; result += a0.a0[57]; result += a0.a0[58]; result += a0.a0[59]; result += a0.a0[60]; result += a0.a0[61]; result += a0.a0[62]; result += a0.a0[63]; result += a0.a0[64]; result += a0.a0[65]; result += a0.a0[66]; result += a0.a0[67]; result += a0.a0[68]; result += a0.a0[69]; result += a0.a0[70]; result += a0.a0[71]; result += a0.a0[72]; result += a0.a0[73]; result += a0.a0[74]; result += a0.a0[75]; result += a0.a0[76]; result += a0.a0[77]; result += a0.a0[78]; result += a0.a0[79]; result += a0.a0[80]; result += a0.a0[81]; result += a0.a0[82]; result += a0.a0[83]; result += a0.a0[84]; result += a0.a0[85]; result += a0.a0[86]; result += a0.a0[87]; result += a0.a0[88]; result += a0.a0[89]; result += a0.a0[90]; result += a0.a0[91]; result += a0.a0[92]; result += a0.a0[93]; result += a0.a0[94]; result += a0.a0[95]; result += a0.a0[96]; result += a0.a0[97]; result += a0.a0[98]; result += a0.a0[99]; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Arguments in FPU registers on arm hardfp and arm64. // 5 struct arguments will exhaust available registers. DART_EXPORT float PassStructStruct16BytesHomogeneousFloat2x5( StructStruct16BytesHomogeneousFloat2 a0, StructStruct16BytesHomogeneousFloat2 a1, StructStruct16BytesHomogeneousFloat2 a2, StructStruct16BytesHomogeneousFloat2 a3, StructStruct16BytesHomogeneousFloat2 a4) { std::cout << "PassStructStruct16BytesHomogeneousFloat2x5" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << "), (" << a0.a1[1].a0 << ")], " << a0.a2 << "), ((" << a1.a0.a0 << "), [(" << a1.a1[0].a0 << "), (" << a1.a1[1].a0 << ")], " << a1.a2 << "), ((" << a2.a0.a0 << "), [(" << a2.a1[0].a0 << "), (" << a2.a1[1].a0 << ")], " << a2.a2 << "), ((" << a3.a0.a0 << "), [(" << a3.a1[0].a0 << "), (" << a3.a1[1].a0 << ")], " << a3.a2 << "), ((" << a4.a0.a0 << "), [(" << a4.a1[0].a0 << "), (" << a4.a1[1].a0 << ")], " << a4.a2 << "))" << "\n"; float result = 0; result += a0.a0.a0; result += a0.a1[0].a0; result += a0.a1[1].a0; result += a0.a2; result += a1.a0.a0; result += a1.a1[0].a0; result += a1.a1[1].a0; result += a1.a2; result += a2.a0.a0; result += a2.a1[0].a0; result += a2.a1[1].a0; result += a2.a2; result += a3.a0.a0; result += a3.a1[0].a0; result += a3.a1[1].a0; result += a3.a2; result += a4.a0.a0; result += a4.a1[0].a0; result += a4.a1[1].a0; result += a4.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Arguments in FPU registers on arm64. // 5 struct arguments will exhaust available registers. DART_EXPORT double PassStructStruct32BytesHomogeneousDouble2x5( StructStruct32BytesHomogeneousDouble2 a0, StructStruct32BytesHomogeneousDouble2 a1, StructStruct32BytesHomogeneousDouble2 a2, StructStruct32BytesHomogeneousDouble2 a3, StructStruct32BytesHomogeneousDouble2 a4) { std::cout << "PassStructStruct32BytesHomogeneousDouble2x5" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << "), (" << a0.a1[1].a0 << ")], " << a0.a2 << "), ((" << a1.a0.a0 << "), [(" << a1.a1[0].a0 << "), (" << a1.a1[1].a0 << ")], " << a1.a2 << "), ((" << a2.a0.a0 << "), [(" << a2.a1[0].a0 << "), (" << a2.a1[1].a0 << ")], " << a2.a2 << "), ((" << a3.a0.a0 << "), [(" << a3.a1[0].a0 << "), (" << a3.a1[1].a0 << ")], " << a3.a2 << "), ((" << a4.a0.a0 << "), [(" << a4.a1[0].a0 << "), (" << a4.a1[1].a0 << ")], " << a4.a2 << "))" << "\n"; double result = 0; result += a0.a0.a0; result += a0.a1[0].a0; result += a0.a1[1].a0; result += a0.a2; result += a1.a0.a0; result += a1.a1[0].a0; result += a1.a1[1].a0; result += a1.a2; result += a2.a0.a0; result += a2.a1[0].a0; result += a2.a1[1].a0; result += a2.a2; result += a3.a0.a0; result += a3.a1[0].a0; result += a3.a1[1].a0; result += a3.a2; result += a4.a0.a0; result += a4.a1[0].a0; result += a4.a1[1].a0; result += a4.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT float PassStructStruct16BytesMixed3x10( StructStruct16BytesMixed3 a0, StructStruct16BytesMixed3 a1, StructStruct16BytesMixed3 a2, StructStruct16BytesMixed3 a3, StructStruct16BytesMixed3 a4, StructStruct16BytesMixed3 a5, StructStruct16BytesMixed3 a6, StructStruct16BytesMixed3 a7, StructStruct16BytesMixed3 a8, StructStruct16BytesMixed3 a9) { std::cout << "PassStructStruct16BytesMixed3x10" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << ", " << a0.a1[0].a1 << ", " << a0.a1[0].a2 << ")], [" << a0.a2[0] << ", " << a0.a2[1] << "]), ((" << a1.a0.a0 << "), [(" << a1.a1[0].a0 << ", " << a1.a1[0].a1 << ", " << a1.a1[0].a2 << ")], [" << a1.a2[0] << ", " << a1.a2[1] << "]), ((" << a2.a0.a0 << "), [(" << a2.a1[0].a0 << ", " << a2.a1[0].a1 << ", " << a2.a1[0].a2 << ")], [" << a2.a2[0] << ", " << a2.a2[1] << "]), ((" << a3.a0.a0 << "), [(" << a3.a1[0].a0 << ", " << a3.a1[0].a1 << ", " << a3.a1[0].a2 << ")], [" << a3.a2[0] << ", " << a3.a2[1] << "]), ((" << a4.a0.a0 << "), [(" << a4.a1[0].a0 << ", " << a4.a1[0].a1 << ", " << a4.a1[0].a2 << ")], [" << a4.a2[0] << ", " << a4.a2[1] << "]), ((" << a5.a0.a0 << "), [(" << a5.a1[0].a0 << ", " << a5.a1[0].a1 << ", " << a5.a1[0].a2 << ")], [" << a5.a2[0] << ", " << a5.a2[1] << "]), ((" << a6.a0.a0 << "), [(" << a6.a1[0].a0 << ", " << a6.a1[0].a1 << ", " << a6.a1[0].a2 << ")], [" << a6.a2[0] << ", " << a6.a2[1] << "]), ((" << a7.a0.a0 << "), [(" << a7.a1[0].a0 << ", " << a7.a1[0].a1 << ", " << a7.a1[0].a2 << ")], [" << a7.a2[0] << ", " << a7.a2[1] << "]), ((" << a8.a0.a0 << "), [(" << a8.a1[0].a0 << ", " << a8.a1[0].a1 << ", " << a8.a1[0].a2 << ")], [" << a8.a2[0] << ", " << a8.a2[1] << "]), ((" << a9.a0.a0 << "), [(" << a9.a1[0].a0 << ", " << a9.a1[0].a1 << ", " << a9.a1[0].a2 << ")], [" << a9.a2[0] << ", " << a9.a2[1] << "]))" << "\n"; float result = 0; result += a0.a0.a0; result += a0.a1[0].a0; result += a0.a1[0].a1; result += a0.a1[0].a2; result += a0.a2[0]; result += a0.a2[1]; result += a1.a0.a0; result += a1.a1[0].a0; result += a1.a1[0].a1; result += a1.a1[0].a2; result += a1.a2[0]; result += a1.a2[1]; result += a2.a0.a0; result += a2.a1[0].a0; result += a2.a1[0].a1; result += a2.a1[0].a2; result += a2.a2[0]; result += a2.a2[1]; result += a3.a0.a0; result += a3.a1[0].a0; result += a3.a1[0].a1; result += a3.a1[0].a2; result += a3.a2[0]; result += a3.a2[1]; result += a4.a0.a0; result += a4.a1[0].a0; result += a4.a1[0].a1; result += a4.a1[0].a2; result += a4.a2[0]; result += a4.a2[1]; result += a5.a0.a0; result += a5.a1[0].a0; result += a5.a1[0].a1; result += a5.a1[0].a2; result += a5.a2[0]; result += a5.a2[1]; result += a6.a0.a0; result += a6.a1[0].a0; result += a6.a1[0].a1; result += a6.a1[0].a2; result += a6.a2[0]; result += a6.a2[1]; result += a7.a0.a0; result += a7.a1[0].a0; result += a7.a1[0].a1; result += a7.a1[0].a2; result += a7.a2[0]; result += a7.a2[1]; result += a8.a0.a0; result += a8.a1[0].a0; result += a8.a1[0].a1; result += a8.a1[0].a2; result += a8.a2[0]; result += a8.a2[1]; result += a9.a0.a0; result += a9.a1[0].a0; result += a9.a1[0].a1; result += a9.a1[0].a2; result += a9.a2[0]; result += a9.a2[1]; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Test multi dimensional inline array struct as argument. DART_EXPORT uint32_t PassUint8Struct32BytesInlineArrayMultiDimensionalI( uint8_t a0, Struct32BytesInlineArrayMultiDimensionalInt a1, uint8_t a2, Struct8BytesInlineArrayMultiDimensionalInt a3, uint8_t a4, Struct8BytesInlineArrayMultiDimensionalInt a5, uint8_t a6) { std::cout << "PassUint8Struct32BytesInlineArrayMultiDimensionalI" << "(" << static_cast(a0) << ", ([[[[[" << static_cast(a1.a0[0][0][0][0][0]) << ", " << static_cast(a1.a0[0][0][0][0][1]) << "], [" << static_cast(a1.a0[0][0][0][1][0]) << ", " << static_cast(a1.a0[0][0][0][1][1]) << "]], [[" << static_cast(a1.a0[0][0][1][0][0]) << ", " << static_cast(a1.a0[0][0][1][0][1]) << "], [" << static_cast(a1.a0[0][0][1][1][0]) << ", " << static_cast(a1.a0[0][0][1][1][1]) << "]]], [[[" << static_cast(a1.a0[0][1][0][0][0]) << ", " << static_cast(a1.a0[0][1][0][0][1]) << "], [" << static_cast(a1.a0[0][1][0][1][0]) << ", " << static_cast(a1.a0[0][1][0][1][1]) << "]], [[" << static_cast(a1.a0[0][1][1][0][0]) << ", " << static_cast(a1.a0[0][1][1][0][1]) << "], [" << static_cast(a1.a0[0][1][1][1][0]) << ", " << static_cast(a1.a0[0][1][1][1][1]) << "]]]], [[[[" << static_cast(a1.a0[1][0][0][0][0]) << ", " << static_cast(a1.a0[1][0][0][0][1]) << "], [" << static_cast(a1.a0[1][0][0][1][0]) << ", " << static_cast(a1.a0[1][0][0][1][1]) << "]], [[" << static_cast(a1.a0[1][0][1][0][0]) << ", " << static_cast(a1.a0[1][0][1][0][1]) << "], [" << static_cast(a1.a0[1][0][1][1][0]) << ", " << static_cast(a1.a0[1][0][1][1][1]) << "]]], [[[" << static_cast(a1.a0[1][1][0][0][0]) << ", " << static_cast(a1.a0[1][1][0][0][1]) << "], [" << static_cast(a1.a0[1][1][0][1][0]) << ", " << static_cast(a1.a0[1][1][0][1][1]) << "]], [[" << static_cast(a1.a0[1][1][1][0][0]) << ", " << static_cast(a1.a0[1][1][1][0][1]) << "], [" << static_cast(a1.a0[1][1][1][1][0]) << ", " << static_cast(a1.a0[1][1][1][1][1]) << "]]]]]), " << static_cast(a2) << ", ([[[" << static_cast(a3.a0[0][0][0]) << ", " << static_cast(a3.a0[0][0][1]) << "], [" << static_cast(a3.a0[0][1][0]) << ", " << static_cast(a3.a0[0][1][1]) << "]], [[" << static_cast(a3.a0[1][0][0]) << ", " << static_cast(a3.a0[1][0][1]) << "], [" << static_cast(a3.a0[1][1][0]) << ", " << static_cast(a3.a0[1][1][1]) << "]]]), " << static_cast(a4) << ", ([[[" << static_cast(a5.a0[0][0][0]) << ", " << static_cast(a5.a0[0][0][1]) << "], [" << static_cast(a5.a0[0][1][0]) << ", " << static_cast(a5.a0[0][1][1]) << "]], [[" << static_cast(a5.a0[1][0][0]) << ", " << static_cast(a5.a0[1][0][1]) << "], [" << static_cast(a5.a0[1][1][0]) << ", " << static_cast(a5.a0[1][1][1]) << "]]]), " << static_cast(a6) << ")" << "\n"; uint32_t result = 0; result += a0; result += a1.a0[0][0][0][0][0]; result += a1.a0[0][0][0][0][1]; result += a1.a0[0][0][0][1][0]; result += a1.a0[0][0][0][1][1]; result += a1.a0[0][0][1][0][0]; result += a1.a0[0][0][1][0][1]; result += a1.a0[0][0][1][1][0]; result += a1.a0[0][0][1][1][1]; result += a1.a0[0][1][0][0][0]; result += a1.a0[0][1][0][0][1]; result += a1.a0[0][1][0][1][0]; result += a1.a0[0][1][0][1][1]; result += a1.a0[0][1][1][0][0]; result += a1.a0[0][1][1][0][1]; result += a1.a0[0][1][1][1][0]; result += a1.a0[0][1][1][1][1]; result += a1.a0[1][0][0][0][0]; result += a1.a0[1][0][0][0][1]; result += a1.a0[1][0][0][1][0]; result += a1.a0[1][0][0][1][1]; result += a1.a0[1][0][1][0][0]; result += a1.a0[1][0][1][0][1]; result += a1.a0[1][0][1][1][0]; result += a1.a0[1][0][1][1][1]; result += a1.a0[1][1][0][0][0]; result += a1.a0[1][1][0][0][1]; result += a1.a0[1][1][0][1][0]; result += a1.a0[1][1][0][1][1]; result += a1.a0[1][1][1][0][0]; result += a1.a0[1][1][1][0][1]; result += a1.a0[1][1][1][1][0]; result += a1.a0[1][1][1][1][1]; result += a2; result += a3.a0[0][0][0]; result += a3.a0[0][0][1]; result += a3.a0[0][1][0]; result += a3.a0[0][1][1]; result += a3.a0[1][0][0]; result += a3.a0[1][0][1]; result += a3.a0[1][1][0]; result += a3.a0[1][1][1]; result += a4; result += a5.a0[0][0][0]; result += a5.a0[0][0][1]; result += a5.a0[0][1][0]; result += a5.a0[0][1][1]; result += a5.a0[1][0][0]; result += a5.a0[1][0][1]; result += a5.a0[1][1][0]; result += a5.a0[1][1][1]; result += a6; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Test struct in multi dimensional inline array. DART_EXPORT uint32_t PassUint8Struct4BytesInlineArrayMultiDimensionalIn( uint8_t a0, Struct4BytesInlineArrayMultiDimensionalInt a1, uint8_t a2) { std::cout << "PassUint8Struct4BytesInlineArrayMultiDimensionalIn" << "(" << static_cast(a0) << ", ([[(" << static_cast(a1.a0[0][0].a0) << "), (" << static_cast(a1.a0[0][1].a0) << ")], [(" << static_cast(a1.a0[1][0].a0) << "), (" << static_cast(a1.a0[1][1].a0) << ")]]), " << static_cast(a2) << ")" << "\n"; uint32_t result = 0; result += a0; result += a1.a0[0][0].a0; result += a1.a0[0][1].a0; result += a1.a0[1][0].a0; result += a1.a0[1][1].a0; result += a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Small struct with mis-aligned member. DART_EXPORT int64_t PassStruct3BytesPackedIntx10(Struct3BytesPackedInt a0, Struct3BytesPackedInt a1, Struct3BytesPackedInt a2, Struct3BytesPackedInt a3, Struct3BytesPackedInt a4, Struct3BytesPackedInt a5, Struct3BytesPackedInt a6, Struct3BytesPackedInt a7, Struct3BytesPackedInt a8, Struct3BytesPackedInt a9) { std::cout << "PassStruct3BytesPackedIntx10" << "((" << static_cast(a0.a0) << ", " << a0.a1 << "), (" << static_cast(a1.a0) << ", " << a1.a1 << "), (" << static_cast(a2.a0) << ", " << a2.a1 << "), (" << static_cast(a3.a0) << ", " << a3.a1 << "), (" << static_cast(a4.a0) << ", " << a4.a1 << "), (" << static_cast(a5.a0) << ", " << a5.a1 << "), (" << static_cast(a6.a0) << ", " << a6.a1 << "), (" << static_cast(a7.a0) << ", " << a7.a1 << "), (" << static_cast(a8.a0) << ", " << a8.a1 << "), (" << static_cast(a9.a0) << ", " << a9.a1 << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a1.a0; result += a1.a1; result += a2.a0; result += a2.a1; result += a3.a0; result += a3.a1; result += a4.a0; result += a4.a1; result += a5.a0; result += a5.a1; result += a6.a0; result += a6.a1; result += a7.a0; result += a7.a1; result += a8.a0; result += a8.a1; result += a9.a0; result += a9.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Struct with mis-aligned member. DART_EXPORT int64_t PassStruct8BytesPackedIntx10(Struct8BytesPackedInt a0, Struct8BytesPackedInt a1, Struct8BytesPackedInt a2, Struct8BytesPackedInt a3, Struct8BytesPackedInt a4, Struct8BytesPackedInt a5, Struct8BytesPackedInt a6, Struct8BytesPackedInt a7, Struct8BytesPackedInt a8, Struct8BytesPackedInt a9) { std::cout << "PassStruct8BytesPackedIntx10" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << ", " << static_cast(a0.a3) << ", " << static_cast(a0.a4) << "), (" << static_cast(a1.a0) << ", " << a1.a1 << ", " << static_cast(a1.a2) << ", " << static_cast(a1.a3) << ", " << static_cast(a1.a4) << "), (" << static_cast(a2.a0) << ", " << a2.a1 << ", " << static_cast(a2.a2) << ", " << static_cast(a2.a3) << ", " << static_cast(a2.a4) << "), (" << static_cast(a3.a0) << ", " << a3.a1 << ", " << static_cast(a3.a2) << ", " << static_cast(a3.a3) << ", " << static_cast(a3.a4) << "), (" << static_cast(a4.a0) << ", " << a4.a1 << ", " << static_cast(a4.a2) << ", " << static_cast(a4.a3) << ", " << static_cast(a4.a4) << "), (" << static_cast(a5.a0) << ", " << a5.a1 << ", " << static_cast(a5.a2) << ", " << static_cast(a5.a3) << ", " << static_cast(a5.a4) << "), (" << static_cast(a6.a0) << ", " << a6.a1 << ", " << static_cast(a6.a2) << ", " << static_cast(a6.a3) << ", " << static_cast(a6.a4) << "), (" << static_cast(a7.a0) << ", " << a7.a1 << ", " << static_cast(a7.a2) << ", " << static_cast(a7.a3) << ", " << static_cast(a7.a4) << "), (" << static_cast(a8.a0) << ", " << a8.a1 << ", " << static_cast(a8.a2) << ", " << static_cast(a8.a3) << ", " << static_cast(a8.a4) << "), (" << static_cast(a9.a0) << ", " << a9.a1 << ", " << static_cast(a9.a2) << ", " << static_cast(a9.a3) << ", " << static_cast(a9.a4) << "))" << "\n"; int64_t result = 0; result += a0.a0; result += a0.a1; result += a0.a2; result += a0.a3; result += a0.a4; result += a1.a0; result += a1.a1; result += a1.a2; result += a1.a3; result += a1.a4; result += a2.a0; result += a2.a1; result += a2.a2; result += a2.a3; result += a2.a4; result += a3.a0; result += a3.a1; result += a3.a2; result += a3.a3; result += a3.a4; result += a4.a0; result += a4.a1; result += a4.a2; result += a4.a3; result += a4.a4; result += a5.a0; result += a5.a1; result += a5.a2; result += a5.a3; result += a5.a4; result += a6.a0; result += a6.a1; result += a6.a2; result += a6.a3; result += a6.a4; result += a7.a0; result += a7.a1; result += a7.a2; result += a7.a3; result += a7.a4; result += a8.a0; result += a8.a1; result += a8.a2; result += a8.a3; result += a8.a4; result += a9.a0; result += a9.a1; result += a9.a2; result += a9.a3; result += a9.a4; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Struct with mis-aligned member. // Tests backfilling of CPU and FPU registers. DART_EXPORT double PassStruct9BytesPackedMixedx10DoubleInt32( Struct9BytesPackedMixed a0, Struct9BytesPackedMixed a1, Struct9BytesPackedMixed a2, Struct9BytesPackedMixed a3, Struct9BytesPackedMixed a4, Struct9BytesPackedMixed a5, Struct9BytesPackedMixed a6, Struct9BytesPackedMixed a7, Struct9BytesPackedMixed a8, Struct9BytesPackedMixed a9, double a10, int32_t a11) { std::cout << "PassStruct9BytesPackedMixedx10DoubleInt32" << "((" << static_cast(a0.a0) << ", " << a0.a1 << "), (" << static_cast(a1.a0) << ", " << a1.a1 << "), (" << static_cast(a2.a0) << ", " << a2.a1 << "), (" << static_cast(a3.a0) << ", " << a3.a1 << "), (" << static_cast(a4.a0) << ", " << a4.a1 << "), (" << static_cast(a5.a0) << ", " << a5.a1 << "), (" << static_cast(a6.a0) << ", " << a6.a1 << "), (" << static_cast(a7.a0) << ", " << a7.a1 << "), (" << static_cast(a8.a0) << ", " << a8.a1 << "), (" << static_cast(a9.a0) << ", " << a9.a1 << "), " << a10 << ", " << a11 << ")" << "\n"; double result = 0; result += a0.a0; result += a0.a1; result += a1.a0; result += a1.a1; result += a2.a0; result += a2.a1; result += a3.a0; result += a3.a1; result += a4.a0; result += a4.a1; result += a5.a0; result += a5.a1; result += a6.a0; result += a6.a1; result += a7.a0; result += a7.a1; result += a8.a0; result += a8.a1; result += a9.a0; result += a9.a1; result += a10; result += a11; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // This packed struct happens to have only aligned members. DART_EXPORT double PassStruct5BytesPackedMixed(Struct5BytesPackedMixed a0) { std::cout << "PassStruct5BytesPackedMixed" << "((" << a0.a0 << ", " << static_cast(a0.a1) << "))" << "\n"; double result = 0; result += a0.a0; result += a0.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Check alignment of packed struct in non-packed struct. DART_EXPORT double PassStructNestedAlignmentStruct5BytesPackedMixed( StructNestedAlignmentStruct5BytesPackedMixed a0) { std::cout << "PassStructNestedAlignmentStruct5BytesPackedMixed" << "((" << static_cast(a0.a0) << ", (" << a0.a1.a0 << ", " << static_cast(a0.a1.a1) << ")))" << "\n"; double result = 0; result += a0.a0; result += a0.a1.a0; result += a0.a1.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Check alignment of packed struct array in non-packed struct. DART_EXPORT double PassStruct6BytesInlineArrayInt( Struct6BytesInlineArrayInt a0) { std::cout << "PassStruct6BytesInlineArrayInt" << "(([(" << static_cast(a0.a0[0].a0) << ", " << a0.a0[0].a1 << "), (" << static_cast(a0.a0[1].a0) << ", " << a0.a0[1].a1 << ")]))" << "\n"; double result = 0; result += a0.a0[0].a0; result += a0.a0[0].a1; result += a0.a0[1].a0; result += a0.a0[1].a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Check alignment of packed struct array in non-packed struct. DART_EXPORT double PassStruct15BytesInlineArrayMixed( Struct15BytesInlineArrayMixed a0) { std::cout << "PassStruct15BytesInlineArrayMixed" << "(([(" << a0.a0[0].a0 << ", " << static_cast(a0.a0[0].a1) << "), (" << a0.a0[1].a0 << ", " << static_cast(a0.a0[1].a1) << "), (" << a0.a0[2].a0 << ", " << static_cast(a0.a0[2].a1) << ")]))" << "\n"; double result = 0; result += a0.a0[0].a0; result += a0.a0[0].a1; result += a0.a0[1].a0; result += a0.a0[1].a1; result += a0.a0[2].a0; result += a0.a0[2].a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Check placement of mixed integer/float union. DART_EXPORT double PassUnion4BytesMixedx10(Union4BytesMixed a0, Union4BytesMixed a1, Union4BytesMixed a2, Union4BytesMixed a3, Union4BytesMixed a4, Union4BytesMixed a5, Union4BytesMixed a6, Union4BytesMixed a7, Union4BytesMixed a8, Union4BytesMixed a9) { std::cout << "PassUnion4BytesMixedx10" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", " << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0 << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))" << "\n"; double result = 0; result += a0.a0; result += a1.a0; result += a2.a0; result += a3.a0; result += a4.a0; result += a5.a0; result += a6.a0; result += a7.a0; result += a8.a0; result += a9.a0; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Check placement of mixed floats union. DART_EXPORT double PassUnion8BytesNestedFloatx10(Union8BytesNestedFloat a0, Union8BytesNestedFloat a1, Union8BytesNestedFloat a2, Union8BytesNestedFloat a3, Union8BytesNestedFloat a4, Union8BytesNestedFloat a5, Union8BytesNestedFloat a6, Union8BytesNestedFloat a7, Union8BytesNestedFloat a8, Union8BytesNestedFloat a9) { std::cout << "PassUnion8BytesNestedFloatx10" << "((" << a0.a0 << ", (" << a0.a1.a0 << ", " << a0.a1.a1 << ")), (" << a1.a0 << ", (" << a1.a1.a0 << ", " << a1.a1.a1 << ")), (" << a2.a0 << ", (" << a2.a1.a0 << ", " << a2.a1.a1 << ")), (" << a3.a0 << ", (" << a3.a1.a0 << ", " << a3.a1.a1 << ")), (" << a4.a0 << ", (" << a4.a1.a0 << ", " << a4.a1.a1 << ")), (" << a5.a0 << ", (" << a5.a1.a0 << ", " << a5.a1.a1 << ")), (" << a6.a0 << ", (" << a6.a1.a0 << ", " << a6.a1.a1 << ")), (" << a7.a0 << ", (" << a7.a1.a0 << ", " << a7.a1.a1 << ")), (" << a8.a0 << ", (" << a8.a1.a0 << ", " << a8.a1.a1 << ")), (" << a9.a0 << ", (" << a9.a1.a0 << ", " << a9.a1.a1 << ")))" << "\n"; double result = 0; result += a0.a0; result += a1.a0; result += a2.a0; result += a3.a0; result += a4.a0; result += a5.a0; result += a6.a0; result += a7.a0; result += a8.a0; result += a9.a0; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Mixed-size union argument. DART_EXPORT double PassUnion9BytesNestedIntx10(Union9BytesNestedInt a0, Union9BytesNestedInt a1, Union9BytesNestedInt a2, Union9BytesNestedInt a3, Union9BytesNestedInt a4, Union9BytesNestedInt a5, Union9BytesNestedInt a6, Union9BytesNestedInt a7, Union9BytesNestedInt a8, Union9BytesNestedInt a9) { std::cout << "PassUnion9BytesNestedIntx10" << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << ", " << a0.a0.a2 << "), (" << static_cast(a0.a1.a0) << ", " << static_cast(a0.a1.a1) << ", " << static_cast(a0.a1.a2) << ", " << static_cast(a0.a1.a3) << ", " << static_cast(a0.a1.a4) << ", " << static_cast(a0.a1.a5) << ", " << static_cast(a0.a1.a6) << ", " << static_cast(a0.a1.a7) << ", " << static_cast(a0.a1.a8) << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << ", " << a1.a0.a2 << "), (" << static_cast(a1.a1.a0) << ", " << static_cast(a1.a1.a1) << ", " << static_cast(a1.a1.a2) << ", " << static_cast(a1.a1.a3) << ", " << static_cast(a1.a1.a4) << ", " << static_cast(a1.a1.a5) << ", " << static_cast(a1.a1.a6) << ", " << static_cast(a1.a1.a7) << ", " << static_cast(a1.a1.a8) << ")), ((" << a2.a0.a0 << ", " << a2.a0.a1 << ", " << a2.a0.a2 << "), (" << static_cast(a2.a1.a0) << ", " << static_cast(a2.a1.a1) << ", " << static_cast(a2.a1.a2) << ", " << static_cast(a2.a1.a3) << ", " << static_cast(a2.a1.a4) << ", " << static_cast(a2.a1.a5) << ", " << static_cast(a2.a1.a6) << ", " << static_cast(a2.a1.a7) << ", " << static_cast(a2.a1.a8) << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << ", " << a3.a0.a2 << "), (" << static_cast(a3.a1.a0) << ", " << static_cast(a3.a1.a1) << ", " << static_cast(a3.a1.a2) << ", " << static_cast(a3.a1.a3) << ", " << static_cast(a3.a1.a4) << ", " << static_cast(a3.a1.a5) << ", " << static_cast(a3.a1.a6) << ", " << static_cast(a3.a1.a7) << ", " << static_cast(a3.a1.a8) << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1 << ", " << a4.a0.a2 << "), (" << static_cast(a4.a1.a0) << ", " << static_cast(a4.a1.a1) << ", " << static_cast(a4.a1.a2) << ", " << static_cast(a4.a1.a3) << ", " << static_cast(a4.a1.a4) << ", " << static_cast(a4.a1.a5) << ", " << static_cast(a4.a1.a6) << ", " << static_cast(a4.a1.a7) << ", " << static_cast(a4.a1.a8) << ")), ((" << a5.a0.a0 << ", " << a5.a0.a1 << ", " << a5.a0.a2 << "), (" << static_cast(a5.a1.a0) << ", " << static_cast(a5.a1.a1) << ", " << static_cast(a5.a1.a2) << ", " << static_cast(a5.a1.a3) << ", " << static_cast(a5.a1.a4) << ", " << static_cast(a5.a1.a5) << ", " << static_cast(a5.a1.a6) << ", " << static_cast(a5.a1.a7) << ", " << static_cast(a5.a1.a8) << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << ", " << a6.a0.a2 << "), (" << static_cast(a6.a1.a0) << ", " << static_cast(a6.a1.a1) << ", " << static_cast(a6.a1.a2) << ", " << static_cast(a6.a1.a3) << ", " << static_cast(a6.a1.a4) << ", " << static_cast(a6.a1.a5) << ", " << static_cast(a6.a1.a6) << ", " << static_cast(a6.a1.a7) << ", " << static_cast(a6.a1.a8) << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1 << ", " << a7.a0.a2 << "), (" << static_cast(a7.a1.a0) << ", " << static_cast(a7.a1.a1) << ", " << static_cast(a7.a1.a2) << ", " << static_cast(a7.a1.a3) << ", " << static_cast(a7.a1.a4) << ", " << static_cast(a7.a1.a5) << ", " << static_cast(a7.a1.a6) << ", " << static_cast(a7.a1.a7) << ", " << static_cast(a7.a1.a8) << ")), ((" << a8.a0.a0 << ", " << a8.a0.a1 << ", " << a8.a0.a2 << "), (" << static_cast(a8.a1.a0) << ", " << static_cast(a8.a1.a1) << ", " << static_cast(a8.a1.a2) << ", " << static_cast(a8.a1.a3) << ", " << static_cast(a8.a1.a4) << ", " << static_cast(a8.a1.a5) << ", " << static_cast(a8.a1.a6) << ", " << static_cast(a8.a1.a7) << ", " << static_cast(a8.a1.a8) << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << ", " << a9.a0.a2 << "), (" << static_cast(a9.a1.a0) << ", " << static_cast(a9.a1.a1) << ", " << static_cast(a9.a1.a2) << ", " << static_cast(a9.a1.a3) << ", " << static_cast(a9.a1.a4) << ", " << static_cast(a9.a1.a5) << ", " << static_cast(a9.a1.a6) << ", " << static_cast(a9.a1.a7) << ", " << static_cast(a9.a1.a8) << ")))" << "\n"; double result = 0; result += a0.a0.a0; result += a0.a0.a1; result += a0.a0.a2; result += a1.a0.a0; result += a1.a0.a1; result += a1.a0.a2; result += a2.a0.a0; result += a2.a0.a1; result += a2.a0.a2; result += a3.a0.a0; result += a3.a0.a1; result += a3.a0.a2; result += a4.a0.a0; result += a4.a0.a1; result += a4.a0.a2; result += a5.a0.a0; result += a5.a0.a1; result += a5.a0.a2; result += a6.a0.a0; result += a6.a0.a1; result += a6.a0.a2; result += a7.a0.a0; result += a7.a0.a1; result += a7.a0.a2; result += a8.a0.a0; result += a8.a0.a1; result += a8.a0.a2; result += a9.a0.a0; result += a9.a0.a1; result += a9.a0.a2; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Union with homogenous floats. DART_EXPORT double PassUnion16BytesNestedInlineArrayFloatx10( Union16BytesNestedInlineArrayFloat a0, Union16BytesNestedInlineArrayFloat a1, Union16BytesNestedInlineArrayFloat a2, Union16BytesNestedInlineArrayFloat a3, Union16BytesNestedInlineArrayFloat a4, Union16BytesNestedInlineArrayFloat a5, Union16BytesNestedInlineArrayFloat a6, Union16BytesNestedInlineArrayFloat a7, Union16BytesNestedInlineArrayFloat a8, Union16BytesNestedInlineArrayFloat a9) { std::cout << "PassUnion16BytesNestedInlineArrayFloatx10" << "(([" << a0.a0[0] << ", " << a0.a0[1] << ", " << a0.a0[2] << ", " << a0.a0[3] << "], (" << a0.a1.a0 << ", " << a0.a1.a1 << ", " << a0.a1.a2 << ", " << a0.a1.a3 << ")), ([" << a1.a0[0] << ", " << a1.a0[1] << ", " << a1.a0[2] << ", " << a1.a0[3] << "], (" << a1.a1.a0 << ", " << a1.a1.a1 << ", " << a1.a1.a2 << ", " << a1.a1.a3 << ")), ([" << a2.a0[0] << ", " << a2.a0[1] << ", " << a2.a0[2] << ", " << a2.a0[3] << "], (" << a2.a1.a0 << ", " << a2.a1.a1 << ", " << a2.a1.a2 << ", " << a2.a1.a3 << ")), ([" << a3.a0[0] << ", " << a3.a0[1] << ", " << a3.a0[2] << ", " << a3.a0[3] << "], (" << a3.a1.a0 << ", " << a3.a1.a1 << ", " << a3.a1.a2 << ", " << a3.a1.a3 << ")), ([" << a4.a0[0] << ", " << a4.a0[1] << ", " << a4.a0[2] << ", " << a4.a0[3] << "], (" << a4.a1.a0 << ", " << a4.a1.a1 << ", " << a4.a1.a2 << ", " << a4.a1.a3 << ")), ([" << a5.a0[0] << ", " << a5.a0[1] << ", " << a5.a0[2] << ", " << a5.a0[3] << "], (" << a5.a1.a0 << ", " << a5.a1.a1 << ", " << a5.a1.a2 << ", " << a5.a1.a3 << ")), ([" << a6.a0[0] << ", " << a6.a0[1] << ", " << a6.a0[2] << ", " << a6.a0[3] << "], (" << a6.a1.a0 << ", " << a6.a1.a1 << ", " << a6.a1.a2 << ", " << a6.a1.a3 << ")), ([" << a7.a0[0] << ", " << a7.a0[1] << ", " << a7.a0[2] << ", " << a7.a0[3] << "], (" << a7.a1.a0 << ", " << a7.a1.a1 << ", " << a7.a1.a2 << ", " << a7.a1.a3 << ")), ([" << a8.a0[0] << ", " << a8.a0[1] << ", " << a8.a0[2] << ", " << a8.a0[3] << "], (" << a8.a1.a0 << ", " << a8.a1.a1 << ", " << a8.a1.a2 << ", " << a8.a1.a3 << ")), ([" << a9.a0[0] << ", " << a9.a0[1] << ", " << a9.a0[2] << ", " << a9.a0[3] << "], (" << a9.a1.a0 << ", " << a9.a1.a1 << ", " << a9.a1.a2 << ", " << a9.a1.a3 << ")))" << "\n"; double result = 0; result += a0.a0[0]; result += a0.a0[1]; result += a0.a0[2]; result += a0.a0[3]; result += a1.a0[0]; result += a1.a0[1]; result += a1.a0[2]; result += a1.a0[3]; result += a2.a0[0]; result += a2.a0[1]; result += a2.a0[2]; result += a2.a0[3]; result += a3.a0[0]; result += a3.a0[1]; result += a3.a0[2]; result += a3.a0[3]; result += a4.a0[0]; result += a4.a0[1]; result += a4.a0[2]; result += a4.a0[3]; result += a5.a0[0]; result += a5.a0[1]; result += a5.a0[2]; result += a5.a0[3]; result += a6.a0[0]; result += a6.a0[1]; result += a6.a0[2]; result += a6.a0[3]; result += a7.a0[0]; result += a7.a0[1]; result += a7.a0[2]; result += a7.a0[3]; result += a8.a0[0]; result += a8.a0[1]; result += a8.a0[2]; result += a8.a0[3]; result += a9.a0[0]; result += a9.a0[1]; result += a9.a0[2]; result += a9.a0[3]; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Union with homogenous floats. DART_EXPORT double PassUnion16BytesNestedFloatx10(Union16BytesNestedFloat a0, Union16BytesNestedFloat a1, Union16BytesNestedFloat a2, Union16BytesNestedFloat a3, Union16BytesNestedFloat a4, Union16BytesNestedFloat a5, Union16BytesNestedFloat a6, Union16BytesNestedFloat a7, Union16BytesNestedFloat a8, Union16BytesNestedFloat a9) { std::cout << "PassUnion16BytesNestedFloatx10" << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0 << ", " << a0.a1.a1 << ", " << a0.a1.a2 << "), (" << a0.a2.a0 << ", " << a0.a2.a1 << ", " << a0.a2.a2 << ", " << a0.a2.a3 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << "), (" << a1.a1.a0 << ", " << a1.a1.a1 << ", " << a1.a1.a2 << "), (" << a1.a2.a0 << ", " << a1.a2.a1 << ", " << a1.a2.a2 << ", " << a1.a2.a3 << ")), ((" << a2.a0.a0 << ", " << a2.a0.a1 << "), (" << a2.a1.a0 << ", " << a2.a1.a1 << ", " << a2.a1.a2 << "), (" << a2.a2.a0 << ", " << a2.a2.a1 << ", " << a2.a2.a2 << ", " << a2.a2.a3 << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << "), (" << a3.a1.a0 << ", " << a3.a1.a1 << ", " << a3.a1.a2 << "), (" << a3.a2.a0 << ", " << a3.a2.a1 << ", " << a3.a2.a2 << ", " << a3.a2.a3 << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1 << "), (" << a4.a1.a0 << ", " << a4.a1.a1 << ", " << a4.a1.a2 << "), (" << a4.a2.a0 << ", " << a4.a2.a1 << ", " << a4.a2.a2 << ", " << a4.a2.a3 << ")), ((" << a5.a0.a0 << ", " << a5.a0.a1 << "), (" << a5.a1.a0 << ", " << a5.a1.a1 << ", " << a5.a1.a2 << "), (" << a5.a2.a0 << ", " << a5.a2.a1 << ", " << a5.a2.a2 << ", " << a5.a2.a3 << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << "), (" << a6.a1.a0 << ", " << a6.a1.a1 << ", " << a6.a1.a2 << "), (" << a6.a2.a0 << ", " << a6.a2.a1 << ", " << a6.a2.a2 << ", " << a6.a2.a3 << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1 << "), (" << a7.a1.a0 << ", " << a7.a1.a1 << ", " << a7.a1.a2 << "), (" << a7.a2.a0 << ", " << a7.a2.a1 << ", " << a7.a2.a2 << ", " << a7.a2.a3 << ")), ((" << a8.a0.a0 << ", " << a8.a0.a1 << "), (" << a8.a1.a0 << ", " << a8.a1.a1 << ", " << a8.a1.a2 << "), (" << a8.a2.a0 << ", " << a8.a2.a1 << ", " << a8.a2.a2 << ", " << a8.a2.a3 << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << "), (" << a9.a1.a0 << ", " << a9.a1.a1 << ", " << a9.a1.a2 << "), (" << a9.a2.a0 << ", " << a9.a2.a1 << ", " << a9.a2.a2 << ", " << a9.a2.a3 << ")))" << "\n"; double result = 0; result += a0.a0.a0; result += a0.a0.a1; result += a1.a0.a0; result += a1.a0.a1; result += a2.a0.a0; result += a2.a0.a1; result += a3.a0.a0; result += a3.a0.a1; result += a4.a0.a0; result += a4.a0.a1; result += a5.a0.a0; result += a5.a0.a1; result += a6.a0.a0; result += a6.a0.a1; result += a7.a0.a0; result += a7.a0.a1; result += a8.a0.a0; result += a8.a0.a1; result += a9.a0.a0; result += a9.a0.a1; std::cout << "result = " << result << "\n"; return result; } // Used for testing structs and unions by value. // Smallest struct with data. DART_EXPORT Struct1ByteInt ReturnStruct1ByteInt(int8_t a0) { std::cout << "ReturnStruct1ByteInt" << "(" << static_cast(a0) << ")" << "\n"; Struct1ByteInt result; result.a0 = a0; std::cout << "result = " << "(" << static_cast(result.a0) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Smaller than word size return value on all architectures. DART_EXPORT Struct3BytesHomogeneousUint8 ReturnStruct3BytesHomogeneousUint8(uint8_t a0, uint8_t a1, uint8_t a2) { std::cout << "ReturnStruct3BytesHomogeneousUint8" << "(" << static_cast(a0) << ", " << static_cast(a1) << ", " << static_cast(a2) << ")" << "\n"; Struct3BytesHomogeneousUint8 result; result.a0 = a0; result.a1 = a1; result.a2 = a2; std::cout << "result = " << "(" << static_cast(result.a0) << ", " << static_cast(result.a1) << ", " << static_cast(result.a2) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Smaller than word size return value on all architectures. // With alignment rules taken into account size is 4 bytes. DART_EXPORT Struct3BytesInt2ByteAligned ReturnStruct3BytesInt2ByteAligned(int16_t a0, int8_t a1) { std::cout << "ReturnStruct3BytesInt2ByteAligned" << "(" << a0 << ", " << static_cast(a1) << ")" << "\n"; Struct3BytesInt2ByteAligned result; result.a0 = a0; result.a1 = a1; std::cout << "result = " << "(" << result.a0 << ", " << static_cast(result.a1) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Word size return value on 32 bit architectures.. DART_EXPORT Struct4BytesHomogeneousInt16 ReturnStruct4BytesHomogeneousInt16(int16_t a0, int16_t a1) { std::cout << "ReturnStruct4BytesHomogeneousInt16" << "(" << a0 << ", " << a1 << ")" << "\n"; Struct4BytesHomogeneousInt16 result; result.a0 = a0; result.a1 = a1; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Non-wordsize return value. DART_EXPORT Struct7BytesHomogeneousUint8 ReturnStruct7BytesHomogeneousUint8(uint8_t a0, uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6) { std::cout << "ReturnStruct7BytesHomogeneousUint8" << "(" << static_cast(a0) << ", " << static_cast(a1) << ", " << static_cast(a2) << ", " << static_cast(a3) << ", " << static_cast(a4) << ", " << static_cast(a5) << ", " << static_cast(a6) << ")" << "\n"; Struct7BytesHomogeneousUint8 result; result.a0 = a0; result.a1 = a1; result.a2 = a2; result.a3 = a3; result.a4 = a4; result.a5 = a5; result.a6 = a6; std::cout << "result = " << "(" << static_cast(result.a0) << ", " << static_cast(result.a1) << ", " << static_cast(result.a2) << ", " << static_cast(result.a3) << ", " << static_cast(result.a4) << ", " << static_cast(result.a5) << ", " << static_cast(result.a6) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Non-wordsize return value. // With alignment rules taken into account size is 8 bytes. DART_EXPORT Struct7BytesInt4ByteAligned ReturnStruct7BytesInt4ByteAligned(int32_t a0, int16_t a1, int8_t a2) { std::cout << "ReturnStruct7BytesInt4ByteAligned" << "(" << a0 << ", " << a1 << ", " << static_cast(a2) << ")" << "\n"; Struct7BytesInt4ByteAligned result; result.a0 = a0; result.a1 = a1; result.a2 = a2; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << static_cast(result.a2) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value in integer registers on many architectures. DART_EXPORT Struct8BytesInt ReturnStruct8BytesInt(int16_t a0, int16_t a1, int32_t a2) { std::cout << "ReturnStruct8BytesInt" << "(" << a0 << ", " << a1 << ", " << a2 << ")" << "\n"; Struct8BytesInt result; result.a0 = a0; result.a1 = a1; result.a2 = a2; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value in FP registers on many architectures. DART_EXPORT Struct8BytesHomogeneousFloat ReturnStruct8BytesHomogeneousFloat(float a0, float a1) { std::cout << "ReturnStruct8BytesHomogeneousFloat" << "(" << a0 << ", " << a1 << ")" << "\n"; Struct8BytesHomogeneousFloat result; result.a0 = a0; result.a1 = a1; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value split over FP and integer register in x64. DART_EXPORT Struct8BytesMixed ReturnStruct8BytesMixed(float a0, int16_t a1, int16_t a2) { std::cout << "ReturnStruct8BytesMixed" << "(" << a0 << ", " << a1 << ", " << a2 << ")" << "\n"; Struct8BytesMixed result; result.a0 = a0; result.a1 = a1; result.a2 = a2; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT Struct9BytesHomogeneousUint8 ReturnStruct9BytesHomogeneousUint8(uint8_t a0, uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6, uint8_t a7, uint8_t a8) { std::cout << "ReturnStruct9BytesHomogeneousUint8" << "(" << static_cast(a0) << ", " << static_cast(a1) << ", " << static_cast(a2) << ", " << static_cast(a3) << ", " << static_cast(a4) << ", " << static_cast(a5) << ", " << static_cast(a6) << ", " << static_cast(a7) << ", " << static_cast(a8) << ")" << "\n"; Struct9BytesHomogeneousUint8 result; result.a0 = a0; result.a1 = a1; result.a2 = a2; result.a3 = a3; result.a4 = a4; result.a5 = a5; result.a6 = a6; result.a7 = a7; result.a8 = a8; std::cout << "result = " << "(" << static_cast(result.a0) << ", " << static_cast(result.a1) << ", " << static_cast(result.a2) << ", " << static_cast(result.a3) << ", " << static_cast(result.a4) << ", " << static_cast(result.a5) << ", " << static_cast(result.a6) << ", " << static_cast(result.a7) << ", " << static_cast(result.a8) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value in two integer registers on x64. // With alignment rules taken into account size is 12 or 16 bytes. DART_EXPORT Struct9BytesInt4Or8ByteAligned ReturnStruct9BytesInt4Or8ByteAligned(int64_t a0, int8_t a1) { std::cout << "ReturnStruct9BytesInt4Or8ByteAligned" << "(" << a0 << ", " << static_cast(a1) << ")" << "\n"; Struct9BytesInt4Or8ByteAligned result; result.a0 = a0; result.a1 = a1; std::cout << "result = " << "(" << result.a0 << ", " << static_cast(result.a1) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value in FPU registers, but does not use all registers on arm hardfp // and arm64. DART_EXPORT Struct12BytesHomogeneousFloat ReturnStruct12BytesHomogeneousFloat(float a0, float a1, float a2) { std::cout << "ReturnStruct12BytesHomogeneousFloat" << "(" << a0 << ", " << a1 << ", " << a2 << ")" << "\n"; Struct12BytesHomogeneousFloat result; result.a0 = a0; result.a1 = a1; result.a2 = a2; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value in FPU registers on arm hardfp and arm64. DART_EXPORT Struct16BytesHomogeneousFloat ReturnStruct16BytesHomogeneousFloat(float a0, float a1, float a2, float a3) { std::cout << "ReturnStruct16BytesHomogeneousFloat" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")" << "\n"; Struct16BytesHomogeneousFloat result; result.a0 = a0; result.a1 = a1; result.a2 = a2; result.a3 = a3; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value split over FP and integer register in x64. DART_EXPORT Struct16BytesMixed ReturnStruct16BytesMixed(double a0, int64_t a1) { std::cout << "ReturnStruct16BytesMixed" << "(" << a0 << ", " << a1 << ")" << "\n"; Struct16BytesMixed result; result.a0 = a0; result.a1 = a1; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value split over FP and integer register in x64. // The integer register contains half float half int. DART_EXPORT Struct16BytesMixed2 ReturnStruct16BytesMixed2(float a0, float a1, float a2, int32_t a3) { std::cout << "ReturnStruct16BytesMixed2" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")" << "\n"; Struct16BytesMixed2 result; result.a0 = a0; result.a1 = a1; result.a2 = a2; result.a3 = a3; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT Struct17BytesInt ReturnStruct17BytesInt(int64_t a0, int64_t a1, int8_t a2) { std::cout << "ReturnStruct17BytesInt" << "(" << a0 << ", " << a1 << ", " << static_cast(a2) << ")" << "\n"; Struct17BytesInt result; result.a0 = a0; result.a1 = a1; result.a2 = a2; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << static_cast(result.a2) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // 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. DART_EXPORT Struct19BytesHomogeneousUint8 ReturnStruct19BytesHomogeneousUint8(uint8_t a0, uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6, uint8_t a7, uint8_t a8, uint8_t a9, uint8_t a10, uint8_t a11, uint8_t a12, uint8_t a13, uint8_t a14, uint8_t a15, uint8_t a16, uint8_t a17, uint8_t a18) { std::cout << "ReturnStruct19BytesHomogeneousUint8" << "(" << static_cast(a0) << ", " << static_cast(a1) << ", " << static_cast(a2) << ", " << static_cast(a3) << ", " << static_cast(a4) << ", " << static_cast(a5) << ", " << static_cast(a6) << ", " << static_cast(a7) << ", " << static_cast(a8) << ", " << static_cast(a9) << ", " << static_cast(a10) << ", " << static_cast(a11) << ", " << static_cast(a12) << ", " << static_cast(a13) << ", " << static_cast(a14) << ", " << static_cast(a15) << ", " << static_cast(a16) << ", " << static_cast(a17) << ", " << static_cast(a18) << ")" << "\n"; Struct19BytesHomogeneousUint8 result; result.a0 = a0; result.a1 = a1; result.a2 = a2; result.a3 = a3; result.a4 = a4; result.a5 = a5; result.a6 = a6; result.a7 = a7; result.a8 = a8; result.a9 = a9; result.a10 = a10; result.a11 = a11; result.a12 = a12; result.a13 = a13; result.a14 = a14; result.a15 = a15; result.a16 = a16; result.a17 = a17; result.a18 = a18; std::cout << "result = " << "(" << static_cast(result.a0) << ", " << static_cast(result.a1) << ", " << static_cast(result.a2) << ", " << static_cast(result.a3) << ", " << static_cast(result.a4) << ", " << static_cast(result.a5) << ", " << static_cast(result.a6) << ", " << static_cast(result.a7) << ", " << static_cast(result.a8) << ", " << static_cast(result.a9) << ", " << static_cast(result.a10) << ", " << static_cast(result.a11) << ", " << static_cast(result.a12) << ", " << static_cast(result.a13) << ", " << static_cast(result.a14) << ", " << static_cast(result.a15) << ", " << static_cast(result.a16) << ", " << static_cast(result.a17) << ", " << static_cast(result.a18) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value too big to go in cpu registers on arm64. DART_EXPORT Struct20BytesHomogeneousInt32 ReturnStruct20BytesHomogeneousInt32(int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4) { std::cout << "ReturnStruct20BytesHomogeneousInt32" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ")" << "\n"; Struct20BytesHomogeneousInt32 result; result.a0 = a0; result.a1 = a1; result.a2 = a2; result.a3 = a3; result.a4 = a4; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value too big to go in FPU registers on x64, arm hardfp and arm64. DART_EXPORT Struct20BytesHomogeneousFloat ReturnStruct20BytesHomogeneousFloat(float a0, float a1, float a2, float a3, float a4) { std::cout << "ReturnStruct20BytesHomogeneousFloat" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ")" << "\n"; Struct20BytesHomogeneousFloat result; result.a0 = a0; result.a1 = a1; result.a2 = a2; result.a3 = a3; result.a4 = a4; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value in FPU registers on arm64. DART_EXPORT Struct32BytesHomogeneousDouble ReturnStruct32BytesHomogeneousDouble(double a0, double a1, double a2, double a3) { std::cout << "ReturnStruct32BytesHomogeneousDouble" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")" << "\n"; Struct32BytesHomogeneousDouble result; result.a0 = a0; result.a1 = a1; result.a2 = a2; result.a3 = a3; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value too big to go in FPU registers on arm64. DART_EXPORT Struct40BytesHomogeneousDouble ReturnStruct40BytesHomogeneousDouble(double a0, double a1, double a2, double a3, double a4) { std::cout << "ReturnStruct40BytesHomogeneousDouble" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ")" << "\n"; Struct40BytesHomogeneousDouble result; result.a0 = a0; result.a1 = a1; result.a2 = a2; result.a3 = a3; result.a4 = a4; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Test 1kb struct. DART_EXPORT Struct1024BytesHomogeneousUint64 ReturnStruct1024BytesHomogeneousUint64(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6, uint64_t a7, uint64_t a8, uint64_t a9, uint64_t a10, uint64_t a11, uint64_t a12, uint64_t a13, uint64_t a14, uint64_t a15, uint64_t a16, uint64_t a17, uint64_t a18, uint64_t a19, uint64_t a20, uint64_t a21, uint64_t a22, uint64_t a23, uint64_t a24, uint64_t a25, uint64_t a26, uint64_t a27, uint64_t a28, uint64_t a29, uint64_t a30, uint64_t a31, uint64_t a32, uint64_t a33, uint64_t a34, uint64_t a35, uint64_t a36, uint64_t a37, uint64_t a38, uint64_t a39, uint64_t a40, uint64_t a41, uint64_t a42, uint64_t a43, uint64_t a44, uint64_t a45, uint64_t a46, uint64_t a47, uint64_t a48, uint64_t a49, uint64_t a50, uint64_t a51, uint64_t a52, uint64_t a53, uint64_t a54, uint64_t a55, uint64_t a56, uint64_t a57, uint64_t a58, uint64_t a59, uint64_t a60, uint64_t a61, uint64_t a62, uint64_t a63, uint64_t a64, uint64_t a65, uint64_t a66, uint64_t a67, uint64_t a68, uint64_t a69, uint64_t a70, uint64_t a71, uint64_t a72, uint64_t a73, uint64_t a74, uint64_t a75, uint64_t a76, uint64_t a77, uint64_t a78, uint64_t a79, uint64_t a80, uint64_t a81, uint64_t a82, uint64_t a83, uint64_t a84, uint64_t a85, uint64_t a86, uint64_t a87, uint64_t a88, uint64_t a89, uint64_t a90, uint64_t a91, uint64_t a92, uint64_t a93, uint64_t a94, uint64_t a95, uint64_t a96, uint64_t a97, uint64_t a98, uint64_t a99, uint64_t a100, uint64_t a101, uint64_t a102, uint64_t a103, uint64_t a104, uint64_t a105, uint64_t a106, uint64_t a107, uint64_t a108, uint64_t a109, uint64_t a110, uint64_t a111, uint64_t a112, uint64_t a113, uint64_t a114, uint64_t a115, uint64_t a116, uint64_t a117, uint64_t a118, uint64_t a119, uint64_t a120, uint64_t a121, uint64_t a122, uint64_t a123, uint64_t a124, uint64_t a125, uint64_t a126, uint64_t a127) { std::cout << "ReturnStruct1024BytesHomogeneousUint64" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7 << ", " << a8 << ", " << a9 << ", " << a10 << ", " << a11 << ", " << a12 << ", " << a13 << ", " << a14 << ", " << a15 << ", " << a16 << ", " << a17 << ", " << a18 << ", " << a19 << ", " << a20 << ", " << a21 << ", " << a22 << ", " << a23 << ", " << a24 << ", " << a25 << ", " << a26 << ", " << a27 << ", " << a28 << ", " << a29 << ", " << a30 << ", " << a31 << ", " << a32 << ", " << a33 << ", " << a34 << ", " << a35 << ", " << a36 << ", " << a37 << ", " << a38 << ", " << a39 << ", " << a40 << ", " << a41 << ", " << a42 << ", " << a43 << ", " << a44 << ", " << a45 << ", " << a46 << ", " << a47 << ", " << a48 << ", " << a49 << ", " << a50 << ", " << a51 << ", " << a52 << ", " << a53 << ", " << a54 << ", " << a55 << ", " << a56 << ", " << a57 << ", " << a58 << ", " << a59 << ", " << a60 << ", " << a61 << ", " << a62 << ", " << a63 << ", " << a64 << ", " << a65 << ", " << a66 << ", " << a67 << ", " << a68 << ", " << a69 << ", " << a70 << ", " << a71 << ", " << a72 << ", " << a73 << ", " << a74 << ", " << a75 << ", " << a76 << ", " << a77 << ", " << a78 << ", " << a79 << ", " << a80 << ", " << a81 << ", " << a82 << ", " << a83 << ", " << a84 << ", " << a85 << ", " << a86 << ", " << a87 << ", " << a88 << ", " << a89 << ", " << a90 << ", " << a91 << ", " << a92 << ", " << a93 << ", " << a94 << ", " << a95 << ", " << a96 << ", " << a97 << ", " << a98 << ", " << a99 << ", " << a100 << ", " << a101 << ", " << a102 << ", " << a103 << ", " << a104 << ", " << a105 << ", " << a106 << ", " << a107 << ", " << a108 << ", " << a109 << ", " << a110 << ", " << a111 << ", " << a112 << ", " << a113 << ", " << a114 << ", " << a115 << ", " << a116 << ", " << a117 << ", " << a118 << ", " << a119 << ", " << a120 << ", " << a121 << ", " << a122 << ", " << a123 << ", " << a124 << ", " << a125 << ", " << a126 << ", " << a127 << ")" << "\n"; Struct1024BytesHomogeneousUint64 result; result.a0 = a0; result.a1 = a1; result.a2 = a2; result.a3 = a3; result.a4 = a4; result.a5 = a5; result.a6 = a6; result.a7 = a7; result.a8 = a8; result.a9 = a9; result.a10 = a10; result.a11 = a11; result.a12 = a12; result.a13 = a13; result.a14 = a14; result.a15 = a15; result.a16 = a16; result.a17 = a17; result.a18 = a18; result.a19 = a19; result.a20 = a20; result.a21 = a21; result.a22 = a22; result.a23 = a23; result.a24 = a24; result.a25 = a25; result.a26 = a26; result.a27 = a27; result.a28 = a28; result.a29 = a29; result.a30 = a30; result.a31 = a31; result.a32 = a32; result.a33 = a33; result.a34 = a34; result.a35 = a35; result.a36 = a36; result.a37 = a37; result.a38 = a38; result.a39 = a39; result.a40 = a40; result.a41 = a41; result.a42 = a42; result.a43 = a43; result.a44 = a44; result.a45 = a45; result.a46 = a46; result.a47 = a47; result.a48 = a48; result.a49 = a49; result.a50 = a50; result.a51 = a51; result.a52 = a52; result.a53 = a53; result.a54 = a54; result.a55 = a55; result.a56 = a56; result.a57 = a57; result.a58 = a58; result.a59 = a59; result.a60 = a60; result.a61 = a61; result.a62 = a62; result.a63 = a63; result.a64 = a64; result.a65 = a65; result.a66 = a66; result.a67 = a67; result.a68 = a68; result.a69 = a69; result.a70 = a70; result.a71 = a71; result.a72 = a72; result.a73 = a73; result.a74 = a74; result.a75 = a75; result.a76 = a76; result.a77 = a77; result.a78 = a78; result.a79 = a79; result.a80 = a80; result.a81 = a81; result.a82 = a82; result.a83 = a83; result.a84 = a84; result.a85 = a85; result.a86 = a86; result.a87 = a87; result.a88 = a88; result.a89 = a89; result.a90 = a90; result.a91 = a91; result.a92 = a92; result.a93 = a93; result.a94 = a94; result.a95 = a95; result.a96 = a96; result.a97 = a97; result.a98 = a98; result.a99 = a99; result.a100 = a100; result.a101 = a101; result.a102 = a102; result.a103 = a103; result.a104 = a104; result.a105 = a105; result.a106 = a106; result.a107 = a107; result.a108 = a108; result.a109 = a109; result.a110 = a110; result.a111 = a111; result.a112 = a112; result.a113 = a113; result.a114 = a114; result.a115 = a115; result.a116 = a116; result.a117 = a117; result.a118 = a118; result.a119 = a119; result.a120 = a120; result.a121 = a121; result.a122 = a122; result.a123 = a123; result.a124 = a124; result.a125 = a125; result.a126 = a126; result.a127 = a127; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ", " << result.a5 << ", " << result.a6 << ", " << result.a7 << ", " << result.a8 << ", " << result.a9 << ", " << result.a10 << ", " << result.a11 << ", " << result.a12 << ", " << result.a13 << ", " << result.a14 << ", " << result.a15 << ", " << result.a16 << ", " << result.a17 << ", " << result.a18 << ", " << result.a19 << ", " << result.a20 << ", " << result.a21 << ", " << result.a22 << ", " << result.a23 << ", " << result.a24 << ", " << result.a25 << ", " << result.a26 << ", " << result.a27 << ", " << result.a28 << ", " << result.a29 << ", " << result.a30 << ", " << result.a31 << ", " << result.a32 << ", " << result.a33 << ", " << result.a34 << ", " << result.a35 << ", " << result.a36 << ", " << result.a37 << ", " << result.a38 << ", " << result.a39 << ", " << result.a40 << ", " << result.a41 << ", " << result.a42 << ", " << result.a43 << ", " << result.a44 << ", " << result.a45 << ", " << result.a46 << ", " << result.a47 << ", " << result.a48 << ", " << result.a49 << ", " << result.a50 << ", " << result.a51 << ", " << result.a52 << ", " << result.a53 << ", " << result.a54 << ", " << result.a55 << ", " << result.a56 << ", " << result.a57 << ", " << result.a58 << ", " << result.a59 << ", " << result.a60 << ", " << result.a61 << ", " << result.a62 << ", " << result.a63 << ", " << result.a64 << ", " << result.a65 << ", " << result.a66 << ", " << result.a67 << ", " << result.a68 << ", " << result.a69 << ", " << result.a70 << ", " << result.a71 << ", " << result.a72 << ", " << result.a73 << ", " << result.a74 << ", " << result.a75 << ", " << result.a76 << ", " << result.a77 << ", " << result.a78 << ", " << result.a79 << ", " << result.a80 << ", " << result.a81 << ", " << result.a82 << ", " << result.a83 << ", " << result.a84 << ", " << result.a85 << ", " << result.a86 << ", " << result.a87 << ", " << result.a88 << ", " << result.a89 << ", " << result.a90 << ", " << result.a91 << ", " << result.a92 << ", " << result.a93 << ", " << result.a94 << ", " << result.a95 << ", " << result.a96 << ", " << result.a97 << ", " << result.a98 << ", " << result.a99 << ", " << result.a100 << ", " << result.a101 << ", " << result.a102 << ", " << result.a103 << ", " << result.a104 << ", " << result.a105 << ", " << result.a106 << ", " << result.a107 << ", " << result.a108 << ", " << result.a109 << ", " << result.a110 << ", " << result.a111 << ", " << result.a112 << ", " << result.a113 << ", " << result.a114 << ", " << result.a115 << ", " << result.a116 << ", " << result.a117 << ", " << result.a118 << ", " << result.a119 << ", " << result.a120 << ", " << result.a121 << ", " << result.a122 << ", " << result.a123 << ", " << result.a124 << ", " << result.a125 << ", " << result.a126 << ", " << result.a127 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Small struct with mis-aligned member. DART_EXPORT Struct3BytesPackedInt ReturnStruct3BytesPackedInt(int8_t a0, int16_t a1) { std::cout << "ReturnStruct3BytesPackedInt" << "(" << static_cast(a0) << ", " << a1 << ")" << "\n"; Struct3BytesPackedInt result; result.a0 = a0; result.a1 = a1; std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Struct with mis-aligned member. DART_EXPORT Struct8BytesPackedInt ReturnStruct8BytesPackedInt(uint8_t a0, uint32_t a1, uint8_t a2, uint8_t a3, uint8_t a4) { std::cout << "ReturnStruct8BytesPackedInt" << "(" << static_cast(a0) << ", " << a1 << ", " << static_cast(a2) << ", " << static_cast(a3) << ", " << static_cast(a4) << ")" << "\n"; Struct8BytesPackedInt result; result.a0 = a0; result.a1 = a1; result.a2 = a2; result.a3 = a3; result.a4 = a4; std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ", " << static_cast(result.a2) << ", " << static_cast(result.a3) << ", " << static_cast(result.a4) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Struct with mis-aligned member. // Tests backfilling of CPU and FPU registers. DART_EXPORT Struct9BytesPackedMixed ReturnStruct9BytesPackedMixed(uint8_t a0, double a1) { std::cout << "ReturnStruct9BytesPackedMixed" << "(" << static_cast(a0) << ", " << a1 << ")" << "\n"; Struct9BytesPackedMixed result; result.a0 = a0; result.a1 = a1; std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Returning a mixed integer/float union. DART_EXPORT Union4BytesMixed ReturnUnion4BytesMixed(uint32_t a0) { std::cout << "ReturnUnion4BytesMixed" << "(" << a0 << ")" << "\n"; Union4BytesMixed result; result.a0 = a0; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Returning a floating point only union. DART_EXPORT Union8BytesNestedFloat ReturnUnion8BytesNestedFloat(double a0) { std::cout << "ReturnUnion8BytesNestedFloat" << "(" << a0 << ")" << "\n"; Union8BytesNestedFloat result; result.a0 = a0; std::cout << "result = " << "(" << result.a0 << ", (" << result.a1.a0 << ", " << result.a1.a1 << "))" << "\n"; return result; } // Used for testing structs and unions by value. // Returning a mixed-size union. DART_EXPORT Union9BytesNestedInt ReturnUnion9BytesNestedInt(Struct8BytesInt a0) { std::cout << "ReturnUnion9BytesNestedInt" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "))" << "\n"; Union9BytesNestedInt result; result.a0.a0 = a0.a0; result.a0.a1 = a0.a1; result.a0.a2 = a0.a2; std::cout << "result = " << "((" << result.a0.a0 << ", " << result.a0.a1 << ", " << result.a0.a2 << "), (" << static_cast(result.a1.a0) << ", " << static_cast(result.a1.a1) << ", " << static_cast(result.a1.a2) << ", " << static_cast(result.a1.a3) << ", " << static_cast(result.a1.a4) << ", " << static_cast(result.a1.a5) << ", " << static_cast(result.a1.a6) << ", " << static_cast(result.a1.a7) << ", " << static_cast(result.a1.a8) << "))" << "\n"; return result; } // Used for testing structs and unions by value. // Returning union with homogenous floats. DART_EXPORT Union16BytesNestedFloat ReturnUnion16BytesNestedFloat(Struct8BytesHomogeneousFloat a0) { std::cout << "ReturnUnion16BytesNestedFloat" << "((" << a0.a0 << ", " << a0.a1 << "))" << "\n"; Union16BytesNestedFloat result; result.a0.a0 = a0.a0; result.a0.a1 = a0.a1; std::cout << "result = " << "((" << result.a0.a0 << ", " << result.a0.a1 << "), (" << result.a1.a0 << ", " << result.a1.a1 << ", " << result.a1.a2 << "), (" << result.a2.a0 << ", " << result.a2.a1 << ", " << result.a2.a2 << ", " << result.a2.a3 << "))" << "\n"; return result; } // Used for testing structs and unions by value. // Test that a struct passed in as argument can be returned. // Especially for ffi callbacks. // Struct is passed in int registers in most ABIs. DART_EXPORT Struct1ByteInt ReturnStructArgumentStruct1ByteInt(Struct1ByteInt a0) { std::cout << "ReturnStructArgumentStruct1ByteInt" << "((" << static_cast(a0.a0) << "))" << "\n"; Struct1ByteInt result = a0; std::cout << "result = " << "(" << static_cast(result.a0) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Test that a struct passed in as argument can be returned. // Especially for ffi callbacks. // Struct is passed on stack on all ABIs. DART_EXPORT Struct1ByteInt ReturnStructArgumentInt32x8Struct1ByteInt(int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, Struct1ByteInt a8) { std::cout << "ReturnStructArgumentInt32x8Struct1ByteInt" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7 << ", (" << static_cast(a8.a0) << "))" << "\n"; Struct1ByteInt result = a8; std::cout << "result = " << "(" << static_cast(result.a0) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Test that a struct passed in as argument can be returned. // Especially for ffi callbacks. // Struct is passed in float registers in most ABIs. DART_EXPORT Struct8BytesHomogeneousFloat ReturnStructArgumentStruct8BytesHomogeneousFloat( Struct8BytesHomogeneousFloat a0) { std::cout << "ReturnStructArgumentStruct8BytesHomogeneousFloat" << "((" << a0.a0 << ", " << a0.a1 << "))" << "\n"; Struct8BytesHomogeneousFloat result = a0; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // On arm64, both argument and return value are passed in by pointer. DART_EXPORT Struct20BytesHomogeneousInt32 ReturnStructArgumentStruct20BytesHomogeneousInt32( Struct20BytesHomogeneousInt32 a0) { std::cout << "ReturnStructArgumentStruct20BytesHomogeneousInt32" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << "))" << "\n"; Struct20BytesHomogeneousInt32 result = a0; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // On arm64, both argument and return value are passed in by pointer. // Ints exhaust registers, so that pointer is passed on stack. DART_EXPORT Struct20BytesHomogeneousInt32 ReturnStructArgumentInt32x8Struct20BytesHomogeneou( int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, Struct20BytesHomogeneousInt32 a8) { std::cout << "ReturnStructArgumentInt32x8Struct20BytesHomogeneou" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7 << ", (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << ", " << a8.a3 << ", " << a8.a4 << "))" << "\n"; Struct20BytesHomogeneousInt32 result = a8; std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Test returning struct with inline array. DART_EXPORT Struct8BytesInlineArrayInt ReturnStructArgumentStruct8BytesInlineArrayInt(Struct8BytesInlineArrayInt a0) { std::cout << "ReturnStructArgumentStruct8BytesInlineArrayInt" << "(([" << static_cast(a0.a0[0]) << ", " << static_cast(a0.a0[1]) << ", " << static_cast(a0.a0[2]) << ", " << static_cast(a0.a0[3]) << ", " << static_cast(a0.a0[4]) << ", " << static_cast(a0.a0[5]) << ", " << static_cast(a0.a0[6]) << ", " << static_cast(a0.a0[7]) << "]))" << "\n"; Struct8BytesInlineArrayInt result = a0; std::cout << "result = " << "([" << static_cast(result.a0[0]) << ", " << static_cast(result.a0[1]) << ", " << static_cast(result.a0[2]) << ", " << static_cast(result.a0[3]) << ", " << static_cast(result.a0[4]) << ", " << static_cast(result.a0[5]) << ", " << static_cast(result.a0[6]) << ", " << static_cast(result.a0[7]) << "])" << "\n"; return result; } // Used for testing structs and unions by value. // Return value in FPU registers on arm hardfp and arm64. DART_EXPORT StructStruct16BytesHomogeneousFloat2 ReturnStructArgumentStructStruct16BytesHomogeneous( StructStruct16BytesHomogeneousFloat2 a0) { std::cout << "ReturnStructArgumentStructStruct16BytesHomogeneous" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << "), (" << a0.a1[1].a0 << ")], " << a0.a2 << "))" << "\n"; StructStruct16BytesHomogeneousFloat2 result = a0; std::cout << "result = " << "((" << result.a0.a0 << "), [(" << result.a1[0].a0 << "), (" << result.a1[1].a0 << ")], " << result.a2 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Return value in FPU registers on arm64. DART_EXPORT StructStruct32BytesHomogeneousDouble2 ReturnStructArgumentStructStruct32BytesHomogeneous( StructStruct32BytesHomogeneousDouble2 a0) { std::cout << "ReturnStructArgumentStructStruct32BytesHomogeneous" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << "), (" << a0.a1[1].a0 << ")], " << a0.a2 << "))" << "\n"; StructStruct32BytesHomogeneousDouble2 result = a0; std::cout << "result = " << "((" << result.a0.a0 << "), [(" << result.a1[0].a0 << "), (" << result.a1[1].a0 << ")], " << result.a2 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // On x64 Linux, return value is split over FP and int registers. DART_EXPORT StructStruct16BytesMixed3 ReturnStructArgumentStructStruct16BytesMixed3(StructStruct16BytesMixed3 a0) { std::cout << "ReturnStructArgumentStructStruct16BytesMixed3" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << ", " << a0.a1[0].a1 << ", " << a0.a1[0].a2 << ")], [" << a0.a2[0] << ", " << a0.a2[1] << "]))" << "\n"; StructStruct16BytesMixed3 result = a0; std::cout << "result = " << "((" << result.a0.a0 << "), [(" << result.a1[0].a0 << ", " << result.a1[0].a1 << ", " << result.a1[0].a2 << ")], [" << result.a2[0] << ", " << result.a2[1] << "])" << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of 16 byte int within struct. DART_EXPORT StructAlignmentInt16 ReturnStructAlignmentInt16(int8_t a0, int16_t a1, int8_t a2) { std::cout << "ReturnStructAlignmentInt16" << "(" << static_cast(a0) << ", " << a1 << ", " << static_cast(a2) << ")" << "\n"; StructAlignmentInt16 result; result.a0 = a0; result.a1 = a1; result.a2 = a2; std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ", " << static_cast(result.a2) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of 32 byte int within struct. DART_EXPORT StructAlignmentInt32 ReturnStructAlignmentInt32(int8_t a0, int32_t a1, int8_t a2) { std::cout << "ReturnStructAlignmentInt32" << "(" << static_cast(a0) << ", " << a1 << ", " << static_cast(a2) << ")" << "\n"; StructAlignmentInt32 result; result.a0 = a0; result.a1 = a1; result.a2 = a2; std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ", " << static_cast(result.a2) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of 64 byte int within struct. DART_EXPORT StructAlignmentInt64 ReturnStructAlignmentInt64(int8_t a0, int64_t a1, int8_t a2) { std::cout << "ReturnStructAlignmentInt64" << "(" << static_cast(a0) << ", " << a1 << ", " << static_cast(a2) << ")" << "\n"; StructAlignmentInt64 result; result.a0 = a0; result.a1 = a1; result.a2 = a2; std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ", " << static_cast(result.a2) << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Simple nested struct. DART_EXPORT Struct8BytesNestedInt ReturnStruct8BytesNestedInt(Struct4BytesHomogeneousInt16 a0, Struct4BytesHomogeneousInt16 a1) { std::cout << "ReturnStruct8BytesNestedInt" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", " << a1.a1 << "))" << "\n"; Struct8BytesNestedInt result; result.a0.a0 = a0.a0; result.a0.a1 = a0.a1; result.a1.a0 = a1.a0; result.a1.a1 = a1.a1; std::cout << "result = " << "((" << result.a0.a0 << ", " << result.a0.a1 << "), (" << result.a1.a0 << ", " << result.a1.a1 << "))" << "\n"; return result; } // Used for testing structs and unions by value. // Simple nested struct with floats. DART_EXPORT Struct8BytesNestedFloat ReturnStruct8BytesNestedFloat(Struct4BytesFloat a0, Struct4BytesFloat a1) { std::cout << "ReturnStruct8BytesNestedFloat" << "((" << a0.a0 << "), (" << a1.a0 << "))" << "\n"; Struct8BytesNestedFloat result; result.a0.a0 = a0.a0; result.a1.a0 = a1.a0; std::cout << "result = " << "((" << result.a0.a0 << "), (" << result.a1.a0 << "))" << "\n"; return result; } // Used for testing structs and unions by value. // The nesting is irregular, testing homogenous float rules on arm and arm64, // and the fpu register usage on x64. DART_EXPORT Struct8BytesNestedFloat2 ReturnStruct8BytesNestedFloat2(Struct4BytesFloat a0, float a1) { std::cout << "ReturnStruct8BytesNestedFloat2" << "((" << a0.a0 << "), " << a1 << ")" << "\n"; Struct8BytesNestedFloat2 result; result.a0.a0 = a0.a0; result.a1 = a1; std::cout << "result = " << "((" << result.a0.a0 << "), " << result.a1 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Simple nested struct with mixed members. DART_EXPORT Struct8BytesNestedMixed ReturnStruct8BytesNestedMixed(Struct4BytesHomogeneousInt16 a0, Struct4BytesFloat a1) { std::cout << "ReturnStruct8BytesNestedMixed" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << "))" << "\n"; Struct8BytesNestedMixed result; result.a0.a0 = a0.a0; result.a0.a1 = a0.a1; result.a1.a0 = a1.a0; std::cout << "result = " << "((" << result.a0.a0 << ", " << result.a0.a1 << "), (" << result.a1.a0 << "))" << "\n"; return result; } // Used for testing structs and unions by value. // Deeper nested struct to test recursive member access. DART_EXPORT Struct16BytesNestedInt ReturnStruct16BytesNestedInt(Struct8BytesNestedInt a0, Struct8BytesNestedInt a1) { std::cout << "ReturnStruct16BytesNestedInt" << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0 << ", " << a0.a1.a1 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << "), (" << a1.a1.a0 << ", " << a1.a1.a1 << ")))" << "\n"; Struct16BytesNestedInt result; result.a0.a0.a0 = a0.a0.a0; result.a0.a0.a1 = a0.a0.a1; result.a0.a1.a0 = a0.a1.a0; result.a0.a1.a1 = a0.a1.a1; result.a1.a0.a0 = a1.a0.a0; result.a1.a0.a1 = a1.a0.a1; result.a1.a1.a0 = a1.a1.a0; result.a1.a1.a1 = a1.a1.a1; std::cout << "result = " << "(((" << result.a0.a0.a0 << ", " << result.a0.a0.a1 << "), (" << result.a0.a1.a0 << ", " << result.a0.a1.a1 << ")), ((" << result.a1.a0.a0 << ", " << result.a1.a0.a1 << "), (" << result.a1.a1.a0 << ", " << result.a1.a1.a1 << ")))" << "\n"; return result; } // Used for testing structs and unions by value. // Even deeper nested struct to test recursive member access. DART_EXPORT Struct32BytesNestedInt ReturnStruct32BytesNestedInt(Struct16BytesNestedInt a0, Struct16BytesNestedInt a1) { std::cout << "ReturnStruct32BytesNestedInt" << "((((" << a0.a0.a0.a0 << ", " << a0.a0.a0.a1 << "), (" << a0.a0.a1.a0 << ", " << a0.a0.a1.a1 << ")), ((" << a0.a1.a0.a0 << ", " << a0.a1.a0.a1 << "), (" << a0.a1.a1.a0 << ", " << a0.a1.a1.a1 << "))), (((" << a1.a0.a0.a0 << ", " << a1.a0.a0.a1 << "), (" << a1.a0.a1.a0 << ", " << a1.a0.a1.a1 << ")), ((" << a1.a1.a0.a0 << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0 << ", " << a1.a1.a1.a1 << "))))" << "\n"; Struct32BytesNestedInt result; result.a0.a0.a0.a0 = a0.a0.a0.a0; result.a0.a0.a0.a1 = a0.a0.a0.a1; result.a0.a0.a1.a0 = a0.a0.a1.a0; result.a0.a0.a1.a1 = a0.a0.a1.a1; result.a0.a1.a0.a0 = a0.a1.a0.a0; result.a0.a1.a0.a1 = a0.a1.a0.a1; result.a0.a1.a1.a0 = a0.a1.a1.a0; result.a0.a1.a1.a1 = a0.a1.a1.a1; result.a1.a0.a0.a0 = a1.a0.a0.a0; result.a1.a0.a0.a1 = a1.a0.a0.a1; result.a1.a0.a1.a0 = a1.a0.a1.a0; result.a1.a0.a1.a1 = a1.a0.a1.a1; result.a1.a1.a0.a0 = a1.a1.a0.a0; result.a1.a1.a0.a1 = a1.a1.a0.a1; result.a1.a1.a1.a0 = a1.a1.a1.a0; result.a1.a1.a1.a1 = a1.a1.a1.a1; std::cout << "result = " << "((((" << result.a0.a0.a0.a0 << ", " << result.a0.a0.a0.a1 << "), (" << result.a0.a0.a1.a0 << ", " << result.a0.a0.a1.a1 << ")), ((" << result.a0.a1.a0.a0 << ", " << result.a0.a1.a0.a1 << "), (" << result.a0.a1.a1.a0 << ", " << result.a0.a1.a1.a1 << "))), (((" << result.a1.a0.a0.a0 << ", " << result.a1.a0.a0.a1 << "), (" << result.a1.a0.a1.a0 << ", " << result.a1.a0.a1.a1 << ")), ((" << result.a1.a1.a0.a0 << ", " << result.a1.a1.a0.a1 << "), (" << result.a1.a1.a1.a0 << ", " << result.a1.a1.a1.a1 << "))))" << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 16 byte int. DART_EXPORT StructNestedIntStructAlignmentInt16 ReturnStructNestedIntStructAlignmentInt16(StructAlignmentInt16 a0, StructAlignmentInt16 a1) { std::cout << "ReturnStructNestedIntStructAlignmentInt16" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "), (" << static_cast(a1.a0) << ", " << a1.a1 << ", " << static_cast(a1.a2) << "))" << "\n"; StructNestedIntStructAlignmentInt16 result; result.a0.a0 = a0.a0; result.a0.a1 = a0.a1; result.a0.a2 = a0.a2; result.a1.a0 = a1.a0; result.a1.a1 = a1.a1; result.a1.a2 = a1.a2; std::cout << "result = " << "((" << static_cast(result.a0.a0) << ", " << result.a0.a1 << ", " << static_cast(result.a0.a2) << "), (" << static_cast(result.a1.a0) << ", " << result.a1.a1 << ", " << static_cast(result.a1.a2) << "))" << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 32 byte int. DART_EXPORT StructNestedIntStructAlignmentInt32 ReturnStructNestedIntStructAlignmentInt32(StructAlignmentInt32 a0, StructAlignmentInt32 a1) { std::cout << "ReturnStructNestedIntStructAlignmentInt32" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "), (" << static_cast(a1.a0) << ", " << a1.a1 << ", " << static_cast(a1.a2) << "))" << "\n"; StructNestedIntStructAlignmentInt32 result; result.a0.a0 = a0.a0; result.a0.a1 = a0.a1; result.a0.a2 = a0.a2; result.a1.a0 = a1.a0; result.a1.a1 = a1.a1; result.a1.a2 = a1.a2; std::cout << "result = " << "((" << static_cast(result.a0.a0) << ", " << result.a0.a1 << ", " << static_cast(result.a0.a2) << "), (" << static_cast(result.a1.a0) << ", " << result.a1.a1 << ", " << static_cast(result.a1.a2) << "))" << "\n"; return result; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 64 byte int. DART_EXPORT StructNestedIntStructAlignmentInt64 ReturnStructNestedIntStructAlignmentInt64(StructAlignmentInt64 a0, StructAlignmentInt64 a1) { std::cout << "ReturnStructNestedIntStructAlignmentInt64" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "), (" << static_cast(a1.a0) << ", " << a1.a1 << ", " << static_cast(a1.a2) << "))" << "\n"; StructNestedIntStructAlignmentInt64 result; result.a0.a0 = a0.a0; result.a0.a1 = a0.a1; result.a0.a2 = a0.a2; result.a1.a0 = a1.a0; result.a1.a1 = a1.a1; result.a1.a2 = a1.a2; std::cout << "result = " << "((" << static_cast(result.a0.a0) << ", " << result.a0.a1 << ", " << static_cast(result.a0.a2) << "), (" << static_cast(result.a1.a0) << ", " << result.a1.a1 << ", " << static_cast(result.a1.a2) << "))" << "\n"; return result; } // Used for testing structs and unions by value. // Return big irregular struct as smoke test. DART_EXPORT StructNestedIrregularEvenBigger ReturnStructNestedIrregularEvenBigger(uint64_t a0, StructNestedIrregularBigger a1, StructNestedIrregularBigger a2, double a3) { std::cout << "ReturnStructNestedIrregularEvenBigger" << "(" << a0 << ", ((" << a1.a0.a0 << ", ((" << a1.a0.a1.a0.a0 << ", " << a1.a0.a1.a0.a1 << "), (" << a1.a0.a1.a1.a0 << ")), " << a1.a0.a2 << ", ((" << a1.a0.a3.a0.a0 << "), " << a1.a0.a3.a1 << "), " << a1.a0.a4 << ", ((" << a1.a0.a5.a0.a0 << "), (" << a1.a0.a5.a1.a0 << ")), " << a1.a0.a6 << "), ((" << a1.a1.a0.a0 << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0 << ")), " << a1.a2 << ", " << a1.a3 << "), ((" << a2.a0.a0 << ", ((" << a2.a0.a1.a0.a0 << ", " << a2.a0.a1.a0.a1 << "), (" << a2.a0.a1.a1.a0 << ")), " << a2.a0.a2 << ", ((" << a2.a0.a3.a0.a0 << "), " << a2.a0.a3.a1 << "), " << a2.a0.a4 << ", ((" << a2.a0.a5.a0.a0 << "), (" << a2.a0.a5.a1.a0 << ")), " << a2.a0.a6 << "), ((" << a2.a1.a0.a0 << ", " << a2.a1.a0.a1 << "), (" << a2.a1.a1.a0 << ")), " << a2.a2 << ", " << a2.a3 << "), " << a3 << ")" << "\n"; StructNestedIrregularEvenBigger result; result.a0 = a0; result.a1.a0.a0 = a1.a0.a0; result.a1.a0.a1.a0.a0 = a1.a0.a1.a0.a0; result.a1.a0.a1.a0.a1 = a1.a0.a1.a0.a1; result.a1.a0.a1.a1.a0 = a1.a0.a1.a1.a0; result.a1.a0.a2 = a1.a0.a2; result.a1.a0.a3.a0.a0 = a1.a0.a3.a0.a0; result.a1.a0.a3.a1 = a1.a0.a3.a1; result.a1.a0.a4 = a1.a0.a4; result.a1.a0.a5.a0.a0 = a1.a0.a5.a0.a0; result.a1.a0.a5.a1.a0 = a1.a0.a5.a1.a0; result.a1.a0.a6 = a1.a0.a6; result.a1.a1.a0.a0 = a1.a1.a0.a0; result.a1.a1.a0.a1 = a1.a1.a0.a1; result.a1.a1.a1.a0 = a1.a1.a1.a0; result.a1.a2 = a1.a2; result.a1.a3 = a1.a3; result.a2.a0.a0 = a2.a0.a0; result.a2.a0.a1.a0.a0 = a2.a0.a1.a0.a0; result.a2.a0.a1.a0.a1 = a2.a0.a1.a0.a1; result.a2.a0.a1.a1.a0 = a2.a0.a1.a1.a0; result.a2.a0.a2 = a2.a0.a2; result.a2.a0.a3.a0.a0 = a2.a0.a3.a0.a0; result.a2.a0.a3.a1 = a2.a0.a3.a1; result.a2.a0.a4 = a2.a0.a4; result.a2.a0.a5.a0.a0 = a2.a0.a5.a0.a0; result.a2.a0.a5.a1.a0 = a2.a0.a5.a1.a0; result.a2.a0.a6 = a2.a0.a6; result.a2.a1.a0.a0 = a2.a1.a0.a0; result.a2.a1.a0.a1 = a2.a1.a0.a1; result.a2.a1.a1.a0 = a2.a1.a1.a0; result.a2.a2 = a2.a2; result.a2.a3 = a2.a3; result.a3 = a3; std::cout << "result = " << "(" << result.a0 << ", ((" << result.a1.a0.a0 << ", ((" << result.a1.a0.a1.a0.a0 << ", " << result.a1.a0.a1.a0.a1 << "), (" << result.a1.a0.a1.a1.a0 << ")), " << result.a1.a0.a2 << ", ((" << result.a1.a0.a3.a0.a0 << "), " << result.a1.a0.a3.a1 << "), " << result.a1.a0.a4 << ", ((" << result.a1.a0.a5.a0.a0 << "), (" << result.a1.a0.a5.a1.a0 << ")), " << result.a1.a0.a6 << "), ((" << result.a1.a1.a0.a0 << ", " << result.a1.a1.a0.a1 << "), (" << result.a1.a1.a1.a0 << ")), " << result.a1.a2 << ", " << result.a1.a3 << "), ((" << result.a2.a0.a0 << ", ((" << result.a2.a0.a1.a0.a0 << ", " << result.a2.a0.a1.a0.a1 << "), (" << result.a2.a0.a1.a1.a0 << ")), " << result.a2.a0.a2 << ", ((" << result.a2.a0.a3.a0.a0 << "), " << result.a2.a0.a3.a1 << "), " << result.a2.a0.a4 << ", ((" << result.a2.a0.a5.a0.a0 << "), (" << result.a2.a0.a5.a1.a0 << ")), " << result.a2.a0.a6 << "), ((" << result.a2.a1.a0.a0 << ", " << result.a2.a1.a0.a1 << "), (" << result.a2.a1.a1.a0 << ")), " << result.a2.a2 << ", " << result.a2.a3 << "), " << result.a3 << ")" << "\n"; return result; } // Used for testing structs and unions by value. // Smallest struct with data. // 10 struct arguments will exhaust available registers. DART_EXPORT intptr_t TestPassStruct1ByteIntx10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct1ByteInt a0, Struct1ByteInt a1, Struct1ByteInt a2, Struct1ByteInt a3, Struct1ByteInt a4, Struct1ByteInt a5, Struct1ByteInt a6, Struct1ByteInt a7, Struct1ByteInt a8, Struct1ByteInt a9)) { Struct1ByteInt a0; Struct1ByteInt a1; Struct1ByteInt a2; Struct1ByteInt a3; Struct1ByteInt a4; Struct1ByteInt a5; Struct1ByteInt a6; Struct1ByteInt a7; Struct1ByteInt a8; Struct1ByteInt a9; a0.a0 = -1; a1.a0 = 2; a2.a0 = -3; a3.a0 = 4; a4.a0 = -5; a5.a0 = 6; a6.a0 = -7; a7.a0 = 8; a8.a0 = -9; a9.a0 = 10; std::cout << "Calling TestPassStruct1ByteIntx10(" << "((" << static_cast(a0.a0) << "), (" << static_cast(a1.a0) << "), (" << static_cast(a2.a0) << "), (" << static_cast(a3.a0) << "), (" << static_cast(a4.a0) << "), (" << static_cast(a5.a0) << "), (" << static_cast(a6.a0) << "), (" << static_cast(a7.a0) << "), (" << static_cast(a8.a0) << "), (" << static_cast(a9.a0) << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(5, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Not a multiple of word size, not a power of two. // 10 struct arguments will exhaust available registers. DART_EXPORT intptr_t TestPassStruct3BytesHomogeneousUint8x10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct3BytesHomogeneousUint8 a0, Struct3BytesHomogeneousUint8 a1, Struct3BytesHomogeneousUint8 a2, Struct3BytesHomogeneousUint8 a3, Struct3BytesHomogeneousUint8 a4, Struct3BytesHomogeneousUint8 a5, Struct3BytesHomogeneousUint8 a6, Struct3BytesHomogeneousUint8 a7, Struct3BytesHomogeneousUint8 a8, Struct3BytesHomogeneousUint8 a9)) { Struct3BytesHomogeneousUint8 a0; Struct3BytesHomogeneousUint8 a1; Struct3BytesHomogeneousUint8 a2; Struct3BytesHomogeneousUint8 a3; Struct3BytesHomogeneousUint8 a4; Struct3BytesHomogeneousUint8 a5; Struct3BytesHomogeneousUint8 a6; Struct3BytesHomogeneousUint8 a7; Struct3BytesHomogeneousUint8 a8; Struct3BytesHomogeneousUint8 a9; a0.a0 = 1; a0.a1 = 2; a0.a2 = 3; a1.a0 = 4; a1.a1 = 5; a1.a2 = 6; a2.a0 = 7; a2.a1 = 8; a2.a2 = 9; a3.a0 = 10; a3.a1 = 11; a3.a2 = 12; a4.a0 = 13; a4.a1 = 14; a4.a2 = 15; a5.a0 = 16; a5.a1 = 17; a5.a2 = 18; a6.a0 = 19; a6.a1 = 20; a6.a2 = 21; a7.a0 = 22; a7.a1 = 23; a7.a2 = 24; a8.a0 = 25; a8.a1 = 26; a8.a2 = 27; a9.a0 = 28; a9.a1 = 29; a9.a2 = 30; std::cout << "Calling TestPassStruct3BytesHomogeneousUint8x10(" << "((" << static_cast(a0.a0) << ", " << static_cast(a0.a1) << ", " << static_cast(a0.a2) << "), (" << static_cast(a1.a0) << ", " << static_cast(a1.a1) << ", " << static_cast(a1.a2) << "), (" << static_cast(a2.a0) << ", " << static_cast(a2.a1) << ", " << static_cast(a2.a2) << "), (" << static_cast(a3.a0) << ", " << static_cast(a3.a1) << ", " << static_cast(a3.a2) << "), (" << static_cast(a4.a0) << ", " << static_cast(a4.a1) << ", " << static_cast(a4.a2) << "), (" << static_cast(a5.a0) << ", " << static_cast(a5.a1) << ", " << static_cast(a5.a2) << "), (" << static_cast(a6.a0) << ", " << static_cast(a6.a1) << ", " << static_cast(a6.a2) << "), (" << static_cast(a7.a0) << ", " << static_cast(a7.a1) << ", " << static_cast(a7.a2) << "), (" << static_cast(a8.a0) << ", " << static_cast(a8.a1) << ", " << static_cast(a8.a2) << "), (" << static_cast(a9.a0) << ", " << static_cast(a9.a1) << ", " << static_cast(a9.a2) << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(465, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassStruct3BytesInt2ByteAlignedx10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct3BytesInt2ByteAligned a0, Struct3BytesInt2ByteAligned a1, Struct3BytesInt2ByteAligned a2, Struct3BytesInt2ByteAligned a3, Struct3BytesInt2ByteAligned a4, Struct3BytesInt2ByteAligned a5, Struct3BytesInt2ByteAligned a6, Struct3BytesInt2ByteAligned a7, Struct3BytesInt2ByteAligned a8, Struct3BytesInt2ByteAligned a9)) { Struct3BytesInt2ByteAligned a0; Struct3BytesInt2ByteAligned a1; Struct3BytesInt2ByteAligned a2; Struct3BytesInt2ByteAligned a3; Struct3BytesInt2ByteAligned a4; Struct3BytesInt2ByteAligned a5; Struct3BytesInt2ByteAligned a6; Struct3BytesInt2ByteAligned a7; Struct3BytesInt2ByteAligned a8; Struct3BytesInt2ByteAligned a9; a0.a0 = -1; a0.a1 = 2; a1.a0 = -3; a1.a1 = 4; a2.a0 = -5; a2.a1 = 6; a3.a0 = -7; a3.a1 = 8; a4.a0 = -9; a4.a1 = 10; a5.a0 = -11; a5.a1 = 12; a6.a0 = -13; a6.a1 = 14; a7.a0 = -15; a7.a1 = 16; a8.a0 = -17; a8.a1 = 18; a9.a0 = -19; a9.a1 = 20; std::cout << "Calling TestPassStruct3BytesInt2ByteAlignedx10(" << "((" << a0.a0 << ", " << static_cast(a0.a1) << "), (" << a1.a0 << ", " << static_cast(a1.a1) << "), (" << a2.a0 << ", " << static_cast(a2.a1) << "), (" << a3.a0 << ", " << static_cast(a3.a1) << "), (" << a4.a0 << ", " << static_cast(a4.a1) << "), (" << a5.a0 << ", " << static_cast(a5.a1) << "), (" << a6.a0 << ", " << static_cast(a6.a1) << "), (" << a7.a0 << ", " << static_cast(a7.a1) << "), (" << a8.a0 << ", " << static_cast(a8.a1) << "), (" << a9.a0 << ", " << static_cast(a9.a1) << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(10, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Exactly word size on 32-bit architectures. // 10 struct arguments will exhaust available registers. DART_EXPORT intptr_t TestPassStruct4BytesHomogeneousInt16x10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct4BytesHomogeneousInt16 a0, Struct4BytesHomogeneousInt16 a1, Struct4BytesHomogeneousInt16 a2, Struct4BytesHomogeneousInt16 a3, Struct4BytesHomogeneousInt16 a4, Struct4BytesHomogeneousInt16 a5, Struct4BytesHomogeneousInt16 a6, Struct4BytesHomogeneousInt16 a7, Struct4BytesHomogeneousInt16 a8, Struct4BytesHomogeneousInt16 a9)) { Struct4BytesHomogeneousInt16 a0; Struct4BytesHomogeneousInt16 a1; Struct4BytesHomogeneousInt16 a2; Struct4BytesHomogeneousInt16 a3; Struct4BytesHomogeneousInt16 a4; Struct4BytesHomogeneousInt16 a5; Struct4BytesHomogeneousInt16 a6; Struct4BytesHomogeneousInt16 a7; Struct4BytesHomogeneousInt16 a8; Struct4BytesHomogeneousInt16 a9; a0.a0 = -1; a0.a1 = 2; a1.a0 = -3; a1.a1 = 4; a2.a0 = -5; a2.a1 = 6; a3.a0 = -7; a3.a1 = 8; a4.a0 = -9; a4.a1 = 10; a5.a0 = -11; a5.a1 = 12; a6.a0 = -13; a6.a1 = 14; a7.a0 = -15; a7.a1 = 16; a8.a0 = -17; a8.a1 = 18; a9.a0 = -19; a9.a1 = 20; std::cout << "Calling TestPassStruct4BytesHomogeneousInt16x10(" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", " << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0 << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(10, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Sub word size on 64 bit architectures. // 10 struct arguments will exhaust available registers. DART_EXPORT intptr_t TestPassStruct7BytesHomogeneousUint8x10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct7BytesHomogeneousUint8 a0, Struct7BytesHomogeneousUint8 a1, Struct7BytesHomogeneousUint8 a2, Struct7BytesHomogeneousUint8 a3, Struct7BytesHomogeneousUint8 a4, Struct7BytesHomogeneousUint8 a5, Struct7BytesHomogeneousUint8 a6, Struct7BytesHomogeneousUint8 a7, Struct7BytesHomogeneousUint8 a8, Struct7BytesHomogeneousUint8 a9)) { Struct7BytesHomogeneousUint8 a0; Struct7BytesHomogeneousUint8 a1; Struct7BytesHomogeneousUint8 a2; Struct7BytesHomogeneousUint8 a3; Struct7BytesHomogeneousUint8 a4; Struct7BytesHomogeneousUint8 a5; Struct7BytesHomogeneousUint8 a6; Struct7BytesHomogeneousUint8 a7; Struct7BytesHomogeneousUint8 a8; Struct7BytesHomogeneousUint8 a9; a0.a0 = 1; a0.a1 = 2; a0.a2 = 3; a0.a3 = 4; a0.a4 = 5; a0.a5 = 6; a0.a6 = 7; a1.a0 = 8; a1.a1 = 9; a1.a2 = 10; a1.a3 = 11; a1.a4 = 12; a1.a5 = 13; a1.a6 = 14; a2.a0 = 15; a2.a1 = 16; a2.a2 = 17; a2.a3 = 18; a2.a4 = 19; a2.a5 = 20; a2.a6 = 21; a3.a0 = 22; a3.a1 = 23; a3.a2 = 24; a3.a3 = 25; a3.a4 = 26; a3.a5 = 27; a3.a6 = 28; a4.a0 = 29; a4.a1 = 30; a4.a2 = 31; a4.a3 = 32; a4.a4 = 33; a4.a5 = 34; a4.a6 = 35; a5.a0 = 36; a5.a1 = 37; a5.a2 = 38; a5.a3 = 39; a5.a4 = 40; a5.a5 = 41; a5.a6 = 42; a6.a0 = 43; a6.a1 = 44; a6.a2 = 45; a6.a3 = 46; a6.a4 = 47; a6.a5 = 48; a6.a6 = 49; a7.a0 = 50; a7.a1 = 51; a7.a2 = 52; a7.a3 = 53; a7.a4 = 54; a7.a5 = 55; a7.a6 = 56; a8.a0 = 57; a8.a1 = 58; a8.a2 = 59; a8.a3 = 60; a8.a4 = 61; a8.a5 = 62; a8.a6 = 63; a9.a0 = 64; a9.a1 = 65; a9.a2 = 66; a9.a3 = 67; a9.a4 = 68; a9.a5 = 69; a9.a6 = 70; std::cout << "Calling TestPassStruct7BytesHomogeneousUint8x10(" << "((" << static_cast(a0.a0) << ", " << static_cast(a0.a1) << ", " << static_cast(a0.a2) << ", " << static_cast(a0.a3) << ", " << static_cast(a0.a4) << ", " << static_cast(a0.a5) << ", " << static_cast(a0.a6) << "), (" << static_cast(a1.a0) << ", " << static_cast(a1.a1) << ", " << static_cast(a1.a2) << ", " << static_cast(a1.a3) << ", " << static_cast(a1.a4) << ", " << static_cast(a1.a5) << ", " << static_cast(a1.a6) << "), (" << static_cast(a2.a0) << ", " << static_cast(a2.a1) << ", " << static_cast(a2.a2) << ", " << static_cast(a2.a3) << ", " << static_cast(a2.a4) << ", " << static_cast(a2.a5) << ", " << static_cast(a2.a6) << "), (" << static_cast(a3.a0) << ", " << static_cast(a3.a1) << ", " << static_cast(a3.a2) << ", " << static_cast(a3.a3) << ", " << static_cast(a3.a4) << ", " << static_cast(a3.a5) << ", " << static_cast(a3.a6) << "), (" << static_cast(a4.a0) << ", " << static_cast(a4.a1) << ", " << static_cast(a4.a2) << ", " << static_cast(a4.a3) << ", " << static_cast(a4.a4) << ", " << static_cast(a4.a5) << ", " << static_cast(a4.a6) << "), (" << static_cast(a5.a0) << ", " << static_cast(a5.a1) << ", " << static_cast(a5.a2) << ", " << static_cast(a5.a3) << ", " << static_cast(a5.a4) << ", " << static_cast(a5.a5) << ", " << static_cast(a5.a6) << "), (" << static_cast(a6.a0) << ", " << static_cast(a6.a1) << ", " << static_cast(a6.a2) << ", " << static_cast(a6.a3) << ", " << static_cast(a6.a4) << ", " << static_cast(a6.a5) << ", " << static_cast(a6.a6) << "), (" << static_cast(a7.a0) << ", " << static_cast(a7.a1) << ", " << static_cast(a7.a2) << ", " << static_cast(a7.a3) << ", " << static_cast(a7.a4) << ", " << static_cast(a7.a5) << ", " << static_cast(a7.a6) << "), (" << static_cast(a8.a0) << ", " << static_cast(a8.a1) << ", " << static_cast(a8.a2) << ", " << static_cast(a8.a3) << ", " << static_cast(a8.a4) << ", " << static_cast(a8.a5) << ", " << static_cast(a8.a6) << "), (" << static_cast(a9.a0) << ", " << static_cast(a9.a1) << ", " << static_cast(a9.a2) << ", " << static_cast(a9.a3) << ", " << static_cast(a9.a4) << ", " << static_cast(a9.a5) << ", " << static_cast(a9.a6) << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(2485, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Sub word size on 64 bit architectures. // With alignment rules taken into account size is 8 bytes. // 10 struct arguments will exhaust available registers. DART_EXPORT intptr_t TestPassStruct7BytesInt4ByteAlignedx10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct7BytesInt4ByteAligned a0, Struct7BytesInt4ByteAligned a1, Struct7BytesInt4ByteAligned a2, Struct7BytesInt4ByteAligned a3, Struct7BytesInt4ByteAligned a4, Struct7BytesInt4ByteAligned a5, Struct7BytesInt4ByteAligned a6, Struct7BytesInt4ByteAligned a7, Struct7BytesInt4ByteAligned a8, Struct7BytesInt4ByteAligned a9)) { Struct7BytesInt4ByteAligned a0; Struct7BytesInt4ByteAligned a1; Struct7BytesInt4ByteAligned a2; Struct7BytesInt4ByteAligned a3; Struct7BytesInt4ByteAligned a4; Struct7BytesInt4ByteAligned a5; Struct7BytesInt4ByteAligned a6; Struct7BytesInt4ByteAligned a7; Struct7BytesInt4ByteAligned a8; Struct7BytesInt4ByteAligned a9; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; a1.a0 = 4; a1.a1 = -5; a1.a2 = 6; a2.a0 = -7; a2.a1 = 8; a2.a2 = -9; a3.a0 = 10; a3.a1 = -11; a3.a2 = 12; a4.a0 = -13; a4.a1 = 14; a4.a2 = -15; a5.a0 = 16; a5.a1 = -17; a5.a2 = 18; a6.a0 = -19; a6.a1 = 20; a6.a2 = -21; a7.a0 = 22; a7.a1 = -23; a7.a2 = 24; a8.a0 = -25; a8.a1 = 26; a8.a2 = -27; a9.a0 = 28; a9.a1 = -29; a9.a2 = 30; std::cout << "Calling TestPassStruct7BytesInt4ByteAlignedx10(" << "((" << a0.a0 << ", " << a0.a1 << ", " << static_cast(a0.a2) << "), (" << a1.a0 << ", " << a1.a1 << ", " << static_cast(a1.a2) << "), (" << a2.a0 << ", " << a2.a1 << ", " << static_cast(a2.a2) << "), (" << a3.a0 << ", " << a3.a1 << ", " << static_cast(a3.a2) << "), (" << a4.a0 << ", " << a4.a1 << ", " << static_cast(a4.a2) << "), (" << a5.a0 << ", " << a5.a1 << ", " << static_cast(a5.a2) << "), (" << a6.a0 << ", " << a6.a1 << ", " << static_cast(a6.a2) << "), (" << a7.a0 << ", " << a7.a1 << ", " << static_cast(a7.a2) << "), (" << a8.a0 << ", " << a8.a1 << ", " << static_cast(a8.a2) << "), (" << a9.a0 << ", " << a9.a1 << ", " << static_cast(a9.a2) << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(15, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Exactly word size struct on 64bit architectures. // 10 struct arguments will exhaust available registers. DART_EXPORT intptr_t TestPassStruct8BytesIntx10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct8BytesInt a0, Struct8BytesInt a1, Struct8BytesInt a2, Struct8BytesInt a3, Struct8BytesInt a4, Struct8BytesInt a5, Struct8BytesInt a6, Struct8BytesInt a7, Struct8BytesInt a8, Struct8BytesInt a9)) { Struct8BytesInt a0; Struct8BytesInt a1; Struct8BytesInt a2; Struct8BytesInt a3; Struct8BytesInt a4; Struct8BytesInt a5; Struct8BytesInt a6; Struct8BytesInt a7; Struct8BytesInt a8; Struct8BytesInt a9; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; a1.a0 = 4; a1.a1 = -5; a1.a2 = 6; a2.a0 = -7; a2.a1 = 8; a2.a2 = -9; a3.a0 = 10; a3.a1 = -11; a3.a2 = 12; a4.a0 = -13; a4.a1 = 14; a4.a2 = -15; a5.a0 = 16; a5.a1 = -17; a5.a2 = 18; a6.a0 = -19; a6.a1 = 20; a6.a2 = -21; a7.a0 = 22; a7.a1 = -23; a7.a2 = 24; a8.a0 = -25; a8.a1 = 26; a8.a2 = -27; a9.a0 = 28; a9.a1 = -29; a9.a2 = 30; std::cout << "Calling TestPassStruct8BytesIntx10(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2 << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << "), (" << a9.a0 << ", " << a9.a1 << ", " << a9.a2 << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(15, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Arguments passed in FP registers as long as they fit. // 10 struct arguments will exhaust available registers. DART_EXPORT intptr_t TestPassStruct8BytesHomogeneousFloatx10( // NOLINTNEXTLINE(whitespace/parens) float (*f)(Struct8BytesHomogeneousFloat a0, Struct8BytesHomogeneousFloat a1, Struct8BytesHomogeneousFloat a2, Struct8BytesHomogeneousFloat a3, Struct8BytesHomogeneousFloat a4, Struct8BytesHomogeneousFloat a5, Struct8BytesHomogeneousFloat a6, Struct8BytesHomogeneousFloat a7, Struct8BytesHomogeneousFloat a8, Struct8BytesHomogeneousFloat a9)) { Struct8BytesHomogeneousFloat a0; Struct8BytesHomogeneousFloat a1; Struct8BytesHomogeneousFloat a2; Struct8BytesHomogeneousFloat a3; Struct8BytesHomogeneousFloat a4; Struct8BytesHomogeneousFloat a5; Struct8BytesHomogeneousFloat a6; Struct8BytesHomogeneousFloat a7; Struct8BytesHomogeneousFloat a8; Struct8BytesHomogeneousFloat a9; a0.a0 = -1.0; a0.a1 = 2.0; a1.a0 = -3.0; a1.a1 = 4.0; a2.a0 = -5.0; a2.a1 = 6.0; a3.a0 = -7.0; a3.a1 = 8.0; a4.a0 = -9.0; a4.a1 = 10.0; a5.a0 = -11.0; a5.a1 = 12.0; a6.a0 = -13.0; a6.a1 = 14.0; a7.a0 = -15.0; a7.a1 = 16.0; a8.a0 = -17.0; a8.a1 = 18.0; a9.a0 = -19.0; a9.a1 = 20.0; std::cout << "Calling TestPassStruct8BytesHomogeneousFloatx10(" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", " << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0 << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))" << ")\n"; float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(10.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); 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); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // On x64, arguments go in int registers because it is not only float. // 10 struct arguments will exhaust available registers. DART_EXPORT intptr_t TestPassStruct8BytesMixedx10( // NOLINTNEXTLINE(whitespace/parens) float (*f)(Struct8BytesMixed a0, Struct8BytesMixed a1, Struct8BytesMixed a2, Struct8BytesMixed a3, Struct8BytesMixed a4, Struct8BytesMixed a5, Struct8BytesMixed a6, Struct8BytesMixed a7, Struct8BytesMixed a8, Struct8BytesMixed a9)) { Struct8BytesMixed a0; Struct8BytesMixed a1; Struct8BytesMixed a2; Struct8BytesMixed a3; Struct8BytesMixed a4; Struct8BytesMixed a5; Struct8BytesMixed a6; Struct8BytesMixed a7; Struct8BytesMixed a8; Struct8BytesMixed a9; a0.a0 = -1.0; a0.a1 = 2; a0.a2 = -3; a1.a0 = 4.0; a1.a1 = -5; a1.a2 = 6; a2.a0 = -7.0; a2.a1 = 8; a2.a2 = -9; a3.a0 = 10.0; a3.a1 = -11; a3.a2 = 12; a4.a0 = -13.0; a4.a1 = 14; a4.a2 = -15; a5.a0 = 16.0; a5.a1 = -17; a5.a2 = 18; a6.a0 = -19.0; a6.a1 = 20; a6.a2 = -21; a7.a0 = 22.0; a7.a1 = -23; a7.a2 = 24; a8.a0 = -25.0; a8.a1 = 26; a8.a2 = -27; a9.a0 = 28.0; a9.a1 = -29; a9.a2 = 30; std::cout << "Calling TestPassStruct8BytesMixedx10(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2 << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << "), (" << a9.a0 << ", " << a9.a1 << ", " << a9.a2 << "))" << ")\n"; float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(15.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); 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); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassStruct9BytesHomogeneousUint8x10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct9BytesHomogeneousUint8 a0, Struct9BytesHomogeneousUint8 a1, Struct9BytesHomogeneousUint8 a2, Struct9BytesHomogeneousUint8 a3, Struct9BytesHomogeneousUint8 a4, Struct9BytesHomogeneousUint8 a5, Struct9BytesHomogeneousUint8 a6, Struct9BytesHomogeneousUint8 a7, Struct9BytesHomogeneousUint8 a8, Struct9BytesHomogeneousUint8 a9)) { Struct9BytesHomogeneousUint8 a0; Struct9BytesHomogeneousUint8 a1; Struct9BytesHomogeneousUint8 a2; Struct9BytesHomogeneousUint8 a3; Struct9BytesHomogeneousUint8 a4; Struct9BytesHomogeneousUint8 a5; Struct9BytesHomogeneousUint8 a6; Struct9BytesHomogeneousUint8 a7; Struct9BytesHomogeneousUint8 a8; Struct9BytesHomogeneousUint8 a9; a0.a0 = 1; a0.a1 = 2; a0.a2 = 3; a0.a3 = 4; a0.a4 = 5; a0.a5 = 6; a0.a6 = 7; a0.a7 = 8; a0.a8 = 9; a1.a0 = 10; a1.a1 = 11; a1.a2 = 12; a1.a3 = 13; a1.a4 = 14; a1.a5 = 15; a1.a6 = 16; a1.a7 = 17; a1.a8 = 18; a2.a0 = 19; a2.a1 = 20; a2.a2 = 21; a2.a3 = 22; a2.a4 = 23; a2.a5 = 24; a2.a6 = 25; a2.a7 = 26; a2.a8 = 27; a3.a0 = 28; a3.a1 = 29; a3.a2 = 30; a3.a3 = 31; a3.a4 = 32; a3.a5 = 33; a3.a6 = 34; a3.a7 = 35; a3.a8 = 36; a4.a0 = 37; a4.a1 = 38; a4.a2 = 39; a4.a3 = 40; a4.a4 = 41; a4.a5 = 42; a4.a6 = 43; a4.a7 = 44; a4.a8 = 45; a5.a0 = 46; a5.a1 = 47; a5.a2 = 48; a5.a3 = 49; a5.a4 = 50; a5.a5 = 51; a5.a6 = 52; a5.a7 = 53; a5.a8 = 54; a6.a0 = 55; a6.a1 = 56; a6.a2 = 57; a6.a3 = 58; a6.a4 = 59; a6.a5 = 60; a6.a6 = 61; a6.a7 = 62; a6.a8 = 63; a7.a0 = 64; a7.a1 = 65; a7.a2 = 66; a7.a3 = 67; a7.a4 = 68; a7.a5 = 69; a7.a6 = 70; a7.a7 = 71; a7.a8 = 72; a8.a0 = 73; a8.a1 = 74; a8.a2 = 75; a8.a3 = 76; a8.a4 = 77; a8.a5 = 78; a8.a6 = 79; a8.a7 = 80; a8.a8 = 81; a9.a0 = 82; a9.a1 = 83; a9.a2 = 84; a9.a3 = 85; a9.a4 = 86; a9.a5 = 87; a9.a6 = 88; a9.a7 = 89; a9.a8 = 90; std::cout << "Calling TestPassStruct9BytesHomogeneousUint8x10(" << "((" << static_cast(a0.a0) << ", " << static_cast(a0.a1) << ", " << static_cast(a0.a2) << ", " << static_cast(a0.a3) << ", " << static_cast(a0.a4) << ", " << static_cast(a0.a5) << ", " << static_cast(a0.a6) << ", " << static_cast(a0.a7) << ", " << static_cast(a0.a8) << "), (" << static_cast(a1.a0) << ", " << static_cast(a1.a1) << ", " << static_cast(a1.a2) << ", " << static_cast(a1.a3) << ", " << static_cast(a1.a4) << ", " << static_cast(a1.a5) << ", " << static_cast(a1.a6) << ", " << static_cast(a1.a7) << ", " << static_cast(a1.a8) << "), (" << static_cast(a2.a0) << ", " << static_cast(a2.a1) << ", " << static_cast(a2.a2) << ", " << static_cast(a2.a3) << ", " << static_cast(a2.a4) << ", " << static_cast(a2.a5) << ", " << static_cast(a2.a6) << ", " << static_cast(a2.a7) << ", " << static_cast(a2.a8) << "), (" << static_cast(a3.a0) << ", " << static_cast(a3.a1) << ", " << static_cast(a3.a2) << ", " << static_cast(a3.a3) << ", " << static_cast(a3.a4) << ", " << static_cast(a3.a5) << ", " << static_cast(a3.a6) << ", " << static_cast(a3.a7) << ", " << static_cast(a3.a8) << "), (" << static_cast(a4.a0) << ", " << static_cast(a4.a1) << ", " << static_cast(a4.a2) << ", " << static_cast(a4.a3) << ", " << static_cast(a4.a4) << ", " << static_cast(a4.a5) << ", " << static_cast(a4.a6) << ", " << static_cast(a4.a7) << ", " << static_cast(a4.a8) << "), (" << static_cast(a5.a0) << ", " << static_cast(a5.a1) << ", " << static_cast(a5.a2) << ", " << static_cast(a5.a3) << ", " << static_cast(a5.a4) << ", " << static_cast(a5.a5) << ", " << static_cast(a5.a6) << ", " << static_cast(a5.a7) << ", " << static_cast(a5.a8) << "), (" << static_cast(a6.a0) << ", " << static_cast(a6.a1) << ", " << static_cast(a6.a2) << ", " << static_cast(a6.a3) << ", " << static_cast(a6.a4) << ", " << static_cast(a6.a5) << ", " << static_cast(a6.a6) << ", " << static_cast(a6.a7) << ", " << static_cast(a6.a8) << "), (" << static_cast(a7.a0) << ", " << static_cast(a7.a1) << ", " << static_cast(a7.a2) << ", " << static_cast(a7.a3) << ", " << static_cast(a7.a4) << ", " << static_cast(a7.a5) << ", " << static_cast(a7.a6) << ", " << static_cast(a7.a7) << ", " << static_cast(a7.a8) << "), (" << static_cast(a8.a0) << ", " << static_cast(a8.a1) << ", " << static_cast(a8.a2) << ", " << static_cast(a8.a3) << ", " << static_cast(a8.a4) << ", " << static_cast(a8.a5) << ", " << static_cast(a8.a6) << ", " << static_cast(a8.a7) << ", " << static_cast(a8.a8) << "), (" << static_cast(a9.a0) << ", " << static_cast(a9.a1) << ", " << static_cast(a9.a2) << ", " << static_cast(a9.a3) << ", " << static_cast(a9.a4) << ", " << static_cast(a9.a5) << ", " << static_cast(a9.a6) << ", " << static_cast(a9.a7) << ", " << static_cast(a9.a8) << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(4095, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // 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. // DART_EXPORT intptr_t TestPassStruct9BytesInt4Or8ByteAlignedx10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct9BytesInt4Or8ByteAligned a0, Struct9BytesInt4Or8ByteAligned a1, Struct9BytesInt4Or8ByteAligned a2, Struct9BytesInt4Or8ByteAligned a3, Struct9BytesInt4Or8ByteAligned a4, Struct9BytesInt4Or8ByteAligned a5, Struct9BytesInt4Or8ByteAligned a6, Struct9BytesInt4Or8ByteAligned a7, Struct9BytesInt4Or8ByteAligned a8, Struct9BytesInt4Or8ByteAligned a9)) { Struct9BytesInt4Or8ByteAligned a0; Struct9BytesInt4Or8ByteAligned a1; Struct9BytesInt4Or8ByteAligned a2; Struct9BytesInt4Or8ByteAligned a3; Struct9BytesInt4Or8ByteAligned a4; Struct9BytesInt4Or8ByteAligned a5; Struct9BytesInt4Or8ByteAligned a6; Struct9BytesInt4Or8ByteAligned a7; Struct9BytesInt4Or8ByteAligned a8; Struct9BytesInt4Or8ByteAligned a9; a0.a0 = -1; a0.a1 = 2; a1.a0 = -3; a1.a1 = 4; a2.a0 = -5; a2.a1 = 6; a3.a0 = -7; a3.a1 = 8; a4.a0 = -9; a4.a1 = 10; a5.a0 = -11; a5.a1 = 12; a6.a0 = -13; a6.a1 = 14; a7.a0 = -15; a7.a1 = 16; a8.a0 = -17; a8.a1 = 18; a9.a0 = -19; a9.a1 = 20; std::cout << "Calling TestPassStruct9BytesInt4Or8ByteAlignedx10(" << "((" << a0.a0 << ", " << static_cast(a0.a1) << "), (" << a1.a0 << ", " << static_cast(a1.a1) << "), (" << a2.a0 << ", " << static_cast(a2.a1) << "), (" << a3.a0 << ", " << static_cast(a3.a1) << "), (" << a4.a0 << ", " << static_cast(a4.a1) << "), (" << a5.a0 << ", " << static_cast(a5.a1) << "), (" << a6.a0 << ", " << static_cast(a6.a1) << "), (" << a7.a0 << ", " << static_cast(a7.a1) << "), (" << a8.a0 << ", " << static_cast(a8.a1) << "), (" << a9.a0 << ", " << static_cast(a9.a1) << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(10, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassStruct12BytesHomogeneousFloatx6( // NOLINTNEXTLINE(whitespace/parens) float (*f)(Struct12BytesHomogeneousFloat a0, Struct12BytesHomogeneousFloat a1, Struct12BytesHomogeneousFloat a2, Struct12BytesHomogeneousFloat a3, Struct12BytesHomogeneousFloat a4, Struct12BytesHomogeneousFloat a5)) { Struct12BytesHomogeneousFloat a0; Struct12BytesHomogeneousFloat a1; Struct12BytesHomogeneousFloat a2; Struct12BytesHomogeneousFloat a3; Struct12BytesHomogeneousFloat a4; Struct12BytesHomogeneousFloat a5; a0.a0 = -1.0; a0.a1 = 2.0; a0.a2 = -3.0; a1.a0 = 4.0; a1.a1 = -5.0; a1.a2 = 6.0; a2.a0 = -7.0; a2.a1 = 8.0; a2.a2 = -9.0; a3.a0 = 10.0; a3.a1 = -11.0; a3.a2 = 12.0; a4.a0 = -13.0; a4.a1 = 14.0; a4.a2 = -15.0; a5.a0 = 16.0; a5.a1 = -17.0; a5.a2 = 18.0; std::cout << "Calling TestPassStruct12BytesHomogeneousFloatx6(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << "), (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << "))" << ")\n"; float result = f(a0, a1, a2, a3, a4, a5); std::cout << "result = " << result << "\n"; CHECK_APPROX(9.0, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1, a2, a3, a4, a5); 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); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassStruct16BytesHomogeneousFloatx5( // NOLINTNEXTLINE(whitespace/parens) float (*f)(Struct16BytesHomogeneousFloat a0, Struct16BytesHomogeneousFloat a1, Struct16BytesHomogeneousFloat a2, Struct16BytesHomogeneousFloat a3, Struct16BytesHomogeneousFloat a4)) { Struct16BytesHomogeneousFloat a0; Struct16BytesHomogeneousFloat a1; Struct16BytesHomogeneousFloat a2; Struct16BytesHomogeneousFloat a3; Struct16BytesHomogeneousFloat a4; a0.a0 = -1.0; a0.a1 = 2.0; a0.a2 = -3.0; a0.a3 = 4.0; a1.a0 = -5.0; a1.a1 = 6.0; a1.a2 = -7.0; a1.a3 = 8.0; a2.a0 = -9.0; a2.a1 = 10.0; a2.a2 = -11.0; a2.a3 = 12.0; a3.a0 = -13.0; a3.a1 = 14.0; a3.a2 = -15.0; a3.a3 = 16.0; a4.a0 = -17.0; a4.a1 = 18.0; a4.a2 = -19.0; a4.a3 = 20.0; std::cout << "Calling TestPassStruct16BytesHomogeneousFloatx5(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << ", " << a4.a3 << "))" << ")\n"; float result = f(a0, a1, a2, a3, a4); std::cout << "result = " << result << "\n"; CHECK_APPROX(10.0, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1, a2, a3, a4); 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); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassStruct16BytesMixedx10( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Struct16BytesMixed a0, Struct16BytesMixed a1, Struct16BytesMixed a2, Struct16BytesMixed a3, Struct16BytesMixed a4, Struct16BytesMixed a5, Struct16BytesMixed a6, Struct16BytesMixed a7, Struct16BytesMixed a8, Struct16BytesMixed a9)) { Struct16BytesMixed a0; Struct16BytesMixed a1; Struct16BytesMixed a2; Struct16BytesMixed a3; Struct16BytesMixed a4; Struct16BytesMixed a5; Struct16BytesMixed a6; Struct16BytesMixed a7; Struct16BytesMixed a8; Struct16BytesMixed a9; a0.a0 = -1.0; a0.a1 = 2; a1.a0 = -3.0; a1.a1 = 4; a2.a0 = -5.0; a2.a1 = 6; a3.a0 = -7.0; a3.a1 = 8; a4.a0 = -9.0; a4.a1 = 10; a5.a0 = -11.0; a5.a1 = 12; a6.a0 = -13.0; a6.a1 = 14; a7.a0 = -15.0; a7.a1 = 16; a8.a0 = -17.0; a8.a1 = 18; a9.a0 = -19.0; a9.a1 = 20; std::cout << "Calling TestPassStruct16BytesMixedx10(" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", " << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0 << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(10.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); 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); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassStruct16BytesMixed2x10( // NOLINTNEXTLINE(whitespace/parens) float (*f)(Struct16BytesMixed2 a0, Struct16BytesMixed2 a1, Struct16BytesMixed2 a2, Struct16BytesMixed2 a3, Struct16BytesMixed2 a4, Struct16BytesMixed2 a5, Struct16BytesMixed2 a6, Struct16BytesMixed2 a7, Struct16BytesMixed2 a8, Struct16BytesMixed2 a9)) { Struct16BytesMixed2 a0; Struct16BytesMixed2 a1; Struct16BytesMixed2 a2; Struct16BytesMixed2 a3; Struct16BytesMixed2 a4; Struct16BytesMixed2 a5; Struct16BytesMixed2 a6; Struct16BytesMixed2 a7; Struct16BytesMixed2 a8; Struct16BytesMixed2 a9; a0.a0 = -1.0; a0.a1 = 2.0; a0.a2 = -3.0; a0.a3 = 4; a1.a0 = -5.0; a1.a1 = 6.0; a1.a2 = -7.0; a1.a3 = 8; a2.a0 = -9.0; a2.a1 = 10.0; a2.a2 = -11.0; a2.a3 = 12; a3.a0 = -13.0; a3.a1 = 14.0; a3.a2 = -15.0; a3.a3 = 16; a4.a0 = -17.0; a4.a1 = 18.0; a4.a2 = -19.0; a4.a3 = 20; a5.a0 = -21.0; a5.a1 = 22.0; a5.a2 = -23.0; a5.a3 = 24; a6.a0 = -25.0; a6.a1 = 26.0; a6.a2 = -27.0; a6.a3 = 28; a7.a0 = -29.0; a7.a1 = 30.0; a7.a2 = -31.0; a7.a3 = 32; a8.a0 = -33.0; a8.a1 = 34.0; a8.a2 = -35.0; a8.a3 = 36; a9.a0 = -37.0; a9.a1 = 38.0; a9.a2 = -39.0; a9.a3 = 40; std::cout << "Calling TestPassStruct16BytesMixed2x10(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << ", " << a4.a3 << "), (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2 << ", " << a6.a3 << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3 << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << ", " << a8.a3 << "), (" << a9.a0 << ", " << a9.a1 << ", " << a9.a2 << ", " << a9.a3 << "))" << ")\n"; float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(20.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); 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); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Arguments are passed as pointer to copy on arm64. // Tests that the memory allocated for copies are rounded up to word size. DART_EXPORT intptr_t TestPassStruct17BytesIntx10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct17BytesInt a0, Struct17BytesInt a1, Struct17BytesInt a2, Struct17BytesInt a3, Struct17BytesInt a4, Struct17BytesInt a5, Struct17BytesInt a6, Struct17BytesInt a7, Struct17BytesInt a8, Struct17BytesInt a9)) { Struct17BytesInt a0; Struct17BytesInt a1; Struct17BytesInt a2; Struct17BytesInt a3; Struct17BytesInt a4; Struct17BytesInt a5; Struct17BytesInt a6; Struct17BytesInt a7; Struct17BytesInt a8; Struct17BytesInt a9; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; a1.a0 = 4; a1.a1 = -5; a1.a2 = 6; a2.a0 = -7; a2.a1 = 8; a2.a2 = -9; a3.a0 = 10; a3.a1 = -11; a3.a2 = 12; a4.a0 = -13; a4.a1 = 14; a4.a2 = -15; a5.a0 = 16; a5.a1 = -17; a5.a2 = 18; a6.a0 = -19; a6.a1 = 20; a6.a2 = -21; a7.a0 = 22; a7.a1 = -23; a7.a2 = 24; a8.a0 = -25; a8.a1 = 26; a8.a2 = -27; a9.a0 = 28; a9.a1 = -29; a9.a2 = 30; std::cout << "Calling TestPassStruct17BytesIntx10(" << "((" << a0.a0 << ", " << a0.a1 << ", " << static_cast(a0.a2) << "), (" << a1.a0 << ", " << a1.a1 << ", " << static_cast(a1.a2) << "), (" << a2.a0 << ", " << a2.a1 << ", " << static_cast(a2.a2) << "), (" << a3.a0 << ", " << a3.a1 << ", " << static_cast(a3.a2) << "), (" << a4.a0 << ", " << a4.a1 << ", " << static_cast(a4.a2) << "), (" << a5.a0 << ", " << a5.a1 << ", " << static_cast(a5.a2) << "), (" << a6.a0 << ", " << a6.a1 << ", " << static_cast(a6.a2) << "), (" << a7.a0 << ", " << a7.a1 << ", " << static_cast(a7.a2) << "), (" << a8.a0 << ", " << a8.a1 << ", " << static_cast(a8.a2) << "), (" << a9.a0 << ", " << a9.a1 << ", " << static_cast(a9.a2) << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(15, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // 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. // DART_EXPORT intptr_t TestPassStruct19BytesHomogeneousUint8x10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct19BytesHomogeneousUint8 a0, Struct19BytesHomogeneousUint8 a1, Struct19BytesHomogeneousUint8 a2, Struct19BytesHomogeneousUint8 a3, Struct19BytesHomogeneousUint8 a4, Struct19BytesHomogeneousUint8 a5, Struct19BytesHomogeneousUint8 a6, Struct19BytesHomogeneousUint8 a7, Struct19BytesHomogeneousUint8 a8, Struct19BytesHomogeneousUint8 a9)) { Struct19BytesHomogeneousUint8 a0; Struct19BytesHomogeneousUint8 a1; Struct19BytesHomogeneousUint8 a2; Struct19BytesHomogeneousUint8 a3; Struct19BytesHomogeneousUint8 a4; Struct19BytesHomogeneousUint8 a5; Struct19BytesHomogeneousUint8 a6; Struct19BytesHomogeneousUint8 a7; Struct19BytesHomogeneousUint8 a8; Struct19BytesHomogeneousUint8 a9; a0.a0 = 1; a0.a1 = 2; a0.a2 = 3; a0.a3 = 4; a0.a4 = 5; a0.a5 = 6; a0.a6 = 7; a0.a7 = 8; a0.a8 = 9; a0.a9 = 10; a0.a10 = 11; a0.a11 = 12; a0.a12 = 13; a0.a13 = 14; a0.a14 = 15; a0.a15 = 16; a0.a16 = 17; a0.a17 = 18; a0.a18 = 19; a1.a0 = 20; a1.a1 = 21; a1.a2 = 22; a1.a3 = 23; a1.a4 = 24; a1.a5 = 25; a1.a6 = 26; a1.a7 = 27; a1.a8 = 28; a1.a9 = 29; a1.a10 = 30; a1.a11 = 31; a1.a12 = 32; a1.a13 = 33; a1.a14 = 34; a1.a15 = 35; a1.a16 = 36; a1.a17 = 37; a1.a18 = 38; a2.a0 = 39; a2.a1 = 40; a2.a2 = 41; a2.a3 = 42; a2.a4 = 43; a2.a5 = 44; a2.a6 = 45; a2.a7 = 46; a2.a8 = 47; a2.a9 = 48; a2.a10 = 49; a2.a11 = 50; a2.a12 = 51; a2.a13 = 52; a2.a14 = 53; a2.a15 = 54; a2.a16 = 55; a2.a17 = 56; a2.a18 = 57; a3.a0 = 58; a3.a1 = 59; a3.a2 = 60; a3.a3 = 61; a3.a4 = 62; a3.a5 = 63; a3.a6 = 64; a3.a7 = 65; a3.a8 = 66; a3.a9 = 67; a3.a10 = 68; a3.a11 = 69; a3.a12 = 70; a3.a13 = 71; a3.a14 = 72; a3.a15 = 73; a3.a16 = 74; a3.a17 = 75; a3.a18 = 76; a4.a0 = 77; a4.a1 = 78; a4.a2 = 79; a4.a3 = 80; a4.a4 = 81; a4.a5 = 82; a4.a6 = 83; a4.a7 = 84; a4.a8 = 85; a4.a9 = 86; a4.a10 = 87; a4.a11 = 88; a4.a12 = 89; a4.a13 = 90; a4.a14 = 91; a4.a15 = 92; a4.a16 = 93; a4.a17 = 94; a4.a18 = 95; a5.a0 = 96; a5.a1 = 97; a5.a2 = 98; a5.a3 = 99; a5.a4 = 100; a5.a5 = 101; a5.a6 = 102; a5.a7 = 103; a5.a8 = 104; a5.a9 = 105; a5.a10 = 106; a5.a11 = 107; a5.a12 = 108; a5.a13 = 109; a5.a14 = 110; a5.a15 = 111; a5.a16 = 112; a5.a17 = 113; a5.a18 = 114; a6.a0 = 115; a6.a1 = 116; a6.a2 = 117; a6.a3 = 118; a6.a4 = 119; a6.a5 = 120; a6.a6 = 121; a6.a7 = 122; a6.a8 = 123; a6.a9 = 124; a6.a10 = 125; a6.a11 = 126; a6.a12 = 127; a6.a13 = 128; a6.a14 = 129; a6.a15 = 130; a6.a16 = 131; a6.a17 = 132; a6.a18 = 133; a7.a0 = 134; a7.a1 = 135; a7.a2 = 136; a7.a3 = 137; a7.a4 = 138; a7.a5 = 139; a7.a6 = 140; a7.a7 = 141; a7.a8 = 142; a7.a9 = 143; a7.a10 = 144; a7.a11 = 145; a7.a12 = 146; a7.a13 = 147; a7.a14 = 148; a7.a15 = 149; a7.a16 = 150; a7.a17 = 151; a7.a18 = 152; a8.a0 = 153; a8.a1 = 154; a8.a2 = 155; a8.a3 = 156; a8.a4 = 157; a8.a5 = 158; a8.a6 = 159; a8.a7 = 160; a8.a8 = 161; a8.a9 = 162; a8.a10 = 163; a8.a11 = 164; a8.a12 = 165; a8.a13 = 166; a8.a14 = 167; a8.a15 = 168; a8.a16 = 169; a8.a17 = 170; a8.a18 = 171; a9.a0 = 172; a9.a1 = 173; a9.a2 = 174; a9.a3 = 175; a9.a4 = 176; a9.a5 = 177; a9.a6 = 178; a9.a7 = 179; a9.a8 = 180; a9.a9 = 181; a9.a10 = 182; a9.a11 = 183; a9.a12 = 184; a9.a13 = 185; a9.a14 = 186; a9.a15 = 187; a9.a16 = 188; a9.a17 = 189; a9.a18 = 190; std::cout << "Calling TestPassStruct19BytesHomogeneousUint8x10(" << "((" << static_cast(a0.a0) << ", " << static_cast(a0.a1) << ", " << static_cast(a0.a2) << ", " << static_cast(a0.a3) << ", " << static_cast(a0.a4) << ", " << static_cast(a0.a5) << ", " << static_cast(a0.a6) << ", " << static_cast(a0.a7) << ", " << static_cast(a0.a8) << ", " << static_cast(a0.a9) << ", " << static_cast(a0.a10) << ", " << static_cast(a0.a11) << ", " << static_cast(a0.a12) << ", " << static_cast(a0.a13) << ", " << static_cast(a0.a14) << ", " << static_cast(a0.a15) << ", " << static_cast(a0.a16) << ", " << static_cast(a0.a17) << ", " << static_cast(a0.a18) << "), (" << static_cast(a1.a0) << ", " << static_cast(a1.a1) << ", " << static_cast(a1.a2) << ", " << static_cast(a1.a3) << ", " << static_cast(a1.a4) << ", " << static_cast(a1.a5) << ", " << static_cast(a1.a6) << ", " << static_cast(a1.a7) << ", " << static_cast(a1.a8) << ", " << static_cast(a1.a9) << ", " << static_cast(a1.a10) << ", " << static_cast(a1.a11) << ", " << static_cast(a1.a12) << ", " << static_cast(a1.a13) << ", " << static_cast(a1.a14) << ", " << static_cast(a1.a15) << ", " << static_cast(a1.a16) << ", " << static_cast(a1.a17) << ", " << static_cast(a1.a18) << "), (" << static_cast(a2.a0) << ", " << static_cast(a2.a1) << ", " << static_cast(a2.a2) << ", " << static_cast(a2.a3) << ", " << static_cast(a2.a4) << ", " << static_cast(a2.a5) << ", " << static_cast(a2.a6) << ", " << static_cast(a2.a7) << ", " << static_cast(a2.a8) << ", " << static_cast(a2.a9) << ", " << static_cast(a2.a10) << ", " << static_cast(a2.a11) << ", " << static_cast(a2.a12) << ", " << static_cast(a2.a13) << ", " << static_cast(a2.a14) << ", " << static_cast(a2.a15) << ", " << static_cast(a2.a16) << ", " << static_cast(a2.a17) << ", " << static_cast(a2.a18) << "), (" << static_cast(a3.a0) << ", " << static_cast(a3.a1) << ", " << static_cast(a3.a2) << ", " << static_cast(a3.a3) << ", " << static_cast(a3.a4) << ", " << static_cast(a3.a5) << ", " << static_cast(a3.a6) << ", " << static_cast(a3.a7) << ", " << static_cast(a3.a8) << ", " << static_cast(a3.a9) << ", " << static_cast(a3.a10) << ", " << static_cast(a3.a11) << ", " << static_cast(a3.a12) << ", " << static_cast(a3.a13) << ", " << static_cast(a3.a14) << ", " << static_cast(a3.a15) << ", " << static_cast(a3.a16) << ", " << static_cast(a3.a17) << ", " << static_cast(a3.a18) << "), (" << static_cast(a4.a0) << ", " << static_cast(a4.a1) << ", " << static_cast(a4.a2) << ", " << static_cast(a4.a3) << ", " << static_cast(a4.a4) << ", " << static_cast(a4.a5) << ", " << static_cast(a4.a6) << ", " << static_cast(a4.a7) << ", " << static_cast(a4.a8) << ", " << static_cast(a4.a9) << ", " << static_cast(a4.a10) << ", " << static_cast(a4.a11) << ", " << static_cast(a4.a12) << ", " << static_cast(a4.a13) << ", " << static_cast(a4.a14) << ", " << static_cast(a4.a15) << ", " << static_cast(a4.a16) << ", " << static_cast(a4.a17) << ", " << static_cast(a4.a18) << "), (" << static_cast(a5.a0) << ", " << static_cast(a5.a1) << ", " << static_cast(a5.a2) << ", " << static_cast(a5.a3) << ", " << static_cast(a5.a4) << ", " << static_cast(a5.a5) << ", " << static_cast(a5.a6) << ", " << static_cast(a5.a7) << ", " << static_cast(a5.a8) << ", " << static_cast(a5.a9) << ", " << static_cast(a5.a10) << ", " << static_cast(a5.a11) << ", " << static_cast(a5.a12) << ", " << static_cast(a5.a13) << ", " << static_cast(a5.a14) << ", " << static_cast(a5.a15) << ", " << static_cast(a5.a16) << ", " << static_cast(a5.a17) << ", " << static_cast(a5.a18) << "), (" << static_cast(a6.a0) << ", " << static_cast(a6.a1) << ", " << static_cast(a6.a2) << ", " << static_cast(a6.a3) << ", " << static_cast(a6.a4) << ", " << static_cast(a6.a5) << ", " << static_cast(a6.a6) << ", " << static_cast(a6.a7) << ", " << static_cast(a6.a8) << ", " << static_cast(a6.a9) << ", " << static_cast(a6.a10) << ", " << static_cast(a6.a11) << ", " << static_cast(a6.a12) << ", " << static_cast(a6.a13) << ", " << static_cast(a6.a14) << ", " << static_cast(a6.a15) << ", " << static_cast(a6.a16) << ", " << static_cast(a6.a17) << ", " << static_cast(a6.a18) << "), (" << static_cast(a7.a0) << ", " << static_cast(a7.a1) << ", " << static_cast(a7.a2) << ", " << static_cast(a7.a3) << ", " << static_cast(a7.a4) << ", " << static_cast(a7.a5) << ", " << static_cast(a7.a6) << ", " << static_cast(a7.a7) << ", " << static_cast(a7.a8) << ", " << static_cast(a7.a9) << ", " << static_cast(a7.a10) << ", " << static_cast(a7.a11) << ", " << static_cast(a7.a12) << ", " << static_cast(a7.a13) << ", " << static_cast(a7.a14) << ", " << static_cast(a7.a15) << ", " << static_cast(a7.a16) << ", " << static_cast(a7.a17) << ", " << static_cast(a7.a18) << "), (" << static_cast(a8.a0) << ", " << static_cast(a8.a1) << ", " << static_cast(a8.a2) << ", " << static_cast(a8.a3) << ", " << static_cast(a8.a4) << ", " << static_cast(a8.a5) << ", " << static_cast(a8.a6) << ", " << static_cast(a8.a7) << ", " << static_cast(a8.a8) << ", " << static_cast(a8.a9) << ", " << static_cast(a8.a10) << ", " << static_cast(a8.a11) << ", " << static_cast(a8.a12) << ", " << static_cast(a8.a13) << ", " << static_cast(a8.a14) << ", " << static_cast(a8.a15) << ", " << static_cast(a8.a16) << ", " << static_cast(a8.a17) << ", " << static_cast(a8.a18) << "), (" << static_cast(a9.a0) << ", " << static_cast(a9.a1) << ", " << static_cast(a9.a2) << ", " << static_cast(a9.a3) << ", " << static_cast(a9.a4) << ", " << static_cast(a9.a5) << ", " << static_cast(a9.a6) << ", " << static_cast(a9.a7) << ", " << static_cast(a9.a8) << ", " << static_cast(a9.a9) << ", " << static_cast(a9.a10) << ", " << static_cast(a9.a11) << ", " << static_cast(a9.a12) << ", " << static_cast(a9.a13) << ", " << static_cast(a9.a14) << ", " << static_cast(a9.a15) << ", " << static_cast(a9.a16) << ", " << static_cast(a9.a17) << ", " << static_cast(a9.a18) << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(18145, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassStruct20BytesHomogeneousInt32x10( // NOLINTNEXTLINE(whitespace/parens) int32_t (*f)(Struct20BytesHomogeneousInt32 a0, Struct20BytesHomogeneousInt32 a1, Struct20BytesHomogeneousInt32 a2, Struct20BytesHomogeneousInt32 a3, Struct20BytesHomogeneousInt32 a4, Struct20BytesHomogeneousInt32 a5, Struct20BytesHomogeneousInt32 a6, Struct20BytesHomogeneousInt32 a7, Struct20BytesHomogeneousInt32 a8, Struct20BytesHomogeneousInt32 a9)) { Struct20BytesHomogeneousInt32 a0; Struct20BytesHomogeneousInt32 a1; Struct20BytesHomogeneousInt32 a2; Struct20BytesHomogeneousInt32 a3; Struct20BytesHomogeneousInt32 a4; Struct20BytesHomogeneousInt32 a5; Struct20BytesHomogeneousInt32 a6; Struct20BytesHomogeneousInt32 a7; Struct20BytesHomogeneousInt32 a8; Struct20BytesHomogeneousInt32 a9; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; a0.a3 = 4; a0.a4 = -5; a1.a0 = 6; a1.a1 = -7; a1.a2 = 8; a1.a3 = -9; a1.a4 = 10; a2.a0 = -11; a2.a1 = 12; a2.a2 = -13; a2.a3 = 14; a2.a4 = -15; a3.a0 = 16; a3.a1 = -17; a3.a2 = 18; a3.a3 = -19; a3.a4 = 20; a4.a0 = -21; a4.a1 = 22; a4.a2 = -23; a4.a3 = 24; a4.a4 = -25; a5.a0 = 26; a5.a1 = -27; a5.a2 = 28; a5.a3 = -29; a5.a4 = 30; a6.a0 = -31; a6.a1 = 32; a6.a2 = -33; a6.a3 = 34; a6.a4 = -35; a7.a0 = 36; a7.a1 = -37; a7.a2 = 38; a7.a3 = -39; a7.a4 = 40; a8.a0 = -41; a8.a1 = 42; a8.a2 = -43; a8.a3 = 44; a8.a4 = -45; a9.a0 = 46; a9.a1 = -47; a9.a2 = 48; a9.a3 = -49; a9.a4 = 50; std::cout << "Calling TestPassStruct20BytesHomogeneousInt32x10(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << ", " << a1.a4 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << ", " << a2.a3 << ", " << a2.a4 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << ", " << a3.a4 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << ", " << a4.a3 << ", " << a4.a4 << "), (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << ", " << a5.a4 << "), (" << a6.a0 << ", " << a6.a1 << ", " << a6.a2 << ", " << a6.a3 << ", " << a6.a4 << "), (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3 << ", " << a7.a4 << "), (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << ", " << a8.a3 << ", " << a8.a4 << "), (" << a9.a0 << ", " << a9.a1 << ", " << a9.a2 << ", " << a9.a3 << ", " << a9.a4 << "))" << ")\n"; int32_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(25, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Argument too big to go into FPU registers in hardfp and arm64. DART_EXPORT intptr_t TestPassStruct20BytesHomogeneousFloat( // NOLINTNEXTLINE(whitespace/parens) float (*f)(Struct20BytesHomogeneousFloat a0)) { Struct20BytesHomogeneousFloat a0; a0.a0 = -1.0; a0.a1 = 2.0; a0.a2 = -3.0; a0.a3 = 4.0; a0.a4 = -5.0; std::cout << "Calling TestPassStruct20BytesHomogeneousFloat(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << "))" << ")\n"; float result = f(a0); std::cout << "result = " << result << "\n"; CHECK_APPROX(-3.0, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Arguments in FPU registers on arm64. // 5 struct arguments will exhaust available registers. DART_EXPORT intptr_t TestPassStruct32BytesHomogeneousDoublex5( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Struct32BytesHomogeneousDouble a0, Struct32BytesHomogeneousDouble a1, Struct32BytesHomogeneousDouble a2, Struct32BytesHomogeneousDouble a3, Struct32BytesHomogeneousDouble a4)) { Struct32BytesHomogeneousDouble a0; Struct32BytesHomogeneousDouble a1; Struct32BytesHomogeneousDouble a2; Struct32BytesHomogeneousDouble a3; Struct32BytesHomogeneousDouble a4; a0.a0 = -1.0; a0.a1 = 2.0; a0.a2 = -3.0; a0.a3 = 4.0; a1.a0 = -5.0; a1.a1 = 6.0; a1.a2 = -7.0; a1.a3 = 8.0; a2.a0 = -9.0; a2.a1 = 10.0; a2.a2 = -11.0; a2.a3 = 12.0; a3.a0 = -13.0; a3.a1 = 14.0; a3.a2 = -15.0; a3.a3 = 16.0; a4.a0 = -17.0; a4.a1 = 18.0; a4.a2 = -19.0; a4.a3 = 20.0; std::cout << "Calling TestPassStruct32BytesHomogeneousDoublex5(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << "), (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << "), (" << a2.a0 << ", " << a2.a1 << ", " << a2.a2 << ", " << a2.a3 << "), (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << "), (" << a4.a0 << ", " << a4.a1 << ", " << a4.a2 << ", " << a4.a3 << "))" << ")\n"; double result = f(a0, a1, a2, a3, a4); std::cout << "result = " << result << "\n"; CHECK_APPROX(10.0, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1, a2, a3, a4); 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); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Argument too big to go into FPU registers in arm64. DART_EXPORT intptr_t TestPassStruct40BytesHomogeneousDouble( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Struct40BytesHomogeneousDouble a0)) { Struct40BytesHomogeneousDouble a0; a0.a0 = -1.0; a0.a1 = 2.0; a0.a2 = -3.0; a0.a3 = 4.0; a0.a4 = -5.0; std::cout << "Calling TestPassStruct40BytesHomogeneousDouble(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << "))" << ")\n"; double result = f(a0); std::cout << "result = " << result << "\n"; CHECK_APPROX(-3.0, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Test 1kb struct. DART_EXPORT intptr_t TestPassStruct1024BytesHomogeneousUint64( // NOLINTNEXTLINE(whitespace/parens) uint64_t (*f)(Struct1024BytesHomogeneousUint64 a0)) { Struct1024BytesHomogeneousUint64 a0; a0.a0 = 1; a0.a1 = 2; a0.a2 = 3; a0.a3 = 4; a0.a4 = 5; a0.a5 = 6; a0.a6 = 7; a0.a7 = 8; a0.a8 = 9; a0.a9 = 10; a0.a10 = 11; a0.a11 = 12; a0.a12 = 13; a0.a13 = 14; a0.a14 = 15; a0.a15 = 16; a0.a16 = 17; a0.a17 = 18; a0.a18 = 19; a0.a19 = 20; a0.a20 = 21; a0.a21 = 22; a0.a22 = 23; a0.a23 = 24; a0.a24 = 25; a0.a25 = 26; a0.a26 = 27; a0.a27 = 28; a0.a28 = 29; a0.a29 = 30; a0.a30 = 31; a0.a31 = 32; a0.a32 = 33; a0.a33 = 34; a0.a34 = 35; a0.a35 = 36; a0.a36 = 37; a0.a37 = 38; a0.a38 = 39; a0.a39 = 40; a0.a40 = 41; a0.a41 = 42; a0.a42 = 43; a0.a43 = 44; a0.a44 = 45; a0.a45 = 46; a0.a46 = 47; a0.a47 = 48; a0.a48 = 49; a0.a49 = 50; a0.a50 = 51; a0.a51 = 52; a0.a52 = 53; a0.a53 = 54; a0.a54 = 55; a0.a55 = 56; a0.a56 = 57; a0.a57 = 58; a0.a58 = 59; a0.a59 = 60; a0.a60 = 61; a0.a61 = 62; a0.a62 = 63; a0.a63 = 64; a0.a64 = 65; a0.a65 = 66; a0.a66 = 67; a0.a67 = 68; a0.a68 = 69; a0.a69 = 70; a0.a70 = 71; a0.a71 = 72; a0.a72 = 73; a0.a73 = 74; a0.a74 = 75; a0.a75 = 76; a0.a76 = 77; a0.a77 = 78; a0.a78 = 79; a0.a79 = 80; a0.a80 = 81; a0.a81 = 82; a0.a82 = 83; a0.a83 = 84; a0.a84 = 85; a0.a85 = 86; a0.a86 = 87; a0.a87 = 88; a0.a88 = 89; a0.a89 = 90; a0.a90 = 91; a0.a91 = 92; a0.a92 = 93; a0.a93 = 94; a0.a94 = 95; a0.a95 = 96; a0.a96 = 97; a0.a97 = 98; a0.a98 = 99; a0.a99 = 100; a0.a100 = 101; a0.a101 = 102; a0.a102 = 103; a0.a103 = 104; a0.a104 = 105; a0.a105 = 106; a0.a106 = 107; a0.a107 = 108; a0.a108 = 109; a0.a109 = 110; a0.a110 = 111; a0.a111 = 112; a0.a112 = 113; a0.a113 = 114; a0.a114 = 115; a0.a115 = 116; a0.a116 = 117; a0.a117 = 118; a0.a118 = 119; a0.a119 = 120; a0.a120 = 121; a0.a121 = 122; a0.a122 = 123; a0.a123 = 124; a0.a124 = 125; a0.a125 = 126; a0.a126 = 127; a0.a127 = 128; std::cout << "Calling TestPassStruct1024BytesHomogeneousUint64(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << ", " << a0.a5 << ", " << a0.a6 << ", " << a0.a7 << ", " << a0.a8 << ", " << a0.a9 << ", " << a0.a10 << ", " << a0.a11 << ", " << a0.a12 << ", " << a0.a13 << ", " << a0.a14 << ", " << a0.a15 << ", " << a0.a16 << ", " << a0.a17 << ", " << a0.a18 << ", " << a0.a19 << ", " << a0.a20 << ", " << a0.a21 << ", " << a0.a22 << ", " << a0.a23 << ", " << a0.a24 << ", " << a0.a25 << ", " << a0.a26 << ", " << a0.a27 << ", " << a0.a28 << ", " << a0.a29 << ", " << a0.a30 << ", " << a0.a31 << ", " << a0.a32 << ", " << a0.a33 << ", " << a0.a34 << ", " << a0.a35 << ", " << a0.a36 << ", " << a0.a37 << ", " << a0.a38 << ", " << a0.a39 << ", " << a0.a40 << ", " << a0.a41 << ", " << a0.a42 << ", " << a0.a43 << ", " << a0.a44 << ", " << a0.a45 << ", " << a0.a46 << ", " << a0.a47 << ", " << a0.a48 << ", " << a0.a49 << ", " << a0.a50 << ", " << a0.a51 << ", " << a0.a52 << ", " << a0.a53 << ", " << a0.a54 << ", " << a0.a55 << ", " << a0.a56 << ", " << a0.a57 << ", " << a0.a58 << ", " << a0.a59 << ", " << a0.a60 << ", " << a0.a61 << ", " << a0.a62 << ", " << a0.a63 << ", " << a0.a64 << ", " << a0.a65 << ", " << a0.a66 << ", " << a0.a67 << ", " << a0.a68 << ", " << a0.a69 << ", " << a0.a70 << ", " << a0.a71 << ", " << a0.a72 << ", " << a0.a73 << ", " << a0.a74 << ", " << a0.a75 << ", " << a0.a76 << ", " << a0.a77 << ", " << a0.a78 << ", " << a0.a79 << ", " << a0.a80 << ", " << a0.a81 << ", " << a0.a82 << ", " << a0.a83 << ", " << a0.a84 << ", " << a0.a85 << ", " << a0.a86 << ", " << a0.a87 << ", " << a0.a88 << ", " << a0.a89 << ", " << a0.a90 << ", " << a0.a91 << ", " << a0.a92 << ", " << a0.a93 << ", " << a0.a94 << ", " << a0.a95 << ", " << a0.a96 << ", " << a0.a97 << ", " << a0.a98 << ", " << a0.a99 << ", " << a0.a100 << ", " << a0.a101 << ", " << a0.a102 << ", " << a0.a103 << ", " << a0.a104 << ", " << a0.a105 << ", " << a0.a106 << ", " << a0.a107 << ", " << a0.a108 << ", " << a0.a109 << ", " << a0.a110 << ", " << a0.a111 << ", " << a0.a112 << ", " << a0.a113 << ", " << a0.a114 << ", " << a0.a115 << ", " << a0.a116 << ", " << a0.a117 << ", " << a0.a118 << ", " << a0.a119 << ", " << a0.a120 << ", " << a0.a121 << ", " << a0.a122 << ", " << a0.a123 << ", " << a0.a124 << ", " << a0.a125 << ", " << a0.a126 << ", " << a0.a127 << "))" << ")\n"; uint64_t result = f(a0); std::cout << "result = " << result << "\n"; CHECK_EQ(8256, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Tests the alignment of structs in FPU registers and backfilling. DART_EXPORT intptr_t TestPassFloatStruct16BytesHomogeneousFloatFloatStruct1( // NOLINTNEXTLINE(whitespace/parens) float (*f)(float a0, Struct16BytesHomogeneousFloat a1, float a2, Struct16BytesHomogeneousFloat a3, float a4, Struct16BytesHomogeneousFloat a5, float a6, Struct16BytesHomogeneousFloat a7, float a8)) { float a0; Struct16BytesHomogeneousFloat a1; float a2; Struct16BytesHomogeneousFloat a3; float a4; Struct16BytesHomogeneousFloat a5; float a6; Struct16BytesHomogeneousFloat a7; float a8; a0 = -1.0; a1.a0 = 2.0; a1.a1 = -3.0; a1.a2 = 4.0; a1.a3 = -5.0; a2 = 6.0; a3.a0 = -7.0; a3.a1 = 8.0; a3.a2 = -9.0; a3.a3 = 10.0; a4 = -11.0; a5.a0 = 12.0; a5.a1 = -13.0; a5.a2 = 14.0; a5.a3 = -15.0; a6 = 16.0; a7.a0 = -17.0; a7.a1 = 18.0; a7.a2 = -19.0; a7.a3 = 20.0; a8 = -21.0; std::cout << "Calling TestPassFloatStruct16BytesHomogeneousFloatFloatStruct1(" << "(" << a0 << ", (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << "), " << a2 << ", (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << "), " << a4 << ", (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), " << a6 << ", (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3 << "), " << a8 << ")" << ")\n"; float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); std::cout << "result = " << result << "\n"; CHECK_APPROX(-11.0, result); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Tests the alignment of structs in FPU registers and backfilling. DART_EXPORT intptr_t TestPassFloatStruct32BytesHomogeneousDoubleFloatStruct( // NOLINTNEXTLINE(whitespace/parens) double (*f)(float a0, Struct32BytesHomogeneousDouble a1, float a2, Struct32BytesHomogeneousDouble a3, float a4, Struct32BytesHomogeneousDouble a5, float a6, Struct32BytesHomogeneousDouble a7, float a8)) { float a0; Struct32BytesHomogeneousDouble a1; float a2; Struct32BytesHomogeneousDouble a3; float a4; Struct32BytesHomogeneousDouble a5; float a6; Struct32BytesHomogeneousDouble a7; float a8; a0 = -1.0; a1.a0 = 2.0; a1.a1 = -3.0; a1.a2 = 4.0; a1.a3 = -5.0; a2 = 6.0; a3.a0 = -7.0; a3.a1 = 8.0; a3.a2 = -9.0; a3.a3 = 10.0; a4 = -11.0; a5.a0 = 12.0; a5.a1 = -13.0; a5.a2 = 14.0; a5.a3 = -15.0; a6 = 16.0; a7.a0 = -17.0; a7.a1 = 18.0; a7.a2 = -19.0; a7.a3 = 20.0; a8 = -21.0; std::cout << "Calling TestPassFloatStruct32BytesHomogeneousDoubleFloatStruct(" << "(" << a0 << ", (" << a1.a0 << ", " << a1.a1 << ", " << a1.a2 << ", " << a1.a3 << "), " << a2 << ", (" << a3.a0 << ", " << a3.a1 << ", " << a3.a2 << ", " << a3.a3 << "), " << a4 << ", (" << a5.a0 << ", " << a5.a1 << ", " << a5.a2 << ", " << a5.a3 << "), " << a6 << ", (" << a7.a0 << ", " << a7.a1 << ", " << a7.a2 << ", " << a7.a3 << "), " << a8 << ")" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); std::cout << "result = " << result << "\n"; CHECK_APPROX(-11.0, result); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassInt8Struct16BytesMixedInt8Struct16BytesMixedIn( // NOLINTNEXTLINE(whitespace/parens) double (*f)(int8_t a0, Struct16BytesMixed a1, int8_t a2, Struct16BytesMixed a3, int8_t a4, Struct16BytesMixed a5, int8_t a6, Struct16BytesMixed a7, int8_t a8)) { int8_t a0; Struct16BytesMixed a1; int8_t a2; Struct16BytesMixed a3; int8_t a4; Struct16BytesMixed a5; int8_t a6; Struct16BytesMixed a7; int8_t a8; a0 = -1; a1.a0 = 2.0; a1.a1 = -3; a2 = 4; a3.a0 = -5.0; a3.a1 = 6; a4 = -7; a5.a0 = 8.0; a5.a1 = -9; a6 = 10; a7.a0 = -11.0; a7.a1 = 12; a8 = -13; std::cout << "Calling TestPassInt8Struct16BytesMixedInt8Struct16BytesMixedIn(" << "(" << static_cast(a0) << ", (" << a1.a0 << ", " << a1.a1 << "), " << static_cast(a2) << ", (" << a3.a0 << ", " << a3.a1 << "), " << static_cast(a4) << ", (" << a5.a0 << ", " << a5.a1 << "), " << static_cast(a6) << ", (" << a7.a0 << ", " << a7.a1 << "), " << static_cast(a8) << ")" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); std::cout << "result = " << result << "\n"; CHECK_APPROX(-7.0, result); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassDoublex6Struct16BytesMixedx4Int32( // NOLINTNEXTLINE(whitespace/parens) double (*f)(double a0, double a1, double a2, double a3, double a4, double a5, Struct16BytesMixed a6, Struct16BytesMixed a7, Struct16BytesMixed a8, Struct16BytesMixed a9, int32_t a10)) { double a0; double a1; double a2; double a3; double a4; double a5; Struct16BytesMixed a6; Struct16BytesMixed a7; Struct16BytesMixed a8; Struct16BytesMixed a9; int32_t a10; a0 = -1.0; a1 = 2.0; a2 = -3.0; a3 = 4.0; a4 = -5.0; a5 = 6.0; a6.a0 = -7.0; a6.a1 = 8; a7.a0 = -9.0; a7.a1 = 10; a8.a0 = -11.0; a8.a1 = 12; a9.a0 = -13.0; a9.a1 = 14; a10 = -15; std::cout << "Calling TestPassDoublex6Struct16BytesMixedx4Int32(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ", " << a5 << ", (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "), " << a10 << ")" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); std::cout << "result = " << result << "\n"; CHECK_APPROX(-8.0, result); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassInt32x4Struct16BytesMixedx4Double( // NOLINTNEXTLINE(whitespace/parens) double (*f)(int32_t a0, int32_t a1, int32_t a2, int32_t a3, Struct16BytesMixed a4, Struct16BytesMixed a5, Struct16BytesMixed a6, Struct16BytesMixed a7, double a8)) { int32_t a0; int32_t a1; int32_t a2; int32_t a3; Struct16BytesMixed a4; Struct16BytesMixed a5; Struct16BytesMixed a6; Struct16BytesMixed a7; double a8; a0 = -1; a1 = 2; a2 = -3; a3 = 4; a4.a0 = -5.0; a4.a1 = 6; a5.a0 = -7.0; a5.a1 = 8; a6.a0 = -9.0; a6.a1 = 10; a7.a0 = -11.0; a7.a1 = 12; a8 = -13.0; std::cout << "Calling TestPassInt32x4Struct16BytesMixedx4Double(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", (" << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), " << a8 << ")" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); std::cout << "result = " << result << "\n"; CHECK_APPROX(-7.0, result); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // On various architectures, first struct is allocated on stack. // Check that the other two arguments are allocated on registers. DART_EXPORT intptr_t TestPassStruct40BytesHomogeneousDoubleStruct4BytesHomo( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Struct40BytesHomogeneousDouble a0, Struct4BytesHomogeneousInt16 a1, Struct8BytesHomogeneousFloat a2)) { Struct40BytesHomogeneousDouble a0; Struct4BytesHomogeneousInt16 a1; Struct8BytesHomogeneousFloat a2; a0.a0 = -1.0; a0.a1 = 2.0; a0.a2 = -3.0; a0.a3 = 4.0; a0.a4 = -5.0; a1.a0 = 6; a1.a1 = -7; a2.a0 = 8.0; a2.a1 = -9.0; std::cout << "Calling TestPassStruct40BytesHomogeneousDoubleStruct4BytesHomo(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << "), (" << a1.a0 << ", " << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "))" << ")\n"; double result = f(a0, a1, a2); std::cout << "result = " << result << "\n"; CHECK_APPROX(-5.0, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1, a2); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0, a1, a2); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of 16 byte int within struct. DART_EXPORT intptr_t TestPassInt32x8Doublex8Int64Int8Struct1ByteIntInt64Int( // NOLINTNEXTLINE(whitespace/parens) double (*f)(int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, double a8, double a9, double a10, double a11, double a12, double a13, double a14, double a15, int64_t a16, int8_t a17, Struct1ByteInt a18, int64_t a19, int8_t a20, Struct4BytesHomogeneousInt16 a21, int64_t a22, int8_t a23, Struct8BytesInt a24, int64_t a25, int8_t a26, Struct8BytesHomogeneousFloat a27, int64_t a28, int8_t a29, Struct8BytesMixed a30, int64_t a31, int8_t a32, StructAlignmentInt16 a33, int64_t a34, int8_t a35, StructAlignmentInt32 a36, int64_t a37, int8_t a38, StructAlignmentInt64 a39)) { int32_t a0; int32_t a1; int32_t a2; int32_t a3; int32_t a4; int32_t a5; int32_t a6; int32_t a7; double a8; double a9; double a10; double a11; double a12; double a13; double a14; double a15; int64_t a16; int8_t a17; Struct1ByteInt a18; int64_t a19; int8_t a20; Struct4BytesHomogeneousInt16 a21; int64_t a22; int8_t a23; Struct8BytesInt a24; int64_t a25; int8_t a26; Struct8BytesHomogeneousFloat a27; int64_t a28; int8_t a29; Struct8BytesMixed a30; int64_t a31; int8_t a32; StructAlignmentInt16 a33; int64_t a34; int8_t a35; StructAlignmentInt32 a36; int64_t a37; int8_t a38; StructAlignmentInt64 a39; a0 = -1; a1 = 2; a2 = -3; a3 = 4; a4 = -5; a5 = 6; a6 = -7; a7 = 8; a8 = -9.0; a9 = 10.0; a10 = -11.0; a11 = 12.0; a12 = -13.0; a13 = 14.0; a14 = -15.0; a15 = 16.0; a16 = -17; a17 = 18; a18.a0 = -19; a19 = 20; a20 = -21; a21.a0 = 22; a21.a1 = -23; a22 = 24; a23 = -25; a24.a0 = 26; a24.a1 = -27; a24.a2 = 28; a25 = -29; a26 = 30; a27.a0 = -31.0; a27.a1 = 32.0; a28 = -33; a29 = 34; a30.a0 = -35.0; a30.a1 = 36; a30.a2 = -37; a31 = 38; a32 = -39; a33.a0 = 40; a33.a1 = -41; a33.a2 = 42; a34 = -43; a35 = 44; a36.a0 = -45; a36.a1 = 46; a36.a2 = -47; a37 = 48; a38 = -49; a39.a0 = 50; a39.a1 = -51; a39.a2 = 52; std::cout << "Calling TestPassInt32x8Doublex8Int64Int8Struct1ByteIntInt64Int(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7 << ", " << a8 << ", " << a9 << ", " << a10 << ", " << a11 << ", " << a12 << ", " << a13 << ", " << a14 << ", " << a15 << ", " << a16 << ", " << static_cast(a17) << ", (" << static_cast(a18.a0) << "), " << a19 << ", " << static_cast(a20) << ", (" << a21.a0 << ", " << a21.a1 << "), " << a22 << ", " << static_cast(a23) << ", (" << a24.a0 << ", " << a24.a1 << ", " << a24.a2 << "), " << a25 << ", " << static_cast(a26) << ", (" << a27.a0 << ", " << a27.a1 << "), " << a28 << ", " << static_cast(a29) << ", (" << a30.a0 << ", " << a30.a1 << ", " << a30.a2 << "), " << a31 << ", " << static_cast(a32) << ", (" << static_cast(a33.a0) << ", " << a33.a1 << ", " << static_cast(a33.a2) << "), " << a34 << ", " << static_cast(a35) << ", (" << static_cast(a36.a0) << ", " << a36.a1 << ", " << static_cast(a36.a2) << "), " << a37 << ", " << static_cast(a38) << ", (" << static_cast(a39.a0) << ", " << a39.a1 << ", " << static_cast(a39.a2) << "))" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39); std::cout << "result = " << result << "\n"; CHECK_APPROX(26.0, result); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of 16 byte int within struct. DART_EXPORT intptr_t TestPassStructAlignmentInt16( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(StructAlignmentInt16 a0)) { StructAlignmentInt16 a0; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; std::cout << "Calling TestPassStructAlignmentInt16(" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "))" << ")\n"; int64_t result = f(a0); std::cout << "result = " << result << "\n"; CHECK_EQ(-2, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of 32 byte int within struct. DART_EXPORT intptr_t TestPassStructAlignmentInt32( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(StructAlignmentInt32 a0)) { StructAlignmentInt32 a0; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; std::cout << "Calling TestPassStructAlignmentInt32(" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "))" << ")\n"; int64_t result = f(a0); std::cout << "result = " << result << "\n"; CHECK_EQ(-2, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of 64 byte int within struct. DART_EXPORT intptr_t TestPassStructAlignmentInt64( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(StructAlignmentInt64 a0)) { StructAlignmentInt64 a0; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; std::cout << "Calling TestPassStructAlignmentInt64(" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "))" << ")\n"; int64_t result = f(a0); std::cout << "result = " << result << "\n"; CHECK_EQ(-2, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Simple nested struct. No alignment gaps on any architectures. // 10 arguments exhaust registers on all platforms. DART_EXPORT intptr_t TestPassStruct8BytesNestedIntx10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct8BytesNestedInt a0, Struct8BytesNestedInt a1, Struct8BytesNestedInt a2, Struct8BytesNestedInt a3, Struct8BytesNestedInt a4, Struct8BytesNestedInt a5, Struct8BytesNestedInt a6, Struct8BytesNestedInt a7, Struct8BytesNestedInt a8, Struct8BytesNestedInt a9)) { Struct8BytesNestedInt a0; Struct8BytesNestedInt a1; Struct8BytesNestedInt a2; Struct8BytesNestedInt a3; Struct8BytesNestedInt a4; Struct8BytesNestedInt a5; Struct8BytesNestedInt a6; Struct8BytesNestedInt a7; Struct8BytesNestedInt a8; Struct8BytesNestedInt a9; a0.a0.a0 = -1; a0.a0.a1 = 2; a0.a1.a0 = -3; a0.a1.a1 = 4; a1.a0.a0 = -5; a1.a0.a1 = 6; a1.a1.a0 = -7; a1.a1.a1 = 8; a2.a0.a0 = -9; a2.a0.a1 = 10; a2.a1.a0 = -11; a2.a1.a1 = 12; a3.a0.a0 = -13; a3.a0.a1 = 14; a3.a1.a0 = -15; a3.a1.a1 = 16; a4.a0.a0 = -17; a4.a0.a1 = 18; a4.a1.a0 = -19; a4.a1.a1 = 20; a5.a0.a0 = -21; a5.a0.a1 = 22; a5.a1.a0 = -23; a5.a1.a1 = 24; a6.a0.a0 = -25; a6.a0.a1 = 26; a6.a1.a0 = -27; a6.a1.a1 = 28; a7.a0.a0 = -29; a7.a0.a1 = 30; a7.a1.a0 = -31; a7.a1.a1 = 32; a8.a0.a0 = -33; a8.a0.a1 = 34; a8.a1.a0 = -35; a8.a1.a1 = 36; a9.a0.a0 = -37; a9.a0.a1 = 38; a9.a1.a0 = -39; a9.a1.a1 = 40; std::cout << "Calling TestPassStruct8BytesNestedIntx10(" << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0 << ", " << a0.a1.a1 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << "), (" << a1.a1.a0 << ", " << a1.a1.a1 << ")), ((" << a2.a0.a0 << ", " << a2.a0.a1 << "), (" << a2.a1.a0 << ", " << a2.a1.a1 << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << "), (" << a3.a1.a0 << ", " << a3.a1.a1 << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1 << "), (" << a4.a1.a0 << ", " << a4.a1.a1 << ")), ((" << a5.a0.a0 << ", " << a5.a0.a1 << "), (" << a5.a1.a0 << ", " << a5.a1.a1 << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << "), (" << a6.a1.a0 << ", " << a6.a1.a1 << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1 << "), (" << a7.a1.a0 << ", " << a7.a1.a1 << ")), ((" << a8.a0.a0 << ", " << a8.a0.a1 << "), (" << a8.a1.a0 << ", " << a8.a1.a1 << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << "), (" << a9.a1.a0 << ", " << a9.a1.a1 << ")))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(20, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Simple nested struct. No alignment gaps on any architectures. // 10 arguments exhaust fpu registers on all platforms. DART_EXPORT intptr_t TestPassStruct8BytesNestedFloatx10( // NOLINTNEXTLINE(whitespace/parens) float (*f)(Struct8BytesNestedFloat a0, Struct8BytesNestedFloat a1, Struct8BytesNestedFloat a2, Struct8BytesNestedFloat a3, Struct8BytesNestedFloat a4, Struct8BytesNestedFloat a5, Struct8BytesNestedFloat a6, Struct8BytesNestedFloat a7, Struct8BytesNestedFloat a8, Struct8BytesNestedFloat a9)) { Struct8BytesNestedFloat a0; Struct8BytesNestedFloat a1; Struct8BytesNestedFloat a2; Struct8BytesNestedFloat a3; Struct8BytesNestedFloat a4; Struct8BytesNestedFloat a5; Struct8BytesNestedFloat a6; Struct8BytesNestedFloat a7; Struct8BytesNestedFloat a8; Struct8BytesNestedFloat a9; a0.a0.a0 = -1.0; a0.a1.a0 = 2.0; a1.a0.a0 = -3.0; a1.a1.a0 = 4.0; a2.a0.a0 = -5.0; a2.a1.a0 = 6.0; a3.a0.a0 = -7.0; a3.a1.a0 = 8.0; a4.a0.a0 = -9.0; a4.a1.a0 = 10.0; a5.a0.a0 = -11.0; a5.a1.a0 = 12.0; a6.a0.a0 = -13.0; a6.a1.a0 = 14.0; a7.a0.a0 = -15.0; a7.a1.a0 = 16.0; a8.a0.a0 = -17.0; a8.a1.a0 = 18.0; a9.a0.a0 = -19.0; a9.a1.a0 = 20.0; std::cout << "Calling TestPassStruct8BytesNestedFloatx10(" << "(((" << a0.a0.a0 << "), (" << a0.a1.a0 << ")), ((" << a1.a0.a0 << "), (" << a1.a1.a0 << ")), ((" << a2.a0.a0 << "), (" << a2.a1.a0 << ")), ((" << a3.a0.a0 << "), (" << a3.a1.a0 << ")), ((" << a4.a0.a0 << "), (" << a4.a1.a0 << ")), ((" << a5.a0.a0 << "), (" << a5.a1.a0 << ")), ((" << a6.a0.a0 << "), (" << a6.a1.a0 << ")), ((" << a7.a0.a0 << "), (" << a7.a1.a0 << ")), ((" << a8.a0.a0 << "), (" << a8.a1.a0 << ")), ((" << a9.a0.a0 << "), (" << a9.a1.a0 << ")))" << ")\n"; float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(10.0, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassStruct8BytesNestedFloat2x10( // NOLINTNEXTLINE(whitespace/parens) float (*f)(Struct8BytesNestedFloat2 a0, Struct8BytesNestedFloat2 a1, Struct8BytesNestedFloat2 a2, Struct8BytesNestedFloat2 a3, Struct8BytesNestedFloat2 a4, Struct8BytesNestedFloat2 a5, Struct8BytesNestedFloat2 a6, Struct8BytesNestedFloat2 a7, Struct8BytesNestedFloat2 a8, Struct8BytesNestedFloat2 a9)) { Struct8BytesNestedFloat2 a0; Struct8BytesNestedFloat2 a1; Struct8BytesNestedFloat2 a2; Struct8BytesNestedFloat2 a3; Struct8BytesNestedFloat2 a4; Struct8BytesNestedFloat2 a5; Struct8BytesNestedFloat2 a6; Struct8BytesNestedFloat2 a7; Struct8BytesNestedFloat2 a8; Struct8BytesNestedFloat2 a9; a0.a0.a0 = -1.0; a0.a1 = 2.0; a1.a0.a0 = -3.0; a1.a1 = 4.0; a2.a0.a0 = -5.0; a2.a1 = 6.0; a3.a0.a0 = -7.0; a3.a1 = 8.0; a4.a0.a0 = -9.0; a4.a1 = 10.0; a5.a0.a0 = -11.0; a5.a1 = 12.0; a6.a0.a0 = -13.0; a6.a1 = 14.0; a7.a0.a0 = -15.0; a7.a1 = 16.0; a8.a0.a0 = -17.0; a8.a1 = 18.0; a9.a0.a0 = -19.0; a9.a1 = 20.0; std::cout << "Calling TestPassStruct8BytesNestedFloat2x10(" << "(((" << a0.a0.a0 << "), " << a0.a1 << "), ((" << a1.a0.a0 << "), " << a1.a1 << "), ((" << a2.a0.a0 << "), " << a2.a1 << "), ((" << a3.a0.a0 << "), " << a3.a1 << "), ((" << a4.a0.a0 << "), " << a4.a1 << "), ((" << a5.a0.a0 << "), " << a5.a1 << "), ((" << a6.a0.a0 << "), " << a6.a1 << "), ((" << a7.a0.a0 << "), " << a7.a1 << "), ((" << a8.a0.a0 << "), " << a8.a1 << "), ((" << a9.a0.a0 << "), " << a9.a1 << "))" << ")\n"; float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(10.0, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Simple nested struct. No alignment gaps on any architectures. // 10 arguments exhaust all registers on all platforms. DART_EXPORT intptr_t TestPassStruct8BytesNestedMixedx10( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Struct8BytesNestedMixed a0, Struct8BytesNestedMixed a1, Struct8BytesNestedMixed a2, Struct8BytesNestedMixed a3, Struct8BytesNestedMixed a4, Struct8BytesNestedMixed a5, Struct8BytesNestedMixed a6, Struct8BytesNestedMixed a7, Struct8BytesNestedMixed a8, Struct8BytesNestedMixed a9)) { Struct8BytesNestedMixed a0; Struct8BytesNestedMixed a1; Struct8BytesNestedMixed a2; Struct8BytesNestedMixed a3; Struct8BytesNestedMixed a4; Struct8BytesNestedMixed a5; Struct8BytesNestedMixed a6; Struct8BytesNestedMixed a7; Struct8BytesNestedMixed a8; Struct8BytesNestedMixed a9; a0.a0.a0 = -1; a0.a0.a1 = 2; a0.a1.a0 = -3.0; a1.a0.a0 = 4; a1.a0.a1 = -5; a1.a1.a0 = 6.0; a2.a0.a0 = -7; a2.a0.a1 = 8; a2.a1.a0 = -9.0; a3.a0.a0 = 10; a3.a0.a1 = -11; a3.a1.a0 = 12.0; a4.a0.a0 = -13; a4.a0.a1 = 14; a4.a1.a0 = -15.0; a5.a0.a0 = 16; a5.a0.a1 = -17; a5.a1.a0 = 18.0; a6.a0.a0 = -19; a6.a0.a1 = 20; a6.a1.a0 = -21.0; a7.a0.a0 = 22; a7.a0.a1 = -23; a7.a1.a0 = 24.0; a8.a0.a0 = -25; a8.a0.a1 = 26; a8.a1.a0 = -27.0; a9.a0.a0 = 28; a9.a0.a1 = -29; a9.a1.a0 = 30.0; std::cout << "Calling TestPassStruct8BytesNestedMixedx10(" << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << "), (" << a1.a1.a0 << ")), ((" << a2.a0.a0 << ", " << a2.a0.a1 << "), (" << a2.a1.a0 << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << "), (" << a3.a1.a0 << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1 << "), (" << a4.a1.a0 << ")), ((" << a5.a0.a0 << ", " << a5.a0.a1 << "), (" << a5.a1.a0 << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << "), (" << a6.a1.a0 << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1 << "), (" << a7.a1.a0 << ")), ((" << a8.a0.a0 << ", " << a8.a0.a1 << "), (" << a8.a1.a0 << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << "), (" << a9.a1.a0 << ")))" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(15.0, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Deeper nested struct to test recursive member access. DART_EXPORT intptr_t TestPassStruct16BytesNestedIntx2( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct16BytesNestedInt a0, Struct16BytesNestedInt a1)) { Struct16BytesNestedInt a0; Struct16BytesNestedInt a1; a0.a0.a0.a0 = -1; a0.a0.a0.a1 = 2; a0.a0.a1.a0 = -3; a0.a0.a1.a1 = 4; a0.a1.a0.a0 = -5; a0.a1.a0.a1 = 6; a0.a1.a1.a0 = -7; a0.a1.a1.a1 = 8; a1.a0.a0.a0 = -9; a1.a0.a0.a1 = 10; a1.a0.a1.a0 = -11; a1.a0.a1.a1 = 12; a1.a1.a0.a0 = -13; a1.a1.a0.a1 = 14; a1.a1.a1.a0 = -15; a1.a1.a1.a1 = 16; std::cout << "Calling TestPassStruct16BytesNestedIntx2(" << "((((" << a0.a0.a0.a0 << ", " << a0.a0.a0.a1 << "), (" << a0.a0.a1.a0 << ", " << a0.a0.a1.a1 << ")), ((" << a0.a1.a0.a0 << ", " << a0.a1.a0.a1 << "), (" << a0.a1.a1.a0 << ", " << a0.a1.a1.a1 << "))), (((" << a1.a0.a0.a0 << ", " << a1.a0.a0.a1 << "), (" << a1.a0.a1.a0 << ", " << a1.a0.a1.a1 << ")), ((" << a1.a1.a0.a0 << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0 << ", " << a1.a1.a1.a1 << "))))" << ")\n"; int64_t result = f(a0, a1); std::cout << "result = " << result << "\n"; CHECK_EQ(8, result); // Pass argument that will make the Dart callback throw. a0.a0.a0.a0 = 42; result = f(a0, a1); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0.a0 = 84; result = f(a0, a1); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Even deeper nested struct to test recursive member access. DART_EXPORT intptr_t TestPassStruct32BytesNestedIntx2( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct32BytesNestedInt a0, Struct32BytesNestedInt a1)) { Struct32BytesNestedInt a0; Struct32BytesNestedInt a1; a0.a0.a0.a0.a0 = -1; a0.a0.a0.a0.a1 = 2; a0.a0.a0.a1.a0 = -3; a0.a0.a0.a1.a1 = 4; a0.a0.a1.a0.a0 = -5; a0.a0.a1.a0.a1 = 6; a0.a0.a1.a1.a0 = -7; a0.a0.a1.a1.a1 = 8; a0.a1.a0.a0.a0 = -9; a0.a1.a0.a0.a1 = 10; a0.a1.a0.a1.a0 = -11; a0.a1.a0.a1.a1 = 12; a0.a1.a1.a0.a0 = -13; a0.a1.a1.a0.a1 = 14; a0.a1.a1.a1.a0 = -15; a0.a1.a1.a1.a1 = 16; a1.a0.a0.a0.a0 = -17; a1.a0.a0.a0.a1 = 18; a1.a0.a0.a1.a0 = -19; a1.a0.a0.a1.a1 = 20; a1.a0.a1.a0.a0 = -21; a1.a0.a1.a0.a1 = 22; a1.a0.a1.a1.a0 = -23; a1.a0.a1.a1.a1 = 24; a1.a1.a0.a0.a0 = -25; a1.a1.a0.a0.a1 = 26; a1.a1.a0.a1.a0 = -27; a1.a1.a0.a1.a1 = 28; a1.a1.a1.a0.a0 = -29; a1.a1.a1.a0.a1 = 30; a1.a1.a1.a1.a0 = -31; a1.a1.a1.a1.a1 = 32; std::cout << "Calling TestPassStruct32BytesNestedIntx2(" << "(((((" << a0.a0.a0.a0.a0 << ", " << a0.a0.a0.a0.a1 << "), (" << a0.a0.a0.a1.a0 << ", " << a0.a0.a0.a1.a1 << ")), ((" << a0.a0.a1.a0.a0 << ", " << a0.a0.a1.a0.a1 << "), (" << a0.a0.a1.a1.a0 << ", " << a0.a0.a1.a1.a1 << "))), (((" << a0.a1.a0.a0.a0 << ", " << a0.a1.a0.a0.a1 << "), (" << a0.a1.a0.a1.a0 << ", " << a0.a1.a0.a1.a1 << ")), ((" << a0.a1.a1.a0.a0 << ", " << a0.a1.a1.a0.a1 << "), (" << a0.a1.a1.a1.a0 << ", " << a0.a1.a1.a1.a1 << ")))), ((((" << a1.a0.a0.a0.a0 << ", " << a1.a0.a0.a0.a1 << "), (" << a1.a0.a0.a1.a0 << ", " << a1.a0.a0.a1.a1 << ")), ((" << a1.a0.a1.a0.a0 << ", " << a1.a0.a1.a0.a1 << "), (" << a1.a0.a1.a1.a0 << ", " << a1.a0.a1.a1.a1 << "))), (((" << a1.a1.a0.a0.a0 << ", " << a1.a1.a0.a0.a1 << "), (" << a1.a1.a0.a1.a0 << ", " << a1.a1.a0.a1.a1 << ")), ((" << a1.a1.a1.a0.a0 << ", " << a1.a1.a1.a0.a1 << "), (" << a1.a1.a1.a1.a0 << ", " << a1.a1.a1.a1.a1 << ")))))" << ")\n"; int64_t result = f(a0, a1); std::cout << "result = " << result << "\n"; CHECK_EQ(16, result); // Pass argument that will make the Dart callback throw. a0.a0.a0.a0.a0 = 42; result = f(a0, a1); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0.a0.a0 = 84; result = f(a0, a1); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 16 byte int. DART_EXPORT intptr_t TestPassStructNestedIntStructAlignmentInt16( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(StructNestedIntStructAlignmentInt16 a0)) { StructNestedIntStructAlignmentInt16 a0; a0.a0.a0 = -1; a0.a0.a1 = 2; a0.a0.a2 = -3; a0.a1.a0 = 4; a0.a1.a1 = -5; a0.a1.a2 = 6; std::cout << "Calling TestPassStructNestedIntStructAlignmentInt16(" << "(((" << static_cast(a0.a0.a0) << ", " << a0.a0.a1 << ", " << static_cast(a0.a0.a2) << "), (" << static_cast(a0.a1.a0) << ", " << a0.a1.a1 << ", " << static_cast(a0.a1.a2) << ")))" << ")\n"; int64_t result = f(a0); std::cout << "result = " << result << "\n"; CHECK_EQ(3, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 32 byte int. DART_EXPORT intptr_t TestPassStructNestedIntStructAlignmentInt32( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(StructNestedIntStructAlignmentInt32 a0)) { StructNestedIntStructAlignmentInt32 a0; a0.a0.a0 = -1; a0.a0.a1 = 2; a0.a0.a2 = -3; a0.a1.a0 = 4; a0.a1.a1 = -5; a0.a1.a2 = 6; std::cout << "Calling TestPassStructNestedIntStructAlignmentInt32(" << "(((" << static_cast(a0.a0.a0) << ", " << a0.a0.a1 << ", " << static_cast(a0.a0.a2) << "), (" << static_cast(a0.a1.a0) << ", " << a0.a1.a1 << ", " << static_cast(a0.a1.a2) << ")))" << ")\n"; int64_t result = f(a0); std::cout << "result = " << result << "\n"; CHECK_EQ(3, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 64 byte int. DART_EXPORT intptr_t TestPassStructNestedIntStructAlignmentInt64( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(StructNestedIntStructAlignmentInt64 a0)) { StructNestedIntStructAlignmentInt64 a0; a0.a0.a0 = -1; a0.a0.a1 = 2; a0.a0.a2 = -3; a0.a1.a0 = 4; a0.a1.a1 = -5; a0.a1.a2 = 6; std::cout << "Calling TestPassStructNestedIntStructAlignmentInt64(" << "(((" << static_cast(a0.a0.a0) << ", " << a0.a0.a1 << ", " << static_cast(a0.a0.a2) << "), (" << static_cast(a0.a1.a0) << ", " << a0.a1.a1 << ", " << static_cast(a0.a1.a2) << ")))" << ")\n"; int64_t result = f(a0); std::cout << "result = " << result << "\n"; CHECK_EQ(3, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Return big irregular struct as smoke test. DART_EXPORT intptr_t TestPassStructNestedIrregularEvenBiggerx4( // NOLINTNEXTLINE(whitespace/parens) double (*f)(StructNestedIrregularEvenBigger a0, StructNestedIrregularEvenBigger a1, StructNestedIrregularEvenBigger a2, StructNestedIrregularEvenBigger a3)) { StructNestedIrregularEvenBigger a0; StructNestedIrregularEvenBigger a1; StructNestedIrregularEvenBigger a2; StructNestedIrregularEvenBigger a3; a0.a0 = 1; a0.a1.a0.a0 = 2; a0.a1.a0.a1.a0.a0 = -3; a0.a1.a0.a1.a0.a1 = 4; a0.a1.a0.a1.a1.a0 = -5.0; a0.a1.a0.a2 = 6; a0.a1.a0.a3.a0.a0 = -7.0; a0.a1.a0.a3.a1 = 8.0; a0.a1.a0.a4 = 9; a0.a1.a0.a5.a0.a0 = 10.0; a0.a1.a0.a5.a1.a0 = -11.0; a0.a1.a0.a6 = 12; a0.a1.a1.a0.a0 = -13; a0.a1.a1.a0.a1 = 14; a0.a1.a1.a1.a0 = -15.0; a0.a1.a2 = 16.0; a0.a1.a3 = -17.0; a0.a2.a0.a0 = 18; a0.a2.a0.a1.a0.a0 = -19; a0.a2.a0.a1.a0.a1 = 20; a0.a2.a0.a1.a1.a0 = -21.0; a0.a2.a0.a2 = 22; a0.a2.a0.a3.a0.a0 = -23.0; a0.a2.a0.a3.a1 = 24.0; a0.a2.a0.a4 = 25; a0.a2.a0.a5.a0.a0 = 26.0; a0.a2.a0.a5.a1.a0 = -27.0; a0.a2.a0.a6 = 28; a0.a2.a1.a0.a0 = -29; a0.a2.a1.a0.a1 = 30; a0.a2.a1.a1.a0 = -31.0; a0.a2.a2 = 32.0; a0.a2.a3 = -33.0; a0.a3 = 34.0; a1.a0 = 35; a1.a1.a0.a0 = 36; a1.a1.a0.a1.a0.a0 = -37; a1.a1.a0.a1.a0.a1 = 38; a1.a1.a0.a1.a1.a0 = -39.0; a1.a1.a0.a2 = 40; a1.a1.a0.a3.a0.a0 = -41.0; a1.a1.a0.a3.a1 = 42.0; a1.a1.a0.a4 = 43; a1.a1.a0.a5.a0.a0 = 44.0; a1.a1.a0.a5.a1.a0 = -45.0; a1.a1.a0.a6 = 46; a1.a1.a1.a0.a0 = -47; a1.a1.a1.a0.a1 = 48; a1.a1.a1.a1.a0 = -49.0; a1.a1.a2 = 50.0; a1.a1.a3 = -51.0; a1.a2.a0.a0 = 52; a1.a2.a0.a1.a0.a0 = -53; a1.a2.a0.a1.a0.a1 = 54; a1.a2.a0.a1.a1.a0 = -55.0; a1.a2.a0.a2 = 56; a1.a2.a0.a3.a0.a0 = -57.0; a1.a2.a0.a3.a1 = 58.0; a1.a2.a0.a4 = 59; a1.a2.a0.a5.a0.a0 = 60.0; a1.a2.a0.a5.a1.a0 = -61.0; a1.a2.a0.a6 = 62; a1.a2.a1.a0.a0 = -63; a1.a2.a1.a0.a1 = 64; a1.a2.a1.a1.a0 = -65.0; a1.a2.a2 = 66.0; a1.a2.a3 = -67.0; a1.a3 = 68.0; a2.a0 = 69; a2.a1.a0.a0 = 70; a2.a1.a0.a1.a0.a0 = -71; a2.a1.a0.a1.a0.a1 = 72; a2.a1.a0.a1.a1.a0 = -73.0; a2.a1.a0.a2 = 74; a2.a1.a0.a3.a0.a0 = -75.0; a2.a1.a0.a3.a1 = 76.0; a2.a1.a0.a4 = 77; a2.a1.a0.a5.a0.a0 = 78.0; a2.a1.a0.a5.a1.a0 = -79.0; a2.a1.a0.a6 = 80; a2.a1.a1.a0.a0 = -81; a2.a1.a1.a0.a1 = 82; a2.a1.a1.a1.a0 = -83.0; a2.a1.a2 = 84.0; a2.a1.a3 = -85.0; a2.a2.a0.a0 = 86; a2.a2.a0.a1.a0.a0 = -87; a2.a2.a0.a1.a0.a1 = 88; a2.a2.a0.a1.a1.a0 = -89.0; a2.a2.a0.a2 = 90; a2.a2.a0.a3.a0.a0 = -91.0; a2.a2.a0.a3.a1 = 92.0; a2.a2.a0.a4 = 93; a2.a2.a0.a5.a0.a0 = 94.0; a2.a2.a0.a5.a1.a0 = -95.0; a2.a2.a0.a6 = 96; a2.a2.a1.a0.a0 = -97; a2.a2.a1.a0.a1 = 98; a2.a2.a1.a1.a0 = -99.0; a2.a2.a2 = 100.0; a2.a2.a3 = -101.0; a2.a3 = 102.0; a3.a0 = 103; a3.a1.a0.a0 = 104; a3.a1.a0.a1.a0.a0 = -105; a3.a1.a0.a1.a0.a1 = 106; a3.a1.a0.a1.a1.a0 = -107.0; a3.a1.a0.a2 = 108; a3.a1.a0.a3.a0.a0 = -109.0; a3.a1.a0.a3.a1 = 110.0; a3.a1.a0.a4 = 111; a3.a1.a0.a5.a0.a0 = 112.0; a3.a1.a0.a5.a1.a0 = -113.0; a3.a1.a0.a6 = 114; a3.a1.a1.a0.a0 = -115; a3.a1.a1.a0.a1 = 116; a3.a1.a1.a1.a0 = -117.0; a3.a1.a2 = 118.0; a3.a1.a3 = -119.0; a3.a2.a0.a0 = 120; a3.a2.a0.a1.a0.a0 = -121; a3.a2.a0.a1.a0.a1 = 122; a3.a2.a0.a1.a1.a0 = -123.0; a3.a2.a0.a2 = 124; a3.a2.a0.a3.a0.a0 = -125.0; a3.a2.a0.a3.a1 = 126.0; a3.a2.a0.a4 = 127; a3.a2.a0.a5.a0.a0 = 128.0; a3.a2.a0.a5.a1.a0 = -129.0; a3.a2.a0.a6 = 130; a3.a2.a1.a0.a0 = -131; a3.a2.a1.a0.a1 = 132; a3.a2.a1.a1.a0 = -133.0; a3.a2.a2 = 134.0; a3.a2.a3 = -135.0; a3.a3 = 136.0; std::cout << "Calling TestPassStructNestedIrregularEvenBiggerx4(" << "((" << a0.a0 << ", ((" << a0.a1.a0.a0 << ", ((" << a0.a1.a0.a1.a0.a0 << ", " << a0.a1.a0.a1.a0.a1 << "), (" << a0.a1.a0.a1.a1.a0 << ")), " << a0.a1.a0.a2 << ", ((" << a0.a1.a0.a3.a0.a0 << "), " << a0.a1.a0.a3.a1 << "), " << a0.a1.a0.a4 << ", ((" << a0.a1.a0.a5.a0.a0 << "), (" << a0.a1.a0.a5.a1.a0 << ")), " << a0.a1.a0.a6 << "), ((" << a0.a1.a1.a0.a0 << ", " << a0.a1.a1.a0.a1 << "), (" << a0.a1.a1.a1.a0 << ")), " << a0.a1.a2 << ", " << a0.a1.a3 << "), ((" << a0.a2.a0.a0 << ", ((" << a0.a2.a0.a1.a0.a0 << ", " << a0.a2.a0.a1.a0.a1 << "), (" << a0.a2.a0.a1.a1.a0 << ")), " << a0.a2.a0.a2 << ", ((" << a0.a2.a0.a3.a0.a0 << "), " << a0.a2.a0.a3.a1 << "), " << a0.a2.a0.a4 << ", ((" << a0.a2.a0.a5.a0.a0 << "), (" << a0.a2.a0.a5.a1.a0 << ")), " << a0.a2.a0.a6 << "), ((" << a0.a2.a1.a0.a0 << ", " << a0.a2.a1.a0.a1 << "), (" << a0.a2.a1.a1.a0 << ")), " << a0.a2.a2 << ", " << a0.a2.a3 << "), " << a0.a3 << "), (" << a1.a0 << ", ((" << a1.a1.a0.a0 << ", ((" << a1.a1.a0.a1.a0.a0 << ", " << a1.a1.a0.a1.a0.a1 << "), (" << a1.a1.a0.a1.a1.a0 << ")), " << a1.a1.a0.a2 << ", ((" << a1.a1.a0.a3.a0.a0 << "), " << a1.a1.a0.a3.a1 << "), " << a1.a1.a0.a4 << ", ((" << a1.a1.a0.a5.a0.a0 << "), (" << a1.a1.a0.a5.a1.a0 << ")), " << a1.a1.a0.a6 << "), ((" << a1.a1.a1.a0.a0 << ", " << a1.a1.a1.a0.a1 << "), (" << a1.a1.a1.a1.a0 << ")), " << a1.a1.a2 << ", " << a1.a1.a3 << "), ((" << a1.a2.a0.a0 << ", ((" << a1.a2.a0.a1.a0.a0 << ", " << a1.a2.a0.a1.a0.a1 << "), (" << a1.a2.a0.a1.a1.a0 << ")), " << a1.a2.a0.a2 << ", ((" << a1.a2.a0.a3.a0.a0 << "), " << a1.a2.a0.a3.a1 << "), " << a1.a2.a0.a4 << ", ((" << a1.a2.a0.a5.a0.a0 << "), (" << a1.a2.a0.a5.a1.a0 << ")), " << a1.a2.a0.a6 << "), ((" << a1.a2.a1.a0.a0 << ", " << a1.a2.a1.a0.a1 << "), (" << a1.a2.a1.a1.a0 << ")), " << a1.a2.a2 << ", " << a1.a2.a3 << "), " << a1.a3 << "), (" << a2.a0 << ", ((" << a2.a1.a0.a0 << ", ((" << a2.a1.a0.a1.a0.a0 << ", " << a2.a1.a0.a1.a0.a1 << "), (" << a2.a1.a0.a1.a1.a0 << ")), " << a2.a1.a0.a2 << ", ((" << a2.a1.a0.a3.a0.a0 << "), " << a2.a1.a0.a3.a1 << "), " << a2.a1.a0.a4 << ", ((" << a2.a1.a0.a5.a0.a0 << "), (" << a2.a1.a0.a5.a1.a0 << ")), " << a2.a1.a0.a6 << "), ((" << a2.a1.a1.a0.a0 << ", " << a2.a1.a1.a0.a1 << "), (" << a2.a1.a1.a1.a0 << ")), " << a2.a1.a2 << ", " << a2.a1.a3 << "), ((" << a2.a2.a0.a0 << ", ((" << a2.a2.a0.a1.a0.a0 << ", " << a2.a2.a0.a1.a0.a1 << "), (" << a2.a2.a0.a1.a1.a0 << ")), " << a2.a2.a0.a2 << ", ((" << a2.a2.a0.a3.a0.a0 << "), " << a2.a2.a0.a3.a1 << "), " << a2.a2.a0.a4 << ", ((" << a2.a2.a0.a5.a0.a0 << "), (" << a2.a2.a0.a5.a1.a0 << ")), " << a2.a2.a0.a6 << "), ((" << a2.a2.a1.a0.a0 << ", " << a2.a2.a1.a0.a1 << "), (" << a2.a2.a1.a1.a0 << ")), " << a2.a2.a2 << ", " << a2.a2.a3 << "), " << a2.a3 << "), (" << a3.a0 << ", ((" << a3.a1.a0.a0 << ", ((" << a3.a1.a0.a1.a0.a0 << ", " << a3.a1.a0.a1.a0.a1 << "), (" << a3.a1.a0.a1.a1.a0 << ")), " << a3.a1.a0.a2 << ", ((" << a3.a1.a0.a3.a0.a0 << "), " << a3.a1.a0.a3.a1 << "), " << a3.a1.a0.a4 << ", ((" << a3.a1.a0.a5.a0.a0 << "), (" << a3.a1.a0.a5.a1.a0 << ")), " << a3.a1.a0.a6 << "), ((" << a3.a1.a1.a0.a0 << ", " << a3.a1.a1.a0.a1 << "), (" << a3.a1.a1.a1.a0 << ")), " << a3.a1.a2 << ", " << a3.a1.a3 << "), ((" << a3.a2.a0.a0 << ", ((" << a3.a2.a0.a1.a0.a0 << ", " << a3.a2.a0.a1.a0.a1 << "), (" << a3.a2.a0.a1.a1.a0 << ")), " << a3.a2.a0.a2 << ", ((" << a3.a2.a0.a3.a0.a0 << "), " << a3.a2.a0.a3.a1 << "), " << a3.a2.a0.a4 << ", ((" << a3.a2.a0.a5.a0.a0 << "), (" << a3.a2.a0.a5.a1.a0 << ")), " << a3.a2.a0.a6 << "), ((" << a3.a2.a1.a0.a0 << ", " << a3.a2.a1.a0.a1 << "), (" << a3.a2.a1.a1.a0 << ")), " << a3.a2.a2 << ", " << a3.a2.a3 << "), " << a3.a3 << "))" << ")\n"; double result = f(a0, a1, a2, a3); std::cout << "result = " << result << "\n"; CHECK_APPROX(1572.0, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1, a2, a3); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0, a1, a2, a3); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Simple struct with inline array. DART_EXPORT intptr_t TestPassStruct8BytesInlineArrayIntx4( // NOLINTNEXTLINE(whitespace/parens) int32_t (*f)(Struct8BytesInlineArrayInt a0, Struct8BytesInlineArrayInt a1, Struct8BytesInlineArrayInt a2, Struct8BytesInlineArrayInt a3)) { Struct8BytesInlineArrayInt a0; Struct8BytesInlineArrayInt a1; Struct8BytesInlineArrayInt a2; Struct8BytesInlineArrayInt a3; a0.a0[0] = 1; a0.a0[1] = 2; a0.a0[2] = 3; a0.a0[3] = 4; a0.a0[4] = 5; a0.a0[5] = 6; a0.a0[6] = 7; a0.a0[7] = 8; a1.a0[0] = 9; a1.a0[1] = 10; a1.a0[2] = 11; a1.a0[3] = 12; a1.a0[4] = 13; a1.a0[5] = 14; a1.a0[6] = 15; a1.a0[7] = 16; a2.a0[0] = 17; a2.a0[1] = 18; a2.a0[2] = 19; a2.a0[3] = 20; a2.a0[4] = 21; a2.a0[5] = 22; a2.a0[6] = 23; a2.a0[7] = 24; a3.a0[0] = 25; a3.a0[1] = 26; a3.a0[2] = 27; a3.a0[3] = 28; a3.a0[4] = 29; a3.a0[5] = 30; a3.a0[6] = 31; a3.a0[7] = 32; std::cout << "Calling TestPassStruct8BytesInlineArrayIntx4(" << "(([" << static_cast(a0.a0[0]) << ", " << static_cast(a0.a0[1]) << ", " << static_cast(a0.a0[2]) << ", " << static_cast(a0.a0[3]) << ", " << static_cast(a0.a0[4]) << ", " << static_cast(a0.a0[5]) << ", " << static_cast(a0.a0[6]) << ", " << static_cast(a0.a0[7]) << "]), ([" << static_cast(a1.a0[0]) << ", " << static_cast(a1.a0[1]) << ", " << static_cast(a1.a0[2]) << ", " << static_cast(a1.a0[3]) << ", " << static_cast(a1.a0[4]) << ", " << static_cast(a1.a0[5]) << ", " << static_cast(a1.a0[6]) << ", " << static_cast(a1.a0[7]) << "]), ([" << static_cast(a2.a0[0]) << ", " << static_cast(a2.a0[1]) << ", " << static_cast(a2.a0[2]) << ", " << static_cast(a2.a0[3]) << ", " << static_cast(a2.a0[4]) << ", " << static_cast(a2.a0[5]) << ", " << static_cast(a2.a0[6]) << ", " << static_cast(a2.a0[7]) << "]), ([" << static_cast(a3.a0[0]) << ", " << static_cast(a3.a0[1]) << ", " << static_cast(a3.a0[2]) << ", " << static_cast(a3.a0[3]) << ", " << static_cast(a3.a0[4]) << ", " << static_cast(a3.a0[5]) << ", " << static_cast(a3.a0[6]) << ", " << static_cast(a3.a0[7]) << "]))" << ")\n"; int32_t result = f(a0, a1, a2, a3); std::cout << "result = " << result << "\n"; CHECK_EQ(528, result); // Pass argument that will make the Dart callback throw. a0.a0[0] = 42; result = f(a0, a1, a2, a3); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0[0] = 84; result = f(a0, a1, a2, a3); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Irregular struct with inline array. DART_EXPORT intptr_t TestPassStructInlineArrayIrregularx4( // NOLINTNEXTLINE(whitespace/parens) int32_t (*f)(StructInlineArrayIrregular a0, StructInlineArrayIrregular a1, StructInlineArrayIrregular a2, StructInlineArrayIrregular a3)) { StructInlineArrayIrregular a0; StructInlineArrayIrregular a1; StructInlineArrayIrregular a2; StructInlineArrayIrregular a3; a0.a0[0].a0 = -1; a0.a0[0].a1 = 2; a0.a0[1].a0 = -3; a0.a0[1].a1 = 4; a0.a1 = 5; a1.a0[0].a0 = 6; a1.a0[0].a1 = -7; a1.a0[1].a0 = 8; a1.a0[1].a1 = -9; a1.a1 = 10; a2.a0[0].a0 = -11; a2.a0[0].a1 = 12; a2.a0[1].a0 = -13; a2.a0[1].a1 = 14; a2.a1 = 15; a3.a0[0].a0 = 16; a3.a0[0].a1 = -17; a3.a0[1].a0 = 18; a3.a0[1].a1 = -19; a3.a1 = 20; std::cout << "Calling TestPassStructInlineArrayIrregularx4(" << "(([(" << a0.a0[0].a0 << ", " << static_cast(a0.a0[0].a1) << "), (" << a0.a0[1].a0 << ", " << static_cast(a0.a0[1].a1) << ")], " << static_cast(a0.a1) << "), ([(" << a1.a0[0].a0 << ", " << static_cast(a1.a0[0].a1) << "), (" << a1.a0[1].a0 << ", " << static_cast(a1.a0[1].a1) << ")], " << static_cast(a1.a1) << "), ([(" << a2.a0[0].a0 << ", " << static_cast(a2.a0[0].a1) << "), (" << a2.a0[1].a0 << ", " << static_cast(a2.a0[1].a1) << ")], " << static_cast(a2.a1) << "), ([(" << a3.a0[0].a0 << ", " << static_cast(a3.a0[0].a1) << "), (" << a3.a0[1].a0 << ", " << static_cast(a3.a0[1].a1) << ")], " << static_cast(a3.a1) << "))" << ")\n"; int32_t result = f(a0, a1, a2, a3); std::cout << "result = " << result << "\n"; CHECK_EQ(50, result); // Pass argument that will make the Dart callback throw. a0.a0[0].a0 = 42; result = f(a0, a1, a2, a3); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0[0].a0 = 84; result = f(a0, a1, a2, a3); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Regular larger struct with inline array. DART_EXPORT intptr_t TestPassStructInlineArray100Bytes( // NOLINTNEXTLINE(whitespace/parens) int32_t (*f)(StructInlineArray100Bytes a0)) { StructInlineArray100Bytes a0; a0.a0[0] = 1; a0.a0[1] = 2; a0.a0[2] = 3; a0.a0[3] = 4; a0.a0[4] = 5; a0.a0[5] = 6; a0.a0[6] = 7; a0.a0[7] = 8; a0.a0[8] = 9; a0.a0[9] = 10; a0.a0[10] = 11; a0.a0[11] = 12; a0.a0[12] = 13; a0.a0[13] = 14; a0.a0[14] = 15; a0.a0[15] = 16; a0.a0[16] = 17; a0.a0[17] = 18; a0.a0[18] = 19; a0.a0[19] = 20; a0.a0[20] = 21; a0.a0[21] = 22; a0.a0[22] = 23; a0.a0[23] = 24; a0.a0[24] = 25; a0.a0[25] = 26; a0.a0[26] = 27; a0.a0[27] = 28; a0.a0[28] = 29; a0.a0[29] = 30; a0.a0[30] = 31; a0.a0[31] = 32; a0.a0[32] = 33; a0.a0[33] = 34; a0.a0[34] = 35; a0.a0[35] = 36; a0.a0[36] = 37; a0.a0[37] = 38; a0.a0[38] = 39; a0.a0[39] = 40; a0.a0[40] = 41; a0.a0[41] = 42; a0.a0[42] = 43; a0.a0[43] = 44; a0.a0[44] = 45; a0.a0[45] = 46; a0.a0[46] = 47; a0.a0[47] = 48; a0.a0[48] = 49; a0.a0[49] = 50; a0.a0[50] = 51; a0.a0[51] = 52; a0.a0[52] = 53; a0.a0[53] = 54; a0.a0[54] = 55; a0.a0[55] = 56; a0.a0[56] = 57; a0.a0[57] = 58; a0.a0[58] = 59; a0.a0[59] = 60; a0.a0[60] = 61; a0.a0[61] = 62; a0.a0[62] = 63; a0.a0[63] = 64; a0.a0[64] = 65; a0.a0[65] = 66; a0.a0[66] = 67; a0.a0[67] = 68; a0.a0[68] = 69; a0.a0[69] = 70; a0.a0[70] = 71; a0.a0[71] = 72; a0.a0[72] = 73; a0.a0[73] = 74; a0.a0[74] = 75; a0.a0[75] = 76; a0.a0[76] = 77; a0.a0[77] = 78; a0.a0[78] = 79; a0.a0[79] = 80; a0.a0[80] = 81; a0.a0[81] = 82; a0.a0[82] = 83; a0.a0[83] = 84; a0.a0[84] = 85; a0.a0[85] = 86; a0.a0[86] = 87; a0.a0[87] = 88; a0.a0[88] = 89; a0.a0[89] = 90; a0.a0[90] = 91; a0.a0[91] = 92; a0.a0[92] = 93; a0.a0[93] = 94; a0.a0[94] = 95; a0.a0[95] = 96; a0.a0[96] = 97; a0.a0[97] = 98; a0.a0[98] = 99; a0.a0[99] = 100; std::cout << "Calling TestPassStructInlineArray100Bytes(" << "(([" << static_cast(a0.a0[0]) << ", " << static_cast(a0.a0[1]) << ", " << static_cast(a0.a0[2]) << ", " << static_cast(a0.a0[3]) << ", " << static_cast(a0.a0[4]) << ", " << static_cast(a0.a0[5]) << ", " << static_cast(a0.a0[6]) << ", " << static_cast(a0.a0[7]) << ", " << static_cast(a0.a0[8]) << ", " << static_cast(a0.a0[9]) << ", " << static_cast(a0.a0[10]) << ", " << static_cast(a0.a0[11]) << ", " << static_cast(a0.a0[12]) << ", " << static_cast(a0.a0[13]) << ", " << static_cast(a0.a0[14]) << ", " << static_cast(a0.a0[15]) << ", " << static_cast(a0.a0[16]) << ", " << static_cast(a0.a0[17]) << ", " << static_cast(a0.a0[18]) << ", " << static_cast(a0.a0[19]) << ", " << static_cast(a0.a0[20]) << ", " << static_cast(a0.a0[21]) << ", " << static_cast(a0.a0[22]) << ", " << static_cast(a0.a0[23]) << ", " << static_cast(a0.a0[24]) << ", " << static_cast(a0.a0[25]) << ", " << static_cast(a0.a0[26]) << ", " << static_cast(a0.a0[27]) << ", " << static_cast(a0.a0[28]) << ", " << static_cast(a0.a0[29]) << ", " << static_cast(a0.a0[30]) << ", " << static_cast(a0.a0[31]) << ", " << static_cast(a0.a0[32]) << ", " << static_cast(a0.a0[33]) << ", " << static_cast(a0.a0[34]) << ", " << static_cast(a0.a0[35]) << ", " << static_cast(a0.a0[36]) << ", " << static_cast(a0.a0[37]) << ", " << static_cast(a0.a0[38]) << ", " << static_cast(a0.a0[39]) << ", " << static_cast(a0.a0[40]) << ", " << static_cast(a0.a0[41]) << ", " << static_cast(a0.a0[42]) << ", " << static_cast(a0.a0[43]) << ", " << static_cast(a0.a0[44]) << ", " << static_cast(a0.a0[45]) << ", " << static_cast(a0.a0[46]) << ", " << static_cast(a0.a0[47]) << ", " << static_cast(a0.a0[48]) << ", " << static_cast(a0.a0[49]) << ", " << static_cast(a0.a0[50]) << ", " << static_cast(a0.a0[51]) << ", " << static_cast(a0.a0[52]) << ", " << static_cast(a0.a0[53]) << ", " << static_cast(a0.a0[54]) << ", " << static_cast(a0.a0[55]) << ", " << static_cast(a0.a0[56]) << ", " << static_cast(a0.a0[57]) << ", " << static_cast(a0.a0[58]) << ", " << static_cast(a0.a0[59]) << ", " << static_cast(a0.a0[60]) << ", " << static_cast(a0.a0[61]) << ", " << static_cast(a0.a0[62]) << ", " << static_cast(a0.a0[63]) << ", " << static_cast(a0.a0[64]) << ", " << static_cast(a0.a0[65]) << ", " << static_cast(a0.a0[66]) << ", " << static_cast(a0.a0[67]) << ", " << static_cast(a0.a0[68]) << ", " << static_cast(a0.a0[69]) << ", " << static_cast(a0.a0[70]) << ", " << static_cast(a0.a0[71]) << ", " << static_cast(a0.a0[72]) << ", " << static_cast(a0.a0[73]) << ", " << static_cast(a0.a0[74]) << ", " << static_cast(a0.a0[75]) << ", " << static_cast(a0.a0[76]) << ", " << static_cast(a0.a0[77]) << ", " << static_cast(a0.a0[78]) << ", " << static_cast(a0.a0[79]) << ", " << static_cast(a0.a0[80]) << ", " << static_cast(a0.a0[81]) << ", " << static_cast(a0.a0[82]) << ", " << static_cast(a0.a0[83]) << ", " << static_cast(a0.a0[84]) << ", " << static_cast(a0.a0[85]) << ", " << static_cast(a0.a0[86]) << ", " << static_cast(a0.a0[87]) << ", " << static_cast(a0.a0[88]) << ", " << static_cast(a0.a0[89]) << ", " << static_cast(a0.a0[90]) << ", " << static_cast(a0.a0[91]) << ", " << static_cast(a0.a0[92]) << ", " << static_cast(a0.a0[93]) << ", " << static_cast(a0.a0[94]) << ", " << static_cast(a0.a0[95]) << ", " << static_cast(a0.a0[96]) << ", " << static_cast(a0.a0[97]) << ", " << static_cast(a0.a0[98]) << ", " << static_cast(a0.a0[99]) << "]))" << ")\n"; int32_t result = f(a0); std::cout << "result = " << result << "\n"; CHECK_EQ(5050, result); // Pass argument that will make the Dart callback throw. a0.a0[0] = 42; result = f(a0); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0.a0[0] = 84; result = f(a0); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Arguments in FPU registers on arm hardfp and arm64. // 5 struct arguments will exhaust available registers. DART_EXPORT intptr_t TestPassStructStruct16BytesHomogeneousFloat2x5( // NOLINTNEXTLINE(whitespace/parens) float (*f)(StructStruct16BytesHomogeneousFloat2 a0, StructStruct16BytesHomogeneousFloat2 a1, StructStruct16BytesHomogeneousFloat2 a2, StructStruct16BytesHomogeneousFloat2 a3, StructStruct16BytesHomogeneousFloat2 a4)) { StructStruct16BytesHomogeneousFloat2 a0; StructStruct16BytesHomogeneousFloat2 a1; StructStruct16BytesHomogeneousFloat2 a2; StructStruct16BytesHomogeneousFloat2 a3; StructStruct16BytesHomogeneousFloat2 a4; a0.a0.a0 = -1.0; a0.a1[0].a0 = 2.0; a0.a1[1].a0 = -3.0; a0.a2 = 4.0; a1.a0.a0 = -5.0; a1.a1[0].a0 = 6.0; a1.a1[1].a0 = -7.0; a1.a2 = 8.0; a2.a0.a0 = -9.0; a2.a1[0].a0 = 10.0; a2.a1[1].a0 = -11.0; a2.a2 = 12.0; a3.a0.a0 = -13.0; a3.a1[0].a0 = 14.0; a3.a1[1].a0 = -15.0; a3.a2 = 16.0; a4.a0.a0 = -17.0; a4.a1[0].a0 = 18.0; a4.a1[1].a0 = -19.0; a4.a2 = 20.0; std::cout << "Calling TestPassStructStruct16BytesHomogeneousFloat2x5(" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << "), (" << a0.a1[1].a0 << ")], " << a0.a2 << "), ((" << a1.a0.a0 << "), [(" << a1.a1[0].a0 << "), (" << a1.a1[1].a0 << ")], " << a1.a2 << "), ((" << a2.a0.a0 << "), [(" << a2.a1[0].a0 << "), (" << a2.a1[1].a0 << ")], " << a2.a2 << "), ((" << a3.a0.a0 << "), [(" << a3.a1[0].a0 << "), (" << a3.a1[1].a0 << ")], " << a3.a2 << "), ((" << a4.a0.a0 << "), [(" << a4.a1[0].a0 << "), (" << a4.a1[1].a0 << ")], " << a4.a2 << "))" << ")\n"; float result = f(a0, a1, a2, a3, a4); std::cout << "result = " << result << "\n"; CHECK_APPROX(10.0, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0, a1, a2, a3, a4); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0, a1, a2, a3, a4); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Arguments in FPU registers on arm64. // 5 struct arguments will exhaust available registers. DART_EXPORT intptr_t TestPassStructStruct32BytesHomogeneousDouble2x5( // NOLINTNEXTLINE(whitespace/parens) double (*f)(StructStruct32BytesHomogeneousDouble2 a0, StructStruct32BytesHomogeneousDouble2 a1, StructStruct32BytesHomogeneousDouble2 a2, StructStruct32BytesHomogeneousDouble2 a3, StructStruct32BytesHomogeneousDouble2 a4)) { StructStruct32BytesHomogeneousDouble2 a0; StructStruct32BytesHomogeneousDouble2 a1; StructStruct32BytesHomogeneousDouble2 a2; StructStruct32BytesHomogeneousDouble2 a3; StructStruct32BytesHomogeneousDouble2 a4; a0.a0.a0 = -1.0; a0.a1[0].a0 = 2.0; a0.a1[1].a0 = -3.0; a0.a2 = 4.0; a1.a0.a0 = -5.0; a1.a1[0].a0 = 6.0; a1.a1[1].a0 = -7.0; a1.a2 = 8.0; a2.a0.a0 = -9.0; a2.a1[0].a0 = 10.0; a2.a1[1].a0 = -11.0; a2.a2 = 12.0; a3.a0.a0 = -13.0; a3.a1[0].a0 = 14.0; a3.a1[1].a0 = -15.0; a3.a2 = 16.0; a4.a0.a0 = -17.0; a4.a1[0].a0 = 18.0; a4.a1[1].a0 = -19.0; a4.a2 = 20.0; std::cout << "Calling TestPassStructStruct32BytesHomogeneousDouble2x5(" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << "), (" << a0.a1[1].a0 << ")], " << a0.a2 << "), ((" << a1.a0.a0 << "), [(" << a1.a1[0].a0 << "), (" << a1.a1[1].a0 << ")], " << a1.a2 << "), ((" << a2.a0.a0 << "), [(" << a2.a1[0].a0 << "), (" << a2.a1[1].a0 << ")], " << a2.a2 << "), ((" << a3.a0.a0 << "), [(" << a3.a1[0].a0 << "), (" << a3.a1[1].a0 << ")], " << a3.a2 << "), ((" << a4.a0.a0 << "), [(" << a4.a1[0].a0 << "), (" << a4.a1[1].a0 << ")], " << a4.a2 << "))" << ")\n"; double result = f(a0, a1, a2, a3, a4); std::cout << "result = " << result << "\n"; CHECK_APPROX(10.0, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0, a1, a2, a3, a4); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0, a1, a2, a3, a4); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestPassStructStruct16BytesMixed3x10( // NOLINTNEXTLINE(whitespace/parens) float (*f)(StructStruct16BytesMixed3 a0, StructStruct16BytesMixed3 a1, StructStruct16BytesMixed3 a2, StructStruct16BytesMixed3 a3, StructStruct16BytesMixed3 a4, StructStruct16BytesMixed3 a5, StructStruct16BytesMixed3 a6, StructStruct16BytesMixed3 a7, StructStruct16BytesMixed3 a8, StructStruct16BytesMixed3 a9)) { StructStruct16BytesMixed3 a0; StructStruct16BytesMixed3 a1; StructStruct16BytesMixed3 a2; StructStruct16BytesMixed3 a3; StructStruct16BytesMixed3 a4; StructStruct16BytesMixed3 a5; StructStruct16BytesMixed3 a6; StructStruct16BytesMixed3 a7; StructStruct16BytesMixed3 a8; StructStruct16BytesMixed3 a9; a0.a0.a0 = -1.0; a0.a1[0].a0 = 2.0; a0.a1[0].a1 = -3; a0.a1[0].a2 = 4; a0.a2[0] = -5; a0.a2[1] = 6; a1.a0.a0 = -7.0; a1.a1[0].a0 = 8.0; a1.a1[0].a1 = -9; a1.a1[0].a2 = 10; a1.a2[0] = -11; a1.a2[1] = 12; a2.a0.a0 = -13.0; a2.a1[0].a0 = 14.0; a2.a1[0].a1 = -15; a2.a1[0].a2 = 16; a2.a2[0] = -17; a2.a2[1] = 18; a3.a0.a0 = -19.0; a3.a1[0].a0 = 20.0; a3.a1[0].a1 = -21; a3.a1[0].a2 = 22; a3.a2[0] = -23; a3.a2[1] = 24; a4.a0.a0 = -25.0; a4.a1[0].a0 = 26.0; a4.a1[0].a1 = -27; a4.a1[0].a2 = 28; a4.a2[0] = -29; a4.a2[1] = 30; a5.a0.a0 = -31.0; a5.a1[0].a0 = 32.0; a5.a1[0].a1 = -33; a5.a1[0].a2 = 34; a5.a2[0] = -35; a5.a2[1] = 36; a6.a0.a0 = -37.0; a6.a1[0].a0 = 38.0; a6.a1[0].a1 = -39; a6.a1[0].a2 = 40; a6.a2[0] = -41; a6.a2[1] = 42; a7.a0.a0 = -43.0; a7.a1[0].a0 = 44.0; a7.a1[0].a1 = -45; a7.a1[0].a2 = 46; a7.a2[0] = -47; a7.a2[1] = 48; a8.a0.a0 = -49.0; a8.a1[0].a0 = 50.0; a8.a1[0].a1 = -51; a8.a1[0].a2 = 52; a8.a2[0] = -53; a8.a2[1] = 54; a9.a0.a0 = -55.0; a9.a1[0].a0 = 56.0; a9.a1[0].a1 = -57; a9.a1[0].a2 = 58; a9.a2[0] = -59; a9.a2[1] = 60; std::cout << "Calling TestPassStructStruct16BytesMixed3x10(" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << ", " << a0.a1[0].a1 << ", " << a0.a1[0].a2 << ")], [" << a0.a2[0] << ", " << a0.a2[1] << "]), ((" << a1.a0.a0 << "), [(" << a1.a1[0].a0 << ", " << a1.a1[0].a1 << ", " << a1.a1[0].a2 << ")], [" << a1.a2[0] << ", " << a1.a2[1] << "]), ((" << a2.a0.a0 << "), [(" << a2.a1[0].a0 << ", " << a2.a1[0].a1 << ", " << a2.a1[0].a2 << ")], [" << a2.a2[0] << ", " << a2.a2[1] << "]), ((" << a3.a0.a0 << "), [(" << a3.a1[0].a0 << ", " << a3.a1[0].a1 << ", " << a3.a1[0].a2 << ")], [" << a3.a2[0] << ", " << a3.a2[1] << "]), ((" << a4.a0.a0 << "), [(" << a4.a1[0].a0 << ", " << a4.a1[0].a1 << ", " << a4.a1[0].a2 << ")], [" << a4.a2[0] << ", " << a4.a2[1] << "]), ((" << a5.a0.a0 << "), [(" << a5.a1[0].a0 << ", " << a5.a1[0].a1 << ", " << a5.a1[0].a2 << ")], [" << a5.a2[0] << ", " << a5.a2[1] << "]), ((" << a6.a0.a0 << "), [(" << a6.a1[0].a0 << ", " << a6.a1[0].a1 << ", " << a6.a1[0].a2 << ")], [" << a6.a2[0] << ", " << a6.a2[1] << "]), ((" << a7.a0.a0 << "), [(" << a7.a1[0].a0 << ", " << a7.a1[0].a1 << ", " << a7.a1[0].a2 << ")], [" << a7.a2[0] << ", " << a7.a2[1] << "]), ((" << a8.a0.a0 << "), [(" << a8.a1[0].a0 << ", " << a8.a1[0].a1 << ", " << a8.a1[0].a2 << ")], [" << a8.a2[0] << ", " << a8.a2[1] << "]), ((" << a9.a0.a0 << "), [(" << a9.a1[0].a0 << ", " << a9.a1[0].a1 << ", " << a9.a1[0].a2 << ")], [" << a9.a2[0] << ", " << a9.a2[1] << "]))" << ")\n"; float result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(30.0, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Test multi dimensional inline array struct as argument. DART_EXPORT intptr_t TestPassUint8Struct32BytesInlineArrayMultiDimensionalI( // NOLINTNEXTLINE(whitespace/parens) uint32_t (*f)(uint8_t a0, Struct32BytesInlineArrayMultiDimensionalInt a1, uint8_t a2, Struct8BytesInlineArrayMultiDimensionalInt a3, uint8_t a4, Struct8BytesInlineArrayMultiDimensionalInt a5, uint8_t a6)) { uint8_t a0; Struct32BytesInlineArrayMultiDimensionalInt a1; uint8_t a2; Struct8BytesInlineArrayMultiDimensionalInt a3; uint8_t a4; Struct8BytesInlineArrayMultiDimensionalInt a5; uint8_t a6; a0 = 1; a1.a0[0][0][0][0][0] = 2; a1.a0[0][0][0][0][1] = 3; a1.a0[0][0][0][1][0] = 4; a1.a0[0][0][0][1][1] = 5; a1.a0[0][0][1][0][0] = 6; a1.a0[0][0][1][0][1] = 7; a1.a0[0][0][1][1][0] = 8; a1.a0[0][0][1][1][1] = 9; a1.a0[0][1][0][0][0] = 10; a1.a0[0][1][0][0][1] = 11; a1.a0[0][1][0][1][0] = 12; a1.a0[0][1][0][1][1] = 13; a1.a0[0][1][1][0][0] = 14; a1.a0[0][1][1][0][1] = 15; a1.a0[0][1][1][1][0] = 16; a1.a0[0][1][1][1][1] = 17; a1.a0[1][0][0][0][0] = 18; a1.a0[1][0][0][0][1] = 19; a1.a0[1][0][0][1][0] = 20; a1.a0[1][0][0][1][1] = 21; a1.a0[1][0][1][0][0] = 22; a1.a0[1][0][1][0][1] = 23; a1.a0[1][0][1][1][0] = 24; a1.a0[1][0][1][1][1] = 25; a1.a0[1][1][0][0][0] = 26; a1.a0[1][1][0][0][1] = 27; a1.a0[1][1][0][1][0] = 28; a1.a0[1][1][0][1][1] = 29; a1.a0[1][1][1][0][0] = 30; a1.a0[1][1][1][0][1] = 31; a1.a0[1][1][1][1][0] = 32; a1.a0[1][1][1][1][1] = 33; a2 = 34; a3.a0[0][0][0] = 35; a3.a0[0][0][1] = 36; a3.a0[0][1][0] = 37; a3.a0[0][1][1] = 38; a3.a0[1][0][0] = 39; a3.a0[1][0][1] = 40; a3.a0[1][1][0] = 41; a3.a0[1][1][1] = 42; a4 = 43; a5.a0[0][0][0] = 44; a5.a0[0][0][1] = 45; a5.a0[0][1][0] = 46; a5.a0[0][1][1] = 47; a5.a0[1][0][0] = 48; a5.a0[1][0][1] = 49; a5.a0[1][1][0] = 50; a5.a0[1][1][1] = 51; a6 = 52; std::cout << "Calling TestPassUint8Struct32BytesInlineArrayMultiDimensionalI(" << "(" << static_cast(a0) << ", ([[[[[" << static_cast(a1.a0[0][0][0][0][0]) << ", " << static_cast(a1.a0[0][0][0][0][1]) << "], [" << static_cast(a1.a0[0][0][0][1][0]) << ", " << static_cast(a1.a0[0][0][0][1][1]) << "]], [[" << static_cast(a1.a0[0][0][1][0][0]) << ", " << static_cast(a1.a0[0][0][1][0][1]) << "], [" << static_cast(a1.a0[0][0][1][1][0]) << ", " << static_cast(a1.a0[0][0][1][1][1]) << "]]], [[[" << static_cast(a1.a0[0][1][0][0][0]) << ", " << static_cast(a1.a0[0][1][0][0][1]) << "], [" << static_cast(a1.a0[0][1][0][1][0]) << ", " << static_cast(a1.a0[0][1][0][1][1]) << "]], [[" << static_cast(a1.a0[0][1][1][0][0]) << ", " << static_cast(a1.a0[0][1][1][0][1]) << "], [" << static_cast(a1.a0[0][1][1][1][0]) << ", " << static_cast(a1.a0[0][1][1][1][1]) << "]]]], [[[[" << static_cast(a1.a0[1][0][0][0][0]) << ", " << static_cast(a1.a0[1][0][0][0][1]) << "], [" << static_cast(a1.a0[1][0][0][1][0]) << ", " << static_cast(a1.a0[1][0][0][1][1]) << "]], [[" << static_cast(a1.a0[1][0][1][0][0]) << ", " << static_cast(a1.a0[1][0][1][0][1]) << "], [" << static_cast(a1.a0[1][0][1][1][0]) << ", " << static_cast(a1.a0[1][0][1][1][1]) << "]]], [[[" << static_cast(a1.a0[1][1][0][0][0]) << ", " << static_cast(a1.a0[1][1][0][0][1]) << "], [" << static_cast(a1.a0[1][1][0][1][0]) << ", " << static_cast(a1.a0[1][1][0][1][1]) << "]], [[" << static_cast(a1.a0[1][1][1][0][0]) << ", " << static_cast(a1.a0[1][1][1][0][1]) << "], [" << static_cast(a1.a0[1][1][1][1][0]) << ", " << static_cast(a1.a0[1][1][1][1][1]) << "]]]]]), " << static_cast(a2) << ", ([[[" << static_cast(a3.a0[0][0][0]) << ", " << static_cast(a3.a0[0][0][1]) << "], [" << static_cast(a3.a0[0][1][0]) << ", " << static_cast(a3.a0[0][1][1]) << "]], [[" << static_cast(a3.a0[1][0][0]) << ", " << static_cast(a3.a0[1][0][1]) << "], [" << static_cast(a3.a0[1][1][0]) << ", " << static_cast(a3.a0[1][1][1]) << "]]]), " << static_cast(a4) << ", ([[[" << static_cast(a5.a0[0][0][0]) << ", " << static_cast(a5.a0[0][0][1]) << "], [" << static_cast(a5.a0[0][1][0]) << ", " << static_cast(a5.a0[0][1][1]) << "]], [[" << static_cast(a5.a0[1][0][0]) << ", " << static_cast(a5.a0[1][0][1]) << "], [" << static_cast(a5.a0[1][1][0]) << ", " << static_cast(a5.a0[1][1][1]) << "]]]), " << static_cast(a6) << ")" << ")\n"; uint32_t result = f(a0, a1, a2, a3, a4, a5, a6); std::cout << "result = " << result << "\n"; CHECK_EQ(1378, result); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Test struct in multi dimensional inline array. DART_EXPORT intptr_t TestPassUint8Struct4BytesInlineArrayMultiDimensionalIn( // NOLINTNEXTLINE(whitespace/parens) uint32_t (*f)(uint8_t a0, Struct4BytesInlineArrayMultiDimensionalInt a1, uint8_t a2)) { uint8_t a0; Struct4BytesInlineArrayMultiDimensionalInt a1; uint8_t a2; a0 = 1; a1.a0[0][0].a0 = 2; a1.a0[0][1].a0 = -3; a1.a0[1][0].a0 = 4; a1.a0[1][1].a0 = -5; a2 = 6; std::cout << "Calling TestPassUint8Struct4BytesInlineArrayMultiDimensionalIn(" << "(" << static_cast(a0) << ", ([[(" << static_cast(a1.a0[0][0].a0) << "), (" << static_cast(a1.a0[0][1].a0) << ")], [(" << static_cast(a1.a0[1][0].a0) << "), (" << static_cast(a1.a0[1][1].a0) << ")]]), " << static_cast(a2) << ")" << ")\n"; uint32_t result = f(a0, a1, a2); std::cout << "result = " << result << "\n"; CHECK_EQ(5, result); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2); CHECK_EQ(0, result); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Small struct with mis-aligned member. DART_EXPORT intptr_t TestPassStruct3BytesPackedIntx10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct3BytesPackedInt a0, Struct3BytesPackedInt a1, Struct3BytesPackedInt a2, Struct3BytesPackedInt a3, Struct3BytesPackedInt a4, Struct3BytesPackedInt a5, Struct3BytesPackedInt a6, Struct3BytesPackedInt a7, Struct3BytesPackedInt a8, Struct3BytesPackedInt a9)) { Struct3BytesPackedInt a0; Struct3BytesPackedInt a1; Struct3BytesPackedInt a2; Struct3BytesPackedInt a3; Struct3BytesPackedInt a4; Struct3BytesPackedInt a5; Struct3BytesPackedInt a6; Struct3BytesPackedInt a7; Struct3BytesPackedInt a8; Struct3BytesPackedInt a9; a0.a0 = -1; a0.a1 = 2; a1.a0 = -3; a1.a1 = 4; a2.a0 = -5; a2.a1 = 6; a3.a0 = -7; a3.a1 = 8; a4.a0 = -9; a4.a1 = 10; a5.a0 = -11; a5.a1 = 12; a6.a0 = -13; a6.a1 = 14; a7.a0 = -15; a7.a1 = 16; a8.a0 = -17; a8.a1 = 18; a9.a0 = -19; a9.a1 = 20; std::cout << "Calling TestPassStruct3BytesPackedIntx10(" << "((" << static_cast(a0.a0) << ", " << a0.a1 << "), (" << static_cast(a1.a0) << ", " << a1.a1 << "), (" << static_cast(a2.a0) << ", " << a2.a1 << "), (" << static_cast(a3.a0) << ", " << a3.a1 << "), (" << static_cast(a4.a0) << ", " << a4.a1 << "), (" << static_cast(a5.a0) << ", " << a5.a1 << "), (" << static_cast(a6.a0) << ", " << a6.a1 << "), (" << static_cast(a7.a0) << ", " << a7.a1 << "), (" << static_cast(a8.a0) << ", " << a8.a1 << "), (" << static_cast(a9.a0) << ", " << a9.a1 << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(10, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // Used for testing structs and unions by value. // Struct with mis-aligned member. DART_EXPORT intptr_t TestPassStruct8BytesPackedIntx10( // NOLINTNEXTLINE(whitespace/parens) int64_t (*f)(Struct8BytesPackedInt a0, Struct8BytesPackedInt a1, Struct8BytesPackedInt a2, Struct8BytesPackedInt a3, Struct8BytesPackedInt a4, Struct8BytesPackedInt a5, Struct8BytesPackedInt a6, Struct8BytesPackedInt a7, Struct8BytesPackedInt a8, Struct8BytesPackedInt a9)) { Struct8BytesPackedInt a0; Struct8BytesPackedInt a1; Struct8BytesPackedInt a2; Struct8BytesPackedInt a3; Struct8BytesPackedInt a4; Struct8BytesPackedInt a5; Struct8BytesPackedInt a6; Struct8BytesPackedInt a7; Struct8BytesPackedInt a8; Struct8BytesPackedInt a9; a0.a0 = 1; a0.a1 = 2; a0.a2 = 3; a0.a3 = 4; a0.a4 = 5; a1.a0 = 6; a1.a1 = 7; a1.a2 = 8; a1.a3 = 9; a1.a4 = 10; a2.a0 = 11; a2.a1 = 12; a2.a2 = 13; a2.a3 = 14; a2.a4 = 15; a3.a0 = 16; a3.a1 = 17; a3.a2 = 18; a3.a3 = 19; a3.a4 = 20; a4.a0 = 21; a4.a1 = 22; a4.a2 = 23; a4.a3 = 24; a4.a4 = 25; a5.a0 = 26; a5.a1 = 27; a5.a2 = 28; a5.a3 = 29; a5.a4 = 30; a6.a0 = 31; a6.a1 = 32; a6.a2 = 33; a6.a3 = 34; a6.a4 = 35; a7.a0 = 36; a7.a1 = 37; a7.a2 = 38; a7.a3 = 39; a7.a4 = 40; a8.a0 = 41; a8.a1 = 42; a8.a2 = 43; a8.a3 = 44; a8.a4 = 45; a9.a0 = 46; a9.a1 = 47; a9.a2 = 48; a9.a3 = 49; a9.a4 = 50; std::cout << "Calling TestPassStruct8BytesPackedIntx10(" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << ", " << static_cast(a0.a3) << ", " << static_cast(a0.a4) << "), (" << static_cast(a1.a0) << ", " << a1.a1 << ", " << static_cast(a1.a2) << ", " << static_cast(a1.a3) << ", " << static_cast(a1.a4) << "), (" << static_cast(a2.a0) << ", " << a2.a1 << ", " << static_cast(a2.a2) << ", " << static_cast(a2.a3) << ", " << static_cast(a2.a4) << "), (" << static_cast(a3.a0) << ", " << a3.a1 << ", " << static_cast(a3.a2) << ", " << static_cast(a3.a3) << ", " << static_cast(a3.a4) << "), (" << static_cast(a4.a0) << ", " << a4.a1 << ", " << static_cast(a4.a2) << ", " << static_cast(a4.a3) << ", " << static_cast(a4.a4) << "), (" << static_cast(a5.a0) << ", " << a5.a1 << ", " << static_cast(a5.a2) << ", " << static_cast(a5.a3) << ", " << static_cast(a5.a4) << "), (" << static_cast(a6.a0) << ", " << a6.a1 << ", " << static_cast(a6.a2) << ", " << static_cast(a6.a3) << ", " << static_cast(a6.a4) << "), (" << static_cast(a7.a0) << ", " << a7.a1 << ", " << static_cast(a7.a2) << ", " << static_cast(a7.a3) << ", " << static_cast(a7.a4) << "), (" << static_cast(a8.a0) << ", " << a8.a1 << ", " << static_cast(a8.a2) << ", " << static_cast(a8.a3) << ", " << static_cast(a8.a4) << "), (" << static_cast(a9.a0) << ", " << a9.a1 << ", " << static_cast(a9.a2) << ", " << static_cast(a9.a3) << ", " << static_cast(a9.a4) << "))" << ")\n"; int64_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_EQ(1275, 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); CHECK_EQ(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); CHECK_EQ(0, result); return 0; } // 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( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Struct9BytesPackedMixed a0, Struct9BytesPackedMixed a1, Struct9BytesPackedMixed a2, Struct9BytesPackedMixed a3, Struct9BytesPackedMixed a4, Struct9BytesPackedMixed a5, Struct9BytesPackedMixed a6, Struct9BytesPackedMixed a7, Struct9BytesPackedMixed a8, Struct9BytesPackedMixed a9, double a10, int32_t a11)) { Struct9BytesPackedMixed a0; Struct9BytesPackedMixed a1; Struct9BytesPackedMixed a2; Struct9BytesPackedMixed a3; Struct9BytesPackedMixed a4; Struct9BytesPackedMixed a5; Struct9BytesPackedMixed a6; Struct9BytesPackedMixed a7; Struct9BytesPackedMixed a8; Struct9BytesPackedMixed a9; double a10; int32_t a11; a0.a0 = 1; a0.a1 = 2.0; a1.a0 = 3; a1.a1 = 4.0; a2.a0 = 5; a2.a1 = 6.0; a3.a0 = 7; a3.a1 = 8.0; a4.a0 = 9; a4.a1 = 10.0; a5.a0 = 11; a5.a1 = 12.0; a6.a0 = 13; a6.a1 = 14.0; a7.a0 = 15; a7.a1 = 16.0; a8.a0 = 17; a8.a1 = 18.0; a9.a0 = 19; a9.a1 = 20.0; a10 = -21.0; a11 = 22; std::cout << "Calling TestPassStruct9BytesPackedMixedx10DoubleInt32(" << "((" << static_cast(a0.a0) << ", " << a0.a1 << "), (" << static_cast(a1.a0) << ", " << a1.a1 << "), (" << static_cast(a2.a0) << ", " << a2.a1 << "), (" << static_cast(a3.a0) << ", " << a3.a1 << "), (" << static_cast(a4.a0) << ", " << a4.a1 << "), (" << static_cast(a5.a0) << ", " << a5.a1 << "), (" << static_cast(a6.a0) << ", " << a6.a1 << "), (" << static_cast(a7.a0) << ", " << a7.a1 << "), (" << static_cast(a8.a0) << ", " << a8.a1 << "), (" << static_cast(a9.a0) << ", " << a9.a1 << "), " << a10 << ", " << a11 << ")" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); std::cout << "result = " << result << "\n"; CHECK_APPROX(211.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); 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); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // This packed struct happens to have only aligned members. DART_EXPORT intptr_t TestPassStruct5BytesPackedMixed( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Struct5BytesPackedMixed a0)) { Struct5BytesPackedMixed a0; a0.a0 = -1.0; a0.a1 = 2; std::cout << "Calling TestPassStruct5BytesPackedMixed(" << "((" << a0.a0 << ", " << static_cast(a0.a1) << "))" << ")\n"; double result = f(a0); std::cout << "result = " << result << "\n"; CHECK_APPROX(1.0, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Check alignment of packed struct in non-packed struct. DART_EXPORT intptr_t TestPassStructNestedAlignmentStruct5BytesPackedMixed( // NOLINTNEXTLINE(whitespace/parens) double (*f)(StructNestedAlignmentStruct5BytesPackedMixed a0)) { StructNestedAlignmentStruct5BytesPackedMixed a0; a0.a0 = 1; a0.a1.a0 = 2.0; a0.a1.a1 = 3; std::cout << "Calling TestPassStructNestedAlignmentStruct5BytesPackedMixed(" << "((" << static_cast(a0.a0) << ", (" << a0.a1.a0 << ", " << static_cast(a0.a1.a1) << ")))" << ")\n"; double result = f(a0); std::cout << "result = " << result << "\n"; CHECK_APPROX(6.0, result); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Check alignment of packed struct array in non-packed struct. DART_EXPORT intptr_t TestPassStruct6BytesInlineArrayInt( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Struct6BytesInlineArrayInt a0)) { Struct6BytesInlineArrayInt a0; a0.a0[0].a0 = -1; a0.a0[0].a1 = 2; a0.a0[1].a0 = -3; a0.a0[1].a1 = 4; std::cout << "Calling TestPassStruct6BytesInlineArrayInt(" << "(([(" << static_cast(a0.a0[0].a0) << ", " << a0.a0[0].a1 << "), (" << static_cast(a0.a0[1].a0) << ", " << a0.a0[1].a1 << ")]))" << ")\n"; double result = f(a0); std::cout << "result = " << result << "\n"; CHECK_APPROX(2.0, result); // Pass argument that will make the Dart callback throw. a0.a0[0].a0 = 42; result = f(a0); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0[0].a0 = 84; result = f(a0); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Check alignment of packed struct array in non-packed struct. DART_EXPORT intptr_t TestPassStruct15BytesInlineArrayMixed( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Struct15BytesInlineArrayMixed a0)) { Struct15BytesInlineArrayMixed a0; a0.a0[0].a0 = -1.0; a0.a0[0].a1 = 2; a0.a0[1].a0 = -3.0; a0.a0[1].a1 = 4; a0.a0[2].a0 = -5.0; a0.a0[2].a1 = 6; std::cout << "Calling TestPassStruct15BytesInlineArrayMixed(" << "(([(" << a0.a0[0].a0 << ", " << static_cast(a0.a0[0].a1) << "), (" << a0.a0[1].a0 << ", " << static_cast(a0.a0[1].a1) << "), (" << a0.a0[2].a0 << ", " << static_cast(a0.a0[2].a1) << ")]))" << ")\n"; double result = f(a0); std::cout << "result = " << result << "\n"; CHECK_APPROX(3.0, result); // Pass argument that will make the Dart callback throw. a0.a0[0].a0 = 42; result = f(a0); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0[0].a0 = 84; result = f(a0); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Check placement of mixed integer/float union. DART_EXPORT intptr_t TestPassUnion4BytesMixedx10( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Union4BytesMixed a0, Union4BytesMixed a1, Union4BytesMixed a2, Union4BytesMixed a3, Union4BytesMixed a4, Union4BytesMixed a5, Union4BytesMixed a6, Union4BytesMixed a7, Union4BytesMixed a8, Union4BytesMixed a9)) { Union4BytesMixed a0; Union4BytesMixed a1; Union4BytesMixed a2; Union4BytesMixed a3; Union4BytesMixed a4; Union4BytesMixed a5; Union4BytesMixed a6; Union4BytesMixed a7; Union4BytesMixed a8; Union4BytesMixed a9; a0.a0 = 1; a1.a0 = 2; a2.a0 = 3; a3.a0 = 4; a4.a0 = 5; a5.a0 = 6; a6.a0 = 7; a7.a0 = 8; a8.a0 = 9; a9.a0 = 10; std::cout << "Calling TestPassUnion4BytesMixedx10(" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", " << a1.a1 << "), (" << a2.a0 << ", " << a2.a1 << "), (" << a3.a0 << ", " << a3.a1 << "), (" << a4.a0 << ", " << a4.a1 << "), (" << a5.a0 << ", " << a5.a1 << "), (" << a6.a0 << ", " << a6.a1 << "), (" << a7.a0 << ", " << a7.a1 << "), (" << a8.a0 << ", " << a8.a1 << "), (" << a9.a0 << ", " << a9.a1 << "))" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(55.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); 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); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Check placement of mixed floats union. DART_EXPORT intptr_t TestPassUnion8BytesNestedFloatx10( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Union8BytesNestedFloat a0, Union8BytesNestedFloat a1, Union8BytesNestedFloat a2, Union8BytesNestedFloat a3, Union8BytesNestedFloat a4, Union8BytesNestedFloat a5, Union8BytesNestedFloat a6, Union8BytesNestedFloat a7, Union8BytesNestedFloat a8, Union8BytesNestedFloat a9)) { Union8BytesNestedFloat a0; Union8BytesNestedFloat a1; Union8BytesNestedFloat a2; Union8BytesNestedFloat a3; Union8BytesNestedFloat a4; Union8BytesNestedFloat a5; Union8BytesNestedFloat a6; Union8BytesNestedFloat a7; Union8BytesNestedFloat a8; Union8BytesNestedFloat a9; a0.a0 = -1.0; a1.a0 = 2.0; a2.a0 = -3.0; a3.a0 = 4.0; a4.a0 = -5.0; a5.a0 = 6.0; a6.a0 = -7.0; a7.a0 = 8.0; a8.a0 = -9.0; a9.a0 = 10.0; std::cout << "Calling TestPassUnion8BytesNestedFloatx10(" << "((" << a0.a0 << ", (" << a0.a1.a0 << ", " << a0.a1.a1 << ")), (" << a1.a0 << ", (" << a1.a1.a0 << ", " << a1.a1.a1 << ")), (" << a2.a0 << ", (" << a2.a1.a0 << ", " << a2.a1.a1 << ")), (" << a3.a0 << ", (" << a3.a1.a0 << ", " << a3.a1.a1 << ")), (" << a4.a0 << ", (" << a4.a1.a0 << ", " << a4.a1.a1 << ")), (" << a5.a0 << ", (" << a5.a1.a0 << ", " << a5.a1.a1 << ")), (" << a6.a0 << ", (" << a6.a1.a0 << ", " << a6.a1.a1 << ")), (" << a7.a0 << ", (" << a7.a1.a0 << ", " << a7.a1.a1 << ")), (" << a8.a0 << ", (" << a8.a1.a0 << ", " << a8.a1.a1 << ")), (" << a9.a0 << ", (" << a9.a1.a0 << ", " << a9.a1.a1 << ")))" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(5.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); 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); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Mixed-size union argument. DART_EXPORT intptr_t TestPassUnion9BytesNestedIntx10( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Union9BytesNestedInt a0, Union9BytesNestedInt a1, Union9BytesNestedInt a2, Union9BytesNestedInt a3, Union9BytesNestedInt a4, Union9BytesNestedInt a5, Union9BytesNestedInt a6, Union9BytesNestedInt a7, Union9BytesNestedInt a8, Union9BytesNestedInt a9)) { Union9BytesNestedInt a0; Union9BytesNestedInt a1; Union9BytesNestedInt a2; Union9BytesNestedInt a3; Union9BytesNestedInt a4; Union9BytesNestedInt a5; Union9BytesNestedInt a6; Union9BytesNestedInt a7; Union9BytesNestedInt a8; Union9BytesNestedInt a9; a0.a0.a0 = -1; a0.a0.a1 = 2; a0.a0.a2 = -3; a1.a0.a0 = 4; a1.a0.a1 = -5; a1.a0.a2 = 6; a2.a0.a0 = -7; a2.a0.a1 = 8; a2.a0.a2 = -9; a3.a0.a0 = 10; a3.a0.a1 = -11; a3.a0.a2 = 12; a4.a0.a0 = -13; a4.a0.a1 = 14; a4.a0.a2 = -15; a5.a0.a0 = 16; a5.a0.a1 = -17; a5.a0.a2 = 18; a6.a0.a0 = -19; a6.a0.a1 = 20; a6.a0.a2 = -21; a7.a0.a0 = 22; a7.a0.a1 = -23; a7.a0.a2 = 24; a8.a0.a0 = -25; a8.a0.a1 = 26; a8.a0.a2 = -27; a9.a0.a0 = 28; a9.a0.a1 = -29; a9.a0.a2 = 30; std::cout << "Calling TestPassUnion9BytesNestedIntx10(" << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << ", " << a0.a0.a2 << "), (" << static_cast(a0.a1.a0) << ", " << static_cast(a0.a1.a1) << ", " << static_cast(a0.a1.a2) << ", " << static_cast(a0.a1.a3) << ", " << static_cast(a0.a1.a4) << ", " << static_cast(a0.a1.a5) << ", " << static_cast(a0.a1.a6) << ", " << static_cast(a0.a1.a7) << ", " << static_cast(a0.a1.a8) << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << ", " << a1.a0.a2 << "), (" << static_cast(a1.a1.a0) << ", " << static_cast(a1.a1.a1) << ", " << static_cast(a1.a1.a2) << ", " << static_cast(a1.a1.a3) << ", " << static_cast(a1.a1.a4) << ", " << static_cast(a1.a1.a5) << ", " << static_cast(a1.a1.a6) << ", " << static_cast(a1.a1.a7) << ", " << static_cast(a1.a1.a8) << ")), ((" << a2.a0.a0 << ", " << a2.a0.a1 << ", " << a2.a0.a2 << "), (" << static_cast(a2.a1.a0) << ", " << static_cast(a2.a1.a1) << ", " << static_cast(a2.a1.a2) << ", " << static_cast(a2.a1.a3) << ", " << static_cast(a2.a1.a4) << ", " << static_cast(a2.a1.a5) << ", " << static_cast(a2.a1.a6) << ", " << static_cast(a2.a1.a7) << ", " << static_cast(a2.a1.a8) << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << ", " << a3.a0.a2 << "), (" << static_cast(a3.a1.a0) << ", " << static_cast(a3.a1.a1) << ", " << static_cast(a3.a1.a2) << ", " << static_cast(a3.a1.a3) << ", " << static_cast(a3.a1.a4) << ", " << static_cast(a3.a1.a5) << ", " << static_cast(a3.a1.a6) << ", " << static_cast(a3.a1.a7) << ", " << static_cast(a3.a1.a8) << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1 << ", " << a4.a0.a2 << "), (" << static_cast(a4.a1.a0) << ", " << static_cast(a4.a1.a1) << ", " << static_cast(a4.a1.a2) << ", " << static_cast(a4.a1.a3) << ", " << static_cast(a4.a1.a4) << ", " << static_cast(a4.a1.a5) << ", " << static_cast(a4.a1.a6) << ", " << static_cast(a4.a1.a7) << ", " << static_cast(a4.a1.a8) << ")), ((" << a5.a0.a0 << ", " << a5.a0.a1 << ", " << a5.a0.a2 << "), (" << static_cast(a5.a1.a0) << ", " << static_cast(a5.a1.a1) << ", " << static_cast(a5.a1.a2) << ", " << static_cast(a5.a1.a3) << ", " << static_cast(a5.a1.a4) << ", " << static_cast(a5.a1.a5) << ", " << static_cast(a5.a1.a6) << ", " << static_cast(a5.a1.a7) << ", " << static_cast(a5.a1.a8) << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << ", " << a6.a0.a2 << "), (" << static_cast(a6.a1.a0) << ", " << static_cast(a6.a1.a1) << ", " << static_cast(a6.a1.a2) << ", " << static_cast(a6.a1.a3) << ", " << static_cast(a6.a1.a4) << ", " << static_cast(a6.a1.a5) << ", " << static_cast(a6.a1.a6) << ", " << static_cast(a6.a1.a7) << ", " << static_cast(a6.a1.a8) << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1 << ", " << a7.a0.a2 << "), (" << static_cast(a7.a1.a0) << ", " << static_cast(a7.a1.a1) << ", " << static_cast(a7.a1.a2) << ", " << static_cast(a7.a1.a3) << ", " << static_cast(a7.a1.a4) << ", " << static_cast(a7.a1.a5) << ", " << static_cast(a7.a1.a6) << ", " << static_cast(a7.a1.a7) << ", " << static_cast(a7.a1.a8) << ")), ((" << a8.a0.a0 << ", " << a8.a0.a1 << ", " << a8.a0.a2 << "), (" << static_cast(a8.a1.a0) << ", " << static_cast(a8.a1.a1) << ", " << static_cast(a8.a1.a2) << ", " << static_cast(a8.a1.a3) << ", " << static_cast(a8.a1.a4) << ", " << static_cast(a8.a1.a5) << ", " << static_cast(a8.a1.a6) << ", " << static_cast(a8.a1.a7) << ", " << static_cast(a8.a1.a8) << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << ", " << a9.a0.a2 << "), (" << static_cast(a9.a1.a0) << ", " << static_cast(a9.a1.a1) << ", " << static_cast(a9.a1.a2) << ", " << static_cast(a9.a1.a3) << ", " << static_cast(a9.a1.a4) << ", " << static_cast(a9.a1.a5) << ", " << static_cast(a9.a1.a6) << ", " << static_cast(a9.a1.a7) << ", " << static_cast(a9.a1.a8) << ")))" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(15.0, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Union with homogenous floats. DART_EXPORT intptr_t TestPassUnion16BytesNestedInlineArrayFloatx10( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Union16BytesNestedInlineArrayFloat a0, Union16BytesNestedInlineArrayFloat a1, Union16BytesNestedInlineArrayFloat a2, Union16BytesNestedInlineArrayFloat a3, Union16BytesNestedInlineArrayFloat a4, Union16BytesNestedInlineArrayFloat a5, Union16BytesNestedInlineArrayFloat a6, Union16BytesNestedInlineArrayFloat a7, Union16BytesNestedInlineArrayFloat a8, Union16BytesNestedInlineArrayFloat a9)) { Union16BytesNestedInlineArrayFloat a0; Union16BytesNestedInlineArrayFloat a1; Union16BytesNestedInlineArrayFloat a2; Union16BytesNestedInlineArrayFloat a3; Union16BytesNestedInlineArrayFloat a4; Union16BytesNestedInlineArrayFloat a5; Union16BytesNestedInlineArrayFloat a6; Union16BytesNestedInlineArrayFloat a7; Union16BytesNestedInlineArrayFloat a8; Union16BytesNestedInlineArrayFloat a9; a0.a0[0] = -1.0; a0.a0[1] = 2.0; a0.a0[2] = -3.0; a0.a0[3] = 4.0; a1.a0[0] = -5.0; a1.a0[1] = 6.0; a1.a0[2] = -7.0; a1.a0[3] = 8.0; a2.a0[0] = -9.0; a2.a0[1] = 10.0; a2.a0[2] = -11.0; a2.a0[3] = 12.0; a3.a0[0] = -13.0; a3.a0[1] = 14.0; a3.a0[2] = -15.0; a3.a0[3] = 16.0; a4.a0[0] = -17.0; a4.a0[1] = 18.0; a4.a0[2] = -19.0; a4.a0[3] = 20.0; a5.a0[0] = -21.0; a5.a0[1] = 22.0; a5.a0[2] = -23.0; a5.a0[3] = 24.0; a6.a0[0] = -25.0; a6.a0[1] = 26.0; a6.a0[2] = -27.0; a6.a0[3] = 28.0; a7.a0[0] = -29.0; a7.a0[1] = 30.0; a7.a0[2] = -31.0; a7.a0[3] = 32.0; a8.a0[0] = -33.0; a8.a0[1] = 34.0; a8.a0[2] = -35.0; a8.a0[3] = 36.0; a9.a0[0] = -37.0; a9.a0[1] = 38.0; a9.a0[2] = -39.0; a9.a0[3] = 40.0; std::cout << "Calling TestPassUnion16BytesNestedInlineArrayFloatx10(" << "(([" << a0.a0[0] << ", " << a0.a0[1] << ", " << a0.a0[2] << ", " << a0.a0[3] << "], (" << a0.a1.a0 << ", " << a0.a1.a1 << ", " << a0.a1.a2 << ", " << a0.a1.a3 << ")), ([" << a1.a0[0] << ", " << a1.a0[1] << ", " << a1.a0[2] << ", " << a1.a0[3] << "], (" << a1.a1.a0 << ", " << a1.a1.a1 << ", " << a1.a1.a2 << ", " << a1.a1.a3 << ")), ([" << a2.a0[0] << ", " << a2.a0[1] << ", " << a2.a0[2] << ", " << a2.a0[3] << "], (" << a2.a1.a0 << ", " << a2.a1.a1 << ", " << a2.a1.a2 << ", " << a2.a1.a3 << ")), ([" << a3.a0[0] << ", " << a3.a0[1] << ", " << a3.a0[2] << ", " << a3.a0[3] << "], (" << a3.a1.a0 << ", " << a3.a1.a1 << ", " << a3.a1.a2 << ", " << a3.a1.a3 << ")), ([" << a4.a0[0] << ", " << a4.a0[1] << ", " << a4.a0[2] << ", " << a4.a0[3] << "], (" << a4.a1.a0 << ", " << a4.a1.a1 << ", " << a4.a1.a2 << ", " << a4.a1.a3 << ")), ([" << a5.a0[0] << ", " << a5.a0[1] << ", " << a5.a0[2] << ", " << a5.a0[3] << "], (" << a5.a1.a0 << ", " << a5.a1.a1 << ", " << a5.a1.a2 << ", " << a5.a1.a3 << ")), ([" << a6.a0[0] << ", " << a6.a0[1] << ", " << a6.a0[2] << ", " << a6.a0[3] << "], (" << a6.a1.a0 << ", " << a6.a1.a1 << ", " << a6.a1.a2 << ", " << a6.a1.a3 << ")), ([" << a7.a0[0] << ", " << a7.a0[1] << ", " << a7.a0[2] << ", " << a7.a0[3] << "], (" << a7.a1.a0 << ", " << a7.a1.a1 << ", " << a7.a1.a2 << ", " << a7.a1.a3 << ")), ([" << a8.a0[0] << ", " << a8.a0[1] << ", " << a8.a0[2] << ", " << a8.a0[3] << "], (" << a8.a1.a0 << ", " << a8.a1.a1 << ", " << a8.a1.a2 << ", " << a8.a1.a3 << ")), ([" << a9.a0[0] << ", " << a9.a0[1] << ", " << a9.a0[2] << ", " << a9.a0[3] << "], (" << a9.a1.a0 << ", " << a9.a1.a1 << ", " << a9.a1.a2 << ", " << a9.a1.a3 << ")))" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(20.0, result); // Pass argument that will make the Dart callback throw. a0.a0[0] = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0[0] = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Union with homogenous floats. DART_EXPORT intptr_t TestPassUnion16BytesNestedFloatx10( // NOLINTNEXTLINE(whitespace/parens) double (*f)(Union16BytesNestedFloat a0, Union16BytesNestedFloat a1, Union16BytesNestedFloat a2, Union16BytesNestedFloat a3, Union16BytesNestedFloat a4, Union16BytesNestedFloat a5, Union16BytesNestedFloat a6, Union16BytesNestedFloat a7, Union16BytesNestedFloat a8, Union16BytesNestedFloat a9)) { Union16BytesNestedFloat a0; Union16BytesNestedFloat a1; Union16BytesNestedFloat a2; Union16BytesNestedFloat a3; Union16BytesNestedFloat a4; Union16BytesNestedFloat a5; Union16BytesNestedFloat a6; Union16BytesNestedFloat a7; Union16BytesNestedFloat a8; Union16BytesNestedFloat a9; a0.a0.a0 = -1.0; a0.a0.a1 = 2.0; a1.a0.a0 = -3.0; a1.a0.a1 = 4.0; a2.a0.a0 = -5.0; a2.a0.a1 = 6.0; a3.a0.a0 = -7.0; a3.a0.a1 = 8.0; a4.a0.a0 = -9.0; a4.a0.a1 = 10.0; a5.a0.a0 = -11.0; a5.a0.a1 = 12.0; a6.a0.a0 = -13.0; a6.a0.a1 = 14.0; a7.a0.a0 = -15.0; a7.a0.a1 = 16.0; a8.a0.a0 = -17.0; a8.a0.a1 = 18.0; a9.a0.a0 = -19.0; a9.a0.a1 = 20.0; std::cout << "Calling TestPassUnion16BytesNestedFloatx10(" << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0 << ", " << a0.a1.a1 << ", " << a0.a1.a2 << "), (" << a0.a2.a0 << ", " << a0.a2.a1 << ", " << a0.a2.a2 << ", " << a0.a2.a3 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << "), (" << a1.a1.a0 << ", " << a1.a1.a1 << ", " << a1.a1.a2 << "), (" << a1.a2.a0 << ", " << a1.a2.a1 << ", " << a1.a2.a2 << ", " << a1.a2.a3 << ")), ((" << a2.a0.a0 << ", " << a2.a0.a1 << "), (" << a2.a1.a0 << ", " << a2.a1.a1 << ", " << a2.a1.a2 << "), (" << a2.a2.a0 << ", " << a2.a2.a1 << ", " << a2.a2.a2 << ", " << a2.a2.a3 << ")), ((" << a3.a0.a0 << ", " << a3.a0.a1 << "), (" << a3.a1.a0 << ", " << a3.a1.a1 << ", " << a3.a1.a2 << "), (" << a3.a2.a0 << ", " << a3.a2.a1 << ", " << a3.a2.a2 << ", " << a3.a2.a3 << ")), ((" << a4.a0.a0 << ", " << a4.a0.a1 << "), (" << a4.a1.a0 << ", " << a4.a1.a1 << ", " << a4.a1.a2 << "), (" << a4.a2.a0 << ", " << a4.a2.a1 << ", " << a4.a2.a2 << ", " << a4.a2.a3 << ")), ((" << a5.a0.a0 << ", " << a5.a0.a1 << "), (" << a5.a1.a0 << ", " << a5.a1.a1 << ", " << a5.a1.a2 << "), (" << a5.a2.a0 << ", " << a5.a2.a1 << ", " << a5.a2.a2 << ", " << a5.a2.a3 << ")), ((" << a6.a0.a0 << ", " << a6.a0.a1 << "), (" << a6.a1.a0 << ", " << a6.a1.a1 << ", " << a6.a1.a2 << "), (" << a6.a2.a0 << ", " << a6.a2.a1 << ", " << a6.a2.a2 << ", " << a6.a2.a3 << ")), ((" << a7.a0.a0 << ", " << a7.a0.a1 << "), (" << a7.a1.a0 << ", " << a7.a1.a1 << ", " << a7.a1.a2 << "), (" << a7.a2.a0 << ", " << a7.a2.a1 << ", " << a7.a2.a2 << ", " << a7.a2.a3 << ")), ((" << a8.a0.a0 << ", " << a8.a0.a1 << "), (" << a8.a1.a0 << ", " << a8.a1.a1 << ", " << a8.a1.a2 << "), (" << a8.a2.a0 << ", " << a8.a2.a1 << ", " << a8.a2.a2 << ", " << a8.a2.a3 << ")), ((" << a9.a0.a0 << ", " << a9.a0.a1 << "), (" << a9.a1.a0 << ", " << a9.a1.a1 << ", " << a9.a1.a2 << "), (" << a9.a2.a0 << ", " << a9.a2.a1 << ", " << a9.a2.a2 << ", " << a9.a2.a3 << ")))" << ")\n"; double result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); std::cout << "result = " << result << "\n"; CHECK_APPROX(10.0, result); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); CHECK_APPROX(0.0, result); return 0; } // Used for testing structs and unions by value. // Smallest struct with data. DART_EXPORT intptr_t TestReturnStruct1ByteInt( // NOLINTNEXTLINE(whitespace/parens) Struct1ByteInt (*f)(int8_t a0)) { int8_t a0; a0 = -1; std::cout << "Calling TestReturnStruct1ByteInt(" << "(" << static_cast(a0) << ")" << ")\n"; Struct1ByteInt result = f(a0); std::cout << "result = " << "(" << static_cast(result.a0) << ")" << "\n"; CHECK_EQ(a0, result.a0); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0); CHECK_EQ(0, result.a0); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0); CHECK_EQ(0, result.a0); return 0; } // Used for testing structs and unions by value. // Smaller than word size return value on all architectures. DART_EXPORT intptr_t TestReturnStruct3BytesHomogeneousUint8( // NOLINTNEXTLINE(whitespace/parens) Struct3BytesHomogeneousUint8 (*f)(uint8_t a0, uint8_t a1, uint8_t a2)) { uint8_t a0; uint8_t a1; uint8_t a2; a0 = 1; a1 = 2; a2 = 3; std::cout << "Calling TestReturnStruct3BytesHomogeneousUint8(" << "(" << static_cast(a0) << ", " << static_cast(a1) << ", " << static_cast(a2) << ")" << ")\n"; Struct3BytesHomogeneousUint8 result = f(a0, a1, a2); std::cout << "result = " << "(" << static_cast(result.a0) << ", " << static_cast(result.a1) << ", " << static_cast(result.a2) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); return 0; } // Used for testing structs and unions by value. // Smaller than word size return value on all architectures. // With alignment rules taken into account size is 4 bytes. DART_EXPORT intptr_t TestReturnStruct3BytesInt2ByteAligned( // NOLINTNEXTLINE(whitespace/parens) Struct3BytesInt2ByteAligned (*f)(int16_t a0, int8_t a1)) { int16_t a0; int8_t a1; a0 = -1; a1 = 2; std::cout << "Calling TestReturnStruct3BytesInt2ByteAligned(" << "(" << a0 << ", " << static_cast(a1) << ")" << ")\n"; Struct3BytesInt2ByteAligned result = f(a0, a1); std::cout << "result = " << "(" << result.a0 << ", " << static_cast(result.a1) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); return 0; } // Used for testing structs and unions by value. // Word size return value on 32 bit architectures.. DART_EXPORT intptr_t TestReturnStruct4BytesHomogeneousInt16( // NOLINTNEXTLINE(whitespace/parens) Struct4BytesHomogeneousInt16 (*f)(int16_t a0, int16_t a1)) { int16_t a0; int16_t a1; a0 = -1; a1 = 2; std::cout << "Calling TestReturnStruct4BytesHomogeneousInt16(" << "(" << a0 << ", " << a1 << ")" << ")\n"; Struct4BytesHomogeneousInt16 result = f(a0, a1); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); return 0; } // Used for testing structs and unions by value. // Non-wordsize return value. DART_EXPORT intptr_t TestReturnStruct7BytesHomogeneousUint8( // NOLINTNEXTLINE(whitespace/parens) Struct7BytesHomogeneousUint8 (*f)(uint8_t a0, uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6)) { uint8_t a0; uint8_t a1; uint8_t a2; uint8_t a3; uint8_t a4; uint8_t a5; uint8_t a6; a0 = 1; a1 = 2; a2 = 3; a3 = 4; a4 = 5; a5 = 6; a6 = 7; std::cout << "Calling TestReturnStruct7BytesHomogeneousUint8(" << "(" << static_cast(a0) << ", " << static_cast(a1) << ", " << static_cast(a2) << ", " << static_cast(a3) << ", " << static_cast(a4) << ", " << static_cast(a5) << ", " << static_cast(a6) << ")" << ")\n"; Struct7BytesHomogeneousUint8 result = f(a0, a1, a2, a3, a4, a5, a6); std::cout << "result = " << "(" << static_cast(result.a0) << ", " << static_cast(result.a1) << ", " << static_cast(result.a2) << ", " << static_cast(result.a3) << ", " << static_cast(result.a4) << ", " << static_cast(result.a5) << ", " << static_cast(result.a6) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); CHECK_EQ(a3, result.a3); CHECK_EQ(a4, result.a4); CHECK_EQ(a5, result.a5); CHECK_EQ(a6, result.a6); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); CHECK_EQ(0, result.a5); CHECK_EQ(0, result.a6); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); CHECK_EQ(0, result.a5); CHECK_EQ(0, result.a6); return 0; } // Used for testing structs and unions by value. // Non-wordsize return value. // With alignment rules taken into account size is 8 bytes. DART_EXPORT intptr_t TestReturnStruct7BytesInt4ByteAligned( // NOLINTNEXTLINE(whitespace/parens) Struct7BytesInt4ByteAligned (*f)(int32_t a0, int16_t a1, int8_t a2)) { int32_t a0; int16_t a1; int8_t a2; a0 = -1; a1 = 2; a2 = -3; std::cout << "Calling TestReturnStruct7BytesInt4ByteAligned(" << "(" << a0 << ", " << a1 << ", " << static_cast(a2) << ")" << ")\n"; Struct7BytesInt4ByteAligned result = f(a0, a1, a2); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << static_cast(result.a2) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); return 0; } // Used for testing structs and unions by value. // Return value in integer registers on many architectures. DART_EXPORT intptr_t TestReturnStruct8BytesInt( // NOLINTNEXTLINE(whitespace/parens) Struct8BytesInt (*f)(int16_t a0, int16_t a1, int32_t a2)) { int16_t a0; int16_t a1; int32_t a2; a0 = -1; a1 = 2; a2 = -3; std::cout << "Calling TestReturnStruct8BytesInt(" << "(" << a0 << ", " << a1 << ", " << a2 << ")" << ")\n"; Struct8BytesInt result = f(a0, a1, a2); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); return 0; } // Used for testing structs and unions by value. // Return value in FP registers on many architectures. DART_EXPORT intptr_t TestReturnStruct8BytesHomogeneousFloat( // NOLINTNEXTLINE(whitespace/parens) Struct8BytesHomogeneousFloat (*f)(float a0, float a1)) { float a0; float a1; a0 = -1.0; a1 = 2.0; std::cout << "Calling TestReturnStruct8BytesHomogeneousFloat(" << "(" << a0 << ", " << a1 << ")" << ")\n"; Struct8BytesHomogeneousFloat result = f(a0, a1); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ")" << "\n"; CHECK_APPROX(a0, result.a0); CHECK_APPROX(a1, result.a1); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); return 0; } // Used for testing structs and unions by value. // Return value split over FP and integer register in x64. DART_EXPORT intptr_t TestReturnStruct8BytesMixed( // NOLINTNEXTLINE(whitespace/parens) Struct8BytesMixed (*f)(float a0, int16_t a1, int16_t a2)) { float a0; int16_t a1; int16_t a2; a0 = -1.0; a1 = 2; a2 = -3; std::cout << "Calling TestReturnStruct8BytesMixed(" << "(" << a0 << ", " << a1 << ", " << a2 << ")" << ")\n"; Struct8BytesMixed result = f(a0, a1, a2); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")" << "\n"; CHECK_APPROX(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2); CHECK_APPROX(0.0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2); CHECK_APPROX(0.0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestReturnStruct9BytesHomogeneousUint8( // NOLINTNEXTLINE(whitespace/parens) Struct9BytesHomogeneousUint8 (*f)(uint8_t a0, uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6, uint8_t a7, uint8_t a8)) { uint8_t a0; uint8_t a1; uint8_t a2; uint8_t a3; uint8_t a4; uint8_t a5; uint8_t a6; uint8_t a7; uint8_t a8; a0 = 1; a1 = 2; a2 = 3; a3 = 4; a4 = 5; a5 = 6; a6 = 7; a7 = 8; a8 = 9; std::cout << "Calling TestReturnStruct9BytesHomogeneousUint8(" << "(" << static_cast(a0) << ", " << static_cast(a1) << ", " << static_cast(a2) << ", " << static_cast(a3) << ", " << static_cast(a4) << ", " << static_cast(a5) << ", " << static_cast(a6) << ", " << static_cast(a7) << ", " << static_cast(a8) << ")" << ")\n"; Struct9BytesHomogeneousUint8 result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); std::cout << "result = " << "(" << static_cast(result.a0) << ", " << static_cast(result.a1) << ", " << static_cast(result.a2) << ", " << static_cast(result.a3) << ", " << static_cast(result.a4) << ", " << static_cast(result.a5) << ", " << static_cast(result.a6) << ", " << static_cast(result.a7) << ", " << static_cast(result.a8) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); CHECK_EQ(a3, result.a3); CHECK_EQ(a4, result.a4); CHECK_EQ(a5, result.a5); CHECK_EQ(a6, result.a6); CHECK_EQ(a7, result.a7); CHECK_EQ(a8, result.a8); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); CHECK_EQ(0, result.a5); CHECK_EQ(0, result.a6); CHECK_EQ(0, result.a7); CHECK_EQ(0, result.a8); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); CHECK_EQ(0, result.a5); CHECK_EQ(0, result.a6); CHECK_EQ(0, result.a7); CHECK_EQ(0, result.a8); return 0; } // Used for testing structs and unions by value. // Return value in two integer registers on x64. // With alignment rules taken into account size is 12 or 16 bytes. DART_EXPORT intptr_t TestReturnStruct9BytesInt4Or8ByteAligned( // NOLINTNEXTLINE(whitespace/parens) Struct9BytesInt4Or8ByteAligned (*f)(int64_t a0, int8_t a1)) { int64_t a0; int8_t a1; a0 = -1; a1 = 2; std::cout << "Calling TestReturnStruct9BytesInt4Or8ByteAligned(" << "(" << a0 << ", " << static_cast(a1) << ")" << ")\n"; Struct9BytesInt4Or8ByteAligned result = f(a0, a1); std::cout << "result = " << "(" << result.a0 << ", " << static_cast(result.a1) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); return 0; } // Used for testing structs and unions by value. // Return value in FPU registers, but does not use all registers on arm hardfp // and arm64. DART_EXPORT intptr_t TestReturnStruct12BytesHomogeneousFloat( // NOLINTNEXTLINE(whitespace/parens) Struct12BytesHomogeneousFloat (*f)(float a0, float a1, float a2)) { float a0; float a1; float a2; a0 = -1.0; a1 = 2.0; a2 = -3.0; std::cout << "Calling TestReturnStruct12BytesHomogeneousFloat(" << "(" << a0 << ", " << a1 << ", " << a2 << ")" << ")\n"; Struct12BytesHomogeneousFloat result = f(a0, a1, a2); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ")" << "\n"; CHECK_APPROX(a0, result.a0); CHECK_APPROX(a1, result.a1); CHECK_APPROX(a2, result.a2); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); return 0; } // Used for testing structs and unions by value. // Return value in FPU registers on arm hardfp and arm64. DART_EXPORT intptr_t TestReturnStruct16BytesHomogeneousFloat( // NOLINTNEXTLINE(whitespace/parens) Struct16BytesHomogeneousFloat ( *f)(float a0, float a1, float a2, float a3)) { float a0; float a1; float a2; float a3; a0 = -1.0; a1 = 2.0; a2 = -3.0; a3 = 4.0; std::cout << "Calling TestReturnStruct16BytesHomogeneousFloat(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")" << ")\n"; Struct16BytesHomogeneousFloat result = f(a0, a1, a2, a3); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ")" << "\n"; CHECK_APPROX(a0, result.a0); CHECK_APPROX(a1, result.a1); CHECK_APPROX(a2, result.a2); CHECK_APPROX(a3, result.a3); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); CHECK_APPROX(0.0, result.a3); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); CHECK_APPROX(0.0, result.a3); return 0; } // Used for testing structs and unions by value. // Return value split over FP and integer register in x64. DART_EXPORT intptr_t TestReturnStruct16BytesMixed( // NOLINTNEXTLINE(whitespace/parens) Struct16BytesMixed (*f)(double a0, int64_t a1)) { double a0; int64_t a1; a0 = -1.0; a1 = 2; std::cout << "Calling TestReturnStruct16BytesMixed(" << "(" << a0 << ", " << a1 << ")" << ")\n"; Struct16BytesMixed result = f(a0, a1); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ")" << "\n"; CHECK_APPROX(a0, result.a0); CHECK_EQ(a1, result.a1); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1); CHECK_APPROX(0.0, result.a0); CHECK_EQ(0, result.a1); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1); CHECK_APPROX(0.0, result.a0); CHECK_EQ(0, result.a1); return 0; } // Used for testing structs and unions by value. // Return value split over FP and integer register in x64. // The integer register contains half float half int. DART_EXPORT intptr_t TestReturnStruct16BytesMixed2( // NOLINTNEXTLINE(whitespace/parens) Struct16BytesMixed2 (*f)(float a0, float a1, float a2, int32_t a3)) { float a0; float a1; float a2; int32_t a3; a0 = -1.0; a1 = 2.0; a2 = -3.0; a3 = 4; std::cout << "Calling TestReturnStruct16BytesMixed2(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")" << ")\n"; Struct16BytesMixed2 result = f(a0, a1, a2, a3); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ")" << "\n"; CHECK_APPROX(a0, result.a0); CHECK_APPROX(a1, result.a1); CHECK_APPROX(a2, result.a2); CHECK_EQ(a3, result.a3); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); CHECK_EQ(0, result.a3); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); CHECK_EQ(0, result.a3); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestReturnStruct17BytesInt( // NOLINTNEXTLINE(whitespace/parens) Struct17BytesInt (*f)(int64_t a0, int64_t a1, int8_t a2)) { int64_t a0; int64_t a1; int8_t a2; a0 = -1; a1 = 2; a2 = -3; std::cout << "Calling TestReturnStruct17BytesInt(" << "(" << a0 << ", " << a1 << ", " << static_cast(a2) << ")" << ")\n"; Struct17BytesInt result = f(a0, a1, a2); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << static_cast(result.a2) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); return 0; } // Used for testing structs and unions by value. // 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. DART_EXPORT intptr_t TestReturnStruct19BytesHomogeneousUint8( // NOLINTNEXTLINE(whitespace/parens) Struct19BytesHomogeneousUint8 (*f)(uint8_t a0, uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6, uint8_t a7, uint8_t a8, uint8_t a9, uint8_t a10, uint8_t a11, uint8_t a12, uint8_t a13, uint8_t a14, uint8_t a15, uint8_t a16, uint8_t a17, uint8_t a18)) { uint8_t a0; uint8_t a1; uint8_t a2; uint8_t a3; uint8_t a4; uint8_t a5; uint8_t a6; uint8_t a7; uint8_t a8; uint8_t a9; uint8_t a10; uint8_t a11; uint8_t a12; uint8_t a13; uint8_t a14; uint8_t a15; uint8_t a16; uint8_t a17; uint8_t a18; a0 = 1; a1 = 2; a2 = 3; a3 = 4; a4 = 5; a5 = 6; a6 = 7; a7 = 8; a8 = 9; a9 = 10; a10 = 11; a11 = 12; a12 = 13; a13 = 14; a14 = 15; a15 = 16; a16 = 17; a17 = 18; a18 = 19; std::cout << "Calling TestReturnStruct19BytesHomogeneousUint8(" << "(" << static_cast(a0) << ", " << static_cast(a1) << ", " << static_cast(a2) << ", " << static_cast(a3) << ", " << static_cast(a4) << ", " << static_cast(a5) << ", " << static_cast(a6) << ", " << static_cast(a7) << ", " << static_cast(a8) << ", " << static_cast(a9) << ", " << static_cast(a10) << ", " << static_cast(a11) << ", " << static_cast(a12) << ", " << static_cast(a13) << ", " << static_cast(a14) << ", " << static_cast(a15) << ", " << static_cast(a16) << ", " << static_cast(a17) << ", " << static_cast(a18) << ")" << ")\n"; Struct19BytesHomogeneousUint8 result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); std::cout << "result = " << "(" << static_cast(result.a0) << ", " << static_cast(result.a1) << ", " << static_cast(result.a2) << ", " << static_cast(result.a3) << ", " << static_cast(result.a4) << ", " << static_cast(result.a5) << ", " << static_cast(result.a6) << ", " << static_cast(result.a7) << ", " << static_cast(result.a8) << ", " << static_cast(result.a9) << ", " << static_cast(result.a10) << ", " << static_cast(result.a11) << ", " << static_cast(result.a12) << ", " << static_cast(result.a13) << ", " << static_cast(result.a14) << ", " << static_cast(result.a15) << ", " << static_cast(result.a16) << ", " << static_cast(result.a17) << ", " << static_cast(result.a18) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); CHECK_EQ(a3, result.a3); CHECK_EQ(a4, result.a4); CHECK_EQ(a5, result.a5); CHECK_EQ(a6, result.a6); CHECK_EQ(a7, result.a7); CHECK_EQ(a8, result.a8); CHECK_EQ(a9, result.a9); CHECK_EQ(a10, result.a10); CHECK_EQ(a11, result.a11); CHECK_EQ(a12, result.a12); CHECK_EQ(a13, result.a13); CHECK_EQ(a14, result.a14); CHECK_EQ(a15, result.a15); CHECK_EQ(a16, result.a16); CHECK_EQ(a17, result.a17); CHECK_EQ(a18, result.a18); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); CHECK_EQ(0, result.a5); CHECK_EQ(0, result.a6); CHECK_EQ(0, result.a7); CHECK_EQ(0, result.a8); CHECK_EQ(0, result.a9); CHECK_EQ(0, result.a10); CHECK_EQ(0, result.a11); CHECK_EQ(0, result.a12); CHECK_EQ(0, result.a13); CHECK_EQ(0, result.a14); CHECK_EQ(0, result.a15); CHECK_EQ(0, result.a16); CHECK_EQ(0, result.a17); CHECK_EQ(0, result.a18); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); CHECK_EQ(0, result.a5); CHECK_EQ(0, result.a6); CHECK_EQ(0, result.a7); CHECK_EQ(0, result.a8); CHECK_EQ(0, result.a9); CHECK_EQ(0, result.a10); CHECK_EQ(0, result.a11); CHECK_EQ(0, result.a12); CHECK_EQ(0, result.a13); CHECK_EQ(0, result.a14); CHECK_EQ(0, result.a15); CHECK_EQ(0, result.a16); CHECK_EQ(0, result.a17); CHECK_EQ(0, result.a18); return 0; } // Used for testing structs and unions by value. // Return value too big to go in cpu registers on arm64. DART_EXPORT intptr_t TestReturnStruct20BytesHomogeneousInt32( // NOLINTNEXTLINE(whitespace/parens) Struct20BytesHomogeneousInt32 ( *f)(int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4)) { int32_t a0; int32_t a1; int32_t a2; int32_t a3; int32_t a4; a0 = -1; a1 = 2; a2 = -3; a3 = 4; a4 = -5; std::cout << "Calling TestReturnStruct20BytesHomogeneousInt32(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ")" << ")\n"; Struct20BytesHomogeneousInt32 result = f(a0, a1, a2, a3, a4); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); CHECK_EQ(a3, result.a3); CHECK_EQ(a4, result.a4); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); return 0; } // Used for testing structs and unions by value. // Return value too big to go in FPU registers on x64, arm hardfp and arm64. DART_EXPORT intptr_t TestReturnStruct20BytesHomogeneousFloat( // NOLINTNEXTLINE(whitespace/parens) Struct20BytesHomogeneousFloat ( *f)(float a0, float a1, float a2, float a3, float a4)) { float a0; float a1; float a2; float a3; float a4; a0 = -1.0; a1 = 2.0; a2 = -3.0; a3 = 4.0; a4 = -5.0; std::cout << "Calling TestReturnStruct20BytesHomogeneousFloat(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ")" << ")\n"; Struct20BytesHomogeneousFloat result = f(a0, a1, a2, a3, a4); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ")" << "\n"; CHECK_APPROX(a0, result.a0); CHECK_APPROX(a1, result.a1); CHECK_APPROX(a2, result.a2); CHECK_APPROX(a3, result.a3); CHECK_APPROX(a4, result.a4); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); CHECK_APPROX(0.0, result.a3); CHECK_APPROX(0.0, result.a4); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); CHECK_APPROX(0.0, result.a3); CHECK_APPROX(0.0, result.a4); return 0; } // Used for testing structs and unions by value. // Return value in FPU registers on arm64. DART_EXPORT intptr_t TestReturnStruct32BytesHomogeneousDouble( // NOLINTNEXTLINE(whitespace/parens) Struct32BytesHomogeneousDouble ( *f)(double a0, double a1, double a2, double a3)) { double a0; double a1; double a2; double a3; a0 = -1.0; a1 = 2.0; a2 = -3.0; a3 = 4.0; std::cout << "Calling TestReturnStruct32BytesHomogeneousDouble(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ")" << ")\n"; Struct32BytesHomogeneousDouble result = f(a0, a1, a2, a3); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ")" << "\n"; CHECK_APPROX(a0, result.a0); CHECK_APPROX(a1, result.a1); CHECK_APPROX(a2, result.a2); CHECK_APPROX(a3, result.a3); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); CHECK_APPROX(0.0, result.a3); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); CHECK_APPROX(0.0, result.a3); return 0; } // Used for testing structs and unions by value. // Return value too big to go in FPU registers on arm64. DART_EXPORT intptr_t TestReturnStruct40BytesHomogeneousDouble( // NOLINTNEXTLINE(whitespace/parens) Struct40BytesHomogeneousDouble ( *f)(double a0, double a1, double a2, double a3, double a4)) { double a0; double a1; double a2; double a3; double a4; a0 = -1.0; a1 = 2.0; a2 = -3.0; a3 = 4.0; a4 = -5.0; std::cout << "Calling TestReturnStruct40BytesHomogeneousDouble(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ")" << ")\n"; Struct40BytesHomogeneousDouble result = f(a0, a1, a2, a3, a4); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ")" << "\n"; CHECK_APPROX(a0, result.a0); CHECK_APPROX(a1, result.a1); CHECK_APPROX(a2, result.a2); CHECK_APPROX(a3, result.a3); CHECK_APPROX(a4, result.a4); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); CHECK_APPROX(0.0, result.a3); CHECK_APPROX(0.0, result.a4); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); CHECK_APPROX(0.0, result.a2); CHECK_APPROX(0.0, result.a3); CHECK_APPROX(0.0, result.a4); return 0; } // Used for testing structs and unions by value. // Test 1kb struct. DART_EXPORT intptr_t TestReturnStruct1024BytesHomogeneousUint64( // NOLINTNEXTLINE(whitespace/parens) Struct1024BytesHomogeneousUint64 (*f)(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6, uint64_t a7, uint64_t a8, uint64_t a9, uint64_t a10, uint64_t a11, uint64_t a12, uint64_t a13, uint64_t a14, uint64_t a15, uint64_t a16, uint64_t a17, uint64_t a18, uint64_t a19, uint64_t a20, uint64_t a21, uint64_t a22, uint64_t a23, uint64_t a24, uint64_t a25, uint64_t a26, uint64_t a27, uint64_t a28, uint64_t a29, uint64_t a30, uint64_t a31, uint64_t a32, uint64_t a33, uint64_t a34, uint64_t a35, uint64_t a36, uint64_t a37, uint64_t a38, uint64_t a39, uint64_t a40, uint64_t a41, uint64_t a42, uint64_t a43, uint64_t a44, uint64_t a45, uint64_t a46, uint64_t a47, uint64_t a48, uint64_t a49, uint64_t a50, uint64_t a51, uint64_t a52, uint64_t a53, uint64_t a54, uint64_t a55, uint64_t a56, uint64_t a57, uint64_t a58, uint64_t a59, uint64_t a60, uint64_t a61, uint64_t a62, uint64_t a63, uint64_t a64, uint64_t a65, uint64_t a66, uint64_t a67, uint64_t a68, uint64_t a69, uint64_t a70, uint64_t a71, uint64_t a72, uint64_t a73, uint64_t a74, uint64_t a75, uint64_t a76, uint64_t a77, uint64_t a78, uint64_t a79, uint64_t a80, uint64_t a81, uint64_t a82, uint64_t a83, uint64_t a84, uint64_t a85, uint64_t a86, uint64_t a87, uint64_t a88, uint64_t a89, uint64_t a90, uint64_t a91, uint64_t a92, uint64_t a93, uint64_t a94, uint64_t a95, uint64_t a96, uint64_t a97, uint64_t a98, uint64_t a99, uint64_t a100, uint64_t a101, uint64_t a102, uint64_t a103, uint64_t a104, uint64_t a105, uint64_t a106, uint64_t a107, uint64_t a108, uint64_t a109, uint64_t a110, uint64_t a111, uint64_t a112, uint64_t a113, uint64_t a114, uint64_t a115, uint64_t a116, uint64_t a117, uint64_t a118, uint64_t a119, uint64_t a120, uint64_t a121, uint64_t a122, uint64_t a123, uint64_t a124, uint64_t a125, uint64_t a126, uint64_t a127)) { uint64_t a0; uint64_t a1; uint64_t a2; uint64_t a3; uint64_t a4; uint64_t a5; uint64_t a6; uint64_t a7; uint64_t a8; uint64_t a9; uint64_t a10; uint64_t a11; uint64_t a12; uint64_t a13; uint64_t a14; uint64_t a15; uint64_t a16; uint64_t a17; uint64_t a18; uint64_t a19; uint64_t a20; uint64_t a21; uint64_t a22; uint64_t a23; uint64_t a24; uint64_t a25; uint64_t a26; uint64_t a27; uint64_t a28; uint64_t a29; uint64_t a30; uint64_t a31; uint64_t a32; uint64_t a33; uint64_t a34; uint64_t a35; uint64_t a36; uint64_t a37; uint64_t a38; uint64_t a39; uint64_t a40; uint64_t a41; uint64_t a42; uint64_t a43; uint64_t a44; uint64_t a45; uint64_t a46; uint64_t a47; uint64_t a48; uint64_t a49; uint64_t a50; uint64_t a51; uint64_t a52; uint64_t a53; uint64_t a54; uint64_t a55; uint64_t a56; uint64_t a57; uint64_t a58; uint64_t a59; uint64_t a60; uint64_t a61; uint64_t a62; uint64_t a63; uint64_t a64; uint64_t a65; uint64_t a66; uint64_t a67; uint64_t a68; uint64_t a69; uint64_t a70; uint64_t a71; uint64_t a72; uint64_t a73; uint64_t a74; uint64_t a75; uint64_t a76; uint64_t a77; uint64_t a78; uint64_t a79; uint64_t a80; uint64_t a81; uint64_t a82; uint64_t a83; uint64_t a84; uint64_t a85; uint64_t a86; uint64_t a87; uint64_t a88; uint64_t a89; uint64_t a90; uint64_t a91; uint64_t a92; uint64_t a93; uint64_t a94; uint64_t a95; uint64_t a96; uint64_t a97; uint64_t a98; uint64_t a99; uint64_t a100; uint64_t a101; uint64_t a102; uint64_t a103; uint64_t a104; uint64_t a105; uint64_t a106; uint64_t a107; uint64_t a108; uint64_t a109; uint64_t a110; uint64_t a111; uint64_t a112; uint64_t a113; uint64_t a114; uint64_t a115; uint64_t a116; uint64_t a117; uint64_t a118; uint64_t a119; uint64_t a120; uint64_t a121; uint64_t a122; uint64_t a123; uint64_t a124; uint64_t a125; uint64_t a126; uint64_t a127; a0 = 1; a1 = 2; a2 = 3; a3 = 4; a4 = 5; a5 = 6; a6 = 7; a7 = 8; a8 = 9; a9 = 10; a10 = 11; a11 = 12; a12 = 13; a13 = 14; a14 = 15; a15 = 16; a16 = 17; a17 = 18; a18 = 19; a19 = 20; a20 = 21; a21 = 22; a22 = 23; a23 = 24; a24 = 25; a25 = 26; a26 = 27; a27 = 28; a28 = 29; a29 = 30; a30 = 31; a31 = 32; a32 = 33; a33 = 34; a34 = 35; a35 = 36; a36 = 37; a37 = 38; a38 = 39; a39 = 40; a40 = 41; a41 = 42; a42 = 43; a43 = 44; a44 = 45; a45 = 46; a46 = 47; a47 = 48; a48 = 49; a49 = 50; a50 = 51; a51 = 52; a52 = 53; a53 = 54; a54 = 55; a55 = 56; a56 = 57; a57 = 58; a58 = 59; a59 = 60; a60 = 61; a61 = 62; a62 = 63; a63 = 64; a64 = 65; a65 = 66; a66 = 67; a67 = 68; a68 = 69; a69 = 70; a70 = 71; a71 = 72; a72 = 73; a73 = 74; a74 = 75; a75 = 76; a76 = 77; a77 = 78; a78 = 79; a79 = 80; a80 = 81; a81 = 82; a82 = 83; a83 = 84; a84 = 85; a85 = 86; a86 = 87; a87 = 88; a88 = 89; a89 = 90; a90 = 91; a91 = 92; a92 = 93; a93 = 94; a94 = 95; a95 = 96; a96 = 97; a97 = 98; a98 = 99; a99 = 100; a100 = 101; a101 = 102; a102 = 103; a103 = 104; a104 = 105; a105 = 106; a106 = 107; a107 = 108; a108 = 109; a109 = 110; a110 = 111; a111 = 112; a112 = 113; a113 = 114; a114 = 115; a115 = 116; a116 = 117; a117 = 118; a118 = 119; a119 = 120; a120 = 121; a121 = 122; a122 = 123; a123 = 124; a124 = 125; a125 = 126; a126 = 127; a127 = 128; std::cout << "Calling TestReturnStruct1024BytesHomogeneousUint64(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7 << ", " << a8 << ", " << a9 << ", " << a10 << ", " << a11 << ", " << a12 << ", " << a13 << ", " << a14 << ", " << a15 << ", " << a16 << ", " << a17 << ", " << a18 << ", " << a19 << ", " << a20 << ", " << a21 << ", " << a22 << ", " << a23 << ", " << a24 << ", " << a25 << ", " << a26 << ", " << a27 << ", " << a28 << ", " << a29 << ", " << a30 << ", " << a31 << ", " << a32 << ", " << a33 << ", " << a34 << ", " << a35 << ", " << a36 << ", " << a37 << ", " << a38 << ", " << a39 << ", " << a40 << ", " << a41 << ", " << a42 << ", " << a43 << ", " << a44 << ", " << a45 << ", " << a46 << ", " << a47 << ", " << a48 << ", " << a49 << ", " << a50 << ", " << a51 << ", " << a52 << ", " << a53 << ", " << a54 << ", " << a55 << ", " << a56 << ", " << a57 << ", " << a58 << ", " << a59 << ", " << a60 << ", " << a61 << ", " << a62 << ", " << a63 << ", " << a64 << ", " << a65 << ", " << a66 << ", " << a67 << ", " << a68 << ", " << a69 << ", " << a70 << ", " << a71 << ", " << a72 << ", " << a73 << ", " << a74 << ", " << a75 << ", " << a76 << ", " << a77 << ", " << a78 << ", " << a79 << ", " << a80 << ", " << a81 << ", " << a82 << ", " << a83 << ", " << a84 << ", " << a85 << ", " << a86 << ", " << a87 << ", " << a88 << ", " << a89 << ", " << a90 << ", " << a91 << ", " << a92 << ", " << a93 << ", " << a94 << ", " << a95 << ", " << a96 << ", " << a97 << ", " << a98 << ", " << a99 << ", " << a100 << ", " << a101 << ", " << a102 << ", " << a103 << ", " << a104 << ", " << a105 << ", " << a106 << ", " << a107 << ", " << a108 << ", " << a109 << ", " << a110 << ", " << a111 << ", " << a112 << ", " << a113 << ", " << a114 << ", " << a115 << ", " << a116 << ", " << a117 << ", " << a118 << ", " << a119 << ", " << a120 << ", " << a121 << ", " << a122 << ", " << a123 << ", " << a124 << ", " << a125 << ", " << a126 << ", " << a127 << ")" << ")\n"; Struct1024BytesHomogeneousUint64 result = f( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76, a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104, a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116, a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ", " << result.a5 << ", " << result.a6 << ", " << result.a7 << ", " << result.a8 << ", " << result.a9 << ", " << result.a10 << ", " << result.a11 << ", " << result.a12 << ", " << result.a13 << ", " << result.a14 << ", " << result.a15 << ", " << result.a16 << ", " << result.a17 << ", " << result.a18 << ", " << result.a19 << ", " << result.a20 << ", " << result.a21 << ", " << result.a22 << ", " << result.a23 << ", " << result.a24 << ", " << result.a25 << ", " << result.a26 << ", " << result.a27 << ", " << result.a28 << ", " << result.a29 << ", " << result.a30 << ", " << result.a31 << ", " << result.a32 << ", " << result.a33 << ", " << result.a34 << ", " << result.a35 << ", " << result.a36 << ", " << result.a37 << ", " << result.a38 << ", " << result.a39 << ", " << result.a40 << ", " << result.a41 << ", " << result.a42 << ", " << result.a43 << ", " << result.a44 << ", " << result.a45 << ", " << result.a46 << ", " << result.a47 << ", " << result.a48 << ", " << result.a49 << ", " << result.a50 << ", " << result.a51 << ", " << result.a52 << ", " << result.a53 << ", " << result.a54 << ", " << result.a55 << ", " << result.a56 << ", " << result.a57 << ", " << result.a58 << ", " << result.a59 << ", " << result.a60 << ", " << result.a61 << ", " << result.a62 << ", " << result.a63 << ", " << result.a64 << ", " << result.a65 << ", " << result.a66 << ", " << result.a67 << ", " << result.a68 << ", " << result.a69 << ", " << result.a70 << ", " << result.a71 << ", " << result.a72 << ", " << result.a73 << ", " << result.a74 << ", " << result.a75 << ", " << result.a76 << ", " << result.a77 << ", " << result.a78 << ", " << result.a79 << ", " << result.a80 << ", " << result.a81 << ", " << result.a82 << ", " << result.a83 << ", " << result.a84 << ", " << result.a85 << ", " << result.a86 << ", " << result.a87 << ", " << result.a88 << ", " << result.a89 << ", " << result.a90 << ", " << result.a91 << ", " << result.a92 << ", " << result.a93 << ", " << result.a94 << ", " << result.a95 << ", " << result.a96 << ", " << result.a97 << ", " << result.a98 << ", " << result.a99 << ", " << result.a100 << ", " << result.a101 << ", " << result.a102 << ", " << result.a103 << ", " << result.a104 << ", " << result.a105 << ", " << result.a106 << ", " << result.a107 << ", " << result.a108 << ", " << result.a109 << ", " << result.a110 << ", " << result.a111 << ", " << result.a112 << ", " << result.a113 << ", " << result.a114 << ", " << result.a115 << ", " << result.a116 << ", " << result.a117 << ", " << result.a118 << ", " << result.a119 << ", " << result.a120 << ", " << result.a121 << ", " << result.a122 << ", " << result.a123 << ", " << result.a124 << ", " << result.a125 << ", " << result.a126 << ", " << result.a127 << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); CHECK_EQ(a3, result.a3); CHECK_EQ(a4, result.a4); CHECK_EQ(a5, result.a5); CHECK_EQ(a6, result.a6); CHECK_EQ(a7, result.a7); CHECK_EQ(a8, result.a8); CHECK_EQ(a9, result.a9); CHECK_EQ(a10, result.a10); CHECK_EQ(a11, result.a11); CHECK_EQ(a12, result.a12); CHECK_EQ(a13, result.a13); CHECK_EQ(a14, result.a14); CHECK_EQ(a15, result.a15); CHECK_EQ(a16, result.a16); CHECK_EQ(a17, result.a17); CHECK_EQ(a18, result.a18); CHECK_EQ(a19, result.a19); CHECK_EQ(a20, result.a20); CHECK_EQ(a21, result.a21); CHECK_EQ(a22, result.a22); CHECK_EQ(a23, result.a23); CHECK_EQ(a24, result.a24); CHECK_EQ(a25, result.a25); CHECK_EQ(a26, result.a26); CHECK_EQ(a27, result.a27); CHECK_EQ(a28, result.a28); CHECK_EQ(a29, result.a29); CHECK_EQ(a30, result.a30); CHECK_EQ(a31, result.a31); CHECK_EQ(a32, result.a32); CHECK_EQ(a33, result.a33); CHECK_EQ(a34, result.a34); CHECK_EQ(a35, result.a35); CHECK_EQ(a36, result.a36); CHECK_EQ(a37, result.a37); CHECK_EQ(a38, result.a38); CHECK_EQ(a39, result.a39); CHECK_EQ(a40, result.a40); CHECK_EQ(a41, result.a41); CHECK_EQ(a42, result.a42); CHECK_EQ(a43, result.a43); CHECK_EQ(a44, result.a44); CHECK_EQ(a45, result.a45); CHECK_EQ(a46, result.a46); CHECK_EQ(a47, result.a47); CHECK_EQ(a48, result.a48); CHECK_EQ(a49, result.a49); CHECK_EQ(a50, result.a50); CHECK_EQ(a51, result.a51); CHECK_EQ(a52, result.a52); CHECK_EQ(a53, result.a53); CHECK_EQ(a54, result.a54); CHECK_EQ(a55, result.a55); CHECK_EQ(a56, result.a56); CHECK_EQ(a57, result.a57); CHECK_EQ(a58, result.a58); CHECK_EQ(a59, result.a59); CHECK_EQ(a60, result.a60); CHECK_EQ(a61, result.a61); CHECK_EQ(a62, result.a62); CHECK_EQ(a63, result.a63); CHECK_EQ(a64, result.a64); CHECK_EQ(a65, result.a65); CHECK_EQ(a66, result.a66); CHECK_EQ(a67, result.a67); CHECK_EQ(a68, result.a68); CHECK_EQ(a69, result.a69); CHECK_EQ(a70, result.a70); CHECK_EQ(a71, result.a71); CHECK_EQ(a72, result.a72); CHECK_EQ(a73, result.a73); CHECK_EQ(a74, result.a74); CHECK_EQ(a75, result.a75); CHECK_EQ(a76, result.a76); CHECK_EQ(a77, result.a77); CHECK_EQ(a78, result.a78); CHECK_EQ(a79, result.a79); CHECK_EQ(a80, result.a80); CHECK_EQ(a81, result.a81); CHECK_EQ(a82, result.a82); CHECK_EQ(a83, result.a83); CHECK_EQ(a84, result.a84); CHECK_EQ(a85, result.a85); CHECK_EQ(a86, result.a86); CHECK_EQ(a87, result.a87); CHECK_EQ(a88, result.a88); CHECK_EQ(a89, result.a89); CHECK_EQ(a90, result.a90); CHECK_EQ(a91, result.a91); CHECK_EQ(a92, result.a92); CHECK_EQ(a93, result.a93); CHECK_EQ(a94, result.a94); CHECK_EQ(a95, result.a95); CHECK_EQ(a96, result.a96); CHECK_EQ(a97, result.a97); CHECK_EQ(a98, result.a98); CHECK_EQ(a99, result.a99); CHECK_EQ(a100, result.a100); CHECK_EQ(a101, result.a101); CHECK_EQ(a102, result.a102); CHECK_EQ(a103, result.a103); CHECK_EQ(a104, result.a104); CHECK_EQ(a105, result.a105); CHECK_EQ(a106, result.a106); CHECK_EQ(a107, result.a107); CHECK_EQ(a108, result.a108); CHECK_EQ(a109, result.a109); CHECK_EQ(a110, result.a110); CHECK_EQ(a111, result.a111); CHECK_EQ(a112, result.a112); CHECK_EQ(a113, result.a113); CHECK_EQ(a114, result.a114); CHECK_EQ(a115, result.a115); CHECK_EQ(a116, result.a116); CHECK_EQ(a117, result.a117); CHECK_EQ(a118, result.a118); CHECK_EQ(a119, result.a119); CHECK_EQ(a120, result.a120); CHECK_EQ(a121, result.a121); CHECK_EQ(a122, result.a122); CHECK_EQ(a123, result.a123); CHECK_EQ(a124, result.a124); CHECK_EQ(a125, result.a125); CHECK_EQ(a126, result.a126); CHECK_EQ(a127, result.a127); // Pass argument that will make the Dart callback throw. a0 = 42; result = f( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76, a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104, a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116, a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); CHECK_EQ(0, result.a5); CHECK_EQ(0, result.a6); CHECK_EQ(0, result.a7); CHECK_EQ(0, result.a8); CHECK_EQ(0, result.a9); CHECK_EQ(0, result.a10); CHECK_EQ(0, result.a11); CHECK_EQ(0, result.a12); CHECK_EQ(0, result.a13); CHECK_EQ(0, result.a14); CHECK_EQ(0, result.a15); CHECK_EQ(0, result.a16); CHECK_EQ(0, result.a17); CHECK_EQ(0, result.a18); CHECK_EQ(0, result.a19); CHECK_EQ(0, result.a20); CHECK_EQ(0, result.a21); CHECK_EQ(0, result.a22); CHECK_EQ(0, result.a23); CHECK_EQ(0, result.a24); CHECK_EQ(0, result.a25); CHECK_EQ(0, result.a26); CHECK_EQ(0, result.a27); CHECK_EQ(0, result.a28); CHECK_EQ(0, result.a29); CHECK_EQ(0, result.a30); CHECK_EQ(0, result.a31); CHECK_EQ(0, result.a32); CHECK_EQ(0, result.a33); CHECK_EQ(0, result.a34); CHECK_EQ(0, result.a35); CHECK_EQ(0, result.a36); CHECK_EQ(0, result.a37); CHECK_EQ(0, result.a38); CHECK_EQ(0, result.a39); CHECK_EQ(0, result.a40); CHECK_EQ(0, result.a41); CHECK_EQ(0, result.a42); CHECK_EQ(0, result.a43); CHECK_EQ(0, result.a44); CHECK_EQ(0, result.a45); CHECK_EQ(0, result.a46); CHECK_EQ(0, result.a47); CHECK_EQ(0, result.a48); CHECK_EQ(0, result.a49); CHECK_EQ(0, result.a50); CHECK_EQ(0, result.a51); CHECK_EQ(0, result.a52); CHECK_EQ(0, result.a53); CHECK_EQ(0, result.a54); CHECK_EQ(0, result.a55); CHECK_EQ(0, result.a56); CHECK_EQ(0, result.a57); CHECK_EQ(0, result.a58); CHECK_EQ(0, result.a59); CHECK_EQ(0, result.a60); CHECK_EQ(0, result.a61); CHECK_EQ(0, result.a62); CHECK_EQ(0, result.a63); CHECK_EQ(0, result.a64); CHECK_EQ(0, result.a65); CHECK_EQ(0, result.a66); CHECK_EQ(0, result.a67); CHECK_EQ(0, result.a68); CHECK_EQ(0, result.a69); CHECK_EQ(0, result.a70); CHECK_EQ(0, result.a71); CHECK_EQ(0, result.a72); CHECK_EQ(0, result.a73); CHECK_EQ(0, result.a74); CHECK_EQ(0, result.a75); CHECK_EQ(0, result.a76); CHECK_EQ(0, result.a77); CHECK_EQ(0, result.a78); CHECK_EQ(0, result.a79); CHECK_EQ(0, result.a80); CHECK_EQ(0, result.a81); CHECK_EQ(0, result.a82); CHECK_EQ(0, result.a83); CHECK_EQ(0, result.a84); CHECK_EQ(0, result.a85); CHECK_EQ(0, result.a86); CHECK_EQ(0, result.a87); CHECK_EQ(0, result.a88); CHECK_EQ(0, result.a89); CHECK_EQ(0, result.a90); CHECK_EQ(0, result.a91); CHECK_EQ(0, result.a92); CHECK_EQ(0, result.a93); CHECK_EQ(0, result.a94); CHECK_EQ(0, result.a95); CHECK_EQ(0, result.a96); CHECK_EQ(0, result.a97); CHECK_EQ(0, result.a98); CHECK_EQ(0, result.a99); CHECK_EQ(0, result.a100); CHECK_EQ(0, result.a101); CHECK_EQ(0, result.a102); CHECK_EQ(0, result.a103); CHECK_EQ(0, result.a104); CHECK_EQ(0, result.a105); CHECK_EQ(0, result.a106); CHECK_EQ(0, result.a107); CHECK_EQ(0, result.a108); CHECK_EQ(0, result.a109); CHECK_EQ(0, result.a110); CHECK_EQ(0, result.a111); CHECK_EQ(0, result.a112); CHECK_EQ(0, result.a113); CHECK_EQ(0, result.a114); CHECK_EQ(0, result.a115); CHECK_EQ(0, result.a116); CHECK_EQ(0, result.a117); CHECK_EQ(0, result.a118); CHECK_EQ(0, result.a119); CHECK_EQ(0, result.a120); CHECK_EQ(0, result.a121); CHECK_EQ(0, result.a122); CHECK_EQ(0, result.a123); CHECK_EQ(0, result.a124); CHECK_EQ(0, result.a125); CHECK_EQ(0, result.a126); CHECK_EQ(0, result.a127); // Pass argument that will make the Dart callback return null. a0 = 84; result = f( a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76, a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104, a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116, a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); CHECK_EQ(0, result.a5); CHECK_EQ(0, result.a6); CHECK_EQ(0, result.a7); CHECK_EQ(0, result.a8); CHECK_EQ(0, result.a9); CHECK_EQ(0, result.a10); CHECK_EQ(0, result.a11); CHECK_EQ(0, result.a12); CHECK_EQ(0, result.a13); CHECK_EQ(0, result.a14); CHECK_EQ(0, result.a15); CHECK_EQ(0, result.a16); CHECK_EQ(0, result.a17); CHECK_EQ(0, result.a18); CHECK_EQ(0, result.a19); CHECK_EQ(0, result.a20); CHECK_EQ(0, result.a21); CHECK_EQ(0, result.a22); CHECK_EQ(0, result.a23); CHECK_EQ(0, result.a24); CHECK_EQ(0, result.a25); CHECK_EQ(0, result.a26); CHECK_EQ(0, result.a27); CHECK_EQ(0, result.a28); CHECK_EQ(0, result.a29); CHECK_EQ(0, result.a30); CHECK_EQ(0, result.a31); CHECK_EQ(0, result.a32); CHECK_EQ(0, result.a33); CHECK_EQ(0, result.a34); CHECK_EQ(0, result.a35); CHECK_EQ(0, result.a36); CHECK_EQ(0, result.a37); CHECK_EQ(0, result.a38); CHECK_EQ(0, result.a39); CHECK_EQ(0, result.a40); CHECK_EQ(0, result.a41); CHECK_EQ(0, result.a42); CHECK_EQ(0, result.a43); CHECK_EQ(0, result.a44); CHECK_EQ(0, result.a45); CHECK_EQ(0, result.a46); CHECK_EQ(0, result.a47); CHECK_EQ(0, result.a48); CHECK_EQ(0, result.a49); CHECK_EQ(0, result.a50); CHECK_EQ(0, result.a51); CHECK_EQ(0, result.a52); CHECK_EQ(0, result.a53); CHECK_EQ(0, result.a54); CHECK_EQ(0, result.a55); CHECK_EQ(0, result.a56); CHECK_EQ(0, result.a57); CHECK_EQ(0, result.a58); CHECK_EQ(0, result.a59); CHECK_EQ(0, result.a60); CHECK_EQ(0, result.a61); CHECK_EQ(0, result.a62); CHECK_EQ(0, result.a63); CHECK_EQ(0, result.a64); CHECK_EQ(0, result.a65); CHECK_EQ(0, result.a66); CHECK_EQ(0, result.a67); CHECK_EQ(0, result.a68); CHECK_EQ(0, result.a69); CHECK_EQ(0, result.a70); CHECK_EQ(0, result.a71); CHECK_EQ(0, result.a72); CHECK_EQ(0, result.a73); CHECK_EQ(0, result.a74); CHECK_EQ(0, result.a75); CHECK_EQ(0, result.a76); CHECK_EQ(0, result.a77); CHECK_EQ(0, result.a78); CHECK_EQ(0, result.a79); CHECK_EQ(0, result.a80); CHECK_EQ(0, result.a81); CHECK_EQ(0, result.a82); CHECK_EQ(0, result.a83); CHECK_EQ(0, result.a84); CHECK_EQ(0, result.a85); CHECK_EQ(0, result.a86); CHECK_EQ(0, result.a87); CHECK_EQ(0, result.a88); CHECK_EQ(0, result.a89); CHECK_EQ(0, result.a90); CHECK_EQ(0, result.a91); CHECK_EQ(0, result.a92); CHECK_EQ(0, result.a93); CHECK_EQ(0, result.a94); CHECK_EQ(0, result.a95); CHECK_EQ(0, result.a96); CHECK_EQ(0, result.a97); CHECK_EQ(0, result.a98); CHECK_EQ(0, result.a99); CHECK_EQ(0, result.a100); CHECK_EQ(0, result.a101); CHECK_EQ(0, result.a102); CHECK_EQ(0, result.a103); CHECK_EQ(0, result.a104); CHECK_EQ(0, result.a105); CHECK_EQ(0, result.a106); CHECK_EQ(0, result.a107); CHECK_EQ(0, result.a108); CHECK_EQ(0, result.a109); CHECK_EQ(0, result.a110); CHECK_EQ(0, result.a111); CHECK_EQ(0, result.a112); CHECK_EQ(0, result.a113); CHECK_EQ(0, result.a114); CHECK_EQ(0, result.a115); CHECK_EQ(0, result.a116); CHECK_EQ(0, result.a117); CHECK_EQ(0, result.a118); CHECK_EQ(0, result.a119); CHECK_EQ(0, result.a120); CHECK_EQ(0, result.a121); CHECK_EQ(0, result.a122); CHECK_EQ(0, result.a123); CHECK_EQ(0, result.a124); CHECK_EQ(0, result.a125); CHECK_EQ(0, result.a126); CHECK_EQ(0, result.a127); return 0; } // Used for testing structs and unions by value. // Small struct with mis-aligned member. DART_EXPORT intptr_t TestReturnStruct3BytesPackedInt( // NOLINTNEXTLINE(whitespace/parens) Struct3BytesPackedInt (*f)(int8_t a0, int16_t a1)) { int8_t a0; int16_t a1; a0 = -1; a1 = 2; std::cout << "Calling TestReturnStruct3BytesPackedInt(" << "(" << static_cast(a0) << ", " << a1 << ")" << ")\n"; Struct3BytesPackedInt result = f(a0, a1); std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); return 0; } // Used for testing structs and unions by value. // Struct with mis-aligned member. DART_EXPORT intptr_t TestReturnStruct8BytesPackedInt( // NOLINTNEXTLINE(whitespace/parens) Struct8BytesPackedInt ( *f)(uint8_t a0, uint32_t a1, uint8_t a2, uint8_t a3, uint8_t a4)) { uint8_t a0; uint32_t a1; uint8_t a2; uint8_t a3; uint8_t a4; a0 = 1; a1 = 2; a2 = 3; a3 = 4; a4 = 5; std::cout << "Calling TestReturnStruct8BytesPackedInt(" << "(" << static_cast(a0) << ", " << a1 << ", " << static_cast(a2) << ", " << static_cast(a3) << ", " << static_cast(a4) << ")" << ")\n"; Struct8BytesPackedInt result = f(a0, a1, a2, a3, a4); std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ", " << static_cast(result.a2) << ", " << static_cast(result.a3) << ", " << static_cast(result.a4) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); CHECK_EQ(a3, result.a3); CHECK_EQ(a4, result.a4); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); return 0; } // Used for testing structs and unions by value. // Struct with mis-aligned member. // Tests backfilling of CPU and FPU registers. DART_EXPORT intptr_t TestReturnStruct9BytesPackedMixed( // NOLINTNEXTLINE(whitespace/parens) Struct9BytesPackedMixed (*f)(uint8_t a0, double a1)) { uint8_t a0; double a1; a0 = 1; a1 = 2.0; std::cout << "Calling TestReturnStruct9BytesPackedMixed(" << "(" << static_cast(a0) << ", " << a1 << ")" << ")\n"; Struct9BytesPackedMixed result = f(a0, a1); std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_APPROX(a1, result.a1); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0); CHECK_APPROX(0.0, result.a1); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0); CHECK_APPROX(0.0, result.a1); return 0; } // Used for testing structs and unions by value. // Returning a mixed integer/float union. DART_EXPORT intptr_t TestReturnUnion4BytesMixed( // NOLINTNEXTLINE(whitespace/parens) Union4BytesMixed (*f)(uint32_t a0)) { uint32_t a0; a0 = 1; std::cout << "Calling TestReturnUnion4BytesMixed(" << "(" << a0 << ")" << ")\n"; Union4BytesMixed result = f(a0); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ")" << "\n"; CHECK_EQ(a0, result.a0); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0); CHECK_EQ(0, result.a0); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0); CHECK_EQ(0, result.a0); return 0; } // Used for testing structs and unions by value. // Returning a floating point only union. DART_EXPORT intptr_t TestReturnUnion8BytesNestedFloat( // NOLINTNEXTLINE(whitespace/parens) Union8BytesNestedFloat (*f)(double a0)) { double a0; a0 = -1.0; std::cout << "Calling TestReturnUnion8BytesNestedFloat(" << "(" << a0 << ")" << ")\n"; Union8BytesNestedFloat result = f(a0); std::cout << "result = " << "(" << result.a0 << ", (" << result.a1.a0 << ", " << result.a1.a1 << "))" << "\n"; CHECK_APPROX(a0, result.a0); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0); CHECK_APPROX(0.0, result.a0); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0); CHECK_APPROX(0.0, result.a0); return 0; } // Used for testing structs and unions by value. // Returning a mixed-size union. DART_EXPORT intptr_t TestReturnUnion9BytesNestedInt( // NOLINTNEXTLINE(whitespace/parens) Union9BytesNestedInt (*f)(Struct8BytesInt a0)) { Struct8BytesInt a0; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; std::cout << "Calling TestReturnUnion9BytesNestedInt(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << "))" << ")\n"; Union9BytesNestedInt result = f(a0); std::cout << "result = " << "((" << result.a0.a0 << ", " << result.a0.a1 << ", " << result.a0.a2 << "), (" << static_cast(result.a1.a0) << ", " << static_cast(result.a1.a1) << ", " << static_cast(result.a1.a2) << ", " << static_cast(result.a1.a3) << ", " << static_cast(result.a1.a4) << ", " << static_cast(result.a1.a5) << ", " << static_cast(result.a1.a6) << ", " << static_cast(result.a1.a7) << ", " << static_cast(result.a1.a8) << "))" << "\n"; CHECK_EQ(a0.a0, result.a0.a0); CHECK_EQ(a0.a1, result.a0.a1); CHECK_EQ(a0.a2, result.a0.a2); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_EQ(0, result.a0.a2); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_EQ(0, result.a0.a2); return 0; } // Used for testing structs and unions by value. // Returning union with homogenous floats. DART_EXPORT intptr_t TestReturnUnion16BytesNestedFloat( // NOLINTNEXTLINE(whitespace/parens) Union16BytesNestedFloat (*f)(Struct8BytesHomogeneousFloat a0)) { Struct8BytesHomogeneousFloat a0; a0.a0 = -1.0; a0.a1 = 2.0; std::cout << "Calling TestReturnUnion16BytesNestedFloat(" << "((" << a0.a0 << ", " << a0.a1 << "))" << ")\n"; Union16BytesNestedFloat result = f(a0); std::cout << "result = " << "((" << result.a0.a0 << ", " << result.a0.a1 << "), (" << result.a1.a0 << ", " << result.a1.a1 << ", " << result.a1.a2 << "), (" << result.a2.a0 << ", " << result.a2.a1 << ", " << result.a2.a2 << ", " << result.a2.a3 << "))" << "\n"; CHECK_APPROX(a0.a0, result.a0.a0); CHECK_APPROX(a0.a1, result.a0.a1); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_APPROX(0.0, result.a0.a0); CHECK_APPROX(0.0, result.a0.a1); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_APPROX(0.0, result.a0.a0); CHECK_APPROX(0.0, result.a0.a1); return 0; } // Used for testing structs and unions by value. // Test that a struct passed in as argument can be returned. // Especially for ffi callbacks. // Struct is passed in int registers in most ABIs. DART_EXPORT intptr_t TestReturnStructArgumentStruct1ByteInt( // NOLINTNEXTLINE(whitespace/parens) Struct1ByteInt (*f)(Struct1ByteInt a0)) { Struct1ByteInt a0; a0.a0 = -1; std::cout << "Calling TestReturnStructArgumentStruct1ByteInt(" << "((" << static_cast(a0.a0) << "))" << ")\n"; Struct1ByteInt result = f(a0); std::cout << "result = " << "(" << static_cast(result.a0) << ")" << "\n"; CHECK_EQ(a0.a0, result.a0); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_EQ(0, result.a0); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_EQ(0, result.a0); return 0; } // Used for testing structs and unions by value. // Test that a struct passed in as argument can be returned. // Especially for ffi callbacks. // Struct is passed on stack on all ABIs. DART_EXPORT intptr_t TestReturnStructArgumentInt32x8Struct1ByteInt( // NOLINTNEXTLINE(whitespace/parens) Struct1ByteInt (*f)(int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, Struct1ByteInt a8)) { int32_t a0; int32_t a1; int32_t a2; int32_t a3; int32_t a4; int32_t a5; int32_t a6; int32_t a7; Struct1ByteInt a8; a0 = -1; a1 = 2; a2 = -3; a3 = 4; a4 = -5; a5 = 6; a6 = -7; a7 = 8; a8.a0 = -9; std::cout << "Calling TestReturnStructArgumentInt32x8Struct1ByteInt(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7 << ", (" << static_cast(a8.a0) << "))" << ")\n"; Struct1ByteInt result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); std::cout << "result = " << "(" << static_cast(result.a0) << ")" << "\n"; CHECK_EQ(a8.a0, result.a0); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_EQ(0, result.a0); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_EQ(0, result.a0); return 0; } // Used for testing structs and unions by value. // Test that a struct passed in as argument can be returned. // Especially for ffi callbacks. // Struct is passed in float registers in most ABIs. DART_EXPORT intptr_t TestReturnStructArgumentStruct8BytesHomogeneousFloat( // NOLINTNEXTLINE(whitespace/parens) Struct8BytesHomogeneousFloat (*f)(Struct8BytesHomogeneousFloat a0)) { Struct8BytesHomogeneousFloat a0; a0.a0 = -1.0; a0.a1 = 2.0; std::cout << "Calling TestReturnStructArgumentStruct8BytesHomogeneousFloat(" << "((" << a0.a0 << ", " << a0.a1 << "))" << ")\n"; Struct8BytesHomogeneousFloat result = f(a0); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ")" << "\n"; CHECK_APPROX(a0.a0, result.a0); CHECK_APPROX(a0.a1, result.a1); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_APPROX(0.0, result.a0); CHECK_APPROX(0.0, result.a1); return 0; } // Used for testing structs and unions by value. // On arm64, both argument and return value are passed in by pointer. DART_EXPORT intptr_t TestReturnStructArgumentStruct20BytesHomogeneousInt32( // NOLINTNEXTLINE(whitespace/parens) Struct20BytesHomogeneousInt32 (*f)(Struct20BytesHomogeneousInt32 a0)) { Struct20BytesHomogeneousInt32 a0; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; a0.a3 = 4; a0.a4 = -5; std::cout << "Calling TestReturnStructArgumentStruct20BytesHomogeneousInt32(" << "((" << a0.a0 << ", " << a0.a1 << ", " << a0.a2 << ", " << a0.a3 << ", " << a0.a4 << "))" << ")\n"; Struct20BytesHomogeneousInt32 result = f(a0); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ")" << "\n"; CHECK_EQ(a0.a0, result.a0); CHECK_EQ(a0.a1, result.a1); CHECK_EQ(a0.a2, result.a2); CHECK_EQ(a0.a3, result.a3); CHECK_EQ(a0.a4, result.a4); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); return 0; } // Used for testing structs and unions by value. // On arm64, both argument and return value are passed in by pointer. // Ints exhaust registers, so that pointer is passed on stack. DART_EXPORT intptr_t TestReturnStructArgumentInt32x8Struct20BytesHomogeneou( // NOLINTNEXTLINE(whitespace/parens) Struct20BytesHomogeneousInt32 (*f)(int32_t a0, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, Struct20BytesHomogeneousInt32 a8)) { int32_t a0; int32_t a1; int32_t a2; int32_t a3; int32_t a4; int32_t a5; int32_t a6; int32_t a7; Struct20BytesHomogeneousInt32 a8; a0 = -1; a1 = 2; a2 = -3; a3 = 4; a4 = -5; a5 = 6; a6 = -7; a7 = 8; a8.a0 = -9; a8.a1 = 10; a8.a2 = -11; a8.a3 = 12; a8.a4 = -13; std::cout << "Calling TestReturnStructArgumentInt32x8Struct20BytesHomogeneou(" << "(" << a0 << ", " << a1 << ", " << a2 << ", " << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7 << ", (" << a8.a0 << ", " << a8.a1 << ", " << a8.a2 << ", " << a8.a3 << ", " << a8.a4 << "))" << ")\n"; Struct20BytesHomogeneousInt32 result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); std::cout << "result = " << "(" << result.a0 << ", " << result.a1 << ", " << result.a2 << ", " << result.a3 << ", " << result.a4 << ")" << "\n"; CHECK_EQ(a8.a0, result.a0); CHECK_EQ(a8.a1, result.a1); CHECK_EQ(a8.a2, result.a2); CHECK_EQ(a8.a3, result.a3); CHECK_EQ(a8.a4, result.a4); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); CHECK_EQ(0, result.a3); CHECK_EQ(0, result.a4); return 0; } // Used for testing structs and unions by value. // Test returning struct with inline array. DART_EXPORT intptr_t TestReturnStructArgumentStruct8BytesInlineArrayInt( // NOLINTNEXTLINE(whitespace/parens) Struct8BytesInlineArrayInt (*f)(Struct8BytesInlineArrayInt a0)) { Struct8BytesInlineArrayInt a0; a0.a0[0] = 1; a0.a0[1] = 2; a0.a0[2] = 3; a0.a0[3] = 4; a0.a0[4] = 5; a0.a0[5] = 6; a0.a0[6] = 7; a0.a0[7] = 8; std::cout << "Calling TestReturnStructArgumentStruct8BytesInlineArrayInt(" << "(([" << static_cast(a0.a0[0]) << ", " << static_cast(a0.a0[1]) << ", " << static_cast(a0.a0[2]) << ", " << static_cast(a0.a0[3]) << ", " << static_cast(a0.a0[4]) << ", " << static_cast(a0.a0[5]) << ", " << static_cast(a0.a0[6]) << ", " << static_cast(a0.a0[7]) << "]))" << ")\n"; Struct8BytesInlineArrayInt result = f(a0); std::cout << "result = " << "([" << static_cast(result.a0[0]) << ", " << static_cast(result.a0[1]) << ", " << static_cast(result.a0[2]) << ", " << static_cast(result.a0[3]) << ", " << static_cast(result.a0[4]) << ", " << static_cast(result.a0[5]) << ", " << static_cast(result.a0[6]) << ", " << static_cast(result.a0[7]) << "])" << "\n"; for (intptr_t i = 0; i < 8; i++) { CHECK_EQ(a0.a0[i], result.a0[i]); } // Pass argument that will make the Dart callback throw. a0.a0[0] = 42; result = f(a0); for (intptr_t i = 0; i < 8; i++) { CHECK_EQ(0, result.a0[i]); } // Pass argument that will make the Dart callback return null. a0.a0[0] = 84; result = f(a0); for (intptr_t i = 0; i < 8; i++) { CHECK_EQ(0, result.a0[i]); } return 0; } // Used for testing structs and unions by value. // Return value in FPU registers on arm hardfp and arm64. DART_EXPORT intptr_t TestReturnStructArgumentStructStruct16BytesHomogeneous( // NOLINTNEXTLINE(whitespace/parens) StructStruct16BytesHomogeneousFloat2 (*f)( StructStruct16BytesHomogeneousFloat2 a0)) { StructStruct16BytesHomogeneousFloat2 a0; a0.a0.a0 = -1.0; a0.a1[0].a0 = 2.0; a0.a1[1].a0 = -3.0; a0.a2 = 4.0; std::cout << "Calling TestReturnStructArgumentStructStruct16BytesHomogeneous(" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << "), (" << a0.a1[1].a0 << ")], " << a0.a2 << "))" << ")\n"; StructStruct16BytesHomogeneousFloat2 result = f(a0); std::cout << "result = " << "((" << result.a0.a0 << "), [(" << result.a1[0].a0 << "), (" << result.a1[1].a0 << ")], " << result.a2 << ")" << "\n"; CHECK_APPROX(a0.a0.a0, result.a0.a0); for (intptr_t i = 0; i < 2; i++) { CHECK_APPROX(a0.a1[i].a0, result.a1[i].a0); } CHECK_APPROX(a0.a2, result.a2); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0); CHECK_APPROX(0.0, result.a0.a0); for (intptr_t i = 0; i < 2; i++) { CHECK_APPROX(0.0, result.a1[i].a0); } CHECK_APPROX(0.0, result.a2); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0); CHECK_APPROX(0.0, result.a0.a0); for (intptr_t i = 0; i < 2; i++) { CHECK_APPROX(0.0, result.a1[i].a0); } CHECK_APPROX(0.0, result.a2); return 0; } // Used for testing structs and unions by value. // Return value in FPU registers on arm64. DART_EXPORT intptr_t TestReturnStructArgumentStructStruct32BytesHomogeneous( // NOLINTNEXTLINE(whitespace/parens) StructStruct32BytesHomogeneousDouble2 (*f)( StructStruct32BytesHomogeneousDouble2 a0)) { StructStruct32BytesHomogeneousDouble2 a0; a0.a0.a0 = -1.0; a0.a1[0].a0 = 2.0; a0.a1[1].a0 = -3.0; a0.a2 = 4.0; std::cout << "Calling TestReturnStructArgumentStructStruct32BytesHomogeneous(" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << "), (" << a0.a1[1].a0 << ")], " << a0.a2 << "))" << ")\n"; StructStruct32BytesHomogeneousDouble2 result = f(a0); std::cout << "result = " << "((" << result.a0.a0 << "), [(" << result.a1[0].a0 << "), (" << result.a1[1].a0 << ")], " << result.a2 << ")" << "\n"; CHECK_APPROX(a0.a0.a0, result.a0.a0); for (intptr_t i = 0; i < 2; i++) { CHECK_APPROX(a0.a1[i].a0, result.a1[i].a0); } CHECK_APPROX(a0.a2, result.a2); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0); CHECK_APPROX(0.0, result.a0.a0); for (intptr_t i = 0; i < 2; i++) { CHECK_APPROX(0.0, result.a1[i].a0); } CHECK_APPROX(0.0, result.a2); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0); CHECK_APPROX(0.0, result.a0.a0); for (intptr_t i = 0; i < 2; i++) { CHECK_APPROX(0.0, result.a1[i].a0); } CHECK_APPROX(0.0, result.a2); return 0; } // Used for testing structs and unions by value. // On x64 Linux, return value is split over FP and int registers. DART_EXPORT intptr_t TestReturnStructArgumentStructStruct16BytesMixed3( // NOLINTNEXTLINE(whitespace/parens) StructStruct16BytesMixed3 (*f)(StructStruct16BytesMixed3 a0)) { StructStruct16BytesMixed3 a0; a0.a0.a0 = -1.0; a0.a1[0].a0 = 2.0; a0.a1[0].a1 = -3; a0.a1[0].a2 = 4; a0.a2[0] = -5; a0.a2[1] = 6; std::cout << "Calling TestReturnStructArgumentStructStruct16BytesMixed3(" << "(((" << a0.a0.a0 << "), [(" << a0.a1[0].a0 << ", " << a0.a1[0].a1 << ", " << a0.a1[0].a2 << ")], [" << a0.a2[0] << ", " << a0.a2[1] << "]))" << ")\n"; StructStruct16BytesMixed3 result = f(a0); std::cout << "result = " << "((" << result.a0.a0 << "), [(" << result.a1[0].a0 << ", " << result.a1[0].a1 << ", " << result.a1[0].a2 << ")], [" << result.a2[0] << ", " << result.a2[1] << "])" << "\n"; CHECK_APPROX(a0.a0.a0, result.a0.a0); for (intptr_t i = 0; i < 1; i++) { CHECK_APPROX(a0.a1[i].a0, result.a1[i].a0); CHECK_EQ(a0.a1[i].a1, result.a1[i].a1); CHECK_EQ(a0.a1[i].a2, result.a1[i].a2); } for (intptr_t i = 0; i < 2; i++) { CHECK_EQ(a0.a2[i], result.a2[i]); } // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0); CHECK_APPROX(0.0, result.a0.a0); for (intptr_t i = 0; i < 1; i++) { CHECK_APPROX(0.0, result.a1[i].a0); CHECK_EQ(0, result.a1[i].a1); CHECK_EQ(0, result.a1[i].a2); } for (intptr_t i = 0; i < 2; i++) { CHECK_EQ(0, result.a2[i]); } // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0); CHECK_APPROX(0.0, result.a0.a0); for (intptr_t i = 0; i < 1; i++) { CHECK_APPROX(0.0, result.a1[i].a0); CHECK_EQ(0, result.a1[i].a1); CHECK_EQ(0, result.a1[i].a2); } for (intptr_t i = 0; i < 2; i++) { CHECK_EQ(0, result.a2[i]); } return 0; } // Used for testing structs and unions by value. // Test alignment and padding of 16 byte int within struct. DART_EXPORT intptr_t TestReturnStructAlignmentInt16( // NOLINTNEXTLINE(whitespace/parens) StructAlignmentInt16 (*f)(int8_t a0, int16_t a1, int8_t a2)) { int8_t a0; int16_t a1; int8_t a2; a0 = -1; a1 = 2; a2 = -3; std::cout << "Calling TestReturnStructAlignmentInt16(" << "(" << static_cast(a0) << ", " << a1 << ", " << static_cast(a2) << ")" << ")\n"; StructAlignmentInt16 result = f(a0, a1, a2); std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ", " << static_cast(result.a2) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of 32 byte int within struct. DART_EXPORT intptr_t TestReturnStructAlignmentInt32( // NOLINTNEXTLINE(whitespace/parens) StructAlignmentInt32 (*f)(int8_t a0, int32_t a1, int8_t a2)) { int8_t a0; int32_t a1; int8_t a2; a0 = -1; a1 = 2; a2 = -3; std::cout << "Calling TestReturnStructAlignmentInt32(" << "(" << static_cast(a0) << ", " << a1 << ", " << static_cast(a2) << ")" << ")\n"; StructAlignmentInt32 result = f(a0, a1, a2); std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ", " << static_cast(result.a2) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of 64 byte int within struct. DART_EXPORT intptr_t TestReturnStructAlignmentInt64( // NOLINTNEXTLINE(whitespace/parens) StructAlignmentInt64 (*f)(int8_t a0, int64_t a1, int8_t a2)) { int8_t a0; int64_t a1; int8_t a2; a0 = -1; a1 = 2; a2 = -3; std::cout << "Calling TestReturnStructAlignmentInt64(" << "(" << static_cast(a0) << ", " << a1 << ", " << static_cast(a2) << ")" << ")\n"; StructAlignmentInt64 result = f(a0, a1, a2); std::cout << "result = " << "(" << static_cast(result.a0) << ", " << result.a1 << ", " << static_cast(result.a2) << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1, result.a1); CHECK_EQ(a2, result.a2); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1); CHECK_EQ(0, result.a2); return 0; } // Used for testing structs and unions by value. // Simple nested struct. DART_EXPORT intptr_t TestReturnStruct8BytesNestedInt( // NOLINTNEXTLINE(whitespace/parens) Struct8BytesNestedInt (*f)(Struct4BytesHomogeneousInt16 a0, Struct4BytesHomogeneousInt16 a1)) { Struct4BytesHomogeneousInt16 a0; Struct4BytesHomogeneousInt16 a1; a0.a0 = -1; a0.a1 = 2; a1.a0 = -3; a1.a1 = 4; std::cout << "Calling TestReturnStruct8BytesNestedInt(" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << ", " << a1.a1 << "))" << ")\n"; Struct8BytesNestedInt result = f(a0, a1); std::cout << "result = " << "((" << result.a0.a0 << ", " << result.a0.a1 << "), (" << result.a1.a0 << ", " << result.a1.a1 << "))" << "\n"; CHECK_EQ(a0.a0, result.a0.a0); CHECK_EQ(a0.a1, result.a0.a1); CHECK_EQ(a1.a0, result.a1.a0); CHECK_EQ(a1.a1, result.a1.a1); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_EQ(0, result.a1.a0); CHECK_EQ(0, result.a1.a1); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_EQ(0, result.a1.a0); CHECK_EQ(0, result.a1.a1); return 0; } // Used for testing structs and unions by value. // Simple nested struct with floats. DART_EXPORT intptr_t TestReturnStruct8BytesNestedFloat( // NOLINTNEXTLINE(whitespace/parens) Struct8BytesNestedFloat (*f)(Struct4BytesFloat a0, Struct4BytesFloat a1)) { Struct4BytesFloat a0; Struct4BytesFloat a1; a0.a0 = -1.0; a1.a0 = 2.0; std::cout << "Calling TestReturnStruct8BytesNestedFloat(" << "((" << a0.a0 << "), (" << a1.a0 << "))" << ")\n"; Struct8BytesNestedFloat result = f(a0, a1); std::cout << "result = " << "((" << result.a0.a0 << "), (" << result.a1.a0 << "))" << "\n"; CHECK_APPROX(a0.a0, result.a0.a0); CHECK_APPROX(a1.a0, result.a1.a0); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1); CHECK_APPROX(0.0, result.a0.a0); CHECK_APPROX(0.0, result.a1.a0); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0, a1); CHECK_APPROX(0.0, result.a0.a0); CHECK_APPROX(0.0, result.a1.a0); return 0; } // Used for testing structs and unions by value. // The nesting is irregular, testing homogenous float rules on arm and arm64, // and the fpu register usage on x64. DART_EXPORT intptr_t TestReturnStruct8BytesNestedFloat2( // NOLINTNEXTLINE(whitespace/parens) Struct8BytesNestedFloat2 (*f)(Struct4BytesFloat a0, float a1)) { Struct4BytesFloat a0; float a1; a0.a0 = -1.0; a1 = 2.0; std::cout << "Calling TestReturnStruct8BytesNestedFloat2(" << "((" << a0.a0 << "), " << a1 << ")" << ")\n"; Struct8BytesNestedFloat2 result = f(a0, a1); std::cout << "result = " << "((" << result.a0.a0 << "), " << result.a1 << ")" << "\n"; CHECK_APPROX(a0.a0, result.a0.a0); CHECK_APPROX(a1, result.a1); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1); CHECK_APPROX(0.0, result.a0.a0); CHECK_APPROX(0.0, result.a1); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0, a1); CHECK_APPROX(0.0, result.a0.a0); CHECK_APPROX(0.0, result.a1); return 0; } // Used for testing structs and unions by value. // Simple nested struct with mixed members. DART_EXPORT intptr_t TestReturnStruct8BytesNestedMixed( // NOLINTNEXTLINE(whitespace/parens) Struct8BytesNestedMixed (*f)(Struct4BytesHomogeneousInt16 a0, Struct4BytesFloat a1)) { Struct4BytesHomogeneousInt16 a0; Struct4BytesFloat a1; a0.a0 = -1; a0.a1 = 2; a1.a0 = -3.0; std::cout << "Calling TestReturnStruct8BytesNestedMixed(" << "((" << a0.a0 << ", " << a0.a1 << "), (" << a1.a0 << "))" << ")\n"; Struct8BytesNestedMixed result = f(a0, a1); std::cout << "result = " << "((" << result.a0.a0 << ", " << result.a0.a1 << "), (" << result.a1.a0 << "))" << "\n"; CHECK_EQ(a0.a0, result.a0.a0); CHECK_EQ(a0.a1, result.a0.a1); CHECK_APPROX(a1.a0, result.a1.a0); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_APPROX(0.0, result.a1.a0); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_APPROX(0.0, result.a1.a0); return 0; } // Used for testing structs and unions by value. // Deeper nested struct to test recursive member access. DART_EXPORT intptr_t TestReturnStruct16BytesNestedInt( // NOLINTNEXTLINE(whitespace/parens) Struct16BytesNestedInt (*f)(Struct8BytesNestedInt a0, Struct8BytesNestedInt a1)) { Struct8BytesNestedInt a0; Struct8BytesNestedInt a1; a0.a0.a0 = -1; a0.a0.a1 = 2; a0.a1.a0 = -3; a0.a1.a1 = 4; a1.a0.a0 = -5; a1.a0.a1 = 6; a1.a1.a0 = -7; a1.a1.a1 = 8; std::cout << "Calling TestReturnStruct16BytesNestedInt(" << "(((" << a0.a0.a0 << ", " << a0.a0.a1 << "), (" << a0.a1.a0 << ", " << a0.a1.a1 << ")), ((" << a1.a0.a0 << ", " << a1.a0.a1 << "), (" << a1.a1.a0 << ", " << a1.a1.a1 << ")))" << ")\n"; Struct16BytesNestedInt result = f(a0, a1); std::cout << "result = " << "(((" << result.a0.a0.a0 << ", " << result.a0.a0.a1 << "), (" << result.a0.a1.a0 << ", " << result.a0.a1.a1 << ")), ((" << result.a1.a0.a0 << ", " << result.a1.a0.a1 << "), (" << result.a1.a1.a0 << ", " << result.a1.a1.a1 << ")))" << "\n"; CHECK_EQ(a0.a0.a0, result.a0.a0.a0); CHECK_EQ(a0.a0.a1, result.a0.a0.a1); CHECK_EQ(a0.a1.a0, result.a0.a1.a0); CHECK_EQ(a0.a1.a1, result.a0.a1.a1); CHECK_EQ(a1.a0.a0, result.a1.a0.a0); CHECK_EQ(a1.a0.a1, result.a1.a0.a1); CHECK_EQ(a1.a1.a0, result.a1.a1.a0); CHECK_EQ(a1.a1.a1, result.a1.a1.a1); // Pass argument that will make the Dart callback throw. a0.a0.a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0.a0.a0); CHECK_EQ(0, result.a0.a0.a1); CHECK_EQ(0, result.a0.a1.a0); CHECK_EQ(0, result.a0.a1.a1); CHECK_EQ(0, result.a1.a0.a0); CHECK_EQ(0, result.a1.a0.a1); CHECK_EQ(0, result.a1.a1.a0); CHECK_EQ(0, result.a1.a1.a1); // Pass argument that will make the Dart callback return null. a0.a0.a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0.a0.a0); CHECK_EQ(0, result.a0.a0.a1); CHECK_EQ(0, result.a0.a1.a0); CHECK_EQ(0, result.a0.a1.a1); CHECK_EQ(0, result.a1.a0.a0); CHECK_EQ(0, result.a1.a0.a1); CHECK_EQ(0, result.a1.a1.a0); CHECK_EQ(0, result.a1.a1.a1); return 0; } // Used for testing structs and unions by value. // Even deeper nested struct to test recursive member access. DART_EXPORT intptr_t TestReturnStruct32BytesNestedInt( // NOLINTNEXTLINE(whitespace/parens) Struct32BytesNestedInt (*f)(Struct16BytesNestedInt a0, Struct16BytesNestedInt a1)) { Struct16BytesNestedInt a0; Struct16BytesNestedInt a1; a0.a0.a0.a0 = -1; a0.a0.a0.a1 = 2; a0.a0.a1.a0 = -3; a0.a0.a1.a1 = 4; a0.a1.a0.a0 = -5; a0.a1.a0.a1 = 6; a0.a1.a1.a0 = -7; a0.a1.a1.a1 = 8; a1.a0.a0.a0 = -9; a1.a0.a0.a1 = 10; a1.a0.a1.a0 = -11; a1.a0.a1.a1 = 12; a1.a1.a0.a0 = -13; a1.a1.a0.a1 = 14; a1.a1.a1.a0 = -15; a1.a1.a1.a1 = 16; std::cout << "Calling TestReturnStruct32BytesNestedInt(" << "((((" << a0.a0.a0.a0 << ", " << a0.a0.a0.a1 << "), (" << a0.a0.a1.a0 << ", " << a0.a0.a1.a1 << ")), ((" << a0.a1.a0.a0 << ", " << a0.a1.a0.a1 << "), (" << a0.a1.a1.a0 << ", " << a0.a1.a1.a1 << "))), (((" << a1.a0.a0.a0 << ", " << a1.a0.a0.a1 << "), (" << a1.a0.a1.a0 << ", " << a1.a0.a1.a1 << ")), ((" << a1.a1.a0.a0 << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0 << ", " << a1.a1.a1.a1 << "))))" << ")\n"; Struct32BytesNestedInt result = f(a0, a1); std::cout << "result = " << "((((" << result.a0.a0.a0.a0 << ", " << result.a0.a0.a0.a1 << "), (" << result.a0.a0.a1.a0 << ", " << result.a0.a0.a1.a1 << ")), ((" << result.a0.a1.a0.a0 << ", " << result.a0.a1.a0.a1 << "), (" << result.a0.a1.a1.a0 << ", " << result.a0.a1.a1.a1 << "))), (((" << result.a1.a0.a0.a0 << ", " << result.a1.a0.a0.a1 << "), (" << result.a1.a0.a1.a0 << ", " << result.a1.a0.a1.a1 << ")), ((" << result.a1.a1.a0.a0 << ", " << result.a1.a1.a0.a1 << "), (" << result.a1.a1.a1.a0 << ", " << result.a1.a1.a1.a1 << "))))" << "\n"; CHECK_EQ(a0.a0.a0.a0, result.a0.a0.a0.a0); CHECK_EQ(a0.a0.a0.a1, result.a0.a0.a0.a1); CHECK_EQ(a0.a0.a1.a0, result.a0.a0.a1.a0); CHECK_EQ(a0.a0.a1.a1, result.a0.a0.a1.a1); CHECK_EQ(a0.a1.a0.a0, result.a0.a1.a0.a0); CHECK_EQ(a0.a1.a0.a1, result.a0.a1.a0.a1); CHECK_EQ(a0.a1.a1.a0, result.a0.a1.a1.a0); CHECK_EQ(a0.a1.a1.a1, result.a0.a1.a1.a1); CHECK_EQ(a1.a0.a0.a0, result.a1.a0.a0.a0); CHECK_EQ(a1.a0.a0.a1, result.a1.a0.a0.a1); CHECK_EQ(a1.a0.a1.a0, result.a1.a0.a1.a0); CHECK_EQ(a1.a0.a1.a1, result.a1.a0.a1.a1); CHECK_EQ(a1.a1.a0.a0, result.a1.a1.a0.a0); CHECK_EQ(a1.a1.a0.a1, result.a1.a1.a0.a1); CHECK_EQ(a1.a1.a1.a0, result.a1.a1.a1.a0); CHECK_EQ(a1.a1.a1.a1, result.a1.a1.a1.a1); // Pass argument that will make the Dart callback throw. a0.a0.a0.a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0.a0.a0.a0); CHECK_EQ(0, result.a0.a0.a0.a1); CHECK_EQ(0, result.a0.a0.a1.a0); CHECK_EQ(0, result.a0.a0.a1.a1); CHECK_EQ(0, result.a0.a1.a0.a0); CHECK_EQ(0, result.a0.a1.a0.a1); CHECK_EQ(0, result.a0.a1.a1.a0); CHECK_EQ(0, result.a0.a1.a1.a1); CHECK_EQ(0, result.a1.a0.a0.a0); CHECK_EQ(0, result.a1.a0.a0.a1); CHECK_EQ(0, result.a1.a0.a1.a0); CHECK_EQ(0, result.a1.a0.a1.a1); CHECK_EQ(0, result.a1.a1.a0.a0); CHECK_EQ(0, result.a1.a1.a0.a1); CHECK_EQ(0, result.a1.a1.a1.a0); CHECK_EQ(0, result.a1.a1.a1.a1); // Pass argument that will make the Dart callback return null. a0.a0.a0.a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0.a0.a0.a0); CHECK_EQ(0, result.a0.a0.a0.a1); CHECK_EQ(0, result.a0.a0.a1.a0); CHECK_EQ(0, result.a0.a0.a1.a1); CHECK_EQ(0, result.a0.a1.a0.a0); CHECK_EQ(0, result.a0.a1.a0.a1); CHECK_EQ(0, result.a0.a1.a1.a0); CHECK_EQ(0, result.a0.a1.a1.a1); CHECK_EQ(0, result.a1.a0.a0.a0); CHECK_EQ(0, result.a1.a0.a0.a1); CHECK_EQ(0, result.a1.a0.a1.a0); CHECK_EQ(0, result.a1.a0.a1.a1); CHECK_EQ(0, result.a1.a1.a0.a0); CHECK_EQ(0, result.a1.a1.a0.a1); CHECK_EQ(0, result.a1.a1.a1.a0); CHECK_EQ(0, result.a1.a1.a1.a1); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 16 byte int. DART_EXPORT intptr_t TestReturnStructNestedIntStructAlignmentInt16( // NOLINTNEXTLINE(whitespace/parens) StructNestedIntStructAlignmentInt16 (*f)(StructAlignmentInt16 a0, StructAlignmentInt16 a1)) { StructAlignmentInt16 a0; StructAlignmentInt16 a1; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; a1.a0 = 4; a1.a1 = -5; a1.a2 = 6; std::cout << "Calling TestReturnStructNestedIntStructAlignmentInt16(" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "), (" << static_cast(a1.a0) << ", " << a1.a1 << ", " << static_cast(a1.a2) << "))" << ")\n"; StructNestedIntStructAlignmentInt16 result = f(a0, a1); std::cout << "result = " << "((" << static_cast(result.a0.a0) << ", " << result.a0.a1 << ", " << static_cast(result.a0.a2) << "), (" << static_cast(result.a1.a0) << ", " << result.a1.a1 << ", " << static_cast(result.a1.a2) << "))" << "\n"; CHECK_EQ(a0.a0, result.a0.a0); CHECK_EQ(a0.a1, result.a0.a1); CHECK_EQ(a0.a2, result.a0.a2); CHECK_EQ(a1.a0, result.a1.a0); CHECK_EQ(a1.a1, result.a1.a1); CHECK_EQ(a1.a2, result.a1.a2); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_EQ(0, result.a0.a2); CHECK_EQ(0, result.a1.a0); CHECK_EQ(0, result.a1.a1); CHECK_EQ(0, result.a1.a2); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_EQ(0, result.a0.a2); CHECK_EQ(0, result.a1.a0); CHECK_EQ(0, result.a1.a1); CHECK_EQ(0, result.a1.a2); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 32 byte int. DART_EXPORT intptr_t TestReturnStructNestedIntStructAlignmentInt32( // NOLINTNEXTLINE(whitespace/parens) StructNestedIntStructAlignmentInt32 (*f)(StructAlignmentInt32 a0, StructAlignmentInt32 a1)) { StructAlignmentInt32 a0; StructAlignmentInt32 a1; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; a1.a0 = 4; a1.a1 = -5; a1.a2 = 6; std::cout << "Calling TestReturnStructNestedIntStructAlignmentInt32(" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "), (" << static_cast(a1.a0) << ", " << a1.a1 << ", " << static_cast(a1.a2) << "))" << ")\n"; StructNestedIntStructAlignmentInt32 result = f(a0, a1); std::cout << "result = " << "((" << static_cast(result.a0.a0) << ", " << result.a0.a1 << ", " << static_cast(result.a0.a2) << "), (" << static_cast(result.a1.a0) << ", " << result.a1.a1 << ", " << static_cast(result.a1.a2) << "))" << "\n"; CHECK_EQ(a0.a0, result.a0.a0); CHECK_EQ(a0.a1, result.a0.a1); CHECK_EQ(a0.a2, result.a0.a2); CHECK_EQ(a1.a0, result.a1.a0); CHECK_EQ(a1.a1, result.a1.a1); CHECK_EQ(a1.a2, result.a1.a2); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_EQ(0, result.a0.a2); CHECK_EQ(0, result.a1.a0); CHECK_EQ(0, result.a1.a1); CHECK_EQ(0, result.a1.a2); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_EQ(0, result.a0.a2); CHECK_EQ(0, result.a1.a0); CHECK_EQ(0, result.a1.a1); CHECK_EQ(0, result.a1.a2); return 0; } // Used for testing structs and unions by value. // Test alignment and padding of nested struct with 64 byte int. DART_EXPORT intptr_t TestReturnStructNestedIntStructAlignmentInt64( // NOLINTNEXTLINE(whitespace/parens) StructNestedIntStructAlignmentInt64 (*f)(StructAlignmentInt64 a0, StructAlignmentInt64 a1)) { StructAlignmentInt64 a0; StructAlignmentInt64 a1; a0.a0 = -1; a0.a1 = 2; a0.a2 = -3; a1.a0 = 4; a1.a1 = -5; a1.a2 = 6; std::cout << "Calling TestReturnStructNestedIntStructAlignmentInt64(" << "((" << static_cast(a0.a0) << ", " << a0.a1 << ", " << static_cast(a0.a2) << "), (" << static_cast(a1.a0) << ", " << a1.a1 << ", " << static_cast(a1.a2) << "))" << ")\n"; StructNestedIntStructAlignmentInt64 result = f(a0, a1); std::cout << "result = " << "((" << static_cast(result.a0.a0) << ", " << result.a0.a1 << ", " << static_cast(result.a0.a2) << "), (" << static_cast(result.a1.a0) << ", " << result.a1.a1 << ", " << static_cast(result.a1.a2) << "))" << "\n"; CHECK_EQ(a0.a0, result.a0.a0); CHECK_EQ(a0.a1, result.a0.a1); CHECK_EQ(a0.a2, result.a0.a2); CHECK_EQ(a1.a0, result.a1.a0); CHECK_EQ(a1.a1, result.a1.a1); CHECK_EQ(a1.a2, result.a1.a2); // Pass argument that will make the Dart callback throw. a0.a0 = 42; result = f(a0, a1); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_EQ(0, result.a0.a2); CHECK_EQ(0, result.a1.a0); CHECK_EQ(0, result.a1.a1); CHECK_EQ(0, result.a1.a2); // Pass argument that will make the Dart callback return null. a0.a0 = 84; result = f(a0, a1); CHECK_EQ(0, result.a0.a0); CHECK_EQ(0, result.a0.a1); CHECK_EQ(0, result.a0.a2); CHECK_EQ(0, result.a1.a0); CHECK_EQ(0, result.a1.a1); CHECK_EQ(0, result.a1.a2); return 0; } // Used for testing structs and unions by value. // Return big irregular struct as smoke test. DART_EXPORT intptr_t TestReturnStructNestedIrregularEvenBigger( // NOLINTNEXTLINE(whitespace/parens) StructNestedIrregularEvenBigger (*f)(uint64_t a0, StructNestedIrregularBigger a1, StructNestedIrregularBigger a2, double a3)) { uint64_t a0; StructNestedIrregularBigger a1; StructNestedIrregularBigger a2; double a3; a0 = 1; a1.a0.a0 = 2; a1.a0.a1.a0.a0 = -3; a1.a0.a1.a0.a1 = 4; a1.a0.a1.a1.a0 = -5.0; a1.a0.a2 = 6; a1.a0.a3.a0.a0 = -7.0; a1.a0.a3.a1 = 8.0; a1.a0.a4 = 9; a1.a0.a5.a0.a0 = 10.0; a1.a0.a5.a1.a0 = -11.0; a1.a0.a6 = 12; a1.a1.a0.a0 = -13; a1.a1.a0.a1 = 14; a1.a1.a1.a0 = -15.0; a1.a2 = 16.0; a1.a3 = -17.0; a2.a0.a0 = 18; a2.a0.a1.a0.a0 = -19; a2.a0.a1.a0.a1 = 20; a2.a0.a1.a1.a0 = -21.0; a2.a0.a2 = 22; a2.a0.a3.a0.a0 = -23.0; a2.a0.a3.a1 = 24.0; a2.a0.a4 = 25; a2.a0.a5.a0.a0 = 26.0; a2.a0.a5.a1.a0 = -27.0; a2.a0.a6 = 28; a2.a1.a0.a0 = -29; a2.a1.a0.a1 = 30; a2.a1.a1.a0 = -31.0; a2.a2 = 32.0; a2.a3 = -33.0; a3 = 34.0; std::cout << "Calling TestReturnStructNestedIrregularEvenBigger(" << "(" << a0 << ", ((" << a1.a0.a0 << ", ((" << a1.a0.a1.a0.a0 << ", " << a1.a0.a1.a0.a1 << "), (" << a1.a0.a1.a1.a0 << ")), " << a1.a0.a2 << ", ((" << a1.a0.a3.a0.a0 << "), " << a1.a0.a3.a1 << "), " << a1.a0.a4 << ", ((" << a1.a0.a5.a0.a0 << "), (" << a1.a0.a5.a1.a0 << ")), " << a1.a0.a6 << "), ((" << a1.a1.a0.a0 << ", " << a1.a1.a0.a1 << "), (" << a1.a1.a1.a0 << ")), " << a1.a2 << ", " << a1.a3 << "), ((" << a2.a0.a0 << ", ((" << a2.a0.a1.a0.a0 << ", " << a2.a0.a1.a0.a1 << "), (" << a2.a0.a1.a1.a0 << ")), " << a2.a0.a2 << ", ((" << a2.a0.a3.a0.a0 << "), " << a2.a0.a3.a1 << "), " << a2.a0.a4 << ", ((" << a2.a0.a5.a0.a0 << "), (" << a2.a0.a5.a1.a0 << ")), " << a2.a0.a6 << "), ((" << a2.a1.a0.a0 << ", " << a2.a1.a0.a1 << "), (" << a2.a1.a1.a0 << ")), " << a2.a2 << ", " << a2.a3 << "), " << a3 << ")" << ")\n"; StructNestedIrregularEvenBigger result = f(a0, a1, a2, a3); std::cout << "result = " << "(" << result.a0 << ", ((" << result.a1.a0.a0 << ", ((" << result.a1.a0.a1.a0.a0 << ", " << result.a1.a0.a1.a0.a1 << "), (" << result.a1.a0.a1.a1.a0 << ")), " << result.a1.a0.a2 << ", ((" << result.a1.a0.a3.a0.a0 << "), " << result.a1.a0.a3.a1 << "), " << result.a1.a0.a4 << ", ((" << result.a1.a0.a5.a0.a0 << "), (" << result.a1.a0.a5.a1.a0 << ")), " << result.a1.a0.a6 << "), ((" << result.a1.a1.a0.a0 << ", " << result.a1.a1.a0.a1 << "), (" << result.a1.a1.a1.a0 << ")), " << result.a1.a2 << ", " << result.a1.a3 << "), ((" << result.a2.a0.a0 << ", ((" << result.a2.a0.a1.a0.a0 << ", " << result.a2.a0.a1.a0.a1 << "), (" << result.a2.a0.a1.a1.a0 << ")), " << result.a2.a0.a2 << ", ((" << result.a2.a0.a3.a0.a0 << "), " << result.a2.a0.a3.a1 << "), " << result.a2.a0.a4 << ", ((" << result.a2.a0.a5.a0.a0 << "), (" << result.a2.a0.a5.a1.a0 << ")), " << result.a2.a0.a6 << "), ((" << result.a2.a1.a0.a0 << ", " << result.a2.a1.a0.a1 << "), (" << result.a2.a1.a1.a0 << ")), " << result.a2.a2 << ", " << result.a2.a3 << "), " << result.a3 << ")" << "\n"; CHECK_EQ(a0, result.a0); CHECK_EQ(a1.a0.a0, result.a1.a0.a0); CHECK_EQ(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0); CHECK_EQ(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1); CHECK_APPROX(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0); CHECK_EQ(a1.a0.a2, result.a1.a0.a2); CHECK_APPROX(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0); CHECK_APPROX(a1.a0.a3.a1, result.a1.a0.a3.a1); CHECK_EQ(a1.a0.a4, result.a1.a0.a4); CHECK_APPROX(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0); CHECK_APPROX(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0); CHECK_EQ(a1.a0.a6, result.a1.a0.a6); CHECK_EQ(a1.a1.a0.a0, result.a1.a1.a0.a0); CHECK_EQ(a1.a1.a0.a1, result.a1.a1.a0.a1); CHECK_APPROX(a1.a1.a1.a0, result.a1.a1.a1.a0); CHECK_APPROX(a1.a2, result.a1.a2); CHECK_APPROX(a1.a3, result.a1.a3); CHECK_EQ(a2.a0.a0, result.a2.a0.a0); CHECK_EQ(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0); CHECK_EQ(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1); CHECK_APPROX(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0); CHECK_EQ(a2.a0.a2, result.a2.a0.a2); CHECK_APPROX(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0); CHECK_APPROX(a2.a0.a3.a1, result.a2.a0.a3.a1); CHECK_EQ(a2.a0.a4, result.a2.a0.a4); CHECK_APPROX(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0); CHECK_APPROX(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0); CHECK_EQ(a2.a0.a6, result.a2.a0.a6); CHECK_EQ(a2.a1.a0.a0, result.a2.a1.a0.a0); CHECK_EQ(a2.a1.a0.a1, result.a2.a1.a0.a1); CHECK_APPROX(a2.a1.a1.a0, result.a2.a1.a1.a0); CHECK_APPROX(a2.a2, result.a2.a2); CHECK_APPROX(a2.a3, result.a2.a3); CHECK_APPROX(a3, result.a3); // Pass argument that will make the Dart callback throw. a0 = 42; result = f(a0, a1, a2, a3); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1.a0.a0); CHECK_EQ(0, result.a1.a0.a1.a0.a0); CHECK_EQ(0, result.a1.a0.a1.a0.a1); CHECK_APPROX(0.0, result.a1.a0.a1.a1.a0); CHECK_EQ(0, result.a1.a0.a2); CHECK_APPROX(0.0, result.a1.a0.a3.a0.a0); CHECK_APPROX(0.0, result.a1.a0.a3.a1); CHECK_EQ(0, result.a1.a0.a4); CHECK_APPROX(0.0, result.a1.a0.a5.a0.a0); CHECK_APPROX(0.0, result.a1.a0.a5.a1.a0); CHECK_EQ(0, result.a1.a0.a6); CHECK_EQ(0, result.a1.a1.a0.a0); CHECK_EQ(0, result.a1.a1.a0.a1); CHECK_APPROX(0.0, result.a1.a1.a1.a0); CHECK_APPROX(0.0, result.a1.a2); CHECK_APPROX(0.0, result.a1.a3); CHECK_EQ(0, result.a2.a0.a0); CHECK_EQ(0, result.a2.a0.a1.a0.a0); CHECK_EQ(0, result.a2.a0.a1.a0.a1); CHECK_APPROX(0.0, result.a2.a0.a1.a1.a0); CHECK_EQ(0, result.a2.a0.a2); CHECK_APPROX(0.0, result.a2.a0.a3.a0.a0); CHECK_APPROX(0.0, result.a2.a0.a3.a1); CHECK_EQ(0, result.a2.a0.a4); CHECK_APPROX(0.0, result.a2.a0.a5.a0.a0); CHECK_APPROX(0.0, result.a2.a0.a5.a1.a0); CHECK_EQ(0, result.a2.a0.a6); CHECK_EQ(0, result.a2.a1.a0.a0); CHECK_EQ(0, result.a2.a1.a0.a1); CHECK_APPROX(0.0, result.a2.a1.a1.a0); CHECK_APPROX(0.0, result.a2.a2); CHECK_APPROX(0.0, result.a2.a3); CHECK_APPROX(0.0, result.a3); // Pass argument that will make the Dart callback return null. a0 = 84; result = f(a0, a1, a2, a3); CHECK_EQ(0, result.a0); CHECK_EQ(0, result.a1.a0.a0); CHECK_EQ(0, result.a1.a0.a1.a0.a0); CHECK_EQ(0, result.a1.a0.a1.a0.a1); CHECK_APPROX(0.0, result.a1.a0.a1.a1.a0); CHECK_EQ(0, result.a1.a0.a2); CHECK_APPROX(0.0, result.a1.a0.a3.a0.a0); CHECK_APPROX(0.0, result.a1.a0.a3.a1); CHECK_EQ(0, result.a1.a0.a4); CHECK_APPROX(0.0, result.a1.a0.a5.a0.a0); CHECK_APPROX(0.0, result.a1.a0.a5.a1.a0); CHECK_EQ(0, result.a1.a0.a6); CHECK_EQ(0, result.a1.a1.a0.a0); CHECK_EQ(0, result.a1.a1.a0.a1); CHECK_APPROX(0.0, result.a1.a1.a1.a0); CHECK_APPROX(0.0, result.a1.a2); CHECK_APPROX(0.0, result.a1.a3); CHECK_EQ(0, result.a2.a0.a0); CHECK_EQ(0, result.a2.a0.a1.a0.a0); CHECK_EQ(0, result.a2.a0.a1.a0.a1); CHECK_APPROX(0.0, result.a2.a0.a1.a1.a0); CHECK_EQ(0, result.a2.a0.a2); CHECK_APPROX(0.0, result.a2.a0.a3.a0.a0); CHECK_APPROX(0.0, result.a2.a0.a3.a1); CHECK_EQ(0, result.a2.a0.a4); CHECK_APPROX(0.0, result.a2.a0.a5.a0.a0); CHECK_APPROX(0.0, result.a2.a0.a5.a1.a0); CHECK_EQ(0, result.a2.a0.a6); CHECK_EQ(0, result.a2.a1.a0.a0); CHECK_EQ(0, result.a2.a1.a0.a1); CHECK_APPROX(0.0, result.a2.a1.a1.a0); CHECK_APPROX(0.0, result.a2.a2); CHECK_APPROX(0.0, result.a2.a3); CHECK_APPROX(0.0, result.a3); return 0; } } // namespace dart