From 882e3711ff976fdc04ae9150fefe1e4db95c295c Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Thu, 20 Oct 2022 22:08:53 +0000 Subject: [PATCH] [ffi/tests] Split large auto-generated tests into multiple tests This change tries to avoid timeouts on debug/ia32 bots by replacing each auto-generated tests/ffi{,_2}/function_structs_by_value_generated{,_leaf}_test.dart with 3 separate tests. Also, --optimization-counter-threshold is increased. Fixes https://github.com/dart-lang/sdk/issues/48627 Issue: https://github.com/dart-lang/sdk/issues/45007 Change-Id: I8a9c72927d05a3da3da35a21e9ffba0f3bda2112 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/265021 Reviewed-by: Daco Harkes Commit-Queue: Alexander Markov --- tests/ffi/ffi.status | 7 +- ...ts_by_value_generated_args_leaf_test.dart} | 2442 +---------------- ...structs_by_value_generated_args_test.dart} | 2408 +--------------- ..._by_value_generated_ret_arg_leaf_test.dart | 853 ++++++ ...ructs_by_value_generated_ret_arg_test.dart | 831 ++++++ ...ucts_by_value_generated_ret_leaf_test.dart | 1641 +++++++++++ ...n_structs_by_value_generated_ret_test.dart | 1629 +++++++++++ .../structs_by_value_tests_generator.dart | 22 +- tests/ffi_2/ffi_2.status | 7 +- ...ts_by_value_generated_args_leaf_test.dart} | 2442 +---------------- ...structs_by_value_generated_args_test.dart} | 2408 +--------------- ..._by_value_generated_ret_arg_leaf_test.dart | 855 ++++++ ...ructs_by_value_generated_ret_arg_test.dart | 833 ++++++ ...ucts_by_value_generated_ret_leaf_test.dart | 1643 +++++++++++ ...n_structs_by_value_generated_ret_test.dart | 1631 +++++++++++ 15 files changed, 9950 insertions(+), 9702 deletions(-) rename tests/ffi/{function_structs_by_value_generated_leaf_test.dart => function_structs_by_value_generated_args_leaf_test.dart} (71%) rename tests/ffi/{function_structs_by_value_generated_test.dart => function_structs_by_value_generated_args_test.dart} (71%) create mode 100644 tests/ffi/function_structs_by_value_generated_ret_arg_leaf_test.dart create mode 100644 tests/ffi/function_structs_by_value_generated_ret_arg_test.dart create mode 100644 tests/ffi/function_structs_by_value_generated_ret_leaf_test.dart create mode 100644 tests/ffi/function_structs_by_value_generated_ret_test.dart rename tests/ffi_2/{function_structs_by_value_generated_leaf_test.dart => function_structs_by_value_generated_args_leaf_test.dart} (71%) rename tests/ffi_2/{function_structs_by_value_generated_test.dart => function_structs_by_value_generated_args_test.dart} (71%) create mode 100644 tests/ffi_2/function_structs_by_value_generated_ret_arg_leaf_test.dart create mode 100644 tests/ffi_2/function_structs_by_value_generated_ret_arg_test.dart create mode 100644 tests/ffi_2/function_structs_by_value_generated_ret_leaf_test.dart create mode 100644 tests/ffi_2/function_structs_by_value_generated_ret_test.dart diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status index 413921a3674..2aeb1a0c7dc 100644 --- a/tests/ffi/ffi.status +++ b/tests/ffi/ffi.status @@ -3,7 +3,12 @@ # BSD-style license that can be found in the LICENSE file. function_callbacks_structs_by_value_test: Pass, Slow # https://dartbug.com/47304 https://dartbug.com/45007 -function_structs_by_value_generated_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_args_leaf_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_args_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_ret_arg_leaf_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_ret_arg_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_ret_leaf_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_ret_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 [ $compiler == app_jitk ] vmspecific_leaf_call_test: Skip # https://dartbug.com/46125: Snapshot fails to generate. diff --git a/tests/ffi/function_structs_by_value_generated_leaf_test.dart b/tests/ffi/function_structs_by_value_generated_args_leaf_test.dart similarity index 71% rename from tests/ffi/function_structs_by_value_generated_leaf_test.dart rename to tests/ffi/function_structs_by_value_generated_args_leaf_test.dart index a0334a0b7a5..157b8eda96d 100644 --- a/tests/ffi/function_structs_by_value_generated_leaf_test.dart +++ b/tests/ffi/function_structs_by_value_generated_args_leaf_test.dart @@ -7,7 +7,7 @@ // // SharedObjects=ffi_test_functions // VMOptions= -// VMOptions=--deterministic --optimization-counter-threshold=20 +// VMOptions=--deterministic --optimization-counter-threshold=90 // VMOptions=--use-slow-path // VMOptions=--use-slow-path --stacktrace-every=100 @@ -23,7 +23,7 @@ import 'function_structs_by_value_generated_compounds.dart'; final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); void main() { - for (int i = 0; i < 25; ++i) { + for (int i = 0; i < 100; ++i) { testPassStruct1ByteIntx10Leaf(); testPassStruct3BytesHomogeneousUint8x10Leaf(); testPassStruct3BytesInt2ByteAlignedx10Leaf(); @@ -90,57 +90,6 @@ void main() { testPassUint8Boolx9Struct10BytesInlineArrayBoolBoolLeaf(); testPassUint8Struct1ByteBoolLeaf(); testPassWCharStructInlineArrayIntUintPtrx2LongUnsignedLeaf(); - testReturnStruct1ByteIntLeaf(); - testReturnStruct3BytesHomogeneousUint8Leaf(); - testReturnStruct3BytesInt2ByteAlignedLeaf(); - testReturnStruct4BytesHomogeneousInt16Leaf(); - testReturnStruct7BytesHomogeneousUint8Leaf(); - testReturnStruct7BytesInt4ByteAlignedLeaf(); - testReturnStruct8BytesIntLeaf(); - testReturnStruct8BytesHomogeneousFloatLeaf(); - testReturnStruct8BytesMixedLeaf(); - testReturnStruct9BytesHomogeneousUint8Leaf(); - testReturnStruct9BytesInt4Or8ByteAlignedLeaf(); - testReturnStruct12BytesHomogeneousFloatLeaf(); - testReturnStruct16BytesHomogeneousFloatLeaf(); - testReturnStruct16BytesMixedLeaf(); - testReturnStruct16BytesMixed2Leaf(); - testReturnStruct17BytesIntLeaf(); - testReturnStruct19BytesHomogeneousUint8Leaf(); - testReturnStruct20BytesHomogeneousInt32Leaf(); - testReturnStruct20BytesHomogeneousFloatLeaf(); - testReturnStruct32BytesHomogeneousDoubleLeaf(); - testReturnStruct40BytesHomogeneousDoubleLeaf(); - testReturnStruct1024BytesHomogeneousUint64Leaf(); - testReturnStruct3BytesPackedIntLeaf(); - testReturnStruct8BytesPackedIntLeaf(); - testReturnStruct9BytesPackedMixedLeaf(); - testReturnUnion4BytesMixedLeaf(); - testReturnUnion8BytesNestedFloatLeaf(); - testReturnUnion9BytesNestedIntLeaf(); - testReturnUnion16BytesNestedFloatLeaf(); - testReturnStructArgumentStruct1ByteIntLeaf(); - testReturnStructArgumentInt32x8Struct1ByteIntLeaf(); - testReturnStructArgumentStruct8BytesHomogeneousFloatLeaf(); - testReturnStructArgumentStruct20BytesHomogeneousInt32Leaf(); - testReturnStructArgumentInt32x8Struct20BytesHomogeneouLeaf(); - testReturnStructArgumentStruct8BytesInlineArrayIntLeaf(); - testReturnStructArgumentStructStruct16BytesHomogeneousLeaf(); - testReturnStructArgumentStructStruct32BytesHomogeneousLeaf(); - testReturnStructArgumentStructStruct16BytesMixed3Leaf(); - testReturnStructAlignmentInt16Leaf(); - testReturnStructAlignmentInt32Leaf(); - testReturnStructAlignmentInt64Leaf(); - testReturnStruct8BytesNestedIntLeaf(); - testReturnStruct8BytesNestedFloatLeaf(); - testReturnStruct8BytesNestedFloat2Leaf(); - testReturnStruct8BytesNestedMixedLeaf(); - testReturnStruct16BytesNestedIntLeaf(); - testReturnStruct32BytesNestedIntLeaf(); - testReturnStructNestedIntStructAlignmentInt16Leaf(); - testReturnStructNestedIntStructAlignmentInt32Leaf(); - testReturnStructNestedIntStructAlignmentInt64Leaf(); - testReturnStructNestedIrregularEvenBiggerLeaf(); } } @@ -5505,2390 +5454,3 @@ void testPassWCharStructInlineArrayIntUintPtrx2LongUnsignedLeaf() { calloc.free(a1Pointer); } - -final returnStruct1ByteIntLeaf = ffiTestFunctions.lookupFunction< - Struct1ByteInt Function(Int8), - Struct1ByteInt Function(int)>("ReturnStruct1ByteInt", isLeaf: true); - -/// Smallest struct with data. -void testReturnStruct1ByteIntLeaf() { - int a0; - - a0 = -1; - - final result = returnStruct1ByteIntLeaf(a0); - - print("result = $result"); - - Expect.equals(a0, result.a0); -} - -final returnStruct3BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< - Struct3BytesHomogeneousUint8 Function(Uint8, Uint8, Uint8), - Struct3BytesHomogeneousUint8 Function( - int, int, int)>("ReturnStruct3BytesHomogeneousUint8", isLeaf: true); - -/// Smaller than word size return value on all architectures. -void testReturnStruct3BytesHomogeneousUint8Leaf() { - int a0; - int a1; - int a2; - - a0 = 1; - a1 = 2; - a2 = 3; - - final result = returnStruct3BytesHomogeneousUint8Leaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct3BytesInt2ByteAlignedLeaf = ffiTestFunctions.lookupFunction< - Struct3BytesInt2ByteAligned Function(Int16, Int8), - Struct3BytesInt2ByteAligned Function( - int, int)>("ReturnStruct3BytesInt2ByteAligned", isLeaf: true); - -/// Smaller than word size return value on all architectures. -/// With alignment rules taken into account size is 4 bytes. -void testReturnStruct3BytesInt2ByteAlignedLeaf() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct3BytesInt2ByteAlignedLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct4BytesHomogeneousInt16Leaf = ffiTestFunctions.lookupFunction< - Struct4BytesHomogeneousInt16 Function(Int16, Int16), - Struct4BytesHomogeneousInt16 Function( - int, int)>("ReturnStruct4BytesHomogeneousInt16", isLeaf: true); - -/// Word size return value on 32 bit architectures.. -void testReturnStruct4BytesHomogeneousInt16Leaf() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct4BytesHomogeneousInt16Leaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct7BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< - Struct7BytesHomogeneousUint8 Function( - Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), - Struct7BytesHomogeneousUint8 Function(int, int, int, int, int, int, - int)>("ReturnStruct7BytesHomogeneousUint8", isLeaf: true); - -/// Non-wordsize return value. -void testReturnStruct7BytesHomogeneousUint8Leaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - a5 = 6; - a6 = 7; - - final result = - returnStruct7BytesHomogeneousUint8Leaf(a0, a1, a2, a3, a4, a5, a6); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); -} - -final returnStruct7BytesInt4ByteAlignedLeaf = ffiTestFunctions.lookupFunction< - Struct7BytesInt4ByteAligned Function(Int32, Int16, Int8), - Struct7BytesInt4ByteAligned Function( - int, int, int)>("ReturnStruct7BytesInt4ByteAligned", isLeaf: true); - -/// Non-wordsize return value. -/// With alignment rules taken into account size is 8 bytes. -void testReturnStruct7BytesInt4ByteAlignedLeaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct7BytesInt4ByteAlignedLeaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesIntLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesInt Function(Int16, Int16, Int32), - Struct8BytesInt Function( - int, int, int)>("ReturnStruct8BytesInt", isLeaf: true); - -/// Return value in integer registers on many architectures. -void testReturnStruct8BytesIntLeaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct8BytesIntLeaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesHomogeneousFloat Function(Float, Float), - Struct8BytesHomogeneousFloat Function( - double, double)>("ReturnStruct8BytesHomogeneousFloat", isLeaf: true); - -/// Return value in FP registers on many architectures. -void testReturnStruct8BytesHomogeneousFloatLeaf() { - double a0; - double a1; - - a0 = -1.0; - a1 = 2.0; - - final result = returnStruct8BytesHomogeneousFloatLeaf(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); -} - -final returnStruct8BytesMixedLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesMixed Function(Float, Int16, Int16), - Struct8BytesMixed Function( - double, int, int)>("ReturnStruct8BytesMixed", isLeaf: true); - -/// Return value split over FP and integer register in x64. -void testReturnStruct8BytesMixedLeaf() { - double a0; - int a1; - int a2; - - a0 = -1.0; - a1 = 2; - a2 = -3; - - final result = returnStruct8BytesMixedLeaf(a0, a1, a2); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct9BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< - Struct9BytesHomogeneousUint8 Function( - Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), - Struct9BytesHomogeneousUint8 Function(int, int, int, int, int, int, int, - int, int)>("ReturnStruct9BytesHomogeneousUint8", isLeaf: true); - -/// 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. -void testReturnStruct9BytesHomogeneousUint8Leaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - a5 = 6; - a6 = 7; - a7 = 8; - a8 = 9; - - final result = returnStruct9BytesHomogeneousUint8Leaf( - a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); -} - -final returnStruct9BytesInt4Or8ByteAlignedLeaf = - ffiTestFunctions.lookupFunction< - Struct9BytesInt4Or8ByteAligned Function(Int64, Int8), - Struct9BytesInt4Or8ByteAligned Function( - int, int)>("ReturnStruct9BytesInt4Or8ByteAligned", isLeaf: true); - -/// Return value in two integer registers on x64. -/// With alignment rules taken into account size is 12 or 16 bytes. -void testReturnStruct9BytesInt4Or8ByteAlignedLeaf() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct9BytesInt4Or8ByteAlignedLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct12BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< - Struct12BytesHomogeneousFloat Function(Float, Float, Float), - Struct12BytesHomogeneousFloat Function(double, double, - double)>("ReturnStruct12BytesHomogeneousFloat", isLeaf: true); - -/// Return value in FPU registers, but does not use all registers on arm hardfp -/// and arm64. -void testReturnStruct12BytesHomogeneousFloatLeaf() { - double a0; - double a1; - double a2; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - - final result = returnStruct12BytesHomogeneousFloatLeaf(a0, a1, a2); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); -} - -final returnStruct16BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< - Struct16BytesHomogeneousFloat Function(Float, Float, Float, Float), - Struct16BytesHomogeneousFloat Function(double, double, double, - double)>("ReturnStruct16BytesHomogeneousFloat", isLeaf: true); - -/// Return value in FPU registers on arm hardfp and arm64. -void testReturnStruct16BytesHomogeneousFloatLeaf() { - double a0; - double a1; - double a2; - double a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4.0; - - final result = returnStruct16BytesHomogeneousFloatLeaf(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); -} - -final returnStruct16BytesMixedLeaf = ffiTestFunctions.lookupFunction< - Struct16BytesMixed Function(Double, Int64), - Struct16BytesMixed Function( - double, int)>("ReturnStruct16BytesMixed", isLeaf: true); - -/// Return value split over FP and integer register in x64. -void testReturnStruct16BytesMixedLeaf() { - double a0; - int a1; - - a0 = -1.0; - a1 = 2; - - final result = returnStruct16BytesMixedLeaf(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct16BytesMixed2Leaf = ffiTestFunctions.lookupFunction< - Struct16BytesMixed2 Function(Float, Float, Float, Int32), - Struct16BytesMixed2 Function(double, double, double, - int)>("ReturnStruct16BytesMixed2", isLeaf: true); - -/// Return value split over FP and integer register in x64. -/// The integer register contains half float half int. -void testReturnStruct16BytesMixed2Leaf() { - double a0; - double a1; - double a2; - int a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4; - - final result = returnStruct16BytesMixed2Leaf(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.equals(a3, result.a3); -} - -final returnStruct17BytesIntLeaf = ffiTestFunctions.lookupFunction< - Struct17BytesInt Function(Int64, Int64, Int8), - Struct17BytesInt Function( - int, int, int)>("ReturnStruct17BytesInt", isLeaf: true); - -/// 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. -void testReturnStruct17BytesIntLeaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct17BytesIntLeaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct19BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< - Struct19BytesHomogeneousUint8 Function( - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8), - Struct19BytesHomogeneousUint8 Function( - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int)>("ReturnStruct19BytesHomogeneousUint8", isLeaf: true); - -/// 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. -void testReturnStruct19BytesHomogeneousUint8Leaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - int a9; - int a10; - int a11; - int a12; - int a13; - int a14; - int a15; - int a16; - int a17; - int 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; - - final result = returnStruct19BytesHomogeneousUint8Leaf(a0, a1, a2, a3, a4, a5, - a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); - Expect.equals(a9, result.a9); - Expect.equals(a10, result.a10); - Expect.equals(a11, result.a11); - Expect.equals(a12, result.a12); - Expect.equals(a13, result.a13); - Expect.equals(a14, result.a14); - Expect.equals(a15, result.a15); - Expect.equals(a16, result.a16); - Expect.equals(a17, result.a17); - Expect.equals(a18, result.a18); -} - -final returnStruct20BytesHomogeneousInt32Leaf = ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32), - Struct20BytesHomogeneousInt32 Function(int, int, int, int, - int)>("ReturnStruct20BytesHomogeneousInt32", isLeaf: true); - -/// Return value too big to go in cpu registers on arm64. -void testReturnStruct20BytesHomogeneousInt32Leaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - - a0 = -1; - a1 = 2; - a2 = -3; - a3 = 4; - a4 = -5; - - final result = returnStruct20BytesHomogeneousInt32Leaf(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); -} - -final returnStruct20BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousFloat Function(Float, Float, Float, Float, Float), - Struct20BytesHomogeneousFloat Function(double, double, double, double, - double)>("ReturnStruct20BytesHomogeneousFloat", isLeaf: true); - -/// Return value too big to go in FPU registers on x64, arm hardfp and arm64. -void testReturnStruct20BytesHomogeneousFloatLeaf() { - 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; - - final result = returnStruct20BytesHomogeneousFloatLeaf(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); - Expect.approxEquals(a4, result.a4); -} - -final returnStruct32BytesHomogeneousDoubleLeaf = - ffiTestFunctions.lookupFunction< - Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double), - Struct32BytesHomogeneousDouble Function(double, double, double, - double)>("ReturnStruct32BytesHomogeneousDouble", isLeaf: true); - -/// Return value in FPU registers on arm64. -void testReturnStruct32BytesHomogeneousDoubleLeaf() { - double a0; - double a1; - double a2; - double a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4.0; - - final result = returnStruct32BytesHomogeneousDoubleLeaf(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); -} - -final returnStruct40BytesHomogeneousDoubleLeaf = - ffiTestFunctions.lookupFunction< - Struct40BytesHomogeneousDouble Function( - Double, Double, Double, Double, Double), - Struct40BytesHomogeneousDouble Function(double, double, double, double, - double)>("ReturnStruct40BytesHomogeneousDouble", isLeaf: true); - -/// Return value too big to go in FPU registers on arm64. -void testReturnStruct40BytesHomogeneousDoubleLeaf() { - 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; - - final result = returnStruct40BytesHomogeneousDoubleLeaf(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); - Expect.approxEquals(a4, result.a4); -} - -final returnStruct1024BytesHomogeneousUint64Leaf = - ffiTestFunctions.lookupFunction< - Struct1024BytesHomogeneousUint64 Function( - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64), - Struct1024BytesHomogeneousUint64 Function( - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int)>("ReturnStruct1024BytesHomogeneousUint64", isLeaf: true); - -/// Test 1kb struct. -void testReturnStruct1024BytesHomogeneousUint64Leaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - int a9; - int a10; - int a11; - int a12; - int a13; - int a14; - int a15; - int a16; - int a17; - int a18; - int a19; - int a20; - int a21; - int a22; - int a23; - int a24; - int a25; - int a26; - int a27; - int a28; - int a29; - int a30; - int a31; - int a32; - int a33; - int a34; - int a35; - int a36; - int a37; - int a38; - int a39; - int a40; - int a41; - int a42; - int a43; - int a44; - int a45; - int a46; - int a47; - int a48; - int a49; - int a50; - int a51; - int a52; - int a53; - int a54; - int a55; - int a56; - int a57; - int a58; - int a59; - int a60; - int a61; - int a62; - int a63; - int a64; - int a65; - int a66; - int a67; - int a68; - int a69; - int a70; - int a71; - int a72; - int a73; - int a74; - int a75; - int a76; - int a77; - int a78; - int a79; - int a80; - int a81; - int a82; - int a83; - int a84; - int a85; - int a86; - int a87; - int a88; - int a89; - int a90; - int a91; - int a92; - int a93; - int a94; - int a95; - int a96; - int a97; - int a98; - int a99; - int a100; - int a101; - int a102; - int a103; - int a104; - int a105; - int a106; - int a107; - int a108; - int a109; - int a110; - int a111; - int a112; - int a113; - int a114; - int a115; - int a116; - int a117; - int a118; - int a119; - int a120; - int a121; - int a122; - int a123; - int a124; - int a125; - int a126; - int 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; - - final result = returnStruct1024BytesHomogeneousUint64Leaf( - 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); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); - Expect.equals(a9, result.a9); - Expect.equals(a10, result.a10); - Expect.equals(a11, result.a11); - Expect.equals(a12, result.a12); - Expect.equals(a13, result.a13); - Expect.equals(a14, result.a14); - Expect.equals(a15, result.a15); - Expect.equals(a16, result.a16); - Expect.equals(a17, result.a17); - Expect.equals(a18, result.a18); - Expect.equals(a19, result.a19); - Expect.equals(a20, result.a20); - Expect.equals(a21, result.a21); - Expect.equals(a22, result.a22); - Expect.equals(a23, result.a23); - Expect.equals(a24, result.a24); - Expect.equals(a25, result.a25); - Expect.equals(a26, result.a26); - Expect.equals(a27, result.a27); - Expect.equals(a28, result.a28); - Expect.equals(a29, result.a29); - Expect.equals(a30, result.a30); - Expect.equals(a31, result.a31); - Expect.equals(a32, result.a32); - Expect.equals(a33, result.a33); - Expect.equals(a34, result.a34); - Expect.equals(a35, result.a35); - Expect.equals(a36, result.a36); - Expect.equals(a37, result.a37); - Expect.equals(a38, result.a38); - Expect.equals(a39, result.a39); - Expect.equals(a40, result.a40); - Expect.equals(a41, result.a41); - Expect.equals(a42, result.a42); - Expect.equals(a43, result.a43); - Expect.equals(a44, result.a44); - Expect.equals(a45, result.a45); - Expect.equals(a46, result.a46); - Expect.equals(a47, result.a47); - Expect.equals(a48, result.a48); - Expect.equals(a49, result.a49); - Expect.equals(a50, result.a50); - Expect.equals(a51, result.a51); - Expect.equals(a52, result.a52); - Expect.equals(a53, result.a53); - Expect.equals(a54, result.a54); - Expect.equals(a55, result.a55); - Expect.equals(a56, result.a56); - Expect.equals(a57, result.a57); - Expect.equals(a58, result.a58); - Expect.equals(a59, result.a59); - Expect.equals(a60, result.a60); - Expect.equals(a61, result.a61); - Expect.equals(a62, result.a62); - Expect.equals(a63, result.a63); - Expect.equals(a64, result.a64); - Expect.equals(a65, result.a65); - Expect.equals(a66, result.a66); - Expect.equals(a67, result.a67); - Expect.equals(a68, result.a68); - Expect.equals(a69, result.a69); - Expect.equals(a70, result.a70); - Expect.equals(a71, result.a71); - Expect.equals(a72, result.a72); - Expect.equals(a73, result.a73); - Expect.equals(a74, result.a74); - Expect.equals(a75, result.a75); - Expect.equals(a76, result.a76); - Expect.equals(a77, result.a77); - Expect.equals(a78, result.a78); - Expect.equals(a79, result.a79); - Expect.equals(a80, result.a80); - Expect.equals(a81, result.a81); - Expect.equals(a82, result.a82); - Expect.equals(a83, result.a83); - Expect.equals(a84, result.a84); - Expect.equals(a85, result.a85); - Expect.equals(a86, result.a86); - Expect.equals(a87, result.a87); - Expect.equals(a88, result.a88); - Expect.equals(a89, result.a89); - Expect.equals(a90, result.a90); - Expect.equals(a91, result.a91); - Expect.equals(a92, result.a92); - Expect.equals(a93, result.a93); - Expect.equals(a94, result.a94); - Expect.equals(a95, result.a95); - Expect.equals(a96, result.a96); - Expect.equals(a97, result.a97); - Expect.equals(a98, result.a98); - Expect.equals(a99, result.a99); - Expect.equals(a100, result.a100); - Expect.equals(a101, result.a101); - Expect.equals(a102, result.a102); - Expect.equals(a103, result.a103); - Expect.equals(a104, result.a104); - Expect.equals(a105, result.a105); - Expect.equals(a106, result.a106); - Expect.equals(a107, result.a107); - Expect.equals(a108, result.a108); - Expect.equals(a109, result.a109); - Expect.equals(a110, result.a110); - Expect.equals(a111, result.a111); - Expect.equals(a112, result.a112); - Expect.equals(a113, result.a113); - Expect.equals(a114, result.a114); - Expect.equals(a115, result.a115); - Expect.equals(a116, result.a116); - Expect.equals(a117, result.a117); - Expect.equals(a118, result.a118); - Expect.equals(a119, result.a119); - Expect.equals(a120, result.a120); - Expect.equals(a121, result.a121); - Expect.equals(a122, result.a122); - Expect.equals(a123, result.a123); - Expect.equals(a124, result.a124); - Expect.equals(a125, result.a125); - Expect.equals(a126, result.a126); - Expect.equals(a127, result.a127); -} - -final returnStruct3BytesPackedIntLeaf = ffiTestFunctions.lookupFunction< - Struct3BytesPackedInt Function(Int8, Int16), - Struct3BytesPackedInt Function( - int, int)>("ReturnStruct3BytesPackedInt", isLeaf: true); - -/// Small struct with mis-aligned member. -void testReturnStruct3BytesPackedIntLeaf() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct3BytesPackedIntLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct8BytesPackedIntLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesPackedInt Function(Uint8, Uint32, Uint8, Uint8, Uint8), - Struct8BytesPackedInt Function( - int, int, int, int, int)>("ReturnStruct8BytesPackedInt", isLeaf: true); - -/// Struct with mis-aligned member. -void testReturnStruct8BytesPackedIntLeaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - - final result = returnStruct8BytesPackedIntLeaf(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); -} - -final returnStruct9BytesPackedMixedLeaf = ffiTestFunctions.lookupFunction< - Struct9BytesPackedMixed Function(Uint8, Double), - Struct9BytesPackedMixed Function( - int, double)>("ReturnStruct9BytesPackedMixed", isLeaf: true); - -/// Struct with mis-aligned member. -/// Tests backfilling of CPU and FPU registers. -void testReturnStruct9BytesPackedMixedLeaf() { - int a0; - double a1; - - a0 = 1; - a1 = 2.0; - - final result = returnStruct9BytesPackedMixedLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.approxEquals(a1, result.a1); -} - -final returnUnion4BytesMixedLeaf = ffiTestFunctions.lookupFunction< - Union4BytesMixed Function(Uint32), - Union4BytesMixed Function(int)>("ReturnUnion4BytesMixed", isLeaf: true); - -/// Returning a mixed integer/float union. -void testReturnUnion4BytesMixedLeaf() { - int a0; - - a0 = 1; - - final result = returnUnion4BytesMixedLeaf(a0); - - print("result = $result"); - - Expect.equals(a0, result.a0); -} - -final returnUnion8BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< - Union8BytesNestedFloat Function(Double), - Union8BytesNestedFloat Function( - double)>("ReturnUnion8BytesNestedFloat", isLeaf: true); - -/// Returning a floating point only union. -void testReturnUnion8BytesNestedFloatLeaf() { - double a0; - - a0 = -1.0; - - final result = returnUnion8BytesNestedFloatLeaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); -} - -final returnUnion9BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< - Union9BytesNestedInt Function(Struct8BytesInt), - Union9BytesNestedInt Function( - Struct8BytesInt)>("ReturnUnion9BytesNestedInt", isLeaf: true); - -/// Returning a mixed-size union. -void testReturnUnion9BytesNestedIntLeaf() { - final a0Pointer = calloc(); - final Struct8BytesInt a0 = a0Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - - final result = returnUnion9BytesNestedIntLeaf(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - - calloc.free(a0Pointer); -} - -final returnUnion16BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< - Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat), - Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat)>( - "ReturnUnion16BytesNestedFloat", - isLeaf: true); - -/// Returning union with homogenous floats. -void testReturnUnion16BytesNestedFloatLeaf() { - final a0Pointer = calloc(); - final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; - - a0.a0 = -1.0; - a0.a1 = 2.0; - - final result = returnUnion16BytesNestedFloatLeaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a0.a1, result.a0.a1); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStruct1ByteIntLeaf = ffiTestFunctions.lookupFunction< - Struct1ByteInt Function(Struct1ByteInt), - Struct1ByteInt Function( - Struct1ByteInt)>("ReturnStructArgumentStruct1ByteInt", isLeaf: true); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed in int registers in most ABIs. -void testReturnStructArgumentStruct1ByteIntLeaf() { - final a0Pointer = calloc(); - final Struct1ByteInt a0 = a0Pointer.ref; - - a0.a0 = -1; - - final result = returnStructArgumentStruct1ByteIntLeaf(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0); - - calloc.free(a0Pointer); -} - -final returnStructArgumentInt32x8Struct1ByteIntLeaf = - ffiTestFunctions - .lookupFunction< - Struct1ByteInt Function(Int32, Int32, Int32, Int32, Int32, Int32, - Int32, Int32, Struct1ByteInt), - Struct1ByteInt Function( - int, int, int, int, int, int, int, int, Struct1ByteInt)>( - "ReturnStructArgumentInt32x8Struct1ByteInt", - isLeaf: true); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed on stack on all ABIs. -void testReturnStructArgumentInt32x8Struct1ByteIntLeaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - final a8Pointer = calloc(); - final Struct1ByteInt a8 = a8Pointer.ref; - - a0 = -1; - a1 = 2; - a2 = -3; - a3 = 4; - a4 = -5; - a5 = 6; - a6 = -7; - a7 = 8; - a8.a0 = -9; - - final result = returnStructArgumentInt32x8Struct1ByteIntLeaf( - a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a8.a0, result.a0); - - calloc.free(a8Pointer); -} - -final returnStructArgumentStruct8BytesHomogeneousFloatLeaf = - ffiTestFunctions.lookupFunction< - Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat), - Struct8BytesHomogeneousFloat Function( - Struct8BytesHomogeneousFloat)>( - "ReturnStructArgumentStruct8BytesHomogeneousFloat", - isLeaf: true); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed in float registers in most ABIs. -void testReturnStructArgumentStruct8BytesHomogeneousFloatLeaf() { - final a0Pointer = calloc(); - final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; - - a0.a0 = -1.0; - a0.a1 = 2.0; - - final result = returnStructArgumentStruct8BytesHomogeneousFloatLeaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0); - Expect.approxEquals(a0.a1, result.a1); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStruct20BytesHomogeneousInt32Leaf = - ffiTestFunctions - .lookupFunction< - Struct20BytesHomogeneousInt32 Function( - Struct20BytesHomogeneousInt32), - Struct20BytesHomogeneousInt32 Function( - Struct20BytesHomogeneousInt32)>( - "ReturnStructArgumentStruct20BytesHomogeneousInt32", - isLeaf: true); - -/// On arm64, both argument and return value are passed in by pointer. -void testReturnStructArgumentStruct20BytesHomogeneousInt32Leaf() { - final a0Pointer = calloc(); - final Struct20BytesHomogeneousInt32 a0 = a0Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a0.a3 = 4; - a0.a4 = -5; - - final result = returnStructArgumentStruct20BytesHomogeneousInt32Leaf(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0); - Expect.equals(a0.a1, result.a1); - Expect.equals(a0.a2, result.a2); - Expect.equals(a0.a3, result.a3); - Expect.equals(a0.a4, result.a4); - - calloc.free(a0Pointer); -} - -final returnStructArgumentInt32x8Struct20BytesHomogeneouLeaf = - ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, - Int32, Int32, Int32, Int32, Struct20BytesHomogeneousInt32), - Struct20BytesHomogeneousInt32 Function(int, int, int, int, int, int, - int, int, Struct20BytesHomogeneousInt32)>( - "ReturnStructArgumentInt32x8Struct20BytesHomogeneou", - isLeaf: true); - -/// On arm64, both argument and return value are passed in by pointer. -/// Ints exhaust registers, so that pointer is passed on stack. -void testReturnStructArgumentInt32x8Struct20BytesHomogeneouLeaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - final a8Pointer = calloc(); - final Struct20BytesHomogeneousInt32 a8 = a8Pointer.ref; - - 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; - - final result = returnStructArgumentInt32x8Struct20BytesHomogeneouLeaf( - a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a8.a0, result.a0); - Expect.equals(a8.a1, result.a1); - Expect.equals(a8.a2, result.a2); - Expect.equals(a8.a3, result.a3); - Expect.equals(a8.a4, result.a4); - - calloc.free(a8Pointer); -} - -final returnStructArgumentStruct8BytesInlineArrayIntLeaf = - ffiTestFunctions.lookupFunction< - Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt), - Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt)>( - "ReturnStructArgumentStruct8BytesInlineArrayInt", - isLeaf: true); - -/// Test returning struct with inline array. -void testReturnStructArgumentStruct8BytesInlineArrayIntLeaf() { - final a0Pointer = calloc(); - final Struct8BytesInlineArrayInt a0 = a0Pointer.ref; - - 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; - - final result = returnStructArgumentStruct8BytesInlineArrayIntLeaf(a0); - - print("result = $result"); - - for (int i = 0; i < 8; i++) { - Expect.equals(a0.a0[i], result.a0[i]); - } - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct16BytesHomogeneousLeaf = - ffiTestFunctions.lookupFunction< - StructStruct16BytesHomogeneousFloat2 Function( - StructStruct16BytesHomogeneousFloat2), - StructStruct16BytesHomogeneousFloat2 Function( - StructStruct16BytesHomogeneousFloat2)>( - "ReturnStructArgumentStructStruct16BytesHomogeneous", - isLeaf: true); - -/// Return value in FPU registers on arm hardfp and arm64. -void testReturnStructArgumentStructStruct16BytesHomogeneousLeaf() { - final a0Pointer = calloc(); - final StructStruct16BytesHomogeneousFloat2 a0 = a0Pointer.ref; - - a0.a0.a0 = -1.0; - a0.a1[0].a0 = 2.0; - a0.a1[1].a0 = -3.0; - a0.a2 = 4.0; - - final result = returnStructArgumentStructStruct16BytesHomogeneousLeaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 2; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - } - Expect.approxEquals(a0.a2, result.a2); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct32BytesHomogeneousLeaf = - ffiTestFunctions.lookupFunction< - StructStruct32BytesHomogeneousDouble2 Function( - StructStruct32BytesHomogeneousDouble2), - StructStruct32BytesHomogeneousDouble2 Function( - StructStruct32BytesHomogeneousDouble2)>( - "ReturnStructArgumentStructStruct32BytesHomogeneous", - isLeaf: true); - -/// Return value in FPU registers on arm64. -void testReturnStructArgumentStructStruct32BytesHomogeneousLeaf() { - final a0Pointer = calloc(); - final StructStruct32BytesHomogeneousDouble2 a0 = a0Pointer.ref; - - a0.a0.a0 = -1.0; - a0.a1[0].a0 = 2.0; - a0.a1[1].a0 = -3.0; - a0.a2 = 4.0; - - final result = returnStructArgumentStructStruct32BytesHomogeneousLeaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 2; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - } - Expect.approxEquals(a0.a2, result.a2); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct16BytesMixed3Leaf = - ffiTestFunctions.lookupFunction< - StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3), - StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3)>( - "ReturnStructArgumentStructStruct16BytesMixed3", - isLeaf: true); - -/// On x64 Linux, return value is split over FP and int registers. -void testReturnStructArgumentStructStruct16BytesMixed3Leaf() { - final a0Pointer = calloc(); - final StructStruct16BytesMixed3 a0 = a0Pointer.ref; - - 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; - - final result = returnStructArgumentStructStruct16BytesMixed3Leaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 1; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - Expect.equals(a0.a1[i].a1, result.a1[i].a1); - Expect.equals(a0.a1[i].a2, result.a1[i].a2); - } - for (int i = 0; i < 2; i++) { - Expect.equals(a0.a2[i], result.a2[i]); - } - - calloc.free(a0Pointer); -} - -final returnStructAlignmentInt16Leaf = ffiTestFunctions.lookupFunction< - StructAlignmentInt16 Function(Int8, Int16, Int8), - StructAlignmentInt16 Function( - int, int, int)>("ReturnStructAlignmentInt16", isLeaf: true); - -/// Test alignment and padding of 16 byte int within struct. -void testReturnStructAlignmentInt16Leaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt16Leaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStructAlignmentInt32Leaf = ffiTestFunctions.lookupFunction< - StructAlignmentInt32 Function(Int8, Int32, Int8), - StructAlignmentInt32 Function( - int, int, int)>("ReturnStructAlignmentInt32", isLeaf: true); - -/// Test alignment and padding of 32 byte int within struct. -void testReturnStructAlignmentInt32Leaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt32Leaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStructAlignmentInt64Leaf = ffiTestFunctions.lookupFunction< - StructAlignmentInt64 Function(Int8, Int64, Int8), - StructAlignmentInt64 Function( - int, int, int)>("ReturnStructAlignmentInt64", isLeaf: true); - -/// Test alignment and padding of 64 byte int within struct. -void testReturnStructAlignmentInt64Leaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt64Leaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesNestedInt Function( - Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16), - Struct8BytesNestedInt Function( - Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16)>( - "ReturnStruct8BytesNestedInt", - isLeaf: true); - -/// Simple nested struct. -void testReturnStruct8BytesNestedIntLeaf() { - final a0Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a1.a0 = -3; - a1.a1 = 4; - - final result = returnStruct8BytesNestedIntLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct8BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesNestedFloat Function(Struct4BytesFloat, Struct4BytesFloat), - Struct8BytesNestedFloat Function(Struct4BytesFloat, - Struct4BytesFloat)>("ReturnStruct8BytesNestedFloat", isLeaf: true); - -/// Simple nested struct with floats. -void testReturnStruct8BytesNestedFloatLeaf() { - final a0Pointer = calloc(); - final Struct4BytesFloat a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesFloat a1 = a1Pointer.ref; - - a0.a0 = -1.0; - a1.a0 = 2.0; - - final result = returnStruct8BytesNestedFloatLeaf(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a1.a0, result.a1.a0); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct8BytesNestedFloat2Leaf = ffiTestFunctions.lookupFunction< - Struct8BytesNestedFloat2 Function(Struct4BytesFloat, Float), - Struct8BytesNestedFloat2 Function(Struct4BytesFloat, - double)>("ReturnStruct8BytesNestedFloat2", isLeaf: true); - -/// The nesting is irregular, testing homogenous float rules on arm and arm64, -/// and the fpu register usage on x64. -void testReturnStruct8BytesNestedFloat2Leaf() { - final a0Pointer = calloc(); - final Struct4BytesFloat a0 = a0Pointer.ref; - double a1; - - a0.a0 = -1.0; - a1 = 2.0; - - final result = returnStruct8BytesNestedFloat2Leaf(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a1, result.a1); - - calloc.free(a0Pointer); -} - -final returnStruct8BytesNestedMixedLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesNestedMixed Function( - Struct4BytesHomogeneousInt16, Struct4BytesFloat), - Struct8BytesNestedMixed Function(Struct4BytesHomogeneousInt16, - Struct4BytesFloat)>("ReturnStruct8BytesNestedMixed", isLeaf: true); - -/// Simple nested struct with mixed members. -void testReturnStruct8BytesNestedMixedLeaf() { - final a0Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesFloat a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a1.a0 = -3.0; - - final result = returnStruct8BytesNestedMixedLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.approxEquals(a1.a0, result.a1.a0); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct16BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< - Struct16BytesNestedInt Function( - Struct8BytesNestedInt, Struct8BytesNestedInt), - Struct16BytesNestedInt Function(Struct8BytesNestedInt, - Struct8BytesNestedInt)>("ReturnStruct16BytesNestedInt", isLeaf: true); - -/// Deeper nested struct to test recursive member access. -void testReturnStruct16BytesNestedIntLeaf() { - final a0Pointer = calloc(); - final Struct8BytesNestedInt a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct8BytesNestedInt a1 = a1Pointer.ref; - - 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; - - final result = returnStruct16BytesNestedIntLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0.a0, result.a0.a0.a0); - Expect.equals(a0.a0.a1, result.a0.a0.a1); - Expect.equals(a0.a1.a0, result.a0.a1.a0); - Expect.equals(a0.a1.a1, result.a0.a1.a1); - Expect.equals(a1.a0.a0, result.a1.a0.a0); - Expect.equals(a1.a0.a1, result.a1.a0.a1); - Expect.equals(a1.a1.a0, result.a1.a1.a0); - Expect.equals(a1.a1.a1, result.a1.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct32BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< - Struct32BytesNestedInt Function( - Struct16BytesNestedInt, Struct16BytesNestedInt), - Struct32BytesNestedInt Function(Struct16BytesNestedInt, - Struct16BytesNestedInt)>("ReturnStruct32BytesNestedInt", isLeaf: true); - -/// Even deeper nested struct to test recursive member access. -void testReturnStruct32BytesNestedIntLeaf() { - final a0Pointer = calloc(); - final Struct16BytesNestedInt a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct16BytesNestedInt a1 = a1Pointer.ref; - - 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; - - final result = returnStruct32BytesNestedIntLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0.a0.a0, result.a0.a0.a0.a0); - Expect.equals(a0.a0.a0.a1, result.a0.a0.a0.a1); - Expect.equals(a0.a0.a1.a0, result.a0.a0.a1.a0); - Expect.equals(a0.a0.a1.a1, result.a0.a0.a1.a1); - Expect.equals(a0.a1.a0.a0, result.a0.a1.a0.a0); - Expect.equals(a0.a1.a0.a1, result.a0.a1.a0.a1); - Expect.equals(a0.a1.a1.a0, result.a0.a1.a1.a0); - Expect.equals(a0.a1.a1.a1, result.a0.a1.a1.a1); - Expect.equals(a1.a0.a0.a0, result.a1.a0.a0.a0); - Expect.equals(a1.a0.a0.a1, result.a1.a0.a0.a1); - Expect.equals(a1.a0.a1.a0, result.a1.a0.a1.a0); - Expect.equals(a1.a0.a1.a1, result.a1.a0.a1.a1); - Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); - Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); - Expect.equals(a1.a1.a1.a0, result.a1.a1.a1.a0); - Expect.equals(a1.a1.a1.a1, result.a1.a1.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt16Leaf = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt16 Function( - StructAlignmentInt16, StructAlignmentInt16), - StructNestedIntStructAlignmentInt16 Function( - StructAlignmentInt16, StructAlignmentInt16)>( - "ReturnStructNestedIntStructAlignmentInt16", - isLeaf: true); - -/// Test alignment and padding of nested struct with 16 byte int. -void testReturnStructNestedIntStructAlignmentInt16Leaf() { - final a0Pointer = calloc(); - final StructAlignmentInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt16 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt16Leaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt32Leaf = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt32 Function( - StructAlignmentInt32, StructAlignmentInt32), - StructNestedIntStructAlignmentInt32 Function( - StructAlignmentInt32, StructAlignmentInt32)>( - "ReturnStructNestedIntStructAlignmentInt32", - isLeaf: true); - -/// Test alignment and padding of nested struct with 32 byte int. -void testReturnStructNestedIntStructAlignmentInt32Leaf() { - final a0Pointer = calloc(); - final StructAlignmentInt32 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt32 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt32Leaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt64Leaf = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt64 Function( - StructAlignmentInt64, StructAlignmentInt64), - StructNestedIntStructAlignmentInt64 Function( - StructAlignmentInt64, StructAlignmentInt64)>( - "ReturnStructNestedIntStructAlignmentInt64", - isLeaf: true); - -/// Test alignment and padding of nested struct with 64 byte int. -void testReturnStructNestedIntStructAlignmentInt64Leaf() { - final a0Pointer = calloc(); - final StructAlignmentInt64 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt64 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt64Leaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIrregularEvenBiggerLeaf = - ffiTestFunctions.lookupFunction< - StructNestedIrregularEvenBigger Function(Uint64, - StructNestedIrregularBigger, StructNestedIrregularBigger, Double), - StructNestedIrregularEvenBigger Function( - int, - StructNestedIrregularBigger, - StructNestedIrregularBigger, - double)>("ReturnStructNestedIrregularEvenBigger", isLeaf: true); - -/// Return big irregular struct as smoke test. -void testReturnStructNestedIrregularEvenBiggerLeaf() { - int a0; - final a1Pointer = calloc(); - final StructNestedIrregularBigger a1 = a1Pointer.ref; - final a2Pointer = calloc(); - final StructNestedIrregularBigger a2 = a2Pointer.ref; - 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; - - final result = returnStructNestedIrregularEvenBiggerLeaf(a0, a1, a2, a3); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1.a0.a0, result.a1.a0.a0); - Expect.equals(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0); - Expect.equals(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1); - Expect.approxEquals(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0); - Expect.equals(a1.a0.a2, result.a1.a0.a2); - Expect.approxEquals(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0); - Expect.approxEquals(a1.a0.a3.a1, result.a1.a0.a3.a1); - Expect.equals(a1.a0.a4, result.a1.a0.a4); - Expect.approxEquals(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0); - Expect.approxEquals(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0); - Expect.equals(a1.a0.a6, result.a1.a0.a6); - Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); - Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); - Expect.approxEquals(a1.a1.a1.a0, result.a1.a1.a1.a0); - Expect.approxEquals(a1.a2, result.a1.a2); - Expect.approxEquals(a1.a3, result.a1.a3); - Expect.equals(a2.a0.a0, result.a2.a0.a0); - Expect.equals(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0); - Expect.equals(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1); - Expect.approxEquals(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0); - Expect.equals(a2.a0.a2, result.a2.a0.a2); - Expect.approxEquals(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0); - Expect.approxEquals(a2.a0.a3.a1, result.a2.a0.a3.a1); - Expect.equals(a2.a0.a4, result.a2.a0.a4); - Expect.approxEquals(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0); - Expect.approxEquals(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0); - Expect.equals(a2.a0.a6, result.a2.a0.a6); - Expect.equals(a2.a1.a0.a0, result.a2.a1.a0.a0); - Expect.equals(a2.a1.a0.a1, result.a2.a1.a0.a1); - Expect.approxEquals(a2.a1.a1.a0, result.a2.a1.a1.a0); - Expect.approxEquals(a2.a2, result.a2.a2); - Expect.approxEquals(a2.a3, result.a2.a3); - Expect.approxEquals(a3, result.a3); - - calloc.free(a1Pointer); - calloc.free(a2Pointer); -} diff --git a/tests/ffi/function_structs_by_value_generated_test.dart b/tests/ffi/function_structs_by_value_generated_args_test.dart similarity index 71% rename from tests/ffi/function_structs_by_value_generated_test.dart rename to tests/ffi/function_structs_by_value_generated_args_test.dart index 8eb47dcadb9..d01ee69cdaf 100644 --- a/tests/ffi/function_structs_by_value_generated_test.dart +++ b/tests/ffi/function_structs_by_value_generated_args_test.dart @@ -7,7 +7,7 @@ // // SharedObjects=ffi_test_functions // VMOptions= -// VMOptions=--deterministic --optimization-counter-threshold=20 +// VMOptions=--deterministic --optimization-counter-threshold=90 // VMOptions=--use-slow-path // VMOptions=--use-slow-path --stacktrace-every=100 @@ -23,7 +23,7 @@ import 'function_structs_by_value_generated_compounds.dart'; final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); void main() { - for (int i = 0; i < 25; ++i) { + for (int i = 0; i < 100; ++i) { testPassStruct1ByteIntx10(); testPassStruct3BytesHomogeneousUint8x10(); testPassStruct3BytesInt2ByteAlignedx10(); @@ -90,57 +90,6 @@ void main() { testPassUint8Boolx9Struct10BytesInlineArrayBoolBool(); testPassUint8Struct1ByteBool(); testPassWCharStructInlineArrayIntUintPtrx2LongUnsigned(); - testReturnStruct1ByteInt(); - testReturnStruct3BytesHomogeneousUint8(); - testReturnStruct3BytesInt2ByteAligned(); - testReturnStruct4BytesHomogeneousInt16(); - testReturnStruct7BytesHomogeneousUint8(); - testReturnStruct7BytesInt4ByteAligned(); - testReturnStruct8BytesInt(); - testReturnStruct8BytesHomogeneousFloat(); - testReturnStruct8BytesMixed(); - testReturnStruct9BytesHomogeneousUint8(); - testReturnStruct9BytesInt4Or8ByteAligned(); - testReturnStruct12BytesHomogeneousFloat(); - testReturnStruct16BytesHomogeneousFloat(); - testReturnStruct16BytesMixed(); - testReturnStruct16BytesMixed2(); - testReturnStruct17BytesInt(); - testReturnStruct19BytesHomogeneousUint8(); - testReturnStruct20BytesHomogeneousInt32(); - testReturnStruct20BytesHomogeneousFloat(); - testReturnStruct32BytesHomogeneousDouble(); - testReturnStruct40BytesHomogeneousDouble(); - testReturnStruct1024BytesHomogeneousUint64(); - testReturnStruct3BytesPackedInt(); - testReturnStruct8BytesPackedInt(); - testReturnStruct9BytesPackedMixed(); - testReturnUnion4BytesMixed(); - testReturnUnion8BytesNestedFloat(); - testReturnUnion9BytesNestedInt(); - testReturnUnion16BytesNestedFloat(); - testReturnStructArgumentStruct1ByteInt(); - testReturnStructArgumentInt32x8Struct1ByteInt(); - testReturnStructArgumentStruct8BytesHomogeneousFloat(); - testReturnStructArgumentStruct20BytesHomogeneousInt32(); - testReturnStructArgumentInt32x8Struct20BytesHomogeneou(); - testReturnStructArgumentStruct8BytesInlineArrayInt(); - testReturnStructArgumentStructStruct16BytesHomogeneous(); - testReturnStructArgumentStructStruct32BytesHomogeneous(); - testReturnStructArgumentStructStruct16BytesMixed3(); - testReturnStructAlignmentInt16(); - testReturnStructAlignmentInt32(); - testReturnStructAlignmentInt64(); - testReturnStruct8BytesNestedInt(); - testReturnStruct8BytesNestedFloat(); - testReturnStruct8BytesNestedFloat2(); - testReturnStruct8BytesNestedMixed(); - testReturnStruct16BytesNestedInt(); - testReturnStruct32BytesNestedInt(); - testReturnStructNestedIntStructAlignmentInt16(); - testReturnStructNestedIntStructAlignmentInt32(); - testReturnStructNestedIntStructAlignmentInt64(); - testReturnStructNestedIrregularEvenBigger(); } } @@ -5428,2356 +5377,3 @@ void testPassWCharStructInlineArrayIntUintPtrx2LongUnsigned() { calloc.free(a1Pointer); } - -final returnStruct1ByteInt = ffiTestFunctions.lookupFunction< - Struct1ByteInt Function(Int8), - Struct1ByteInt Function(int)>("ReturnStruct1ByteInt"); - -/// Smallest struct with data. -void testReturnStruct1ByteInt() { - int a0; - - a0 = -1; - - final result = returnStruct1ByteInt(a0); - - print("result = $result"); - - Expect.equals(a0, result.a0); -} - -final returnStruct3BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< - Struct3BytesHomogeneousUint8 Function(Uint8, Uint8, Uint8), - Struct3BytesHomogeneousUint8 Function( - int, int, int)>("ReturnStruct3BytesHomogeneousUint8"); - -/// Smaller than word size return value on all architectures. -void testReturnStruct3BytesHomogeneousUint8() { - int a0; - int a1; - int a2; - - a0 = 1; - a1 = 2; - a2 = 3; - - final result = returnStruct3BytesHomogeneousUint8(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct3BytesInt2ByteAligned = ffiTestFunctions.lookupFunction< - Struct3BytesInt2ByteAligned Function(Int16, Int8), - Struct3BytesInt2ByteAligned Function( - int, int)>("ReturnStruct3BytesInt2ByteAligned"); - -/// Smaller than word size return value on all architectures. -/// With alignment rules taken into account size is 4 bytes. -void testReturnStruct3BytesInt2ByteAligned() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct3BytesInt2ByteAligned(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct4BytesHomogeneousInt16 = ffiTestFunctions.lookupFunction< - Struct4BytesHomogeneousInt16 Function(Int16, Int16), - Struct4BytesHomogeneousInt16 Function( - int, int)>("ReturnStruct4BytesHomogeneousInt16"); - -/// Word size return value on 32 bit architectures.. -void testReturnStruct4BytesHomogeneousInt16() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct4BytesHomogeneousInt16(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct7BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< - Struct7BytesHomogeneousUint8 Function( - Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), - Struct7BytesHomogeneousUint8 Function(int, int, int, int, int, int, - int)>("ReturnStruct7BytesHomogeneousUint8"); - -/// Non-wordsize return value. -void testReturnStruct7BytesHomogeneousUint8() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - a5 = 6; - a6 = 7; - - final result = returnStruct7BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); -} - -final returnStruct7BytesInt4ByteAligned = ffiTestFunctions.lookupFunction< - Struct7BytesInt4ByteAligned Function(Int32, Int16, Int8), - Struct7BytesInt4ByteAligned Function( - int, int, int)>("ReturnStruct7BytesInt4ByteAligned"); - -/// Non-wordsize return value. -/// With alignment rules taken into account size is 8 bytes. -void testReturnStruct7BytesInt4ByteAligned() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct7BytesInt4ByteAligned(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesInt = ffiTestFunctions.lookupFunction< - Struct8BytesInt Function(Int16, Int16, Int32), - Struct8BytesInt Function(int, int, int)>("ReturnStruct8BytesInt"); - -/// Return value in integer registers on many architectures. -void testReturnStruct8BytesInt() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct8BytesInt(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< - Struct8BytesHomogeneousFloat Function(Float, Float), - Struct8BytesHomogeneousFloat Function( - double, double)>("ReturnStruct8BytesHomogeneousFloat"); - -/// Return value in FP registers on many architectures. -void testReturnStruct8BytesHomogeneousFloat() { - double a0; - double a1; - - a0 = -1.0; - a1 = 2.0; - - final result = returnStruct8BytesHomogeneousFloat(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); -} - -final returnStruct8BytesMixed = ffiTestFunctions.lookupFunction< - Struct8BytesMixed Function(Float, Int16, Int16), - Struct8BytesMixed Function(double, int, int)>("ReturnStruct8BytesMixed"); - -/// Return value split over FP and integer register in x64. -void testReturnStruct8BytesMixed() { - double a0; - int a1; - int a2; - - a0 = -1.0; - a1 = 2; - a2 = -3; - - final result = returnStruct8BytesMixed(a0, a1, a2); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct9BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< - Struct9BytesHomogeneousUint8 Function( - Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), - Struct9BytesHomogeneousUint8 Function(int, int, int, int, int, int, int, - int, int)>("ReturnStruct9BytesHomogeneousUint8"); - -/// 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. -void testReturnStruct9BytesHomogeneousUint8() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - a5 = 6; - a6 = 7; - a7 = 8; - a8 = 9; - - final result = - returnStruct9BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); -} - -final returnStruct9BytesInt4Or8ByteAligned = ffiTestFunctions.lookupFunction< - Struct9BytesInt4Or8ByteAligned Function(Int64, Int8), - Struct9BytesInt4Or8ByteAligned Function( - int, int)>("ReturnStruct9BytesInt4Or8ByteAligned"); - -/// Return value in two integer registers on x64. -/// With alignment rules taken into account size is 12 or 16 bytes. -void testReturnStruct9BytesInt4Or8ByteAligned() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct9BytesInt4Or8ByteAligned(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct12BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< - Struct12BytesHomogeneousFloat Function(Float, Float, Float), - Struct12BytesHomogeneousFloat Function( - double, double, double)>("ReturnStruct12BytesHomogeneousFloat"); - -/// Return value in FPU registers, but does not use all registers on arm hardfp -/// and arm64. -void testReturnStruct12BytesHomogeneousFloat() { - double a0; - double a1; - double a2; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - - final result = returnStruct12BytesHomogeneousFloat(a0, a1, a2); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); -} - -final returnStruct16BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< - Struct16BytesHomogeneousFloat Function(Float, Float, Float, Float), - Struct16BytesHomogeneousFloat Function( - double, double, double, double)>("ReturnStruct16BytesHomogeneousFloat"); - -/// Return value in FPU registers on arm hardfp and arm64. -void testReturnStruct16BytesHomogeneousFloat() { - double a0; - double a1; - double a2; - double a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4.0; - - final result = returnStruct16BytesHomogeneousFloat(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); -} - -final returnStruct16BytesMixed = ffiTestFunctions.lookupFunction< - Struct16BytesMixed Function(Double, Int64), - Struct16BytesMixed Function(double, int)>("ReturnStruct16BytesMixed"); - -/// Return value split over FP and integer register in x64. -void testReturnStruct16BytesMixed() { - double a0; - int a1; - - a0 = -1.0; - a1 = 2; - - final result = returnStruct16BytesMixed(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct16BytesMixed2 = ffiTestFunctions.lookupFunction< - Struct16BytesMixed2 Function(Float, Float, Float, Int32), - Struct16BytesMixed2 Function( - double, double, double, int)>("ReturnStruct16BytesMixed2"); - -/// Return value split over FP and integer register in x64. -/// The integer register contains half float half int. -void testReturnStruct16BytesMixed2() { - double a0; - double a1; - double a2; - int a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4; - - final result = returnStruct16BytesMixed2(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.equals(a3, result.a3); -} - -final returnStruct17BytesInt = ffiTestFunctions.lookupFunction< - Struct17BytesInt Function(Int64, Int64, Int8), - Struct17BytesInt Function(int, int, int)>("ReturnStruct17BytesInt"); - -/// 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. -void testReturnStruct17BytesInt() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct17BytesInt(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct19BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< - Struct19BytesHomogeneousUint8 Function( - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8), - Struct19BytesHomogeneousUint8 Function( - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int)>("ReturnStruct19BytesHomogeneousUint8"); - -/// 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. -void testReturnStruct19BytesHomogeneousUint8() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - int a9; - int a10; - int a11; - int a12; - int a13; - int a14; - int a15; - int a16; - int a17; - int 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; - - final result = returnStruct19BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6, - a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); - Expect.equals(a9, result.a9); - Expect.equals(a10, result.a10); - Expect.equals(a11, result.a11); - Expect.equals(a12, result.a12); - Expect.equals(a13, result.a13); - Expect.equals(a14, result.a14); - Expect.equals(a15, result.a15); - Expect.equals(a16, result.a16); - Expect.equals(a17, result.a17); - Expect.equals(a18, result.a18); -} - -final returnStruct20BytesHomogeneousInt32 = ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32), - Struct20BytesHomogeneousInt32 Function( - int, int, int, int, int)>("ReturnStruct20BytesHomogeneousInt32"); - -/// Return value too big to go in cpu registers on arm64. -void testReturnStruct20BytesHomogeneousInt32() { - int a0; - int a1; - int a2; - int a3; - int a4; - - a0 = -1; - a1 = 2; - a2 = -3; - a3 = 4; - a4 = -5; - - final result = returnStruct20BytesHomogeneousInt32(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); -} - -final returnStruct20BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousFloat Function(Float, Float, Float, Float, Float), - Struct20BytesHomogeneousFloat Function(double, double, double, double, - double)>("ReturnStruct20BytesHomogeneousFloat"); - -/// Return value too big to go in FPU registers on x64, arm hardfp and arm64. -void testReturnStruct20BytesHomogeneousFloat() { - 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; - - final result = returnStruct20BytesHomogeneousFloat(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); - Expect.approxEquals(a4, result.a4); -} - -final returnStruct32BytesHomogeneousDouble = ffiTestFunctions.lookupFunction< - Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double), - Struct32BytesHomogeneousDouble Function(double, double, double, - double)>("ReturnStruct32BytesHomogeneousDouble"); - -/// Return value in FPU registers on arm64. -void testReturnStruct32BytesHomogeneousDouble() { - double a0; - double a1; - double a2; - double a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4.0; - - final result = returnStruct32BytesHomogeneousDouble(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); -} - -final returnStruct40BytesHomogeneousDouble = ffiTestFunctions.lookupFunction< - Struct40BytesHomogeneousDouble Function( - Double, Double, Double, Double, Double), - Struct40BytesHomogeneousDouble Function(double, double, double, double, - double)>("ReturnStruct40BytesHomogeneousDouble"); - -/// Return value too big to go in FPU registers on arm64. -void testReturnStruct40BytesHomogeneousDouble() { - 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; - - final result = returnStruct40BytesHomogeneousDouble(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); - Expect.approxEquals(a4, result.a4); -} - -final returnStruct1024BytesHomogeneousUint64 = ffiTestFunctions.lookupFunction< - Struct1024BytesHomogeneousUint64 Function( - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64), - Struct1024BytesHomogeneousUint64 Function( - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int)>("ReturnStruct1024BytesHomogeneousUint64"); - -/// Test 1kb struct. -void testReturnStruct1024BytesHomogeneousUint64() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - int a9; - int a10; - int a11; - int a12; - int a13; - int a14; - int a15; - int a16; - int a17; - int a18; - int a19; - int a20; - int a21; - int a22; - int a23; - int a24; - int a25; - int a26; - int a27; - int a28; - int a29; - int a30; - int a31; - int a32; - int a33; - int a34; - int a35; - int a36; - int a37; - int a38; - int a39; - int a40; - int a41; - int a42; - int a43; - int a44; - int a45; - int a46; - int a47; - int a48; - int a49; - int a50; - int a51; - int a52; - int a53; - int a54; - int a55; - int a56; - int a57; - int a58; - int a59; - int a60; - int a61; - int a62; - int a63; - int a64; - int a65; - int a66; - int a67; - int a68; - int a69; - int a70; - int a71; - int a72; - int a73; - int a74; - int a75; - int a76; - int a77; - int a78; - int a79; - int a80; - int a81; - int a82; - int a83; - int a84; - int a85; - int a86; - int a87; - int a88; - int a89; - int a90; - int a91; - int a92; - int a93; - int a94; - int a95; - int a96; - int a97; - int a98; - int a99; - int a100; - int a101; - int a102; - int a103; - int a104; - int a105; - int a106; - int a107; - int a108; - int a109; - int a110; - int a111; - int a112; - int a113; - int a114; - int a115; - int a116; - int a117; - int a118; - int a119; - int a120; - int a121; - int a122; - int a123; - int a124; - int a125; - int a126; - int 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; - - final result = 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); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); - Expect.equals(a9, result.a9); - Expect.equals(a10, result.a10); - Expect.equals(a11, result.a11); - Expect.equals(a12, result.a12); - Expect.equals(a13, result.a13); - Expect.equals(a14, result.a14); - Expect.equals(a15, result.a15); - Expect.equals(a16, result.a16); - Expect.equals(a17, result.a17); - Expect.equals(a18, result.a18); - Expect.equals(a19, result.a19); - Expect.equals(a20, result.a20); - Expect.equals(a21, result.a21); - Expect.equals(a22, result.a22); - Expect.equals(a23, result.a23); - Expect.equals(a24, result.a24); - Expect.equals(a25, result.a25); - Expect.equals(a26, result.a26); - Expect.equals(a27, result.a27); - Expect.equals(a28, result.a28); - Expect.equals(a29, result.a29); - Expect.equals(a30, result.a30); - Expect.equals(a31, result.a31); - Expect.equals(a32, result.a32); - Expect.equals(a33, result.a33); - Expect.equals(a34, result.a34); - Expect.equals(a35, result.a35); - Expect.equals(a36, result.a36); - Expect.equals(a37, result.a37); - Expect.equals(a38, result.a38); - Expect.equals(a39, result.a39); - Expect.equals(a40, result.a40); - Expect.equals(a41, result.a41); - Expect.equals(a42, result.a42); - Expect.equals(a43, result.a43); - Expect.equals(a44, result.a44); - Expect.equals(a45, result.a45); - Expect.equals(a46, result.a46); - Expect.equals(a47, result.a47); - Expect.equals(a48, result.a48); - Expect.equals(a49, result.a49); - Expect.equals(a50, result.a50); - Expect.equals(a51, result.a51); - Expect.equals(a52, result.a52); - Expect.equals(a53, result.a53); - Expect.equals(a54, result.a54); - Expect.equals(a55, result.a55); - Expect.equals(a56, result.a56); - Expect.equals(a57, result.a57); - Expect.equals(a58, result.a58); - Expect.equals(a59, result.a59); - Expect.equals(a60, result.a60); - Expect.equals(a61, result.a61); - Expect.equals(a62, result.a62); - Expect.equals(a63, result.a63); - Expect.equals(a64, result.a64); - Expect.equals(a65, result.a65); - Expect.equals(a66, result.a66); - Expect.equals(a67, result.a67); - Expect.equals(a68, result.a68); - Expect.equals(a69, result.a69); - Expect.equals(a70, result.a70); - Expect.equals(a71, result.a71); - Expect.equals(a72, result.a72); - Expect.equals(a73, result.a73); - Expect.equals(a74, result.a74); - Expect.equals(a75, result.a75); - Expect.equals(a76, result.a76); - Expect.equals(a77, result.a77); - Expect.equals(a78, result.a78); - Expect.equals(a79, result.a79); - Expect.equals(a80, result.a80); - Expect.equals(a81, result.a81); - Expect.equals(a82, result.a82); - Expect.equals(a83, result.a83); - Expect.equals(a84, result.a84); - Expect.equals(a85, result.a85); - Expect.equals(a86, result.a86); - Expect.equals(a87, result.a87); - Expect.equals(a88, result.a88); - Expect.equals(a89, result.a89); - Expect.equals(a90, result.a90); - Expect.equals(a91, result.a91); - Expect.equals(a92, result.a92); - Expect.equals(a93, result.a93); - Expect.equals(a94, result.a94); - Expect.equals(a95, result.a95); - Expect.equals(a96, result.a96); - Expect.equals(a97, result.a97); - Expect.equals(a98, result.a98); - Expect.equals(a99, result.a99); - Expect.equals(a100, result.a100); - Expect.equals(a101, result.a101); - Expect.equals(a102, result.a102); - Expect.equals(a103, result.a103); - Expect.equals(a104, result.a104); - Expect.equals(a105, result.a105); - Expect.equals(a106, result.a106); - Expect.equals(a107, result.a107); - Expect.equals(a108, result.a108); - Expect.equals(a109, result.a109); - Expect.equals(a110, result.a110); - Expect.equals(a111, result.a111); - Expect.equals(a112, result.a112); - Expect.equals(a113, result.a113); - Expect.equals(a114, result.a114); - Expect.equals(a115, result.a115); - Expect.equals(a116, result.a116); - Expect.equals(a117, result.a117); - Expect.equals(a118, result.a118); - Expect.equals(a119, result.a119); - Expect.equals(a120, result.a120); - Expect.equals(a121, result.a121); - Expect.equals(a122, result.a122); - Expect.equals(a123, result.a123); - Expect.equals(a124, result.a124); - Expect.equals(a125, result.a125); - Expect.equals(a126, result.a126); - Expect.equals(a127, result.a127); -} - -final returnStruct3BytesPackedInt = ffiTestFunctions.lookupFunction< - Struct3BytesPackedInt Function(Int8, Int16), - Struct3BytesPackedInt Function(int, int)>("ReturnStruct3BytesPackedInt"); - -/// Small struct with mis-aligned member. -void testReturnStruct3BytesPackedInt() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct3BytesPackedInt(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct8BytesPackedInt = ffiTestFunctions.lookupFunction< - Struct8BytesPackedInt Function(Uint8, Uint32, Uint8, Uint8, Uint8), - Struct8BytesPackedInt Function( - int, int, int, int, int)>("ReturnStruct8BytesPackedInt"); - -/// Struct with mis-aligned member. -void testReturnStruct8BytesPackedInt() { - int a0; - int a1; - int a2; - int a3; - int a4; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - - final result = returnStruct8BytesPackedInt(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); -} - -final returnStruct9BytesPackedMixed = ffiTestFunctions.lookupFunction< - Struct9BytesPackedMixed Function(Uint8, Double), - Struct9BytesPackedMixed Function( - int, double)>("ReturnStruct9BytesPackedMixed"); - -/// Struct with mis-aligned member. -/// Tests backfilling of CPU and FPU registers. -void testReturnStruct9BytesPackedMixed() { - int a0; - double a1; - - a0 = 1; - a1 = 2.0; - - final result = returnStruct9BytesPackedMixed(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.approxEquals(a1, result.a1); -} - -final returnUnion4BytesMixed = ffiTestFunctions.lookupFunction< - Union4BytesMixed Function(Uint32), - Union4BytesMixed Function(int)>("ReturnUnion4BytesMixed"); - -/// Returning a mixed integer/float union. -void testReturnUnion4BytesMixed() { - int a0; - - a0 = 1; - - final result = returnUnion4BytesMixed(a0); - - print("result = $result"); - - Expect.equals(a0, result.a0); -} - -final returnUnion8BytesNestedFloat = ffiTestFunctions.lookupFunction< - Union8BytesNestedFloat Function(Double), - Union8BytesNestedFloat Function(double)>("ReturnUnion8BytesNestedFloat"); - -/// Returning a floating point only union. -void testReturnUnion8BytesNestedFloat() { - double a0; - - a0 = -1.0; - - final result = returnUnion8BytesNestedFloat(a0); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); -} - -final returnUnion9BytesNestedInt = ffiTestFunctions.lookupFunction< - Union9BytesNestedInt Function(Struct8BytesInt), - Union9BytesNestedInt Function( - Struct8BytesInt)>("ReturnUnion9BytesNestedInt"); - -/// Returning a mixed-size union. -void testReturnUnion9BytesNestedInt() { - final a0Pointer = calloc(); - final Struct8BytesInt a0 = a0Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - - final result = returnUnion9BytesNestedInt(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - - calloc.free(a0Pointer); -} - -final returnUnion16BytesNestedFloat = ffiTestFunctions.lookupFunction< - Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat), - Union16BytesNestedFloat Function( - Struct8BytesHomogeneousFloat)>("ReturnUnion16BytesNestedFloat"); - -/// Returning union with homogenous floats. -void testReturnUnion16BytesNestedFloat() { - final a0Pointer = calloc(); - final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; - - a0.a0 = -1.0; - a0.a1 = 2.0; - - final result = returnUnion16BytesNestedFloat(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a0.a1, result.a0.a1); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStruct1ByteInt = ffiTestFunctions.lookupFunction< - Struct1ByteInt Function(Struct1ByteInt), - Struct1ByteInt Function( - Struct1ByteInt)>("ReturnStructArgumentStruct1ByteInt"); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed in int registers in most ABIs. -void testReturnStructArgumentStruct1ByteInt() { - final a0Pointer = calloc(); - final Struct1ByteInt a0 = a0Pointer.ref; - - a0.a0 = -1; - - final result = returnStructArgumentStruct1ByteInt(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0); - - calloc.free(a0Pointer); -} - -final returnStructArgumentInt32x8Struct1ByteInt = - ffiTestFunctions.lookupFunction< - Struct1ByteInt Function(Int32, Int32, Int32, Int32, Int32, Int32, Int32, - Int32, Struct1ByteInt), - Struct1ByteInt Function(int, int, int, int, int, int, int, int, - Struct1ByteInt)>("ReturnStructArgumentInt32x8Struct1ByteInt"); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed on stack on all ABIs. -void testReturnStructArgumentInt32x8Struct1ByteInt() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - final a8Pointer = calloc(); - final Struct1ByteInt a8 = a8Pointer.ref; - - a0 = -1; - a1 = 2; - a2 = -3; - a3 = 4; - a4 = -5; - a5 = 6; - a6 = -7; - a7 = 8; - a8.a0 = -9; - - final result = returnStructArgumentInt32x8Struct1ByteInt( - a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a8.a0, result.a0); - - calloc.free(a8Pointer); -} - -final returnStructArgumentStruct8BytesHomogeneousFloat = - ffiTestFunctions.lookupFunction< - Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat), - Struct8BytesHomogeneousFloat Function( - Struct8BytesHomogeneousFloat)>( - "ReturnStructArgumentStruct8BytesHomogeneousFloat"); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed in float registers in most ABIs. -void testReturnStructArgumentStruct8BytesHomogeneousFloat() { - final a0Pointer = calloc(); - final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; - - a0.a0 = -1.0; - a0.a1 = 2.0; - - final result = returnStructArgumentStruct8BytesHomogeneousFloat(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0); - Expect.approxEquals(a0.a1, result.a1); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStruct20BytesHomogeneousInt32 = - ffiTestFunctions - .lookupFunction< - Struct20BytesHomogeneousInt32 Function( - Struct20BytesHomogeneousInt32), - Struct20BytesHomogeneousInt32 Function( - Struct20BytesHomogeneousInt32)>( - "ReturnStructArgumentStruct20BytesHomogeneousInt32"); - -/// On arm64, both argument and return value are passed in by pointer. -void testReturnStructArgumentStruct20BytesHomogeneousInt32() { - final a0Pointer = calloc(); - final Struct20BytesHomogeneousInt32 a0 = a0Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a0.a3 = 4; - a0.a4 = -5; - - final result = returnStructArgumentStruct20BytesHomogeneousInt32(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0); - Expect.equals(a0.a1, result.a1); - Expect.equals(a0.a2, result.a2); - Expect.equals(a0.a3, result.a3); - Expect.equals(a0.a4, result.a4); - - calloc.free(a0Pointer); -} - -final returnStructArgumentInt32x8Struct20BytesHomogeneou = - ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, - Int32, Int32, Int32, Int32, Struct20BytesHomogeneousInt32), - Struct20BytesHomogeneousInt32 Function(int, int, int, int, int, int, - int, int, Struct20BytesHomogeneousInt32)>( - "ReturnStructArgumentInt32x8Struct20BytesHomogeneou"); - -/// On arm64, both argument and return value are passed in by pointer. -/// Ints exhaust registers, so that pointer is passed on stack. -void testReturnStructArgumentInt32x8Struct20BytesHomogeneou() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - final a8Pointer = calloc(); - final Struct20BytesHomogeneousInt32 a8 = a8Pointer.ref; - - 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; - - final result = returnStructArgumentInt32x8Struct20BytesHomogeneou( - a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a8.a0, result.a0); - Expect.equals(a8.a1, result.a1); - Expect.equals(a8.a2, result.a2); - Expect.equals(a8.a3, result.a3); - Expect.equals(a8.a4, result.a4); - - calloc.free(a8Pointer); -} - -final returnStructArgumentStruct8BytesInlineArrayInt = - ffiTestFunctions.lookupFunction< - Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt), - Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt)>( - "ReturnStructArgumentStruct8BytesInlineArrayInt"); - -/// Test returning struct with inline array. -void testReturnStructArgumentStruct8BytesInlineArrayInt() { - final a0Pointer = calloc(); - final Struct8BytesInlineArrayInt a0 = a0Pointer.ref; - - 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; - - final result = returnStructArgumentStruct8BytesInlineArrayInt(a0); - - print("result = $result"); - - for (int i = 0; i < 8; i++) { - Expect.equals(a0.a0[i], result.a0[i]); - } - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct16BytesHomogeneous = - ffiTestFunctions.lookupFunction< - StructStruct16BytesHomogeneousFloat2 Function( - StructStruct16BytesHomogeneousFloat2), - StructStruct16BytesHomogeneousFloat2 Function( - StructStruct16BytesHomogeneousFloat2)>( - "ReturnStructArgumentStructStruct16BytesHomogeneous"); - -/// Return value in FPU registers on arm hardfp and arm64. -void testReturnStructArgumentStructStruct16BytesHomogeneous() { - final a0Pointer = calloc(); - final StructStruct16BytesHomogeneousFloat2 a0 = a0Pointer.ref; - - a0.a0.a0 = -1.0; - a0.a1[0].a0 = 2.0; - a0.a1[1].a0 = -3.0; - a0.a2 = 4.0; - - final result = returnStructArgumentStructStruct16BytesHomogeneous(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 2; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - } - Expect.approxEquals(a0.a2, result.a2); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct32BytesHomogeneous = - ffiTestFunctions.lookupFunction< - StructStruct32BytesHomogeneousDouble2 Function( - StructStruct32BytesHomogeneousDouble2), - StructStruct32BytesHomogeneousDouble2 Function( - StructStruct32BytesHomogeneousDouble2)>( - "ReturnStructArgumentStructStruct32BytesHomogeneous"); - -/// Return value in FPU registers on arm64. -void testReturnStructArgumentStructStruct32BytesHomogeneous() { - final a0Pointer = calloc(); - final StructStruct32BytesHomogeneousDouble2 a0 = a0Pointer.ref; - - a0.a0.a0 = -1.0; - a0.a1[0].a0 = 2.0; - a0.a1[1].a0 = -3.0; - a0.a2 = 4.0; - - final result = returnStructArgumentStructStruct32BytesHomogeneous(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 2; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - } - Expect.approxEquals(a0.a2, result.a2); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct16BytesMixed3 = - ffiTestFunctions.lookupFunction< - StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3), - StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3)>( - "ReturnStructArgumentStructStruct16BytesMixed3"); - -/// On x64 Linux, return value is split over FP and int registers. -void testReturnStructArgumentStructStruct16BytesMixed3() { - final a0Pointer = calloc(); - final StructStruct16BytesMixed3 a0 = a0Pointer.ref; - - 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; - - final result = returnStructArgumentStructStruct16BytesMixed3(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 1; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - Expect.equals(a0.a1[i].a1, result.a1[i].a1); - Expect.equals(a0.a1[i].a2, result.a1[i].a2); - } - for (int i = 0; i < 2; i++) { - Expect.equals(a0.a2[i], result.a2[i]); - } - - calloc.free(a0Pointer); -} - -final returnStructAlignmentInt16 = ffiTestFunctions.lookupFunction< - StructAlignmentInt16 Function(Int8, Int16, Int8), - StructAlignmentInt16 Function(int, int, int)>("ReturnStructAlignmentInt16"); - -/// Test alignment and padding of 16 byte int within struct. -void testReturnStructAlignmentInt16() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt16(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStructAlignmentInt32 = ffiTestFunctions.lookupFunction< - StructAlignmentInt32 Function(Int8, Int32, Int8), - StructAlignmentInt32 Function(int, int, int)>("ReturnStructAlignmentInt32"); - -/// Test alignment and padding of 32 byte int within struct. -void testReturnStructAlignmentInt32() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt32(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStructAlignmentInt64 = ffiTestFunctions.lookupFunction< - StructAlignmentInt64 Function(Int8, Int64, Int8), - StructAlignmentInt64 Function(int, int, int)>("ReturnStructAlignmentInt64"); - -/// Test alignment and padding of 64 byte int within struct. -void testReturnStructAlignmentInt64() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt64(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesNestedInt = ffiTestFunctions.lookupFunction< - Struct8BytesNestedInt Function( - Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16), - Struct8BytesNestedInt Function(Struct4BytesHomogeneousInt16, - Struct4BytesHomogeneousInt16)>("ReturnStruct8BytesNestedInt"); - -/// Simple nested struct. -void testReturnStruct8BytesNestedInt() { - final a0Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a1.a0 = -3; - a1.a1 = 4; - - final result = returnStruct8BytesNestedInt(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct8BytesNestedFloat = ffiTestFunctions.lookupFunction< - Struct8BytesNestedFloat Function(Struct4BytesFloat, Struct4BytesFloat), - Struct8BytesNestedFloat Function( - Struct4BytesFloat, Struct4BytesFloat)>("ReturnStruct8BytesNestedFloat"); - -/// Simple nested struct with floats. -void testReturnStruct8BytesNestedFloat() { - final a0Pointer = calloc(); - final Struct4BytesFloat a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesFloat a1 = a1Pointer.ref; - - a0.a0 = -1.0; - a1.a0 = 2.0; - - final result = returnStruct8BytesNestedFloat(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a1.a0, result.a1.a0); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct8BytesNestedFloat2 = ffiTestFunctions.lookupFunction< - Struct8BytesNestedFloat2 Function(Struct4BytesFloat, Float), - Struct8BytesNestedFloat2 Function( - Struct4BytesFloat, double)>("ReturnStruct8BytesNestedFloat2"); - -/// The nesting is irregular, testing homogenous float rules on arm and arm64, -/// and the fpu register usage on x64. -void testReturnStruct8BytesNestedFloat2() { - final a0Pointer = calloc(); - final Struct4BytesFloat a0 = a0Pointer.ref; - double a1; - - a0.a0 = -1.0; - a1 = 2.0; - - final result = returnStruct8BytesNestedFloat2(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a1, result.a1); - - calloc.free(a0Pointer); -} - -final returnStruct8BytesNestedMixed = ffiTestFunctions.lookupFunction< - Struct8BytesNestedMixed Function( - Struct4BytesHomogeneousInt16, Struct4BytesFloat), - Struct8BytesNestedMixed Function(Struct4BytesHomogeneousInt16, - Struct4BytesFloat)>("ReturnStruct8BytesNestedMixed"); - -/// Simple nested struct with mixed members. -void testReturnStruct8BytesNestedMixed() { - final a0Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesFloat a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a1.a0 = -3.0; - - final result = returnStruct8BytesNestedMixed(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.approxEquals(a1.a0, result.a1.a0); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct16BytesNestedInt = ffiTestFunctions.lookupFunction< - Struct16BytesNestedInt Function( - Struct8BytesNestedInt, Struct8BytesNestedInt), - Struct16BytesNestedInt Function(Struct8BytesNestedInt, - Struct8BytesNestedInt)>("ReturnStruct16BytesNestedInt"); - -/// Deeper nested struct to test recursive member access. -void testReturnStruct16BytesNestedInt() { - final a0Pointer = calloc(); - final Struct8BytesNestedInt a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct8BytesNestedInt a1 = a1Pointer.ref; - - 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; - - final result = returnStruct16BytesNestedInt(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0.a0, result.a0.a0.a0); - Expect.equals(a0.a0.a1, result.a0.a0.a1); - Expect.equals(a0.a1.a0, result.a0.a1.a0); - Expect.equals(a0.a1.a1, result.a0.a1.a1); - Expect.equals(a1.a0.a0, result.a1.a0.a0); - Expect.equals(a1.a0.a1, result.a1.a0.a1); - Expect.equals(a1.a1.a0, result.a1.a1.a0); - Expect.equals(a1.a1.a1, result.a1.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct32BytesNestedInt = ffiTestFunctions.lookupFunction< - Struct32BytesNestedInt Function( - Struct16BytesNestedInt, Struct16BytesNestedInt), - Struct32BytesNestedInt Function(Struct16BytesNestedInt, - Struct16BytesNestedInt)>("ReturnStruct32BytesNestedInt"); - -/// Even deeper nested struct to test recursive member access. -void testReturnStruct32BytesNestedInt() { - final a0Pointer = calloc(); - final Struct16BytesNestedInt a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct16BytesNestedInt a1 = a1Pointer.ref; - - 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; - - final result = returnStruct32BytesNestedInt(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0.a0.a0, result.a0.a0.a0.a0); - Expect.equals(a0.a0.a0.a1, result.a0.a0.a0.a1); - Expect.equals(a0.a0.a1.a0, result.a0.a0.a1.a0); - Expect.equals(a0.a0.a1.a1, result.a0.a0.a1.a1); - Expect.equals(a0.a1.a0.a0, result.a0.a1.a0.a0); - Expect.equals(a0.a1.a0.a1, result.a0.a1.a0.a1); - Expect.equals(a0.a1.a1.a0, result.a0.a1.a1.a0); - Expect.equals(a0.a1.a1.a1, result.a0.a1.a1.a1); - Expect.equals(a1.a0.a0.a0, result.a1.a0.a0.a0); - Expect.equals(a1.a0.a0.a1, result.a1.a0.a0.a1); - Expect.equals(a1.a0.a1.a0, result.a1.a0.a1.a0); - Expect.equals(a1.a0.a1.a1, result.a1.a0.a1.a1); - Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); - Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); - Expect.equals(a1.a1.a1.a0, result.a1.a1.a1.a0); - Expect.equals(a1.a1.a1.a1, result.a1.a1.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt16 = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt16 Function( - StructAlignmentInt16, StructAlignmentInt16), - StructNestedIntStructAlignmentInt16 Function(StructAlignmentInt16, - StructAlignmentInt16)>("ReturnStructNestedIntStructAlignmentInt16"); - -/// Test alignment and padding of nested struct with 16 byte int. -void testReturnStructNestedIntStructAlignmentInt16() { - final a0Pointer = calloc(); - final StructAlignmentInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt16 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt16(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt32 = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt32 Function( - StructAlignmentInt32, StructAlignmentInt32), - StructNestedIntStructAlignmentInt32 Function(StructAlignmentInt32, - StructAlignmentInt32)>("ReturnStructNestedIntStructAlignmentInt32"); - -/// Test alignment and padding of nested struct with 32 byte int. -void testReturnStructNestedIntStructAlignmentInt32() { - final a0Pointer = calloc(); - final StructAlignmentInt32 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt32 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt32(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt64 = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt64 Function( - StructAlignmentInt64, StructAlignmentInt64), - StructNestedIntStructAlignmentInt64 Function(StructAlignmentInt64, - StructAlignmentInt64)>("ReturnStructNestedIntStructAlignmentInt64"); - -/// Test alignment and padding of nested struct with 64 byte int. -void testReturnStructNestedIntStructAlignmentInt64() { - final a0Pointer = calloc(); - final StructAlignmentInt64 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt64 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt64(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIrregularEvenBigger = ffiTestFunctions.lookupFunction< - StructNestedIrregularEvenBigger Function(Uint64, - StructNestedIrregularBigger, StructNestedIrregularBigger, Double), - StructNestedIrregularEvenBigger Function( - int, - StructNestedIrregularBigger, - StructNestedIrregularBigger, - double)>("ReturnStructNestedIrregularEvenBigger"); - -/// Return big irregular struct as smoke test. -void testReturnStructNestedIrregularEvenBigger() { - int a0; - final a1Pointer = calloc(); - final StructNestedIrregularBigger a1 = a1Pointer.ref; - final a2Pointer = calloc(); - final StructNestedIrregularBigger a2 = a2Pointer.ref; - 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; - - final result = returnStructNestedIrregularEvenBigger(a0, a1, a2, a3); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1.a0.a0, result.a1.a0.a0); - Expect.equals(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0); - Expect.equals(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1); - Expect.approxEquals(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0); - Expect.equals(a1.a0.a2, result.a1.a0.a2); - Expect.approxEquals(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0); - Expect.approxEquals(a1.a0.a3.a1, result.a1.a0.a3.a1); - Expect.equals(a1.a0.a4, result.a1.a0.a4); - Expect.approxEquals(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0); - Expect.approxEquals(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0); - Expect.equals(a1.a0.a6, result.a1.a0.a6); - Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); - Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); - Expect.approxEquals(a1.a1.a1.a0, result.a1.a1.a1.a0); - Expect.approxEquals(a1.a2, result.a1.a2); - Expect.approxEquals(a1.a3, result.a1.a3); - Expect.equals(a2.a0.a0, result.a2.a0.a0); - Expect.equals(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0); - Expect.equals(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1); - Expect.approxEquals(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0); - Expect.equals(a2.a0.a2, result.a2.a0.a2); - Expect.approxEquals(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0); - Expect.approxEquals(a2.a0.a3.a1, result.a2.a0.a3.a1); - Expect.equals(a2.a0.a4, result.a2.a0.a4); - Expect.approxEquals(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0); - Expect.approxEquals(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0); - Expect.equals(a2.a0.a6, result.a2.a0.a6); - Expect.equals(a2.a1.a0.a0, result.a2.a1.a0.a0); - Expect.equals(a2.a1.a0.a1, result.a2.a1.a0.a1); - Expect.approxEquals(a2.a1.a1.a0, result.a2.a1.a1.a0); - Expect.approxEquals(a2.a2, result.a2.a2); - Expect.approxEquals(a2.a3, result.a2.a3); - Expect.approxEquals(a3, result.a3); - - calloc.free(a1Pointer); - calloc.free(a2Pointer); -} diff --git a/tests/ffi/function_structs_by_value_generated_ret_arg_leaf_test.dart b/tests/ffi/function_structs_by_value_generated_ret_arg_leaf_test.dart new file mode 100644 index 00000000000..9f50890fc56 --- /dev/null +++ b/tests/ffi/function_structs_by_value_generated_ret_arg_leaf_test.dart @@ -0,0 +1,853 @@ +// Copyright (c) 2021, 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. +// Generated by tests/ffi/generator/structs_by_value_tests_generator.dart. +// +// SharedObjects=ffi_test_functions +// VMOptions= +// VMOptions=--deterministic --optimization-counter-threshold=90 +// VMOptions=--use-slow-path +// VMOptions=--use-slow-path --stacktrace-every=100 + +import 'dart:ffi'; + +import "package:expect/expect.dart"; +import "package:ffi/ffi.dart"; + +import 'dylib_utils.dart'; + +// Reuse the compound classes. +import 'function_structs_by_value_generated_compounds.dart'; + +final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); +void main() { + for (int i = 0; i < 100; ++i) { + testReturnStructArgumentStruct1ByteIntLeaf(); + testReturnStructArgumentInt32x8Struct1ByteIntLeaf(); + testReturnStructArgumentStruct8BytesHomogeneousFloatLeaf(); + testReturnStructArgumentStruct20BytesHomogeneousInt32Leaf(); + testReturnStructArgumentInt32x8Struct20BytesHomogeneouLeaf(); + testReturnStructArgumentStruct8BytesInlineArrayIntLeaf(); + testReturnStructArgumentStructStruct16BytesHomogeneousLeaf(); + testReturnStructArgumentStructStruct32BytesHomogeneousLeaf(); + testReturnStructArgumentStructStruct16BytesMixed3Leaf(); + testReturnStructAlignmentInt16Leaf(); + testReturnStructAlignmentInt32Leaf(); + testReturnStructAlignmentInt64Leaf(); + testReturnStruct8BytesNestedIntLeaf(); + testReturnStruct8BytesNestedFloatLeaf(); + testReturnStruct8BytesNestedFloat2Leaf(); + testReturnStruct8BytesNestedMixedLeaf(); + testReturnStruct16BytesNestedIntLeaf(); + testReturnStruct32BytesNestedIntLeaf(); + testReturnStructNestedIntStructAlignmentInt16Leaf(); + testReturnStructNestedIntStructAlignmentInt32Leaf(); + testReturnStructNestedIntStructAlignmentInt64Leaf(); + testReturnStructNestedIrregularEvenBiggerLeaf(); + } +} + +final returnStructArgumentStruct1ByteIntLeaf = ffiTestFunctions.lookupFunction< + Struct1ByteInt Function(Struct1ByteInt), + Struct1ByteInt Function( + Struct1ByteInt)>("ReturnStructArgumentStruct1ByteInt", isLeaf: true); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed in int registers in most ABIs. +void testReturnStructArgumentStruct1ByteIntLeaf() { + final a0Pointer = calloc(); + final Struct1ByteInt a0 = a0Pointer.ref; + + a0.a0 = -1; + + final result = returnStructArgumentStruct1ByteIntLeaf(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0); + + calloc.free(a0Pointer); +} + +final returnStructArgumentInt32x8Struct1ByteIntLeaf = + ffiTestFunctions + .lookupFunction< + Struct1ByteInt Function(Int32, Int32, Int32, Int32, Int32, Int32, + Int32, Int32, Struct1ByteInt), + Struct1ByteInt Function( + int, int, int, int, int, int, int, int, Struct1ByteInt)>( + "ReturnStructArgumentInt32x8Struct1ByteInt", + isLeaf: true); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed on stack on all ABIs. +void testReturnStructArgumentInt32x8Struct1ByteIntLeaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + final a8Pointer = calloc(); + final Struct1ByteInt a8 = a8Pointer.ref; + + a0 = -1; + a1 = 2; + a2 = -3; + a3 = 4; + a4 = -5; + a5 = 6; + a6 = -7; + a7 = 8; + a8.a0 = -9; + + final result = returnStructArgumentInt32x8Struct1ByteIntLeaf( + a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a8.a0, result.a0); + + calloc.free(a8Pointer); +} + +final returnStructArgumentStruct8BytesHomogeneousFloatLeaf = + ffiTestFunctions.lookupFunction< + Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat), + Struct8BytesHomogeneousFloat Function( + Struct8BytesHomogeneousFloat)>( + "ReturnStructArgumentStruct8BytesHomogeneousFloat", + isLeaf: true); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed in float registers in most ABIs. +void testReturnStructArgumentStruct8BytesHomogeneousFloatLeaf() { + final a0Pointer = calloc(); + final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; + + a0.a0 = -1.0; + a0.a1 = 2.0; + + final result = returnStructArgumentStruct8BytesHomogeneousFloatLeaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0); + Expect.approxEquals(a0.a1, result.a1); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStruct20BytesHomogeneousInt32Leaf = + ffiTestFunctions + .lookupFunction< + Struct20BytesHomogeneousInt32 Function( + Struct20BytesHomogeneousInt32), + Struct20BytesHomogeneousInt32 Function( + Struct20BytesHomogeneousInt32)>( + "ReturnStructArgumentStruct20BytesHomogeneousInt32", + isLeaf: true); + +/// On arm64, both argument and return value are passed in by pointer. +void testReturnStructArgumentStruct20BytesHomogeneousInt32Leaf() { + final a0Pointer = calloc(); + final Struct20BytesHomogeneousInt32 a0 = a0Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a0.a3 = 4; + a0.a4 = -5; + + final result = returnStructArgumentStruct20BytesHomogeneousInt32Leaf(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0); + Expect.equals(a0.a1, result.a1); + Expect.equals(a0.a2, result.a2); + Expect.equals(a0.a3, result.a3); + Expect.equals(a0.a4, result.a4); + + calloc.free(a0Pointer); +} + +final returnStructArgumentInt32x8Struct20BytesHomogeneouLeaf = + ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, + Int32, Int32, Int32, Int32, Struct20BytesHomogeneousInt32), + Struct20BytesHomogeneousInt32 Function(int, int, int, int, int, int, + int, int, Struct20BytesHomogeneousInt32)>( + "ReturnStructArgumentInt32x8Struct20BytesHomogeneou", + isLeaf: true); + +/// On arm64, both argument and return value are passed in by pointer. +/// Ints exhaust registers, so that pointer is passed on stack. +void testReturnStructArgumentInt32x8Struct20BytesHomogeneouLeaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + final a8Pointer = calloc(); + final Struct20BytesHomogeneousInt32 a8 = a8Pointer.ref; + + 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; + + final result = returnStructArgumentInt32x8Struct20BytesHomogeneouLeaf( + a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a8.a0, result.a0); + Expect.equals(a8.a1, result.a1); + Expect.equals(a8.a2, result.a2); + Expect.equals(a8.a3, result.a3); + Expect.equals(a8.a4, result.a4); + + calloc.free(a8Pointer); +} + +final returnStructArgumentStruct8BytesInlineArrayIntLeaf = + ffiTestFunctions.lookupFunction< + Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt), + Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt)>( + "ReturnStructArgumentStruct8BytesInlineArrayInt", + isLeaf: true); + +/// Test returning struct with inline array. +void testReturnStructArgumentStruct8BytesInlineArrayIntLeaf() { + final a0Pointer = calloc(); + final Struct8BytesInlineArrayInt a0 = a0Pointer.ref; + + 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; + + final result = returnStructArgumentStruct8BytesInlineArrayIntLeaf(a0); + + print("result = $result"); + + for (int i = 0; i < 8; i++) { + Expect.equals(a0.a0[i], result.a0[i]); + } + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct16BytesHomogeneousLeaf = + ffiTestFunctions.lookupFunction< + StructStruct16BytesHomogeneousFloat2 Function( + StructStruct16BytesHomogeneousFloat2), + StructStruct16BytesHomogeneousFloat2 Function( + StructStruct16BytesHomogeneousFloat2)>( + "ReturnStructArgumentStructStruct16BytesHomogeneous", + isLeaf: true); + +/// Return value in FPU registers on arm hardfp and arm64. +void testReturnStructArgumentStructStruct16BytesHomogeneousLeaf() { + final a0Pointer = calloc(); + final StructStruct16BytesHomogeneousFloat2 a0 = a0Pointer.ref; + + a0.a0.a0 = -1.0; + a0.a1[0].a0 = 2.0; + a0.a1[1].a0 = -3.0; + a0.a2 = 4.0; + + final result = returnStructArgumentStructStruct16BytesHomogeneousLeaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 2; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + } + Expect.approxEquals(a0.a2, result.a2); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct32BytesHomogeneousLeaf = + ffiTestFunctions.lookupFunction< + StructStruct32BytesHomogeneousDouble2 Function( + StructStruct32BytesHomogeneousDouble2), + StructStruct32BytesHomogeneousDouble2 Function( + StructStruct32BytesHomogeneousDouble2)>( + "ReturnStructArgumentStructStruct32BytesHomogeneous", + isLeaf: true); + +/// Return value in FPU registers on arm64. +void testReturnStructArgumentStructStruct32BytesHomogeneousLeaf() { + final a0Pointer = calloc(); + final StructStruct32BytesHomogeneousDouble2 a0 = a0Pointer.ref; + + a0.a0.a0 = -1.0; + a0.a1[0].a0 = 2.0; + a0.a1[1].a0 = -3.0; + a0.a2 = 4.0; + + final result = returnStructArgumentStructStruct32BytesHomogeneousLeaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 2; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + } + Expect.approxEquals(a0.a2, result.a2); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct16BytesMixed3Leaf = + ffiTestFunctions.lookupFunction< + StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3), + StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3)>( + "ReturnStructArgumentStructStruct16BytesMixed3", + isLeaf: true); + +/// On x64 Linux, return value is split over FP and int registers. +void testReturnStructArgumentStructStruct16BytesMixed3Leaf() { + final a0Pointer = calloc(); + final StructStruct16BytesMixed3 a0 = a0Pointer.ref; + + 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; + + final result = returnStructArgumentStructStruct16BytesMixed3Leaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 1; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + Expect.equals(a0.a1[i].a1, result.a1[i].a1); + Expect.equals(a0.a1[i].a2, result.a1[i].a2); + } + for (int i = 0; i < 2; i++) { + Expect.equals(a0.a2[i], result.a2[i]); + } + + calloc.free(a0Pointer); +} + +final returnStructAlignmentInt16Leaf = ffiTestFunctions.lookupFunction< + StructAlignmentInt16 Function(Int8, Int16, Int8), + StructAlignmentInt16 Function( + int, int, int)>("ReturnStructAlignmentInt16", isLeaf: true); + +/// Test alignment and padding of 16 byte int within struct. +void testReturnStructAlignmentInt16Leaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt16Leaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStructAlignmentInt32Leaf = ffiTestFunctions.lookupFunction< + StructAlignmentInt32 Function(Int8, Int32, Int8), + StructAlignmentInt32 Function( + int, int, int)>("ReturnStructAlignmentInt32", isLeaf: true); + +/// Test alignment and padding of 32 byte int within struct. +void testReturnStructAlignmentInt32Leaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt32Leaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStructAlignmentInt64Leaf = ffiTestFunctions.lookupFunction< + StructAlignmentInt64 Function(Int8, Int64, Int8), + StructAlignmentInt64 Function( + int, int, int)>("ReturnStructAlignmentInt64", isLeaf: true); + +/// Test alignment and padding of 64 byte int within struct. +void testReturnStructAlignmentInt64Leaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt64Leaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesNestedInt Function( + Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16), + Struct8BytesNestedInt Function( + Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16)>( + "ReturnStruct8BytesNestedInt", + isLeaf: true); + +/// Simple nested struct. +void testReturnStruct8BytesNestedIntLeaf() { + final a0Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a1.a0 = -3; + a1.a1 = 4; + + final result = returnStruct8BytesNestedIntLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct8BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesNestedFloat Function(Struct4BytesFloat, Struct4BytesFloat), + Struct8BytesNestedFloat Function(Struct4BytesFloat, + Struct4BytesFloat)>("ReturnStruct8BytesNestedFloat", isLeaf: true); + +/// Simple nested struct with floats. +void testReturnStruct8BytesNestedFloatLeaf() { + final a0Pointer = calloc(); + final Struct4BytesFloat a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesFloat a1 = a1Pointer.ref; + + a0.a0 = -1.0; + a1.a0 = 2.0; + + final result = returnStruct8BytesNestedFloatLeaf(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a1.a0, result.a1.a0); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct8BytesNestedFloat2Leaf = ffiTestFunctions.lookupFunction< + Struct8BytesNestedFloat2 Function(Struct4BytesFloat, Float), + Struct8BytesNestedFloat2 Function(Struct4BytesFloat, + double)>("ReturnStruct8BytesNestedFloat2", isLeaf: true); + +/// The nesting is irregular, testing homogenous float rules on arm and arm64, +/// and the fpu register usage on x64. +void testReturnStruct8BytesNestedFloat2Leaf() { + final a0Pointer = calloc(); + final Struct4BytesFloat a0 = a0Pointer.ref; + double a1; + + a0.a0 = -1.0; + a1 = 2.0; + + final result = returnStruct8BytesNestedFloat2Leaf(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a1, result.a1); + + calloc.free(a0Pointer); +} + +final returnStruct8BytesNestedMixedLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesNestedMixed Function( + Struct4BytesHomogeneousInt16, Struct4BytesFloat), + Struct8BytesNestedMixed Function(Struct4BytesHomogeneousInt16, + Struct4BytesFloat)>("ReturnStruct8BytesNestedMixed", isLeaf: true); + +/// Simple nested struct with mixed members. +void testReturnStruct8BytesNestedMixedLeaf() { + final a0Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesFloat a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a1.a0 = -3.0; + + final result = returnStruct8BytesNestedMixedLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.approxEquals(a1.a0, result.a1.a0); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct16BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< + Struct16BytesNestedInt Function( + Struct8BytesNestedInt, Struct8BytesNestedInt), + Struct16BytesNestedInt Function(Struct8BytesNestedInt, + Struct8BytesNestedInt)>("ReturnStruct16BytesNestedInt", isLeaf: true); + +/// Deeper nested struct to test recursive member access. +void testReturnStruct16BytesNestedIntLeaf() { + final a0Pointer = calloc(); + final Struct8BytesNestedInt a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct8BytesNestedInt a1 = a1Pointer.ref; + + 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; + + final result = returnStruct16BytesNestedIntLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0.a0, result.a0.a0.a0); + Expect.equals(a0.a0.a1, result.a0.a0.a1); + Expect.equals(a0.a1.a0, result.a0.a1.a0); + Expect.equals(a0.a1.a1, result.a0.a1.a1); + Expect.equals(a1.a0.a0, result.a1.a0.a0); + Expect.equals(a1.a0.a1, result.a1.a0.a1); + Expect.equals(a1.a1.a0, result.a1.a1.a0); + Expect.equals(a1.a1.a1, result.a1.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct32BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< + Struct32BytesNestedInt Function( + Struct16BytesNestedInt, Struct16BytesNestedInt), + Struct32BytesNestedInt Function(Struct16BytesNestedInt, + Struct16BytesNestedInt)>("ReturnStruct32BytesNestedInt", isLeaf: true); + +/// Even deeper nested struct to test recursive member access. +void testReturnStruct32BytesNestedIntLeaf() { + final a0Pointer = calloc(); + final Struct16BytesNestedInt a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct16BytesNestedInt a1 = a1Pointer.ref; + + 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; + + final result = returnStruct32BytesNestedIntLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0.a0.a0, result.a0.a0.a0.a0); + Expect.equals(a0.a0.a0.a1, result.a0.a0.a0.a1); + Expect.equals(a0.a0.a1.a0, result.a0.a0.a1.a0); + Expect.equals(a0.a0.a1.a1, result.a0.a0.a1.a1); + Expect.equals(a0.a1.a0.a0, result.a0.a1.a0.a0); + Expect.equals(a0.a1.a0.a1, result.a0.a1.a0.a1); + Expect.equals(a0.a1.a1.a0, result.a0.a1.a1.a0); + Expect.equals(a0.a1.a1.a1, result.a0.a1.a1.a1); + Expect.equals(a1.a0.a0.a0, result.a1.a0.a0.a0); + Expect.equals(a1.a0.a0.a1, result.a1.a0.a0.a1); + Expect.equals(a1.a0.a1.a0, result.a1.a0.a1.a0); + Expect.equals(a1.a0.a1.a1, result.a1.a0.a1.a1); + Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); + Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); + Expect.equals(a1.a1.a1.a0, result.a1.a1.a1.a0); + Expect.equals(a1.a1.a1.a1, result.a1.a1.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt16Leaf = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt16 Function( + StructAlignmentInt16, StructAlignmentInt16), + StructNestedIntStructAlignmentInt16 Function( + StructAlignmentInt16, StructAlignmentInt16)>( + "ReturnStructNestedIntStructAlignmentInt16", + isLeaf: true); + +/// Test alignment and padding of nested struct with 16 byte int. +void testReturnStructNestedIntStructAlignmentInt16Leaf() { + final a0Pointer = calloc(); + final StructAlignmentInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt16 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt16Leaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt32Leaf = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt32 Function( + StructAlignmentInt32, StructAlignmentInt32), + StructNestedIntStructAlignmentInt32 Function( + StructAlignmentInt32, StructAlignmentInt32)>( + "ReturnStructNestedIntStructAlignmentInt32", + isLeaf: true); + +/// Test alignment and padding of nested struct with 32 byte int. +void testReturnStructNestedIntStructAlignmentInt32Leaf() { + final a0Pointer = calloc(); + final StructAlignmentInt32 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt32 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt32Leaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt64Leaf = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt64 Function( + StructAlignmentInt64, StructAlignmentInt64), + StructNestedIntStructAlignmentInt64 Function( + StructAlignmentInt64, StructAlignmentInt64)>( + "ReturnStructNestedIntStructAlignmentInt64", + isLeaf: true); + +/// Test alignment and padding of nested struct with 64 byte int. +void testReturnStructNestedIntStructAlignmentInt64Leaf() { + final a0Pointer = calloc(); + final StructAlignmentInt64 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt64 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt64Leaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIrregularEvenBiggerLeaf = + ffiTestFunctions.lookupFunction< + StructNestedIrregularEvenBigger Function(Uint64, + StructNestedIrregularBigger, StructNestedIrregularBigger, Double), + StructNestedIrregularEvenBigger Function( + int, + StructNestedIrregularBigger, + StructNestedIrregularBigger, + double)>("ReturnStructNestedIrregularEvenBigger", isLeaf: true); + +/// Return big irregular struct as smoke test. +void testReturnStructNestedIrregularEvenBiggerLeaf() { + int a0; + final a1Pointer = calloc(); + final StructNestedIrregularBigger a1 = a1Pointer.ref; + final a2Pointer = calloc(); + final StructNestedIrregularBigger a2 = a2Pointer.ref; + 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; + + final result = returnStructNestedIrregularEvenBiggerLeaf(a0, a1, a2, a3); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1.a0.a0, result.a1.a0.a0); + Expect.equals(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0); + Expect.equals(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1); + Expect.approxEquals(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0); + Expect.equals(a1.a0.a2, result.a1.a0.a2); + Expect.approxEquals(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0); + Expect.approxEquals(a1.a0.a3.a1, result.a1.a0.a3.a1); + Expect.equals(a1.a0.a4, result.a1.a0.a4); + Expect.approxEquals(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0); + Expect.approxEquals(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0); + Expect.equals(a1.a0.a6, result.a1.a0.a6); + Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); + Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); + Expect.approxEquals(a1.a1.a1.a0, result.a1.a1.a1.a0); + Expect.approxEquals(a1.a2, result.a1.a2); + Expect.approxEquals(a1.a3, result.a1.a3); + Expect.equals(a2.a0.a0, result.a2.a0.a0); + Expect.equals(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0); + Expect.equals(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1); + Expect.approxEquals(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0); + Expect.equals(a2.a0.a2, result.a2.a0.a2); + Expect.approxEquals(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0); + Expect.approxEquals(a2.a0.a3.a1, result.a2.a0.a3.a1); + Expect.equals(a2.a0.a4, result.a2.a0.a4); + Expect.approxEquals(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0); + Expect.approxEquals(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0); + Expect.equals(a2.a0.a6, result.a2.a0.a6); + Expect.equals(a2.a1.a0.a0, result.a2.a1.a0.a0); + Expect.equals(a2.a1.a0.a1, result.a2.a1.a0.a1); + Expect.approxEquals(a2.a1.a1.a0, result.a2.a1.a1.a0); + Expect.approxEquals(a2.a2, result.a2.a2); + Expect.approxEquals(a2.a3, result.a2.a3); + Expect.approxEquals(a3, result.a3); + + calloc.free(a1Pointer); + calloc.free(a2Pointer); +} diff --git a/tests/ffi/function_structs_by_value_generated_ret_arg_test.dart b/tests/ffi/function_structs_by_value_generated_ret_arg_test.dart new file mode 100644 index 00000000000..29f9194bacd --- /dev/null +++ b/tests/ffi/function_structs_by_value_generated_ret_arg_test.dart @@ -0,0 +1,831 @@ +// 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. +// Generated by tests/ffi/generator/structs_by_value_tests_generator.dart. +// +// SharedObjects=ffi_test_functions +// VMOptions= +// VMOptions=--deterministic --optimization-counter-threshold=90 +// VMOptions=--use-slow-path +// VMOptions=--use-slow-path --stacktrace-every=100 + +import 'dart:ffi'; + +import "package:expect/expect.dart"; +import "package:ffi/ffi.dart"; + +import 'dylib_utils.dart'; + +// Reuse the compound classes. +import 'function_structs_by_value_generated_compounds.dart'; + +final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); +void main() { + for (int i = 0; i < 100; ++i) { + testReturnStructArgumentStruct1ByteInt(); + testReturnStructArgumentInt32x8Struct1ByteInt(); + testReturnStructArgumentStruct8BytesHomogeneousFloat(); + testReturnStructArgumentStruct20BytesHomogeneousInt32(); + testReturnStructArgumentInt32x8Struct20BytesHomogeneou(); + testReturnStructArgumentStruct8BytesInlineArrayInt(); + testReturnStructArgumentStructStruct16BytesHomogeneous(); + testReturnStructArgumentStructStruct32BytesHomogeneous(); + testReturnStructArgumentStructStruct16BytesMixed3(); + testReturnStructAlignmentInt16(); + testReturnStructAlignmentInt32(); + testReturnStructAlignmentInt64(); + testReturnStruct8BytesNestedInt(); + testReturnStruct8BytesNestedFloat(); + testReturnStruct8BytesNestedFloat2(); + testReturnStruct8BytesNestedMixed(); + testReturnStruct16BytesNestedInt(); + testReturnStruct32BytesNestedInt(); + testReturnStructNestedIntStructAlignmentInt16(); + testReturnStructNestedIntStructAlignmentInt32(); + testReturnStructNestedIntStructAlignmentInt64(); + testReturnStructNestedIrregularEvenBigger(); + } +} + +final returnStructArgumentStruct1ByteInt = ffiTestFunctions.lookupFunction< + Struct1ByteInt Function(Struct1ByteInt), + Struct1ByteInt Function( + Struct1ByteInt)>("ReturnStructArgumentStruct1ByteInt"); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed in int registers in most ABIs. +void testReturnStructArgumentStruct1ByteInt() { + final a0Pointer = calloc(); + final Struct1ByteInt a0 = a0Pointer.ref; + + a0.a0 = -1; + + final result = returnStructArgumentStruct1ByteInt(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0); + + calloc.free(a0Pointer); +} + +final returnStructArgumentInt32x8Struct1ByteInt = + ffiTestFunctions.lookupFunction< + Struct1ByteInt Function(Int32, Int32, Int32, Int32, Int32, Int32, Int32, + Int32, Struct1ByteInt), + Struct1ByteInt Function(int, int, int, int, int, int, int, int, + Struct1ByteInt)>("ReturnStructArgumentInt32x8Struct1ByteInt"); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed on stack on all ABIs. +void testReturnStructArgumentInt32x8Struct1ByteInt() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + final a8Pointer = calloc(); + final Struct1ByteInt a8 = a8Pointer.ref; + + a0 = -1; + a1 = 2; + a2 = -3; + a3 = 4; + a4 = -5; + a5 = 6; + a6 = -7; + a7 = 8; + a8.a0 = -9; + + final result = returnStructArgumentInt32x8Struct1ByteInt( + a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a8.a0, result.a0); + + calloc.free(a8Pointer); +} + +final returnStructArgumentStruct8BytesHomogeneousFloat = + ffiTestFunctions.lookupFunction< + Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat), + Struct8BytesHomogeneousFloat Function( + Struct8BytesHomogeneousFloat)>( + "ReturnStructArgumentStruct8BytesHomogeneousFloat"); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed in float registers in most ABIs. +void testReturnStructArgumentStruct8BytesHomogeneousFloat() { + final a0Pointer = calloc(); + final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; + + a0.a0 = -1.0; + a0.a1 = 2.0; + + final result = returnStructArgumentStruct8BytesHomogeneousFloat(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0); + Expect.approxEquals(a0.a1, result.a1); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStruct20BytesHomogeneousInt32 = + ffiTestFunctions + .lookupFunction< + Struct20BytesHomogeneousInt32 Function( + Struct20BytesHomogeneousInt32), + Struct20BytesHomogeneousInt32 Function( + Struct20BytesHomogeneousInt32)>( + "ReturnStructArgumentStruct20BytesHomogeneousInt32"); + +/// On arm64, both argument and return value are passed in by pointer. +void testReturnStructArgumentStruct20BytesHomogeneousInt32() { + final a0Pointer = calloc(); + final Struct20BytesHomogeneousInt32 a0 = a0Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a0.a3 = 4; + a0.a4 = -5; + + final result = returnStructArgumentStruct20BytesHomogeneousInt32(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0); + Expect.equals(a0.a1, result.a1); + Expect.equals(a0.a2, result.a2); + Expect.equals(a0.a3, result.a3); + Expect.equals(a0.a4, result.a4); + + calloc.free(a0Pointer); +} + +final returnStructArgumentInt32x8Struct20BytesHomogeneou = + ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, + Int32, Int32, Int32, Int32, Struct20BytesHomogeneousInt32), + Struct20BytesHomogeneousInt32 Function(int, int, int, int, int, int, + int, int, Struct20BytesHomogeneousInt32)>( + "ReturnStructArgumentInt32x8Struct20BytesHomogeneou"); + +/// On arm64, both argument and return value are passed in by pointer. +/// Ints exhaust registers, so that pointer is passed on stack. +void testReturnStructArgumentInt32x8Struct20BytesHomogeneou() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + final a8Pointer = calloc(); + final Struct20BytesHomogeneousInt32 a8 = a8Pointer.ref; + + 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; + + final result = returnStructArgumentInt32x8Struct20BytesHomogeneou( + a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a8.a0, result.a0); + Expect.equals(a8.a1, result.a1); + Expect.equals(a8.a2, result.a2); + Expect.equals(a8.a3, result.a3); + Expect.equals(a8.a4, result.a4); + + calloc.free(a8Pointer); +} + +final returnStructArgumentStruct8BytesInlineArrayInt = + ffiTestFunctions.lookupFunction< + Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt), + Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt)>( + "ReturnStructArgumentStruct8BytesInlineArrayInt"); + +/// Test returning struct with inline array. +void testReturnStructArgumentStruct8BytesInlineArrayInt() { + final a0Pointer = calloc(); + final Struct8BytesInlineArrayInt a0 = a0Pointer.ref; + + 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; + + final result = returnStructArgumentStruct8BytesInlineArrayInt(a0); + + print("result = $result"); + + for (int i = 0; i < 8; i++) { + Expect.equals(a0.a0[i], result.a0[i]); + } + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct16BytesHomogeneous = + ffiTestFunctions.lookupFunction< + StructStruct16BytesHomogeneousFloat2 Function( + StructStruct16BytesHomogeneousFloat2), + StructStruct16BytesHomogeneousFloat2 Function( + StructStruct16BytesHomogeneousFloat2)>( + "ReturnStructArgumentStructStruct16BytesHomogeneous"); + +/// Return value in FPU registers on arm hardfp and arm64. +void testReturnStructArgumentStructStruct16BytesHomogeneous() { + final a0Pointer = calloc(); + final StructStruct16BytesHomogeneousFloat2 a0 = a0Pointer.ref; + + a0.a0.a0 = -1.0; + a0.a1[0].a0 = 2.0; + a0.a1[1].a0 = -3.0; + a0.a2 = 4.0; + + final result = returnStructArgumentStructStruct16BytesHomogeneous(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 2; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + } + Expect.approxEquals(a0.a2, result.a2); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct32BytesHomogeneous = + ffiTestFunctions.lookupFunction< + StructStruct32BytesHomogeneousDouble2 Function( + StructStruct32BytesHomogeneousDouble2), + StructStruct32BytesHomogeneousDouble2 Function( + StructStruct32BytesHomogeneousDouble2)>( + "ReturnStructArgumentStructStruct32BytesHomogeneous"); + +/// Return value in FPU registers on arm64. +void testReturnStructArgumentStructStruct32BytesHomogeneous() { + final a0Pointer = calloc(); + final StructStruct32BytesHomogeneousDouble2 a0 = a0Pointer.ref; + + a0.a0.a0 = -1.0; + a0.a1[0].a0 = 2.0; + a0.a1[1].a0 = -3.0; + a0.a2 = 4.0; + + final result = returnStructArgumentStructStruct32BytesHomogeneous(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 2; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + } + Expect.approxEquals(a0.a2, result.a2); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct16BytesMixed3 = + ffiTestFunctions.lookupFunction< + StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3), + StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3)>( + "ReturnStructArgumentStructStruct16BytesMixed3"); + +/// On x64 Linux, return value is split over FP and int registers. +void testReturnStructArgumentStructStruct16BytesMixed3() { + final a0Pointer = calloc(); + final StructStruct16BytesMixed3 a0 = a0Pointer.ref; + + 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; + + final result = returnStructArgumentStructStruct16BytesMixed3(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 1; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + Expect.equals(a0.a1[i].a1, result.a1[i].a1); + Expect.equals(a0.a1[i].a2, result.a1[i].a2); + } + for (int i = 0; i < 2; i++) { + Expect.equals(a0.a2[i], result.a2[i]); + } + + calloc.free(a0Pointer); +} + +final returnStructAlignmentInt16 = ffiTestFunctions.lookupFunction< + StructAlignmentInt16 Function(Int8, Int16, Int8), + StructAlignmentInt16 Function(int, int, int)>("ReturnStructAlignmentInt16"); + +/// Test alignment and padding of 16 byte int within struct. +void testReturnStructAlignmentInt16() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt16(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStructAlignmentInt32 = ffiTestFunctions.lookupFunction< + StructAlignmentInt32 Function(Int8, Int32, Int8), + StructAlignmentInt32 Function(int, int, int)>("ReturnStructAlignmentInt32"); + +/// Test alignment and padding of 32 byte int within struct. +void testReturnStructAlignmentInt32() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt32(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStructAlignmentInt64 = ffiTestFunctions.lookupFunction< + StructAlignmentInt64 Function(Int8, Int64, Int8), + StructAlignmentInt64 Function(int, int, int)>("ReturnStructAlignmentInt64"); + +/// Test alignment and padding of 64 byte int within struct. +void testReturnStructAlignmentInt64() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt64(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesNestedInt = ffiTestFunctions.lookupFunction< + Struct8BytesNestedInt Function( + Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16), + Struct8BytesNestedInt Function(Struct4BytesHomogeneousInt16, + Struct4BytesHomogeneousInt16)>("ReturnStruct8BytesNestedInt"); + +/// Simple nested struct. +void testReturnStruct8BytesNestedInt() { + final a0Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a1.a0 = -3; + a1.a1 = 4; + + final result = returnStruct8BytesNestedInt(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct8BytesNestedFloat = ffiTestFunctions.lookupFunction< + Struct8BytesNestedFloat Function(Struct4BytesFloat, Struct4BytesFloat), + Struct8BytesNestedFloat Function( + Struct4BytesFloat, Struct4BytesFloat)>("ReturnStruct8BytesNestedFloat"); + +/// Simple nested struct with floats. +void testReturnStruct8BytesNestedFloat() { + final a0Pointer = calloc(); + final Struct4BytesFloat a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesFloat a1 = a1Pointer.ref; + + a0.a0 = -1.0; + a1.a0 = 2.0; + + final result = returnStruct8BytesNestedFloat(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a1.a0, result.a1.a0); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct8BytesNestedFloat2 = ffiTestFunctions.lookupFunction< + Struct8BytesNestedFloat2 Function(Struct4BytesFloat, Float), + Struct8BytesNestedFloat2 Function( + Struct4BytesFloat, double)>("ReturnStruct8BytesNestedFloat2"); + +/// The nesting is irregular, testing homogenous float rules on arm and arm64, +/// and the fpu register usage on x64. +void testReturnStruct8BytesNestedFloat2() { + final a0Pointer = calloc(); + final Struct4BytesFloat a0 = a0Pointer.ref; + double a1; + + a0.a0 = -1.0; + a1 = 2.0; + + final result = returnStruct8BytesNestedFloat2(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a1, result.a1); + + calloc.free(a0Pointer); +} + +final returnStruct8BytesNestedMixed = ffiTestFunctions.lookupFunction< + Struct8BytesNestedMixed Function( + Struct4BytesHomogeneousInt16, Struct4BytesFloat), + Struct8BytesNestedMixed Function(Struct4BytesHomogeneousInt16, + Struct4BytesFloat)>("ReturnStruct8BytesNestedMixed"); + +/// Simple nested struct with mixed members. +void testReturnStruct8BytesNestedMixed() { + final a0Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesFloat a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a1.a0 = -3.0; + + final result = returnStruct8BytesNestedMixed(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.approxEquals(a1.a0, result.a1.a0); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct16BytesNestedInt = ffiTestFunctions.lookupFunction< + Struct16BytesNestedInt Function( + Struct8BytesNestedInt, Struct8BytesNestedInt), + Struct16BytesNestedInt Function(Struct8BytesNestedInt, + Struct8BytesNestedInt)>("ReturnStruct16BytesNestedInt"); + +/// Deeper nested struct to test recursive member access. +void testReturnStruct16BytesNestedInt() { + final a0Pointer = calloc(); + final Struct8BytesNestedInt a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct8BytesNestedInt a1 = a1Pointer.ref; + + 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; + + final result = returnStruct16BytesNestedInt(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0.a0, result.a0.a0.a0); + Expect.equals(a0.a0.a1, result.a0.a0.a1); + Expect.equals(a0.a1.a0, result.a0.a1.a0); + Expect.equals(a0.a1.a1, result.a0.a1.a1); + Expect.equals(a1.a0.a0, result.a1.a0.a0); + Expect.equals(a1.a0.a1, result.a1.a0.a1); + Expect.equals(a1.a1.a0, result.a1.a1.a0); + Expect.equals(a1.a1.a1, result.a1.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct32BytesNestedInt = ffiTestFunctions.lookupFunction< + Struct32BytesNestedInt Function( + Struct16BytesNestedInt, Struct16BytesNestedInt), + Struct32BytesNestedInt Function(Struct16BytesNestedInt, + Struct16BytesNestedInt)>("ReturnStruct32BytesNestedInt"); + +/// Even deeper nested struct to test recursive member access. +void testReturnStruct32BytesNestedInt() { + final a0Pointer = calloc(); + final Struct16BytesNestedInt a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct16BytesNestedInt a1 = a1Pointer.ref; + + 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; + + final result = returnStruct32BytesNestedInt(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0.a0.a0, result.a0.a0.a0.a0); + Expect.equals(a0.a0.a0.a1, result.a0.a0.a0.a1); + Expect.equals(a0.a0.a1.a0, result.a0.a0.a1.a0); + Expect.equals(a0.a0.a1.a1, result.a0.a0.a1.a1); + Expect.equals(a0.a1.a0.a0, result.a0.a1.a0.a0); + Expect.equals(a0.a1.a0.a1, result.a0.a1.a0.a1); + Expect.equals(a0.a1.a1.a0, result.a0.a1.a1.a0); + Expect.equals(a0.a1.a1.a1, result.a0.a1.a1.a1); + Expect.equals(a1.a0.a0.a0, result.a1.a0.a0.a0); + Expect.equals(a1.a0.a0.a1, result.a1.a0.a0.a1); + Expect.equals(a1.a0.a1.a0, result.a1.a0.a1.a0); + Expect.equals(a1.a0.a1.a1, result.a1.a0.a1.a1); + Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); + Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); + Expect.equals(a1.a1.a1.a0, result.a1.a1.a1.a0); + Expect.equals(a1.a1.a1.a1, result.a1.a1.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt16 = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt16 Function( + StructAlignmentInt16, StructAlignmentInt16), + StructNestedIntStructAlignmentInt16 Function(StructAlignmentInt16, + StructAlignmentInt16)>("ReturnStructNestedIntStructAlignmentInt16"); + +/// Test alignment and padding of nested struct with 16 byte int. +void testReturnStructNestedIntStructAlignmentInt16() { + final a0Pointer = calloc(); + final StructAlignmentInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt16 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt16(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt32 = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt32 Function( + StructAlignmentInt32, StructAlignmentInt32), + StructNestedIntStructAlignmentInt32 Function(StructAlignmentInt32, + StructAlignmentInt32)>("ReturnStructNestedIntStructAlignmentInt32"); + +/// Test alignment and padding of nested struct with 32 byte int. +void testReturnStructNestedIntStructAlignmentInt32() { + final a0Pointer = calloc(); + final StructAlignmentInt32 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt32 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt32(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt64 = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt64 Function( + StructAlignmentInt64, StructAlignmentInt64), + StructNestedIntStructAlignmentInt64 Function(StructAlignmentInt64, + StructAlignmentInt64)>("ReturnStructNestedIntStructAlignmentInt64"); + +/// Test alignment and padding of nested struct with 64 byte int. +void testReturnStructNestedIntStructAlignmentInt64() { + final a0Pointer = calloc(); + final StructAlignmentInt64 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt64 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt64(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIrregularEvenBigger = ffiTestFunctions.lookupFunction< + StructNestedIrregularEvenBigger Function(Uint64, + StructNestedIrregularBigger, StructNestedIrregularBigger, Double), + StructNestedIrregularEvenBigger Function( + int, + StructNestedIrregularBigger, + StructNestedIrregularBigger, + double)>("ReturnStructNestedIrregularEvenBigger"); + +/// Return big irregular struct as smoke test. +void testReturnStructNestedIrregularEvenBigger() { + int a0; + final a1Pointer = calloc(); + final StructNestedIrregularBigger a1 = a1Pointer.ref; + final a2Pointer = calloc(); + final StructNestedIrregularBigger a2 = a2Pointer.ref; + 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; + + final result = returnStructNestedIrregularEvenBigger(a0, a1, a2, a3); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1.a0.a0, result.a1.a0.a0); + Expect.equals(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0); + Expect.equals(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1); + Expect.approxEquals(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0); + Expect.equals(a1.a0.a2, result.a1.a0.a2); + Expect.approxEquals(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0); + Expect.approxEquals(a1.a0.a3.a1, result.a1.a0.a3.a1); + Expect.equals(a1.a0.a4, result.a1.a0.a4); + Expect.approxEquals(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0); + Expect.approxEquals(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0); + Expect.equals(a1.a0.a6, result.a1.a0.a6); + Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); + Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); + Expect.approxEquals(a1.a1.a1.a0, result.a1.a1.a1.a0); + Expect.approxEquals(a1.a2, result.a1.a2); + Expect.approxEquals(a1.a3, result.a1.a3); + Expect.equals(a2.a0.a0, result.a2.a0.a0); + Expect.equals(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0); + Expect.equals(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1); + Expect.approxEquals(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0); + Expect.equals(a2.a0.a2, result.a2.a0.a2); + Expect.approxEquals(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0); + Expect.approxEquals(a2.a0.a3.a1, result.a2.a0.a3.a1); + Expect.equals(a2.a0.a4, result.a2.a0.a4); + Expect.approxEquals(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0); + Expect.approxEquals(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0); + Expect.equals(a2.a0.a6, result.a2.a0.a6); + Expect.equals(a2.a1.a0.a0, result.a2.a1.a0.a0); + Expect.equals(a2.a1.a0.a1, result.a2.a1.a0.a1); + Expect.approxEquals(a2.a1.a1.a0, result.a2.a1.a1.a0); + Expect.approxEquals(a2.a2, result.a2.a2); + Expect.approxEquals(a2.a3, result.a2.a3); + Expect.approxEquals(a3, result.a3); + + calloc.free(a1Pointer); + calloc.free(a2Pointer); +} diff --git a/tests/ffi/function_structs_by_value_generated_ret_leaf_test.dart b/tests/ffi/function_structs_by_value_generated_ret_leaf_test.dart new file mode 100644 index 00000000000..df9ccde4e46 --- /dev/null +++ b/tests/ffi/function_structs_by_value_generated_ret_leaf_test.dart @@ -0,0 +1,1641 @@ +// Copyright (c) 2021, 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. +// Generated by tests/ffi/generator/structs_by_value_tests_generator.dart. +// +// SharedObjects=ffi_test_functions +// VMOptions= +// VMOptions=--deterministic --optimization-counter-threshold=90 +// VMOptions=--use-slow-path +// VMOptions=--use-slow-path --stacktrace-every=100 + +import 'dart:ffi'; + +import "package:expect/expect.dart"; +import "package:ffi/ffi.dart"; + +import 'dylib_utils.dart'; + +// Reuse the compound classes. +import 'function_structs_by_value_generated_compounds.dart'; + +final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); +void main() { + for (int i = 0; i < 100; ++i) { + testReturnStruct1ByteIntLeaf(); + testReturnStruct3BytesHomogeneousUint8Leaf(); + testReturnStruct3BytesInt2ByteAlignedLeaf(); + testReturnStruct4BytesHomogeneousInt16Leaf(); + testReturnStruct7BytesHomogeneousUint8Leaf(); + testReturnStruct7BytesInt4ByteAlignedLeaf(); + testReturnStruct8BytesIntLeaf(); + testReturnStruct8BytesHomogeneousFloatLeaf(); + testReturnStruct8BytesMixedLeaf(); + testReturnStruct9BytesHomogeneousUint8Leaf(); + testReturnStruct9BytesInt4Or8ByteAlignedLeaf(); + testReturnStruct12BytesHomogeneousFloatLeaf(); + testReturnStruct16BytesHomogeneousFloatLeaf(); + testReturnStruct16BytesMixedLeaf(); + testReturnStruct16BytesMixed2Leaf(); + testReturnStruct17BytesIntLeaf(); + testReturnStruct19BytesHomogeneousUint8Leaf(); + testReturnStruct20BytesHomogeneousInt32Leaf(); + testReturnStruct20BytesHomogeneousFloatLeaf(); + testReturnStruct32BytesHomogeneousDoubleLeaf(); + testReturnStruct40BytesHomogeneousDoubleLeaf(); + testReturnStruct1024BytesHomogeneousUint64Leaf(); + testReturnStruct3BytesPackedIntLeaf(); + testReturnStruct8BytesPackedIntLeaf(); + testReturnStruct9BytesPackedMixedLeaf(); + testReturnUnion4BytesMixedLeaf(); + testReturnUnion8BytesNestedFloatLeaf(); + testReturnUnion9BytesNestedIntLeaf(); + testReturnUnion16BytesNestedFloatLeaf(); + } +} + +final returnStruct1ByteIntLeaf = ffiTestFunctions.lookupFunction< + Struct1ByteInt Function(Int8), + Struct1ByteInt Function(int)>("ReturnStruct1ByteInt", isLeaf: true); + +/// Smallest struct with data. +void testReturnStruct1ByteIntLeaf() { + int a0; + + a0 = -1; + + final result = returnStruct1ByteIntLeaf(a0); + + print("result = $result"); + + Expect.equals(a0, result.a0); +} + +final returnStruct3BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< + Struct3BytesHomogeneousUint8 Function(Uint8, Uint8, Uint8), + Struct3BytesHomogeneousUint8 Function( + int, int, int)>("ReturnStruct3BytesHomogeneousUint8", isLeaf: true); + +/// Smaller than word size return value on all architectures. +void testReturnStruct3BytesHomogeneousUint8Leaf() { + int a0; + int a1; + int a2; + + a0 = 1; + a1 = 2; + a2 = 3; + + final result = returnStruct3BytesHomogeneousUint8Leaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct3BytesInt2ByteAlignedLeaf = ffiTestFunctions.lookupFunction< + Struct3BytesInt2ByteAligned Function(Int16, Int8), + Struct3BytesInt2ByteAligned Function( + int, int)>("ReturnStruct3BytesInt2ByteAligned", isLeaf: true); + +/// Smaller than word size return value on all architectures. +/// With alignment rules taken into account size is 4 bytes. +void testReturnStruct3BytesInt2ByteAlignedLeaf() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct3BytesInt2ByteAlignedLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct4BytesHomogeneousInt16Leaf = ffiTestFunctions.lookupFunction< + Struct4BytesHomogeneousInt16 Function(Int16, Int16), + Struct4BytesHomogeneousInt16 Function( + int, int)>("ReturnStruct4BytesHomogeneousInt16", isLeaf: true); + +/// Word size return value on 32 bit architectures.. +void testReturnStruct4BytesHomogeneousInt16Leaf() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct4BytesHomogeneousInt16Leaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct7BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< + Struct7BytesHomogeneousUint8 Function( + Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), + Struct7BytesHomogeneousUint8 Function(int, int, int, int, int, int, + int)>("ReturnStruct7BytesHomogeneousUint8", isLeaf: true); + +/// Non-wordsize return value. +void testReturnStruct7BytesHomogeneousUint8Leaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + a5 = 6; + a6 = 7; + + final result = + returnStruct7BytesHomogeneousUint8Leaf(a0, a1, a2, a3, a4, a5, a6); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); +} + +final returnStruct7BytesInt4ByteAlignedLeaf = ffiTestFunctions.lookupFunction< + Struct7BytesInt4ByteAligned Function(Int32, Int16, Int8), + Struct7BytesInt4ByteAligned Function( + int, int, int)>("ReturnStruct7BytesInt4ByteAligned", isLeaf: true); + +/// Non-wordsize return value. +/// With alignment rules taken into account size is 8 bytes. +void testReturnStruct7BytesInt4ByteAlignedLeaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct7BytesInt4ByteAlignedLeaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesIntLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesInt Function(Int16, Int16, Int32), + Struct8BytesInt Function( + int, int, int)>("ReturnStruct8BytesInt", isLeaf: true); + +/// Return value in integer registers on many architectures. +void testReturnStruct8BytesIntLeaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct8BytesIntLeaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesHomogeneousFloat Function(Float, Float), + Struct8BytesHomogeneousFloat Function( + double, double)>("ReturnStruct8BytesHomogeneousFloat", isLeaf: true); + +/// Return value in FP registers on many architectures. +void testReturnStruct8BytesHomogeneousFloatLeaf() { + double a0; + double a1; + + a0 = -1.0; + a1 = 2.0; + + final result = returnStruct8BytesHomogeneousFloatLeaf(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); +} + +final returnStruct8BytesMixedLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesMixed Function(Float, Int16, Int16), + Struct8BytesMixed Function( + double, int, int)>("ReturnStruct8BytesMixed", isLeaf: true); + +/// Return value split over FP and integer register in x64. +void testReturnStruct8BytesMixedLeaf() { + double a0; + int a1; + int a2; + + a0 = -1.0; + a1 = 2; + a2 = -3; + + final result = returnStruct8BytesMixedLeaf(a0, a1, a2); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct9BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< + Struct9BytesHomogeneousUint8 Function( + Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), + Struct9BytesHomogeneousUint8 Function(int, int, int, int, int, int, int, + int, int)>("ReturnStruct9BytesHomogeneousUint8", isLeaf: true); + +/// 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. +void testReturnStruct9BytesHomogeneousUint8Leaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + a5 = 6; + a6 = 7; + a7 = 8; + a8 = 9; + + final result = returnStruct9BytesHomogeneousUint8Leaf( + a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); +} + +final returnStruct9BytesInt4Or8ByteAlignedLeaf = + ffiTestFunctions.lookupFunction< + Struct9BytesInt4Or8ByteAligned Function(Int64, Int8), + Struct9BytesInt4Or8ByteAligned Function( + int, int)>("ReturnStruct9BytesInt4Or8ByteAligned", isLeaf: true); + +/// Return value in two integer registers on x64. +/// With alignment rules taken into account size is 12 or 16 bytes. +void testReturnStruct9BytesInt4Or8ByteAlignedLeaf() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct9BytesInt4Or8ByteAlignedLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct12BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< + Struct12BytesHomogeneousFloat Function(Float, Float, Float), + Struct12BytesHomogeneousFloat Function(double, double, + double)>("ReturnStruct12BytesHomogeneousFloat", isLeaf: true); + +/// Return value in FPU registers, but does not use all registers on arm hardfp +/// and arm64. +void testReturnStruct12BytesHomogeneousFloatLeaf() { + double a0; + double a1; + double a2; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + + final result = returnStruct12BytesHomogeneousFloatLeaf(a0, a1, a2); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); +} + +final returnStruct16BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< + Struct16BytesHomogeneousFloat Function(Float, Float, Float, Float), + Struct16BytesHomogeneousFloat Function(double, double, double, + double)>("ReturnStruct16BytesHomogeneousFloat", isLeaf: true); + +/// Return value in FPU registers on arm hardfp and arm64. +void testReturnStruct16BytesHomogeneousFloatLeaf() { + double a0; + double a1; + double a2; + double a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4.0; + + final result = returnStruct16BytesHomogeneousFloatLeaf(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); +} + +final returnStruct16BytesMixedLeaf = ffiTestFunctions.lookupFunction< + Struct16BytesMixed Function(Double, Int64), + Struct16BytesMixed Function( + double, int)>("ReturnStruct16BytesMixed", isLeaf: true); + +/// Return value split over FP and integer register in x64. +void testReturnStruct16BytesMixedLeaf() { + double a0; + int a1; + + a0 = -1.0; + a1 = 2; + + final result = returnStruct16BytesMixedLeaf(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct16BytesMixed2Leaf = ffiTestFunctions.lookupFunction< + Struct16BytesMixed2 Function(Float, Float, Float, Int32), + Struct16BytesMixed2 Function(double, double, double, + int)>("ReturnStruct16BytesMixed2", isLeaf: true); + +/// Return value split over FP and integer register in x64. +/// The integer register contains half float half int. +void testReturnStruct16BytesMixed2Leaf() { + double a0; + double a1; + double a2; + int a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4; + + final result = returnStruct16BytesMixed2Leaf(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.equals(a3, result.a3); +} + +final returnStruct17BytesIntLeaf = ffiTestFunctions.lookupFunction< + Struct17BytesInt Function(Int64, Int64, Int8), + Struct17BytesInt Function( + int, int, int)>("ReturnStruct17BytesInt", isLeaf: true); + +/// 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. +void testReturnStruct17BytesIntLeaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct17BytesIntLeaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct19BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< + Struct19BytesHomogeneousUint8 Function( + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8), + Struct19BytesHomogeneousUint8 Function( + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int)>("ReturnStruct19BytesHomogeneousUint8", isLeaf: true); + +/// 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. +void testReturnStruct19BytesHomogeneousUint8Leaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + int a9; + int a10; + int a11; + int a12; + int a13; + int a14; + int a15; + int a16; + int a17; + int 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; + + final result = returnStruct19BytesHomogeneousUint8Leaf(a0, a1, a2, a3, a4, a5, + a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); + Expect.equals(a9, result.a9); + Expect.equals(a10, result.a10); + Expect.equals(a11, result.a11); + Expect.equals(a12, result.a12); + Expect.equals(a13, result.a13); + Expect.equals(a14, result.a14); + Expect.equals(a15, result.a15); + Expect.equals(a16, result.a16); + Expect.equals(a17, result.a17); + Expect.equals(a18, result.a18); +} + +final returnStruct20BytesHomogeneousInt32Leaf = ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32), + Struct20BytesHomogeneousInt32 Function(int, int, int, int, + int)>("ReturnStruct20BytesHomogeneousInt32", isLeaf: true); + +/// Return value too big to go in cpu registers on arm64. +void testReturnStruct20BytesHomogeneousInt32Leaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + + a0 = -1; + a1 = 2; + a2 = -3; + a3 = 4; + a4 = -5; + + final result = returnStruct20BytesHomogeneousInt32Leaf(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); +} + +final returnStruct20BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousFloat Function(Float, Float, Float, Float, Float), + Struct20BytesHomogeneousFloat Function(double, double, double, double, + double)>("ReturnStruct20BytesHomogeneousFloat", isLeaf: true); + +/// Return value too big to go in FPU registers on x64, arm hardfp and arm64. +void testReturnStruct20BytesHomogeneousFloatLeaf() { + 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; + + final result = returnStruct20BytesHomogeneousFloatLeaf(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); + Expect.approxEquals(a4, result.a4); +} + +final returnStruct32BytesHomogeneousDoubleLeaf = + ffiTestFunctions.lookupFunction< + Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double), + Struct32BytesHomogeneousDouble Function(double, double, double, + double)>("ReturnStruct32BytesHomogeneousDouble", isLeaf: true); + +/// Return value in FPU registers on arm64. +void testReturnStruct32BytesHomogeneousDoubleLeaf() { + double a0; + double a1; + double a2; + double a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4.0; + + final result = returnStruct32BytesHomogeneousDoubleLeaf(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); +} + +final returnStruct40BytesHomogeneousDoubleLeaf = + ffiTestFunctions.lookupFunction< + Struct40BytesHomogeneousDouble Function( + Double, Double, Double, Double, Double), + Struct40BytesHomogeneousDouble Function(double, double, double, double, + double)>("ReturnStruct40BytesHomogeneousDouble", isLeaf: true); + +/// Return value too big to go in FPU registers on arm64. +void testReturnStruct40BytesHomogeneousDoubleLeaf() { + 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; + + final result = returnStruct40BytesHomogeneousDoubleLeaf(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); + Expect.approxEquals(a4, result.a4); +} + +final returnStruct1024BytesHomogeneousUint64Leaf = + ffiTestFunctions.lookupFunction< + Struct1024BytesHomogeneousUint64 Function( + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64), + Struct1024BytesHomogeneousUint64 Function( + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int)>("ReturnStruct1024BytesHomogeneousUint64", isLeaf: true); + +/// Test 1kb struct. +void testReturnStruct1024BytesHomogeneousUint64Leaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + int a9; + int a10; + int a11; + int a12; + int a13; + int a14; + int a15; + int a16; + int a17; + int a18; + int a19; + int a20; + int a21; + int a22; + int a23; + int a24; + int a25; + int a26; + int a27; + int a28; + int a29; + int a30; + int a31; + int a32; + int a33; + int a34; + int a35; + int a36; + int a37; + int a38; + int a39; + int a40; + int a41; + int a42; + int a43; + int a44; + int a45; + int a46; + int a47; + int a48; + int a49; + int a50; + int a51; + int a52; + int a53; + int a54; + int a55; + int a56; + int a57; + int a58; + int a59; + int a60; + int a61; + int a62; + int a63; + int a64; + int a65; + int a66; + int a67; + int a68; + int a69; + int a70; + int a71; + int a72; + int a73; + int a74; + int a75; + int a76; + int a77; + int a78; + int a79; + int a80; + int a81; + int a82; + int a83; + int a84; + int a85; + int a86; + int a87; + int a88; + int a89; + int a90; + int a91; + int a92; + int a93; + int a94; + int a95; + int a96; + int a97; + int a98; + int a99; + int a100; + int a101; + int a102; + int a103; + int a104; + int a105; + int a106; + int a107; + int a108; + int a109; + int a110; + int a111; + int a112; + int a113; + int a114; + int a115; + int a116; + int a117; + int a118; + int a119; + int a120; + int a121; + int a122; + int a123; + int a124; + int a125; + int a126; + int 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; + + final result = returnStruct1024BytesHomogeneousUint64Leaf( + 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); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); + Expect.equals(a9, result.a9); + Expect.equals(a10, result.a10); + Expect.equals(a11, result.a11); + Expect.equals(a12, result.a12); + Expect.equals(a13, result.a13); + Expect.equals(a14, result.a14); + Expect.equals(a15, result.a15); + Expect.equals(a16, result.a16); + Expect.equals(a17, result.a17); + Expect.equals(a18, result.a18); + Expect.equals(a19, result.a19); + Expect.equals(a20, result.a20); + Expect.equals(a21, result.a21); + Expect.equals(a22, result.a22); + Expect.equals(a23, result.a23); + Expect.equals(a24, result.a24); + Expect.equals(a25, result.a25); + Expect.equals(a26, result.a26); + Expect.equals(a27, result.a27); + Expect.equals(a28, result.a28); + Expect.equals(a29, result.a29); + Expect.equals(a30, result.a30); + Expect.equals(a31, result.a31); + Expect.equals(a32, result.a32); + Expect.equals(a33, result.a33); + Expect.equals(a34, result.a34); + Expect.equals(a35, result.a35); + Expect.equals(a36, result.a36); + Expect.equals(a37, result.a37); + Expect.equals(a38, result.a38); + Expect.equals(a39, result.a39); + Expect.equals(a40, result.a40); + Expect.equals(a41, result.a41); + Expect.equals(a42, result.a42); + Expect.equals(a43, result.a43); + Expect.equals(a44, result.a44); + Expect.equals(a45, result.a45); + Expect.equals(a46, result.a46); + Expect.equals(a47, result.a47); + Expect.equals(a48, result.a48); + Expect.equals(a49, result.a49); + Expect.equals(a50, result.a50); + Expect.equals(a51, result.a51); + Expect.equals(a52, result.a52); + Expect.equals(a53, result.a53); + Expect.equals(a54, result.a54); + Expect.equals(a55, result.a55); + Expect.equals(a56, result.a56); + Expect.equals(a57, result.a57); + Expect.equals(a58, result.a58); + Expect.equals(a59, result.a59); + Expect.equals(a60, result.a60); + Expect.equals(a61, result.a61); + Expect.equals(a62, result.a62); + Expect.equals(a63, result.a63); + Expect.equals(a64, result.a64); + Expect.equals(a65, result.a65); + Expect.equals(a66, result.a66); + Expect.equals(a67, result.a67); + Expect.equals(a68, result.a68); + Expect.equals(a69, result.a69); + Expect.equals(a70, result.a70); + Expect.equals(a71, result.a71); + Expect.equals(a72, result.a72); + Expect.equals(a73, result.a73); + Expect.equals(a74, result.a74); + Expect.equals(a75, result.a75); + Expect.equals(a76, result.a76); + Expect.equals(a77, result.a77); + Expect.equals(a78, result.a78); + Expect.equals(a79, result.a79); + Expect.equals(a80, result.a80); + Expect.equals(a81, result.a81); + Expect.equals(a82, result.a82); + Expect.equals(a83, result.a83); + Expect.equals(a84, result.a84); + Expect.equals(a85, result.a85); + Expect.equals(a86, result.a86); + Expect.equals(a87, result.a87); + Expect.equals(a88, result.a88); + Expect.equals(a89, result.a89); + Expect.equals(a90, result.a90); + Expect.equals(a91, result.a91); + Expect.equals(a92, result.a92); + Expect.equals(a93, result.a93); + Expect.equals(a94, result.a94); + Expect.equals(a95, result.a95); + Expect.equals(a96, result.a96); + Expect.equals(a97, result.a97); + Expect.equals(a98, result.a98); + Expect.equals(a99, result.a99); + Expect.equals(a100, result.a100); + Expect.equals(a101, result.a101); + Expect.equals(a102, result.a102); + Expect.equals(a103, result.a103); + Expect.equals(a104, result.a104); + Expect.equals(a105, result.a105); + Expect.equals(a106, result.a106); + Expect.equals(a107, result.a107); + Expect.equals(a108, result.a108); + Expect.equals(a109, result.a109); + Expect.equals(a110, result.a110); + Expect.equals(a111, result.a111); + Expect.equals(a112, result.a112); + Expect.equals(a113, result.a113); + Expect.equals(a114, result.a114); + Expect.equals(a115, result.a115); + Expect.equals(a116, result.a116); + Expect.equals(a117, result.a117); + Expect.equals(a118, result.a118); + Expect.equals(a119, result.a119); + Expect.equals(a120, result.a120); + Expect.equals(a121, result.a121); + Expect.equals(a122, result.a122); + Expect.equals(a123, result.a123); + Expect.equals(a124, result.a124); + Expect.equals(a125, result.a125); + Expect.equals(a126, result.a126); + Expect.equals(a127, result.a127); +} + +final returnStruct3BytesPackedIntLeaf = ffiTestFunctions.lookupFunction< + Struct3BytesPackedInt Function(Int8, Int16), + Struct3BytesPackedInt Function( + int, int)>("ReturnStruct3BytesPackedInt", isLeaf: true); + +/// Small struct with mis-aligned member. +void testReturnStruct3BytesPackedIntLeaf() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct3BytesPackedIntLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct8BytesPackedIntLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesPackedInt Function(Uint8, Uint32, Uint8, Uint8, Uint8), + Struct8BytesPackedInt Function( + int, int, int, int, int)>("ReturnStruct8BytesPackedInt", isLeaf: true); + +/// Struct with mis-aligned member. +void testReturnStruct8BytesPackedIntLeaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + + final result = returnStruct8BytesPackedIntLeaf(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); +} + +final returnStruct9BytesPackedMixedLeaf = ffiTestFunctions.lookupFunction< + Struct9BytesPackedMixed Function(Uint8, Double), + Struct9BytesPackedMixed Function( + int, double)>("ReturnStruct9BytesPackedMixed", isLeaf: true); + +/// Struct with mis-aligned member. +/// Tests backfilling of CPU and FPU registers. +void testReturnStruct9BytesPackedMixedLeaf() { + int a0; + double a1; + + a0 = 1; + a1 = 2.0; + + final result = returnStruct9BytesPackedMixedLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.approxEquals(a1, result.a1); +} + +final returnUnion4BytesMixedLeaf = ffiTestFunctions.lookupFunction< + Union4BytesMixed Function(Uint32), + Union4BytesMixed Function(int)>("ReturnUnion4BytesMixed", isLeaf: true); + +/// Returning a mixed integer/float union. +void testReturnUnion4BytesMixedLeaf() { + int a0; + + a0 = 1; + + final result = returnUnion4BytesMixedLeaf(a0); + + print("result = $result"); + + Expect.equals(a0, result.a0); +} + +final returnUnion8BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< + Union8BytesNestedFloat Function(Double), + Union8BytesNestedFloat Function( + double)>("ReturnUnion8BytesNestedFloat", isLeaf: true); + +/// Returning a floating point only union. +void testReturnUnion8BytesNestedFloatLeaf() { + double a0; + + a0 = -1.0; + + final result = returnUnion8BytesNestedFloatLeaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); +} + +final returnUnion9BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< + Union9BytesNestedInt Function(Struct8BytesInt), + Union9BytesNestedInt Function( + Struct8BytesInt)>("ReturnUnion9BytesNestedInt", isLeaf: true); + +/// Returning a mixed-size union. +void testReturnUnion9BytesNestedIntLeaf() { + final a0Pointer = calloc(); + final Struct8BytesInt a0 = a0Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + + final result = returnUnion9BytesNestedIntLeaf(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + + calloc.free(a0Pointer); +} + +final returnUnion16BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< + Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat), + Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat)>( + "ReturnUnion16BytesNestedFloat", + isLeaf: true); + +/// Returning union with homogenous floats. +void testReturnUnion16BytesNestedFloatLeaf() { + final a0Pointer = calloc(); + final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; + + a0.a0 = -1.0; + a0.a1 = 2.0; + + final result = returnUnion16BytesNestedFloatLeaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a0.a1, result.a0.a1); + + calloc.free(a0Pointer); +} diff --git a/tests/ffi/function_structs_by_value_generated_ret_test.dart b/tests/ffi/function_structs_by_value_generated_ret_test.dart new file mode 100644 index 00000000000..03300ac517a --- /dev/null +++ b/tests/ffi/function_structs_by_value_generated_ret_test.dart @@ -0,0 +1,1629 @@ +// 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. +// Generated by tests/ffi/generator/structs_by_value_tests_generator.dart. +// +// SharedObjects=ffi_test_functions +// VMOptions= +// VMOptions=--deterministic --optimization-counter-threshold=90 +// VMOptions=--use-slow-path +// VMOptions=--use-slow-path --stacktrace-every=100 + +import 'dart:ffi'; + +import "package:expect/expect.dart"; +import "package:ffi/ffi.dart"; + +import 'dylib_utils.dart'; + +// Reuse the compound classes. +import 'function_structs_by_value_generated_compounds.dart'; + +final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); +void main() { + for (int i = 0; i < 100; ++i) { + testReturnStruct1ByteInt(); + testReturnStruct3BytesHomogeneousUint8(); + testReturnStruct3BytesInt2ByteAligned(); + testReturnStruct4BytesHomogeneousInt16(); + testReturnStruct7BytesHomogeneousUint8(); + testReturnStruct7BytesInt4ByteAligned(); + testReturnStruct8BytesInt(); + testReturnStruct8BytesHomogeneousFloat(); + testReturnStruct8BytesMixed(); + testReturnStruct9BytesHomogeneousUint8(); + testReturnStruct9BytesInt4Or8ByteAligned(); + testReturnStruct12BytesHomogeneousFloat(); + testReturnStruct16BytesHomogeneousFloat(); + testReturnStruct16BytesMixed(); + testReturnStruct16BytesMixed2(); + testReturnStruct17BytesInt(); + testReturnStruct19BytesHomogeneousUint8(); + testReturnStruct20BytesHomogeneousInt32(); + testReturnStruct20BytesHomogeneousFloat(); + testReturnStruct32BytesHomogeneousDouble(); + testReturnStruct40BytesHomogeneousDouble(); + testReturnStruct1024BytesHomogeneousUint64(); + testReturnStruct3BytesPackedInt(); + testReturnStruct8BytesPackedInt(); + testReturnStruct9BytesPackedMixed(); + testReturnUnion4BytesMixed(); + testReturnUnion8BytesNestedFloat(); + testReturnUnion9BytesNestedInt(); + testReturnUnion16BytesNestedFloat(); + } +} + +final returnStruct1ByteInt = ffiTestFunctions.lookupFunction< + Struct1ByteInt Function(Int8), + Struct1ByteInt Function(int)>("ReturnStruct1ByteInt"); + +/// Smallest struct with data. +void testReturnStruct1ByteInt() { + int a0; + + a0 = -1; + + final result = returnStruct1ByteInt(a0); + + print("result = $result"); + + Expect.equals(a0, result.a0); +} + +final returnStruct3BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< + Struct3BytesHomogeneousUint8 Function(Uint8, Uint8, Uint8), + Struct3BytesHomogeneousUint8 Function( + int, int, int)>("ReturnStruct3BytesHomogeneousUint8"); + +/// Smaller than word size return value on all architectures. +void testReturnStruct3BytesHomogeneousUint8() { + int a0; + int a1; + int a2; + + a0 = 1; + a1 = 2; + a2 = 3; + + final result = returnStruct3BytesHomogeneousUint8(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct3BytesInt2ByteAligned = ffiTestFunctions.lookupFunction< + Struct3BytesInt2ByteAligned Function(Int16, Int8), + Struct3BytesInt2ByteAligned Function( + int, int)>("ReturnStruct3BytesInt2ByteAligned"); + +/// Smaller than word size return value on all architectures. +/// With alignment rules taken into account size is 4 bytes. +void testReturnStruct3BytesInt2ByteAligned() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct3BytesInt2ByteAligned(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct4BytesHomogeneousInt16 = ffiTestFunctions.lookupFunction< + Struct4BytesHomogeneousInt16 Function(Int16, Int16), + Struct4BytesHomogeneousInt16 Function( + int, int)>("ReturnStruct4BytesHomogeneousInt16"); + +/// Word size return value on 32 bit architectures.. +void testReturnStruct4BytesHomogeneousInt16() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct4BytesHomogeneousInt16(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct7BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< + Struct7BytesHomogeneousUint8 Function( + Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), + Struct7BytesHomogeneousUint8 Function(int, int, int, int, int, int, + int)>("ReturnStruct7BytesHomogeneousUint8"); + +/// Non-wordsize return value. +void testReturnStruct7BytesHomogeneousUint8() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + a5 = 6; + a6 = 7; + + final result = returnStruct7BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); +} + +final returnStruct7BytesInt4ByteAligned = ffiTestFunctions.lookupFunction< + Struct7BytesInt4ByteAligned Function(Int32, Int16, Int8), + Struct7BytesInt4ByteAligned Function( + int, int, int)>("ReturnStruct7BytesInt4ByteAligned"); + +/// Non-wordsize return value. +/// With alignment rules taken into account size is 8 bytes. +void testReturnStruct7BytesInt4ByteAligned() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct7BytesInt4ByteAligned(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesInt = ffiTestFunctions.lookupFunction< + Struct8BytesInt Function(Int16, Int16, Int32), + Struct8BytesInt Function(int, int, int)>("ReturnStruct8BytesInt"); + +/// Return value in integer registers on many architectures. +void testReturnStruct8BytesInt() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct8BytesInt(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< + Struct8BytesHomogeneousFloat Function(Float, Float), + Struct8BytesHomogeneousFloat Function( + double, double)>("ReturnStruct8BytesHomogeneousFloat"); + +/// Return value in FP registers on many architectures. +void testReturnStruct8BytesHomogeneousFloat() { + double a0; + double a1; + + a0 = -1.0; + a1 = 2.0; + + final result = returnStruct8BytesHomogeneousFloat(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); +} + +final returnStruct8BytesMixed = ffiTestFunctions.lookupFunction< + Struct8BytesMixed Function(Float, Int16, Int16), + Struct8BytesMixed Function(double, int, int)>("ReturnStruct8BytesMixed"); + +/// Return value split over FP and integer register in x64. +void testReturnStruct8BytesMixed() { + double a0; + int a1; + int a2; + + a0 = -1.0; + a1 = 2; + a2 = -3; + + final result = returnStruct8BytesMixed(a0, a1, a2); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct9BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< + Struct9BytesHomogeneousUint8 Function( + Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), + Struct9BytesHomogeneousUint8 Function(int, int, int, int, int, int, int, + int, int)>("ReturnStruct9BytesHomogeneousUint8"); + +/// 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. +void testReturnStruct9BytesHomogeneousUint8() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + a5 = 6; + a6 = 7; + a7 = 8; + a8 = 9; + + final result = + returnStruct9BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); +} + +final returnStruct9BytesInt4Or8ByteAligned = ffiTestFunctions.lookupFunction< + Struct9BytesInt4Or8ByteAligned Function(Int64, Int8), + Struct9BytesInt4Or8ByteAligned Function( + int, int)>("ReturnStruct9BytesInt4Or8ByteAligned"); + +/// Return value in two integer registers on x64. +/// With alignment rules taken into account size is 12 or 16 bytes. +void testReturnStruct9BytesInt4Or8ByteAligned() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct9BytesInt4Or8ByteAligned(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct12BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< + Struct12BytesHomogeneousFloat Function(Float, Float, Float), + Struct12BytesHomogeneousFloat Function( + double, double, double)>("ReturnStruct12BytesHomogeneousFloat"); + +/// Return value in FPU registers, but does not use all registers on arm hardfp +/// and arm64. +void testReturnStruct12BytesHomogeneousFloat() { + double a0; + double a1; + double a2; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + + final result = returnStruct12BytesHomogeneousFloat(a0, a1, a2); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); +} + +final returnStruct16BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< + Struct16BytesHomogeneousFloat Function(Float, Float, Float, Float), + Struct16BytesHomogeneousFloat Function( + double, double, double, double)>("ReturnStruct16BytesHomogeneousFloat"); + +/// Return value in FPU registers on arm hardfp and arm64. +void testReturnStruct16BytesHomogeneousFloat() { + double a0; + double a1; + double a2; + double a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4.0; + + final result = returnStruct16BytesHomogeneousFloat(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); +} + +final returnStruct16BytesMixed = ffiTestFunctions.lookupFunction< + Struct16BytesMixed Function(Double, Int64), + Struct16BytesMixed Function(double, int)>("ReturnStruct16BytesMixed"); + +/// Return value split over FP and integer register in x64. +void testReturnStruct16BytesMixed() { + double a0; + int a1; + + a0 = -1.0; + a1 = 2; + + final result = returnStruct16BytesMixed(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct16BytesMixed2 = ffiTestFunctions.lookupFunction< + Struct16BytesMixed2 Function(Float, Float, Float, Int32), + Struct16BytesMixed2 Function( + double, double, double, int)>("ReturnStruct16BytesMixed2"); + +/// Return value split over FP and integer register in x64. +/// The integer register contains half float half int. +void testReturnStruct16BytesMixed2() { + double a0; + double a1; + double a2; + int a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4; + + final result = returnStruct16BytesMixed2(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.equals(a3, result.a3); +} + +final returnStruct17BytesInt = ffiTestFunctions.lookupFunction< + Struct17BytesInt Function(Int64, Int64, Int8), + Struct17BytesInt Function(int, int, int)>("ReturnStruct17BytesInt"); + +/// 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. +void testReturnStruct17BytesInt() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct17BytesInt(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct19BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< + Struct19BytesHomogeneousUint8 Function( + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8), + Struct19BytesHomogeneousUint8 Function( + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int)>("ReturnStruct19BytesHomogeneousUint8"); + +/// 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. +void testReturnStruct19BytesHomogeneousUint8() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + int a9; + int a10; + int a11; + int a12; + int a13; + int a14; + int a15; + int a16; + int a17; + int 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; + + final result = returnStruct19BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6, + a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); + Expect.equals(a9, result.a9); + Expect.equals(a10, result.a10); + Expect.equals(a11, result.a11); + Expect.equals(a12, result.a12); + Expect.equals(a13, result.a13); + Expect.equals(a14, result.a14); + Expect.equals(a15, result.a15); + Expect.equals(a16, result.a16); + Expect.equals(a17, result.a17); + Expect.equals(a18, result.a18); +} + +final returnStruct20BytesHomogeneousInt32 = ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32), + Struct20BytesHomogeneousInt32 Function( + int, int, int, int, int)>("ReturnStruct20BytesHomogeneousInt32"); + +/// Return value too big to go in cpu registers on arm64. +void testReturnStruct20BytesHomogeneousInt32() { + int a0; + int a1; + int a2; + int a3; + int a4; + + a0 = -1; + a1 = 2; + a2 = -3; + a3 = 4; + a4 = -5; + + final result = returnStruct20BytesHomogeneousInt32(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); +} + +final returnStruct20BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousFloat Function(Float, Float, Float, Float, Float), + Struct20BytesHomogeneousFloat Function(double, double, double, double, + double)>("ReturnStruct20BytesHomogeneousFloat"); + +/// Return value too big to go in FPU registers on x64, arm hardfp and arm64. +void testReturnStruct20BytesHomogeneousFloat() { + 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; + + final result = returnStruct20BytesHomogeneousFloat(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); + Expect.approxEquals(a4, result.a4); +} + +final returnStruct32BytesHomogeneousDouble = ffiTestFunctions.lookupFunction< + Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double), + Struct32BytesHomogeneousDouble Function(double, double, double, + double)>("ReturnStruct32BytesHomogeneousDouble"); + +/// Return value in FPU registers on arm64. +void testReturnStruct32BytesHomogeneousDouble() { + double a0; + double a1; + double a2; + double a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4.0; + + final result = returnStruct32BytesHomogeneousDouble(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); +} + +final returnStruct40BytesHomogeneousDouble = ffiTestFunctions.lookupFunction< + Struct40BytesHomogeneousDouble Function( + Double, Double, Double, Double, Double), + Struct40BytesHomogeneousDouble Function(double, double, double, double, + double)>("ReturnStruct40BytesHomogeneousDouble"); + +/// Return value too big to go in FPU registers on arm64. +void testReturnStruct40BytesHomogeneousDouble() { + 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; + + final result = returnStruct40BytesHomogeneousDouble(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); + Expect.approxEquals(a4, result.a4); +} + +final returnStruct1024BytesHomogeneousUint64 = ffiTestFunctions.lookupFunction< + Struct1024BytesHomogeneousUint64 Function( + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64), + Struct1024BytesHomogeneousUint64 Function( + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int)>("ReturnStruct1024BytesHomogeneousUint64"); + +/// Test 1kb struct. +void testReturnStruct1024BytesHomogeneousUint64() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + int a9; + int a10; + int a11; + int a12; + int a13; + int a14; + int a15; + int a16; + int a17; + int a18; + int a19; + int a20; + int a21; + int a22; + int a23; + int a24; + int a25; + int a26; + int a27; + int a28; + int a29; + int a30; + int a31; + int a32; + int a33; + int a34; + int a35; + int a36; + int a37; + int a38; + int a39; + int a40; + int a41; + int a42; + int a43; + int a44; + int a45; + int a46; + int a47; + int a48; + int a49; + int a50; + int a51; + int a52; + int a53; + int a54; + int a55; + int a56; + int a57; + int a58; + int a59; + int a60; + int a61; + int a62; + int a63; + int a64; + int a65; + int a66; + int a67; + int a68; + int a69; + int a70; + int a71; + int a72; + int a73; + int a74; + int a75; + int a76; + int a77; + int a78; + int a79; + int a80; + int a81; + int a82; + int a83; + int a84; + int a85; + int a86; + int a87; + int a88; + int a89; + int a90; + int a91; + int a92; + int a93; + int a94; + int a95; + int a96; + int a97; + int a98; + int a99; + int a100; + int a101; + int a102; + int a103; + int a104; + int a105; + int a106; + int a107; + int a108; + int a109; + int a110; + int a111; + int a112; + int a113; + int a114; + int a115; + int a116; + int a117; + int a118; + int a119; + int a120; + int a121; + int a122; + int a123; + int a124; + int a125; + int a126; + int 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; + + final result = 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); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); + Expect.equals(a9, result.a9); + Expect.equals(a10, result.a10); + Expect.equals(a11, result.a11); + Expect.equals(a12, result.a12); + Expect.equals(a13, result.a13); + Expect.equals(a14, result.a14); + Expect.equals(a15, result.a15); + Expect.equals(a16, result.a16); + Expect.equals(a17, result.a17); + Expect.equals(a18, result.a18); + Expect.equals(a19, result.a19); + Expect.equals(a20, result.a20); + Expect.equals(a21, result.a21); + Expect.equals(a22, result.a22); + Expect.equals(a23, result.a23); + Expect.equals(a24, result.a24); + Expect.equals(a25, result.a25); + Expect.equals(a26, result.a26); + Expect.equals(a27, result.a27); + Expect.equals(a28, result.a28); + Expect.equals(a29, result.a29); + Expect.equals(a30, result.a30); + Expect.equals(a31, result.a31); + Expect.equals(a32, result.a32); + Expect.equals(a33, result.a33); + Expect.equals(a34, result.a34); + Expect.equals(a35, result.a35); + Expect.equals(a36, result.a36); + Expect.equals(a37, result.a37); + Expect.equals(a38, result.a38); + Expect.equals(a39, result.a39); + Expect.equals(a40, result.a40); + Expect.equals(a41, result.a41); + Expect.equals(a42, result.a42); + Expect.equals(a43, result.a43); + Expect.equals(a44, result.a44); + Expect.equals(a45, result.a45); + Expect.equals(a46, result.a46); + Expect.equals(a47, result.a47); + Expect.equals(a48, result.a48); + Expect.equals(a49, result.a49); + Expect.equals(a50, result.a50); + Expect.equals(a51, result.a51); + Expect.equals(a52, result.a52); + Expect.equals(a53, result.a53); + Expect.equals(a54, result.a54); + Expect.equals(a55, result.a55); + Expect.equals(a56, result.a56); + Expect.equals(a57, result.a57); + Expect.equals(a58, result.a58); + Expect.equals(a59, result.a59); + Expect.equals(a60, result.a60); + Expect.equals(a61, result.a61); + Expect.equals(a62, result.a62); + Expect.equals(a63, result.a63); + Expect.equals(a64, result.a64); + Expect.equals(a65, result.a65); + Expect.equals(a66, result.a66); + Expect.equals(a67, result.a67); + Expect.equals(a68, result.a68); + Expect.equals(a69, result.a69); + Expect.equals(a70, result.a70); + Expect.equals(a71, result.a71); + Expect.equals(a72, result.a72); + Expect.equals(a73, result.a73); + Expect.equals(a74, result.a74); + Expect.equals(a75, result.a75); + Expect.equals(a76, result.a76); + Expect.equals(a77, result.a77); + Expect.equals(a78, result.a78); + Expect.equals(a79, result.a79); + Expect.equals(a80, result.a80); + Expect.equals(a81, result.a81); + Expect.equals(a82, result.a82); + Expect.equals(a83, result.a83); + Expect.equals(a84, result.a84); + Expect.equals(a85, result.a85); + Expect.equals(a86, result.a86); + Expect.equals(a87, result.a87); + Expect.equals(a88, result.a88); + Expect.equals(a89, result.a89); + Expect.equals(a90, result.a90); + Expect.equals(a91, result.a91); + Expect.equals(a92, result.a92); + Expect.equals(a93, result.a93); + Expect.equals(a94, result.a94); + Expect.equals(a95, result.a95); + Expect.equals(a96, result.a96); + Expect.equals(a97, result.a97); + Expect.equals(a98, result.a98); + Expect.equals(a99, result.a99); + Expect.equals(a100, result.a100); + Expect.equals(a101, result.a101); + Expect.equals(a102, result.a102); + Expect.equals(a103, result.a103); + Expect.equals(a104, result.a104); + Expect.equals(a105, result.a105); + Expect.equals(a106, result.a106); + Expect.equals(a107, result.a107); + Expect.equals(a108, result.a108); + Expect.equals(a109, result.a109); + Expect.equals(a110, result.a110); + Expect.equals(a111, result.a111); + Expect.equals(a112, result.a112); + Expect.equals(a113, result.a113); + Expect.equals(a114, result.a114); + Expect.equals(a115, result.a115); + Expect.equals(a116, result.a116); + Expect.equals(a117, result.a117); + Expect.equals(a118, result.a118); + Expect.equals(a119, result.a119); + Expect.equals(a120, result.a120); + Expect.equals(a121, result.a121); + Expect.equals(a122, result.a122); + Expect.equals(a123, result.a123); + Expect.equals(a124, result.a124); + Expect.equals(a125, result.a125); + Expect.equals(a126, result.a126); + Expect.equals(a127, result.a127); +} + +final returnStruct3BytesPackedInt = ffiTestFunctions.lookupFunction< + Struct3BytesPackedInt Function(Int8, Int16), + Struct3BytesPackedInt Function(int, int)>("ReturnStruct3BytesPackedInt"); + +/// Small struct with mis-aligned member. +void testReturnStruct3BytesPackedInt() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct3BytesPackedInt(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct8BytesPackedInt = ffiTestFunctions.lookupFunction< + Struct8BytesPackedInt Function(Uint8, Uint32, Uint8, Uint8, Uint8), + Struct8BytesPackedInt Function( + int, int, int, int, int)>("ReturnStruct8BytesPackedInt"); + +/// Struct with mis-aligned member. +void testReturnStruct8BytesPackedInt() { + int a0; + int a1; + int a2; + int a3; + int a4; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + + final result = returnStruct8BytesPackedInt(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); +} + +final returnStruct9BytesPackedMixed = ffiTestFunctions.lookupFunction< + Struct9BytesPackedMixed Function(Uint8, Double), + Struct9BytesPackedMixed Function( + int, double)>("ReturnStruct9BytesPackedMixed"); + +/// Struct with mis-aligned member. +/// Tests backfilling of CPU and FPU registers. +void testReturnStruct9BytesPackedMixed() { + int a0; + double a1; + + a0 = 1; + a1 = 2.0; + + final result = returnStruct9BytesPackedMixed(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.approxEquals(a1, result.a1); +} + +final returnUnion4BytesMixed = ffiTestFunctions.lookupFunction< + Union4BytesMixed Function(Uint32), + Union4BytesMixed Function(int)>("ReturnUnion4BytesMixed"); + +/// Returning a mixed integer/float union. +void testReturnUnion4BytesMixed() { + int a0; + + a0 = 1; + + final result = returnUnion4BytesMixed(a0); + + print("result = $result"); + + Expect.equals(a0, result.a0); +} + +final returnUnion8BytesNestedFloat = ffiTestFunctions.lookupFunction< + Union8BytesNestedFloat Function(Double), + Union8BytesNestedFloat Function(double)>("ReturnUnion8BytesNestedFloat"); + +/// Returning a floating point only union. +void testReturnUnion8BytesNestedFloat() { + double a0; + + a0 = -1.0; + + final result = returnUnion8BytesNestedFloat(a0); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); +} + +final returnUnion9BytesNestedInt = ffiTestFunctions.lookupFunction< + Union9BytesNestedInt Function(Struct8BytesInt), + Union9BytesNestedInt Function( + Struct8BytesInt)>("ReturnUnion9BytesNestedInt"); + +/// Returning a mixed-size union. +void testReturnUnion9BytesNestedInt() { + final a0Pointer = calloc(); + final Struct8BytesInt a0 = a0Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + + final result = returnUnion9BytesNestedInt(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + + calloc.free(a0Pointer); +} + +final returnUnion16BytesNestedFloat = ffiTestFunctions.lookupFunction< + Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat), + Union16BytesNestedFloat Function( + Struct8BytesHomogeneousFloat)>("ReturnUnion16BytesNestedFloat"); + +/// Returning union with homogenous floats. +void testReturnUnion16BytesNestedFloat() { + final a0Pointer = calloc(); + final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; + + a0.a0 = -1.0; + a0.a1 = 2.0; + + final result = returnUnion16BytesNestedFloat(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a0.a1, result.a0.a1); + + calloc.free(a0Pointer); +} diff --git a/tests/ffi/generator/structs_by_value_tests_generator.dart b/tests/ffi/generator/structs_by_value_tests_generator.dart index 7518dd8318c..f1d7c358e5e 100644 --- a/tests/ffi/generator/structs_by_value_tests_generator.dart +++ b/tests/ffi/generator/structs_by_value_tests_generator.dart @@ -954,7 +954,7 @@ ${headerCommon(copyrightYear: copyrightYear)} // // SharedObjects=ffi_test_functions // VMOptions= -// VMOptions=--deterministic --optimization-counter-threshold=20 +// VMOptions=--deterministic --optimization-counter-threshold=90 // VMOptions=--use-slow-path // VMOptions=--use-slow-path --stacktrace-every=100 @@ -975,7 +975,8 @@ final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); """; } -Future writeDartCallTest({required bool isLeaf}) async { +Future writeDartCallTest(String nameSuffix, List functions, + {required bool isLeaf}) async { await Future.wait([true, false].map((isNnbd) async { final StringBuffer buffer = StringBuffer(); buffer.write(headerDartCallTest( @@ -984,22 +985,24 @@ Future writeDartCallTest({required bool isLeaf}) async { final suffix = isLeaf ? 'Leaf' : ''; buffer.write(""" void main() { - for (int i = 0; i < 25; ++i) { + for (int i = 0; i < 100; ++i) { ${functions.map((e) => "${e.dartTestName}$suffix();").join("\n")} } } """); buffer.writeAll(functions.map((e) => e.dartCallCode(isLeaf: isLeaf))); - final path = callTestPath(isNnbd: isNnbd, isLeaf: isLeaf); + final path = + callTestPath(isNnbd: isNnbd, isLeaf: isLeaf, nameSuffix: nameSuffix); await File(path).writeAsString(buffer.toString()); await runProcess("dart", ["format", path]); })); } -String callTestPath({required bool isNnbd, required bool isLeaf}) { +String callTestPath( + {required bool isNnbd, required bool isLeaf, String nameSuffix = ''}) { final folder = isNnbd ? 'ffi' : 'ffi_2'; - final suffix = isLeaf ? '_leaf' : ''; + final suffix = nameSuffix + (isLeaf ? '_leaf' : ''); return Platform.script .resolve( "../../$folder/function_structs_by_value_generated${suffix}_test.dart") @@ -1158,8 +1161,11 @@ void main(List arguments) async { await Future.wait([ writeDartCompounds(), - writeDartCallTest(isLeaf: false), - writeDartCallTest(isLeaf: true), + for (bool isLeaf in [false, true]) ...[ + writeDartCallTest('_args', functionsStructArguments, isLeaf: isLeaf), + writeDartCallTest('_ret', functionsStructReturn, isLeaf: isLeaf), + writeDartCallTest('_ret_arg', functionsReturnArgument, isLeaf: isLeaf), + ], writeDartCallbackTest(), writeC(), ]); diff --git a/tests/ffi_2/ffi_2.status b/tests/ffi_2/ffi_2.status index 413921a3674..2aeb1a0c7dc 100644 --- a/tests/ffi_2/ffi_2.status +++ b/tests/ffi_2/ffi_2.status @@ -3,7 +3,12 @@ # BSD-style license that can be found in the LICENSE file. function_callbacks_structs_by_value_test: Pass, Slow # https://dartbug.com/47304 https://dartbug.com/45007 -function_structs_by_value_generated_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_args_leaf_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_args_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_ret_arg_leaf_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_ret_arg_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_ret_leaf_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 +function_structs_by_value_generated_ret_test: Pass, Slow # https://dartbug.com/47303 https://dartbug.com/45007 [ $compiler == app_jitk ] vmspecific_leaf_call_test: Skip # https://dartbug.com/46125: Snapshot fails to generate. diff --git a/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart b/tests/ffi_2/function_structs_by_value_generated_args_leaf_test.dart similarity index 71% rename from tests/ffi_2/function_structs_by_value_generated_leaf_test.dart rename to tests/ffi_2/function_structs_by_value_generated_args_leaf_test.dart index a759e1e2e41..d09a406318b 100644 --- a/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart +++ b/tests/ffi_2/function_structs_by_value_generated_args_leaf_test.dart @@ -7,7 +7,7 @@ // // SharedObjects=ffi_test_functions // VMOptions= -// VMOptions=--deterministic --optimization-counter-threshold=20 +// VMOptions=--deterministic --optimization-counter-threshold=90 // VMOptions=--use-slow-path // VMOptions=--use-slow-path --stacktrace-every=100 @@ -25,7 +25,7 @@ import 'function_structs_by_value_generated_compounds.dart'; final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); void main() { - for (int i = 0; i < 25; ++i) { + for (int i = 0; i < 100; ++i) { testPassStruct1ByteIntx10Leaf(); testPassStruct3BytesHomogeneousUint8x10Leaf(); testPassStruct3BytesInt2ByteAlignedx10Leaf(); @@ -92,57 +92,6 @@ void main() { testPassUint8Boolx9Struct10BytesInlineArrayBoolBoolLeaf(); testPassUint8Struct1ByteBoolLeaf(); testPassWCharStructInlineArrayIntUintPtrx2LongUnsignedLeaf(); - testReturnStruct1ByteIntLeaf(); - testReturnStruct3BytesHomogeneousUint8Leaf(); - testReturnStruct3BytesInt2ByteAlignedLeaf(); - testReturnStruct4BytesHomogeneousInt16Leaf(); - testReturnStruct7BytesHomogeneousUint8Leaf(); - testReturnStruct7BytesInt4ByteAlignedLeaf(); - testReturnStruct8BytesIntLeaf(); - testReturnStruct8BytesHomogeneousFloatLeaf(); - testReturnStruct8BytesMixedLeaf(); - testReturnStruct9BytesHomogeneousUint8Leaf(); - testReturnStruct9BytesInt4Or8ByteAlignedLeaf(); - testReturnStruct12BytesHomogeneousFloatLeaf(); - testReturnStruct16BytesHomogeneousFloatLeaf(); - testReturnStruct16BytesMixedLeaf(); - testReturnStruct16BytesMixed2Leaf(); - testReturnStruct17BytesIntLeaf(); - testReturnStruct19BytesHomogeneousUint8Leaf(); - testReturnStruct20BytesHomogeneousInt32Leaf(); - testReturnStruct20BytesHomogeneousFloatLeaf(); - testReturnStruct32BytesHomogeneousDoubleLeaf(); - testReturnStruct40BytesHomogeneousDoubleLeaf(); - testReturnStruct1024BytesHomogeneousUint64Leaf(); - testReturnStruct3BytesPackedIntLeaf(); - testReturnStruct8BytesPackedIntLeaf(); - testReturnStruct9BytesPackedMixedLeaf(); - testReturnUnion4BytesMixedLeaf(); - testReturnUnion8BytesNestedFloatLeaf(); - testReturnUnion9BytesNestedIntLeaf(); - testReturnUnion16BytesNestedFloatLeaf(); - testReturnStructArgumentStruct1ByteIntLeaf(); - testReturnStructArgumentInt32x8Struct1ByteIntLeaf(); - testReturnStructArgumentStruct8BytesHomogeneousFloatLeaf(); - testReturnStructArgumentStruct20BytesHomogeneousInt32Leaf(); - testReturnStructArgumentInt32x8Struct20BytesHomogeneouLeaf(); - testReturnStructArgumentStruct8BytesInlineArrayIntLeaf(); - testReturnStructArgumentStructStruct16BytesHomogeneousLeaf(); - testReturnStructArgumentStructStruct32BytesHomogeneousLeaf(); - testReturnStructArgumentStructStruct16BytesMixed3Leaf(); - testReturnStructAlignmentInt16Leaf(); - testReturnStructAlignmentInt32Leaf(); - testReturnStructAlignmentInt64Leaf(); - testReturnStruct8BytesNestedIntLeaf(); - testReturnStruct8BytesNestedFloatLeaf(); - testReturnStruct8BytesNestedFloat2Leaf(); - testReturnStruct8BytesNestedMixedLeaf(); - testReturnStruct16BytesNestedIntLeaf(); - testReturnStruct32BytesNestedIntLeaf(); - testReturnStructNestedIntStructAlignmentInt16Leaf(); - testReturnStructNestedIntStructAlignmentInt32Leaf(); - testReturnStructNestedIntStructAlignmentInt64Leaf(); - testReturnStructNestedIrregularEvenBiggerLeaf(); } } @@ -5507,2390 +5456,3 @@ void testPassWCharStructInlineArrayIntUintPtrx2LongUnsignedLeaf() { calloc.free(a1Pointer); } - -final returnStruct1ByteIntLeaf = ffiTestFunctions.lookupFunction< - Struct1ByteInt Function(Int8), - Struct1ByteInt Function(int)>("ReturnStruct1ByteInt", isLeaf: true); - -/// Smallest struct with data. -void testReturnStruct1ByteIntLeaf() { - int a0; - - a0 = -1; - - final result = returnStruct1ByteIntLeaf(a0); - - print("result = $result"); - - Expect.equals(a0, result.a0); -} - -final returnStruct3BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< - Struct3BytesHomogeneousUint8 Function(Uint8, Uint8, Uint8), - Struct3BytesHomogeneousUint8 Function( - int, int, int)>("ReturnStruct3BytesHomogeneousUint8", isLeaf: true); - -/// Smaller than word size return value on all architectures. -void testReturnStruct3BytesHomogeneousUint8Leaf() { - int a0; - int a1; - int a2; - - a0 = 1; - a1 = 2; - a2 = 3; - - final result = returnStruct3BytesHomogeneousUint8Leaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct3BytesInt2ByteAlignedLeaf = ffiTestFunctions.lookupFunction< - Struct3BytesInt2ByteAligned Function(Int16, Int8), - Struct3BytesInt2ByteAligned Function( - int, int)>("ReturnStruct3BytesInt2ByteAligned", isLeaf: true); - -/// Smaller than word size return value on all architectures. -/// With alignment rules taken into account size is 4 bytes. -void testReturnStruct3BytesInt2ByteAlignedLeaf() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct3BytesInt2ByteAlignedLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct4BytesHomogeneousInt16Leaf = ffiTestFunctions.lookupFunction< - Struct4BytesHomogeneousInt16 Function(Int16, Int16), - Struct4BytesHomogeneousInt16 Function( - int, int)>("ReturnStruct4BytesHomogeneousInt16", isLeaf: true); - -/// Word size return value on 32 bit architectures.. -void testReturnStruct4BytesHomogeneousInt16Leaf() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct4BytesHomogeneousInt16Leaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct7BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< - Struct7BytesHomogeneousUint8 Function( - Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), - Struct7BytesHomogeneousUint8 Function(int, int, int, int, int, int, - int)>("ReturnStruct7BytesHomogeneousUint8", isLeaf: true); - -/// Non-wordsize return value. -void testReturnStruct7BytesHomogeneousUint8Leaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - a5 = 6; - a6 = 7; - - final result = - returnStruct7BytesHomogeneousUint8Leaf(a0, a1, a2, a3, a4, a5, a6); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); -} - -final returnStruct7BytesInt4ByteAlignedLeaf = ffiTestFunctions.lookupFunction< - Struct7BytesInt4ByteAligned Function(Int32, Int16, Int8), - Struct7BytesInt4ByteAligned Function( - int, int, int)>("ReturnStruct7BytesInt4ByteAligned", isLeaf: true); - -/// Non-wordsize return value. -/// With alignment rules taken into account size is 8 bytes. -void testReturnStruct7BytesInt4ByteAlignedLeaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct7BytesInt4ByteAlignedLeaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesIntLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesInt Function(Int16, Int16, Int32), - Struct8BytesInt Function( - int, int, int)>("ReturnStruct8BytesInt", isLeaf: true); - -/// Return value in integer registers on many architectures. -void testReturnStruct8BytesIntLeaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct8BytesIntLeaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesHomogeneousFloat Function(Float, Float), - Struct8BytesHomogeneousFloat Function( - double, double)>("ReturnStruct8BytesHomogeneousFloat", isLeaf: true); - -/// Return value in FP registers on many architectures. -void testReturnStruct8BytesHomogeneousFloatLeaf() { - double a0; - double a1; - - a0 = -1.0; - a1 = 2.0; - - final result = returnStruct8BytesHomogeneousFloatLeaf(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); -} - -final returnStruct8BytesMixedLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesMixed Function(Float, Int16, Int16), - Struct8BytesMixed Function( - double, int, int)>("ReturnStruct8BytesMixed", isLeaf: true); - -/// Return value split over FP and integer register in x64. -void testReturnStruct8BytesMixedLeaf() { - double a0; - int a1; - int a2; - - a0 = -1.0; - a1 = 2; - a2 = -3; - - final result = returnStruct8BytesMixedLeaf(a0, a1, a2); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct9BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< - Struct9BytesHomogeneousUint8 Function( - Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), - Struct9BytesHomogeneousUint8 Function(int, int, int, int, int, int, int, - int, int)>("ReturnStruct9BytesHomogeneousUint8", isLeaf: true); - -/// 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. -void testReturnStruct9BytesHomogeneousUint8Leaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - a5 = 6; - a6 = 7; - a7 = 8; - a8 = 9; - - final result = returnStruct9BytesHomogeneousUint8Leaf( - a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); -} - -final returnStruct9BytesInt4Or8ByteAlignedLeaf = - ffiTestFunctions.lookupFunction< - Struct9BytesInt4Or8ByteAligned Function(Int64, Int8), - Struct9BytesInt4Or8ByteAligned Function( - int, int)>("ReturnStruct9BytesInt4Or8ByteAligned", isLeaf: true); - -/// Return value in two integer registers on x64. -/// With alignment rules taken into account size is 12 or 16 bytes. -void testReturnStruct9BytesInt4Or8ByteAlignedLeaf() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct9BytesInt4Or8ByteAlignedLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct12BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< - Struct12BytesHomogeneousFloat Function(Float, Float, Float), - Struct12BytesHomogeneousFloat Function(double, double, - double)>("ReturnStruct12BytesHomogeneousFloat", isLeaf: true); - -/// Return value in FPU registers, but does not use all registers on arm hardfp -/// and arm64. -void testReturnStruct12BytesHomogeneousFloatLeaf() { - double a0; - double a1; - double a2; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - - final result = returnStruct12BytesHomogeneousFloatLeaf(a0, a1, a2); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); -} - -final returnStruct16BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< - Struct16BytesHomogeneousFloat Function(Float, Float, Float, Float), - Struct16BytesHomogeneousFloat Function(double, double, double, - double)>("ReturnStruct16BytesHomogeneousFloat", isLeaf: true); - -/// Return value in FPU registers on arm hardfp and arm64. -void testReturnStruct16BytesHomogeneousFloatLeaf() { - double a0; - double a1; - double a2; - double a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4.0; - - final result = returnStruct16BytesHomogeneousFloatLeaf(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); -} - -final returnStruct16BytesMixedLeaf = ffiTestFunctions.lookupFunction< - Struct16BytesMixed Function(Double, Int64), - Struct16BytesMixed Function( - double, int)>("ReturnStruct16BytesMixed", isLeaf: true); - -/// Return value split over FP and integer register in x64. -void testReturnStruct16BytesMixedLeaf() { - double a0; - int a1; - - a0 = -1.0; - a1 = 2; - - final result = returnStruct16BytesMixedLeaf(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct16BytesMixed2Leaf = ffiTestFunctions.lookupFunction< - Struct16BytesMixed2 Function(Float, Float, Float, Int32), - Struct16BytesMixed2 Function(double, double, double, - int)>("ReturnStruct16BytesMixed2", isLeaf: true); - -/// Return value split over FP and integer register in x64. -/// The integer register contains half float half int. -void testReturnStruct16BytesMixed2Leaf() { - double a0; - double a1; - double a2; - int a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4; - - final result = returnStruct16BytesMixed2Leaf(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.equals(a3, result.a3); -} - -final returnStruct17BytesIntLeaf = ffiTestFunctions.lookupFunction< - Struct17BytesInt Function(Int64, Int64, Int8), - Struct17BytesInt Function( - int, int, int)>("ReturnStruct17BytesInt", isLeaf: true); - -/// 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. -void testReturnStruct17BytesIntLeaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct17BytesIntLeaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct19BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< - Struct19BytesHomogeneousUint8 Function( - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8), - Struct19BytesHomogeneousUint8 Function( - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int)>("ReturnStruct19BytesHomogeneousUint8", isLeaf: true); - -/// 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. -void testReturnStruct19BytesHomogeneousUint8Leaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - int a9; - int a10; - int a11; - int a12; - int a13; - int a14; - int a15; - int a16; - int a17; - int 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; - - final result = returnStruct19BytesHomogeneousUint8Leaf(a0, a1, a2, a3, a4, a5, - a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); - Expect.equals(a9, result.a9); - Expect.equals(a10, result.a10); - Expect.equals(a11, result.a11); - Expect.equals(a12, result.a12); - Expect.equals(a13, result.a13); - Expect.equals(a14, result.a14); - Expect.equals(a15, result.a15); - Expect.equals(a16, result.a16); - Expect.equals(a17, result.a17); - Expect.equals(a18, result.a18); -} - -final returnStruct20BytesHomogeneousInt32Leaf = ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32), - Struct20BytesHomogeneousInt32 Function(int, int, int, int, - int)>("ReturnStruct20BytesHomogeneousInt32", isLeaf: true); - -/// Return value too big to go in cpu registers on arm64. -void testReturnStruct20BytesHomogeneousInt32Leaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - - a0 = -1; - a1 = 2; - a2 = -3; - a3 = 4; - a4 = -5; - - final result = returnStruct20BytesHomogeneousInt32Leaf(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); -} - -final returnStruct20BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousFloat Function(Float, Float, Float, Float, Float), - Struct20BytesHomogeneousFloat Function(double, double, double, double, - double)>("ReturnStruct20BytesHomogeneousFloat", isLeaf: true); - -/// Return value too big to go in FPU registers on x64, arm hardfp and arm64. -void testReturnStruct20BytesHomogeneousFloatLeaf() { - 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; - - final result = returnStruct20BytesHomogeneousFloatLeaf(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); - Expect.approxEquals(a4, result.a4); -} - -final returnStruct32BytesHomogeneousDoubleLeaf = - ffiTestFunctions.lookupFunction< - Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double), - Struct32BytesHomogeneousDouble Function(double, double, double, - double)>("ReturnStruct32BytesHomogeneousDouble", isLeaf: true); - -/// Return value in FPU registers on arm64. -void testReturnStruct32BytesHomogeneousDoubleLeaf() { - double a0; - double a1; - double a2; - double a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4.0; - - final result = returnStruct32BytesHomogeneousDoubleLeaf(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); -} - -final returnStruct40BytesHomogeneousDoubleLeaf = - ffiTestFunctions.lookupFunction< - Struct40BytesHomogeneousDouble Function( - Double, Double, Double, Double, Double), - Struct40BytesHomogeneousDouble Function(double, double, double, double, - double)>("ReturnStruct40BytesHomogeneousDouble", isLeaf: true); - -/// Return value too big to go in FPU registers on arm64. -void testReturnStruct40BytesHomogeneousDoubleLeaf() { - 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; - - final result = returnStruct40BytesHomogeneousDoubleLeaf(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); - Expect.approxEquals(a4, result.a4); -} - -final returnStruct1024BytesHomogeneousUint64Leaf = - ffiTestFunctions.lookupFunction< - Struct1024BytesHomogeneousUint64 Function( - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64), - Struct1024BytesHomogeneousUint64 Function( - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int)>("ReturnStruct1024BytesHomogeneousUint64", isLeaf: true); - -/// Test 1kb struct. -void testReturnStruct1024BytesHomogeneousUint64Leaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - int a9; - int a10; - int a11; - int a12; - int a13; - int a14; - int a15; - int a16; - int a17; - int a18; - int a19; - int a20; - int a21; - int a22; - int a23; - int a24; - int a25; - int a26; - int a27; - int a28; - int a29; - int a30; - int a31; - int a32; - int a33; - int a34; - int a35; - int a36; - int a37; - int a38; - int a39; - int a40; - int a41; - int a42; - int a43; - int a44; - int a45; - int a46; - int a47; - int a48; - int a49; - int a50; - int a51; - int a52; - int a53; - int a54; - int a55; - int a56; - int a57; - int a58; - int a59; - int a60; - int a61; - int a62; - int a63; - int a64; - int a65; - int a66; - int a67; - int a68; - int a69; - int a70; - int a71; - int a72; - int a73; - int a74; - int a75; - int a76; - int a77; - int a78; - int a79; - int a80; - int a81; - int a82; - int a83; - int a84; - int a85; - int a86; - int a87; - int a88; - int a89; - int a90; - int a91; - int a92; - int a93; - int a94; - int a95; - int a96; - int a97; - int a98; - int a99; - int a100; - int a101; - int a102; - int a103; - int a104; - int a105; - int a106; - int a107; - int a108; - int a109; - int a110; - int a111; - int a112; - int a113; - int a114; - int a115; - int a116; - int a117; - int a118; - int a119; - int a120; - int a121; - int a122; - int a123; - int a124; - int a125; - int a126; - int 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; - - final result = returnStruct1024BytesHomogeneousUint64Leaf( - 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); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); - Expect.equals(a9, result.a9); - Expect.equals(a10, result.a10); - Expect.equals(a11, result.a11); - Expect.equals(a12, result.a12); - Expect.equals(a13, result.a13); - Expect.equals(a14, result.a14); - Expect.equals(a15, result.a15); - Expect.equals(a16, result.a16); - Expect.equals(a17, result.a17); - Expect.equals(a18, result.a18); - Expect.equals(a19, result.a19); - Expect.equals(a20, result.a20); - Expect.equals(a21, result.a21); - Expect.equals(a22, result.a22); - Expect.equals(a23, result.a23); - Expect.equals(a24, result.a24); - Expect.equals(a25, result.a25); - Expect.equals(a26, result.a26); - Expect.equals(a27, result.a27); - Expect.equals(a28, result.a28); - Expect.equals(a29, result.a29); - Expect.equals(a30, result.a30); - Expect.equals(a31, result.a31); - Expect.equals(a32, result.a32); - Expect.equals(a33, result.a33); - Expect.equals(a34, result.a34); - Expect.equals(a35, result.a35); - Expect.equals(a36, result.a36); - Expect.equals(a37, result.a37); - Expect.equals(a38, result.a38); - Expect.equals(a39, result.a39); - Expect.equals(a40, result.a40); - Expect.equals(a41, result.a41); - Expect.equals(a42, result.a42); - Expect.equals(a43, result.a43); - Expect.equals(a44, result.a44); - Expect.equals(a45, result.a45); - Expect.equals(a46, result.a46); - Expect.equals(a47, result.a47); - Expect.equals(a48, result.a48); - Expect.equals(a49, result.a49); - Expect.equals(a50, result.a50); - Expect.equals(a51, result.a51); - Expect.equals(a52, result.a52); - Expect.equals(a53, result.a53); - Expect.equals(a54, result.a54); - Expect.equals(a55, result.a55); - Expect.equals(a56, result.a56); - Expect.equals(a57, result.a57); - Expect.equals(a58, result.a58); - Expect.equals(a59, result.a59); - Expect.equals(a60, result.a60); - Expect.equals(a61, result.a61); - Expect.equals(a62, result.a62); - Expect.equals(a63, result.a63); - Expect.equals(a64, result.a64); - Expect.equals(a65, result.a65); - Expect.equals(a66, result.a66); - Expect.equals(a67, result.a67); - Expect.equals(a68, result.a68); - Expect.equals(a69, result.a69); - Expect.equals(a70, result.a70); - Expect.equals(a71, result.a71); - Expect.equals(a72, result.a72); - Expect.equals(a73, result.a73); - Expect.equals(a74, result.a74); - Expect.equals(a75, result.a75); - Expect.equals(a76, result.a76); - Expect.equals(a77, result.a77); - Expect.equals(a78, result.a78); - Expect.equals(a79, result.a79); - Expect.equals(a80, result.a80); - Expect.equals(a81, result.a81); - Expect.equals(a82, result.a82); - Expect.equals(a83, result.a83); - Expect.equals(a84, result.a84); - Expect.equals(a85, result.a85); - Expect.equals(a86, result.a86); - Expect.equals(a87, result.a87); - Expect.equals(a88, result.a88); - Expect.equals(a89, result.a89); - Expect.equals(a90, result.a90); - Expect.equals(a91, result.a91); - Expect.equals(a92, result.a92); - Expect.equals(a93, result.a93); - Expect.equals(a94, result.a94); - Expect.equals(a95, result.a95); - Expect.equals(a96, result.a96); - Expect.equals(a97, result.a97); - Expect.equals(a98, result.a98); - Expect.equals(a99, result.a99); - Expect.equals(a100, result.a100); - Expect.equals(a101, result.a101); - Expect.equals(a102, result.a102); - Expect.equals(a103, result.a103); - Expect.equals(a104, result.a104); - Expect.equals(a105, result.a105); - Expect.equals(a106, result.a106); - Expect.equals(a107, result.a107); - Expect.equals(a108, result.a108); - Expect.equals(a109, result.a109); - Expect.equals(a110, result.a110); - Expect.equals(a111, result.a111); - Expect.equals(a112, result.a112); - Expect.equals(a113, result.a113); - Expect.equals(a114, result.a114); - Expect.equals(a115, result.a115); - Expect.equals(a116, result.a116); - Expect.equals(a117, result.a117); - Expect.equals(a118, result.a118); - Expect.equals(a119, result.a119); - Expect.equals(a120, result.a120); - Expect.equals(a121, result.a121); - Expect.equals(a122, result.a122); - Expect.equals(a123, result.a123); - Expect.equals(a124, result.a124); - Expect.equals(a125, result.a125); - Expect.equals(a126, result.a126); - Expect.equals(a127, result.a127); -} - -final returnStruct3BytesPackedIntLeaf = ffiTestFunctions.lookupFunction< - Struct3BytesPackedInt Function(Int8, Int16), - Struct3BytesPackedInt Function( - int, int)>("ReturnStruct3BytesPackedInt", isLeaf: true); - -/// Small struct with mis-aligned member. -void testReturnStruct3BytesPackedIntLeaf() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct3BytesPackedIntLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct8BytesPackedIntLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesPackedInt Function(Uint8, Uint32, Uint8, Uint8, Uint8), - Struct8BytesPackedInt Function( - int, int, int, int, int)>("ReturnStruct8BytesPackedInt", isLeaf: true); - -/// Struct with mis-aligned member. -void testReturnStruct8BytesPackedIntLeaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - - final result = returnStruct8BytesPackedIntLeaf(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); -} - -final returnStruct9BytesPackedMixedLeaf = ffiTestFunctions.lookupFunction< - Struct9BytesPackedMixed Function(Uint8, Double), - Struct9BytesPackedMixed Function( - int, double)>("ReturnStruct9BytesPackedMixed", isLeaf: true); - -/// Struct with mis-aligned member. -/// Tests backfilling of CPU and FPU registers. -void testReturnStruct9BytesPackedMixedLeaf() { - int a0; - double a1; - - a0 = 1; - a1 = 2.0; - - final result = returnStruct9BytesPackedMixedLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.approxEquals(a1, result.a1); -} - -final returnUnion4BytesMixedLeaf = ffiTestFunctions.lookupFunction< - Union4BytesMixed Function(Uint32), - Union4BytesMixed Function(int)>("ReturnUnion4BytesMixed", isLeaf: true); - -/// Returning a mixed integer/float union. -void testReturnUnion4BytesMixedLeaf() { - int a0; - - a0 = 1; - - final result = returnUnion4BytesMixedLeaf(a0); - - print("result = $result"); - - Expect.equals(a0, result.a0); -} - -final returnUnion8BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< - Union8BytesNestedFloat Function(Double), - Union8BytesNestedFloat Function( - double)>("ReturnUnion8BytesNestedFloat", isLeaf: true); - -/// Returning a floating point only union. -void testReturnUnion8BytesNestedFloatLeaf() { - double a0; - - a0 = -1.0; - - final result = returnUnion8BytesNestedFloatLeaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); -} - -final returnUnion9BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< - Union9BytesNestedInt Function(Struct8BytesInt), - Union9BytesNestedInt Function( - Struct8BytesInt)>("ReturnUnion9BytesNestedInt", isLeaf: true); - -/// Returning a mixed-size union. -void testReturnUnion9BytesNestedIntLeaf() { - final a0Pointer = calloc(); - final Struct8BytesInt a0 = a0Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - - final result = returnUnion9BytesNestedIntLeaf(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - - calloc.free(a0Pointer); -} - -final returnUnion16BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< - Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat), - Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat)>( - "ReturnUnion16BytesNestedFloat", - isLeaf: true); - -/// Returning union with homogenous floats. -void testReturnUnion16BytesNestedFloatLeaf() { - final a0Pointer = calloc(); - final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; - - a0.a0 = -1.0; - a0.a1 = 2.0; - - final result = returnUnion16BytesNestedFloatLeaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a0.a1, result.a0.a1); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStruct1ByteIntLeaf = ffiTestFunctions.lookupFunction< - Struct1ByteInt Function(Struct1ByteInt), - Struct1ByteInt Function( - Struct1ByteInt)>("ReturnStructArgumentStruct1ByteInt", isLeaf: true); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed in int registers in most ABIs. -void testReturnStructArgumentStruct1ByteIntLeaf() { - final a0Pointer = calloc(); - final Struct1ByteInt a0 = a0Pointer.ref; - - a0.a0 = -1; - - final result = returnStructArgumentStruct1ByteIntLeaf(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0); - - calloc.free(a0Pointer); -} - -final returnStructArgumentInt32x8Struct1ByteIntLeaf = - ffiTestFunctions - .lookupFunction< - Struct1ByteInt Function(Int32, Int32, Int32, Int32, Int32, Int32, - Int32, Int32, Struct1ByteInt), - Struct1ByteInt Function( - int, int, int, int, int, int, int, int, Struct1ByteInt)>( - "ReturnStructArgumentInt32x8Struct1ByteInt", - isLeaf: true); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed on stack on all ABIs. -void testReturnStructArgumentInt32x8Struct1ByteIntLeaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - final a8Pointer = calloc(); - final Struct1ByteInt a8 = a8Pointer.ref; - - a0 = -1; - a1 = 2; - a2 = -3; - a3 = 4; - a4 = -5; - a5 = 6; - a6 = -7; - a7 = 8; - a8.a0 = -9; - - final result = returnStructArgumentInt32x8Struct1ByteIntLeaf( - a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a8.a0, result.a0); - - calloc.free(a8Pointer); -} - -final returnStructArgumentStruct8BytesHomogeneousFloatLeaf = - ffiTestFunctions.lookupFunction< - Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat), - Struct8BytesHomogeneousFloat Function( - Struct8BytesHomogeneousFloat)>( - "ReturnStructArgumentStruct8BytesHomogeneousFloat", - isLeaf: true); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed in float registers in most ABIs. -void testReturnStructArgumentStruct8BytesHomogeneousFloatLeaf() { - final a0Pointer = calloc(); - final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; - - a0.a0 = -1.0; - a0.a1 = 2.0; - - final result = returnStructArgumentStruct8BytesHomogeneousFloatLeaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0); - Expect.approxEquals(a0.a1, result.a1); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStruct20BytesHomogeneousInt32Leaf = - ffiTestFunctions - .lookupFunction< - Struct20BytesHomogeneousInt32 Function( - Struct20BytesHomogeneousInt32), - Struct20BytesHomogeneousInt32 Function( - Struct20BytesHomogeneousInt32)>( - "ReturnStructArgumentStruct20BytesHomogeneousInt32", - isLeaf: true); - -/// On arm64, both argument and return value are passed in by pointer. -void testReturnStructArgumentStruct20BytesHomogeneousInt32Leaf() { - final a0Pointer = calloc(); - final Struct20BytesHomogeneousInt32 a0 = a0Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a0.a3 = 4; - a0.a4 = -5; - - final result = returnStructArgumentStruct20BytesHomogeneousInt32Leaf(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0); - Expect.equals(a0.a1, result.a1); - Expect.equals(a0.a2, result.a2); - Expect.equals(a0.a3, result.a3); - Expect.equals(a0.a4, result.a4); - - calloc.free(a0Pointer); -} - -final returnStructArgumentInt32x8Struct20BytesHomogeneouLeaf = - ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, - Int32, Int32, Int32, Int32, Struct20BytesHomogeneousInt32), - Struct20BytesHomogeneousInt32 Function(int, int, int, int, int, int, - int, int, Struct20BytesHomogeneousInt32)>( - "ReturnStructArgumentInt32x8Struct20BytesHomogeneou", - isLeaf: true); - -/// On arm64, both argument and return value are passed in by pointer. -/// Ints exhaust registers, so that pointer is passed on stack. -void testReturnStructArgumentInt32x8Struct20BytesHomogeneouLeaf() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - final a8Pointer = calloc(); - final Struct20BytesHomogeneousInt32 a8 = a8Pointer.ref; - - 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; - - final result = returnStructArgumentInt32x8Struct20BytesHomogeneouLeaf( - a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a8.a0, result.a0); - Expect.equals(a8.a1, result.a1); - Expect.equals(a8.a2, result.a2); - Expect.equals(a8.a3, result.a3); - Expect.equals(a8.a4, result.a4); - - calloc.free(a8Pointer); -} - -final returnStructArgumentStruct8BytesInlineArrayIntLeaf = - ffiTestFunctions.lookupFunction< - Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt), - Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt)>( - "ReturnStructArgumentStruct8BytesInlineArrayInt", - isLeaf: true); - -/// Test returning struct with inline array. -void testReturnStructArgumentStruct8BytesInlineArrayIntLeaf() { - final a0Pointer = calloc(); - final Struct8BytesInlineArrayInt a0 = a0Pointer.ref; - - 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; - - final result = returnStructArgumentStruct8BytesInlineArrayIntLeaf(a0); - - print("result = $result"); - - for (int i = 0; i < 8; i++) { - Expect.equals(a0.a0[i], result.a0[i]); - } - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct16BytesHomogeneousLeaf = - ffiTestFunctions.lookupFunction< - StructStruct16BytesHomogeneousFloat2 Function( - StructStruct16BytesHomogeneousFloat2), - StructStruct16BytesHomogeneousFloat2 Function( - StructStruct16BytesHomogeneousFloat2)>( - "ReturnStructArgumentStructStruct16BytesHomogeneous", - isLeaf: true); - -/// Return value in FPU registers on arm hardfp and arm64. -void testReturnStructArgumentStructStruct16BytesHomogeneousLeaf() { - final a0Pointer = calloc(); - final StructStruct16BytesHomogeneousFloat2 a0 = a0Pointer.ref; - - a0.a0.a0 = -1.0; - a0.a1[0].a0 = 2.0; - a0.a1[1].a0 = -3.0; - a0.a2 = 4.0; - - final result = returnStructArgumentStructStruct16BytesHomogeneousLeaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 2; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - } - Expect.approxEquals(a0.a2, result.a2); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct32BytesHomogeneousLeaf = - ffiTestFunctions.lookupFunction< - StructStruct32BytesHomogeneousDouble2 Function( - StructStruct32BytesHomogeneousDouble2), - StructStruct32BytesHomogeneousDouble2 Function( - StructStruct32BytesHomogeneousDouble2)>( - "ReturnStructArgumentStructStruct32BytesHomogeneous", - isLeaf: true); - -/// Return value in FPU registers on arm64. -void testReturnStructArgumentStructStruct32BytesHomogeneousLeaf() { - final a0Pointer = calloc(); - final StructStruct32BytesHomogeneousDouble2 a0 = a0Pointer.ref; - - a0.a0.a0 = -1.0; - a0.a1[0].a0 = 2.0; - a0.a1[1].a0 = -3.0; - a0.a2 = 4.0; - - final result = returnStructArgumentStructStruct32BytesHomogeneousLeaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 2; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - } - Expect.approxEquals(a0.a2, result.a2); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct16BytesMixed3Leaf = - ffiTestFunctions.lookupFunction< - StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3), - StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3)>( - "ReturnStructArgumentStructStruct16BytesMixed3", - isLeaf: true); - -/// On x64 Linux, return value is split over FP and int registers. -void testReturnStructArgumentStructStruct16BytesMixed3Leaf() { - final a0Pointer = calloc(); - final StructStruct16BytesMixed3 a0 = a0Pointer.ref; - - 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; - - final result = returnStructArgumentStructStruct16BytesMixed3Leaf(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 1; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - Expect.equals(a0.a1[i].a1, result.a1[i].a1); - Expect.equals(a0.a1[i].a2, result.a1[i].a2); - } - for (int i = 0; i < 2; i++) { - Expect.equals(a0.a2[i], result.a2[i]); - } - - calloc.free(a0Pointer); -} - -final returnStructAlignmentInt16Leaf = ffiTestFunctions.lookupFunction< - StructAlignmentInt16 Function(Int8, Int16, Int8), - StructAlignmentInt16 Function( - int, int, int)>("ReturnStructAlignmentInt16", isLeaf: true); - -/// Test alignment and padding of 16 byte int within struct. -void testReturnStructAlignmentInt16Leaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt16Leaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStructAlignmentInt32Leaf = ffiTestFunctions.lookupFunction< - StructAlignmentInt32 Function(Int8, Int32, Int8), - StructAlignmentInt32 Function( - int, int, int)>("ReturnStructAlignmentInt32", isLeaf: true); - -/// Test alignment and padding of 32 byte int within struct. -void testReturnStructAlignmentInt32Leaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt32Leaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStructAlignmentInt64Leaf = ffiTestFunctions.lookupFunction< - StructAlignmentInt64 Function(Int8, Int64, Int8), - StructAlignmentInt64 Function( - int, int, int)>("ReturnStructAlignmentInt64", isLeaf: true); - -/// Test alignment and padding of 64 byte int within struct. -void testReturnStructAlignmentInt64Leaf() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt64Leaf(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesNestedInt Function( - Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16), - Struct8BytesNestedInt Function( - Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16)>( - "ReturnStruct8BytesNestedInt", - isLeaf: true); - -/// Simple nested struct. -void testReturnStruct8BytesNestedIntLeaf() { - final a0Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a1.a0 = -3; - a1.a1 = 4; - - final result = returnStruct8BytesNestedIntLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct8BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesNestedFloat Function(Struct4BytesFloat, Struct4BytesFloat), - Struct8BytesNestedFloat Function(Struct4BytesFloat, - Struct4BytesFloat)>("ReturnStruct8BytesNestedFloat", isLeaf: true); - -/// Simple nested struct with floats. -void testReturnStruct8BytesNestedFloatLeaf() { - final a0Pointer = calloc(); - final Struct4BytesFloat a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesFloat a1 = a1Pointer.ref; - - a0.a0 = -1.0; - a1.a0 = 2.0; - - final result = returnStruct8BytesNestedFloatLeaf(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a1.a0, result.a1.a0); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct8BytesNestedFloat2Leaf = ffiTestFunctions.lookupFunction< - Struct8BytesNestedFloat2 Function(Struct4BytesFloat, Float), - Struct8BytesNestedFloat2 Function(Struct4BytesFloat, - double)>("ReturnStruct8BytesNestedFloat2", isLeaf: true); - -/// The nesting is irregular, testing homogenous float rules on arm and arm64, -/// and the fpu register usage on x64. -void testReturnStruct8BytesNestedFloat2Leaf() { - final a0Pointer = calloc(); - final Struct4BytesFloat a0 = a0Pointer.ref; - double a1; - - a0.a0 = -1.0; - a1 = 2.0; - - final result = returnStruct8BytesNestedFloat2Leaf(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a1, result.a1); - - calloc.free(a0Pointer); -} - -final returnStruct8BytesNestedMixedLeaf = ffiTestFunctions.lookupFunction< - Struct8BytesNestedMixed Function( - Struct4BytesHomogeneousInt16, Struct4BytesFloat), - Struct8BytesNestedMixed Function(Struct4BytesHomogeneousInt16, - Struct4BytesFloat)>("ReturnStruct8BytesNestedMixed", isLeaf: true); - -/// Simple nested struct with mixed members. -void testReturnStruct8BytesNestedMixedLeaf() { - final a0Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesFloat a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a1.a0 = -3.0; - - final result = returnStruct8BytesNestedMixedLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.approxEquals(a1.a0, result.a1.a0); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct16BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< - Struct16BytesNestedInt Function( - Struct8BytesNestedInt, Struct8BytesNestedInt), - Struct16BytesNestedInt Function(Struct8BytesNestedInt, - Struct8BytesNestedInt)>("ReturnStruct16BytesNestedInt", isLeaf: true); - -/// Deeper nested struct to test recursive member access. -void testReturnStruct16BytesNestedIntLeaf() { - final a0Pointer = calloc(); - final Struct8BytesNestedInt a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct8BytesNestedInt a1 = a1Pointer.ref; - - 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; - - final result = returnStruct16BytesNestedIntLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0.a0, result.a0.a0.a0); - Expect.equals(a0.a0.a1, result.a0.a0.a1); - Expect.equals(a0.a1.a0, result.a0.a1.a0); - Expect.equals(a0.a1.a1, result.a0.a1.a1); - Expect.equals(a1.a0.a0, result.a1.a0.a0); - Expect.equals(a1.a0.a1, result.a1.a0.a1); - Expect.equals(a1.a1.a0, result.a1.a1.a0); - Expect.equals(a1.a1.a1, result.a1.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct32BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< - Struct32BytesNestedInt Function( - Struct16BytesNestedInt, Struct16BytesNestedInt), - Struct32BytesNestedInt Function(Struct16BytesNestedInt, - Struct16BytesNestedInt)>("ReturnStruct32BytesNestedInt", isLeaf: true); - -/// Even deeper nested struct to test recursive member access. -void testReturnStruct32BytesNestedIntLeaf() { - final a0Pointer = calloc(); - final Struct16BytesNestedInt a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct16BytesNestedInt a1 = a1Pointer.ref; - - 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; - - final result = returnStruct32BytesNestedIntLeaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0.a0.a0, result.a0.a0.a0.a0); - Expect.equals(a0.a0.a0.a1, result.a0.a0.a0.a1); - Expect.equals(a0.a0.a1.a0, result.a0.a0.a1.a0); - Expect.equals(a0.a0.a1.a1, result.a0.a0.a1.a1); - Expect.equals(a0.a1.a0.a0, result.a0.a1.a0.a0); - Expect.equals(a0.a1.a0.a1, result.a0.a1.a0.a1); - Expect.equals(a0.a1.a1.a0, result.a0.a1.a1.a0); - Expect.equals(a0.a1.a1.a1, result.a0.a1.a1.a1); - Expect.equals(a1.a0.a0.a0, result.a1.a0.a0.a0); - Expect.equals(a1.a0.a0.a1, result.a1.a0.a0.a1); - Expect.equals(a1.a0.a1.a0, result.a1.a0.a1.a0); - Expect.equals(a1.a0.a1.a1, result.a1.a0.a1.a1); - Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); - Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); - Expect.equals(a1.a1.a1.a0, result.a1.a1.a1.a0); - Expect.equals(a1.a1.a1.a1, result.a1.a1.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt16Leaf = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt16 Function( - StructAlignmentInt16, StructAlignmentInt16), - StructNestedIntStructAlignmentInt16 Function( - StructAlignmentInt16, StructAlignmentInt16)>( - "ReturnStructNestedIntStructAlignmentInt16", - isLeaf: true); - -/// Test alignment and padding of nested struct with 16 byte int. -void testReturnStructNestedIntStructAlignmentInt16Leaf() { - final a0Pointer = calloc(); - final StructAlignmentInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt16 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt16Leaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt32Leaf = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt32 Function( - StructAlignmentInt32, StructAlignmentInt32), - StructNestedIntStructAlignmentInt32 Function( - StructAlignmentInt32, StructAlignmentInt32)>( - "ReturnStructNestedIntStructAlignmentInt32", - isLeaf: true); - -/// Test alignment and padding of nested struct with 32 byte int. -void testReturnStructNestedIntStructAlignmentInt32Leaf() { - final a0Pointer = calloc(); - final StructAlignmentInt32 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt32 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt32Leaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt64Leaf = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt64 Function( - StructAlignmentInt64, StructAlignmentInt64), - StructNestedIntStructAlignmentInt64 Function( - StructAlignmentInt64, StructAlignmentInt64)>( - "ReturnStructNestedIntStructAlignmentInt64", - isLeaf: true); - -/// Test alignment and padding of nested struct with 64 byte int. -void testReturnStructNestedIntStructAlignmentInt64Leaf() { - final a0Pointer = calloc(); - final StructAlignmentInt64 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt64 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt64Leaf(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIrregularEvenBiggerLeaf = - ffiTestFunctions.lookupFunction< - StructNestedIrregularEvenBigger Function(Uint64, - StructNestedIrregularBigger, StructNestedIrregularBigger, Double), - StructNestedIrregularEvenBigger Function( - int, - StructNestedIrregularBigger, - StructNestedIrregularBigger, - double)>("ReturnStructNestedIrregularEvenBigger", isLeaf: true); - -/// Return big irregular struct as smoke test. -void testReturnStructNestedIrregularEvenBiggerLeaf() { - int a0; - final a1Pointer = calloc(); - final StructNestedIrregularBigger a1 = a1Pointer.ref; - final a2Pointer = calloc(); - final StructNestedIrregularBigger a2 = a2Pointer.ref; - 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; - - final result = returnStructNestedIrregularEvenBiggerLeaf(a0, a1, a2, a3); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1.a0.a0, result.a1.a0.a0); - Expect.equals(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0); - Expect.equals(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1); - Expect.approxEquals(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0); - Expect.equals(a1.a0.a2, result.a1.a0.a2); - Expect.approxEquals(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0); - Expect.approxEquals(a1.a0.a3.a1, result.a1.a0.a3.a1); - Expect.equals(a1.a0.a4, result.a1.a0.a4); - Expect.approxEquals(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0); - Expect.approxEquals(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0); - Expect.equals(a1.a0.a6, result.a1.a0.a6); - Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); - Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); - Expect.approxEquals(a1.a1.a1.a0, result.a1.a1.a1.a0); - Expect.approxEquals(a1.a2, result.a1.a2); - Expect.approxEquals(a1.a3, result.a1.a3); - Expect.equals(a2.a0.a0, result.a2.a0.a0); - Expect.equals(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0); - Expect.equals(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1); - Expect.approxEquals(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0); - Expect.equals(a2.a0.a2, result.a2.a0.a2); - Expect.approxEquals(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0); - Expect.approxEquals(a2.a0.a3.a1, result.a2.a0.a3.a1); - Expect.equals(a2.a0.a4, result.a2.a0.a4); - Expect.approxEquals(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0); - Expect.approxEquals(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0); - Expect.equals(a2.a0.a6, result.a2.a0.a6); - Expect.equals(a2.a1.a0.a0, result.a2.a1.a0.a0); - Expect.equals(a2.a1.a0.a1, result.a2.a1.a0.a1); - Expect.approxEquals(a2.a1.a1.a0, result.a2.a1.a1.a0); - Expect.approxEquals(a2.a2, result.a2.a2); - Expect.approxEquals(a2.a3, result.a2.a3); - Expect.approxEquals(a3, result.a3); - - calloc.free(a1Pointer); - calloc.free(a2Pointer); -} diff --git a/tests/ffi_2/function_structs_by_value_generated_test.dart b/tests/ffi_2/function_structs_by_value_generated_args_test.dart similarity index 71% rename from tests/ffi_2/function_structs_by_value_generated_test.dart rename to tests/ffi_2/function_structs_by_value_generated_args_test.dart index a25487f33cc..6ee8839dd1c 100644 --- a/tests/ffi_2/function_structs_by_value_generated_test.dart +++ b/tests/ffi_2/function_structs_by_value_generated_args_test.dart @@ -7,7 +7,7 @@ // // SharedObjects=ffi_test_functions // VMOptions= -// VMOptions=--deterministic --optimization-counter-threshold=20 +// VMOptions=--deterministic --optimization-counter-threshold=90 // VMOptions=--use-slow-path // VMOptions=--use-slow-path --stacktrace-every=100 @@ -25,7 +25,7 @@ import 'function_structs_by_value_generated_compounds.dart'; final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); void main() { - for (int i = 0; i < 25; ++i) { + for (int i = 0; i < 100; ++i) { testPassStruct1ByteIntx10(); testPassStruct3BytesHomogeneousUint8x10(); testPassStruct3BytesInt2ByteAlignedx10(); @@ -92,57 +92,6 @@ void main() { testPassUint8Boolx9Struct10BytesInlineArrayBoolBool(); testPassUint8Struct1ByteBool(); testPassWCharStructInlineArrayIntUintPtrx2LongUnsigned(); - testReturnStruct1ByteInt(); - testReturnStruct3BytesHomogeneousUint8(); - testReturnStruct3BytesInt2ByteAligned(); - testReturnStruct4BytesHomogeneousInt16(); - testReturnStruct7BytesHomogeneousUint8(); - testReturnStruct7BytesInt4ByteAligned(); - testReturnStruct8BytesInt(); - testReturnStruct8BytesHomogeneousFloat(); - testReturnStruct8BytesMixed(); - testReturnStruct9BytesHomogeneousUint8(); - testReturnStruct9BytesInt4Or8ByteAligned(); - testReturnStruct12BytesHomogeneousFloat(); - testReturnStruct16BytesHomogeneousFloat(); - testReturnStruct16BytesMixed(); - testReturnStruct16BytesMixed2(); - testReturnStruct17BytesInt(); - testReturnStruct19BytesHomogeneousUint8(); - testReturnStruct20BytesHomogeneousInt32(); - testReturnStruct20BytesHomogeneousFloat(); - testReturnStruct32BytesHomogeneousDouble(); - testReturnStruct40BytesHomogeneousDouble(); - testReturnStruct1024BytesHomogeneousUint64(); - testReturnStruct3BytesPackedInt(); - testReturnStruct8BytesPackedInt(); - testReturnStruct9BytesPackedMixed(); - testReturnUnion4BytesMixed(); - testReturnUnion8BytesNestedFloat(); - testReturnUnion9BytesNestedInt(); - testReturnUnion16BytesNestedFloat(); - testReturnStructArgumentStruct1ByteInt(); - testReturnStructArgumentInt32x8Struct1ByteInt(); - testReturnStructArgumentStruct8BytesHomogeneousFloat(); - testReturnStructArgumentStruct20BytesHomogeneousInt32(); - testReturnStructArgumentInt32x8Struct20BytesHomogeneou(); - testReturnStructArgumentStruct8BytesInlineArrayInt(); - testReturnStructArgumentStructStruct16BytesHomogeneous(); - testReturnStructArgumentStructStruct32BytesHomogeneous(); - testReturnStructArgumentStructStruct16BytesMixed3(); - testReturnStructAlignmentInt16(); - testReturnStructAlignmentInt32(); - testReturnStructAlignmentInt64(); - testReturnStruct8BytesNestedInt(); - testReturnStruct8BytesNestedFloat(); - testReturnStruct8BytesNestedFloat2(); - testReturnStruct8BytesNestedMixed(); - testReturnStruct16BytesNestedInt(); - testReturnStruct32BytesNestedInt(); - testReturnStructNestedIntStructAlignmentInt16(); - testReturnStructNestedIntStructAlignmentInt32(); - testReturnStructNestedIntStructAlignmentInt64(); - testReturnStructNestedIrregularEvenBigger(); } } @@ -5430,2356 +5379,3 @@ void testPassWCharStructInlineArrayIntUintPtrx2LongUnsigned() { calloc.free(a1Pointer); } - -final returnStruct1ByteInt = ffiTestFunctions.lookupFunction< - Struct1ByteInt Function(Int8), - Struct1ByteInt Function(int)>("ReturnStruct1ByteInt"); - -/// Smallest struct with data. -void testReturnStruct1ByteInt() { - int a0; - - a0 = -1; - - final result = returnStruct1ByteInt(a0); - - print("result = $result"); - - Expect.equals(a0, result.a0); -} - -final returnStruct3BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< - Struct3BytesHomogeneousUint8 Function(Uint8, Uint8, Uint8), - Struct3BytesHomogeneousUint8 Function( - int, int, int)>("ReturnStruct3BytesHomogeneousUint8"); - -/// Smaller than word size return value on all architectures. -void testReturnStruct3BytesHomogeneousUint8() { - int a0; - int a1; - int a2; - - a0 = 1; - a1 = 2; - a2 = 3; - - final result = returnStruct3BytesHomogeneousUint8(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct3BytesInt2ByteAligned = ffiTestFunctions.lookupFunction< - Struct3BytesInt2ByteAligned Function(Int16, Int8), - Struct3BytesInt2ByteAligned Function( - int, int)>("ReturnStruct3BytesInt2ByteAligned"); - -/// Smaller than word size return value on all architectures. -/// With alignment rules taken into account size is 4 bytes. -void testReturnStruct3BytesInt2ByteAligned() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct3BytesInt2ByteAligned(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct4BytesHomogeneousInt16 = ffiTestFunctions.lookupFunction< - Struct4BytesHomogeneousInt16 Function(Int16, Int16), - Struct4BytesHomogeneousInt16 Function( - int, int)>("ReturnStruct4BytesHomogeneousInt16"); - -/// Word size return value on 32 bit architectures.. -void testReturnStruct4BytesHomogeneousInt16() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct4BytesHomogeneousInt16(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct7BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< - Struct7BytesHomogeneousUint8 Function( - Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), - Struct7BytesHomogeneousUint8 Function(int, int, int, int, int, int, - int)>("ReturnStruct7BytesHomogeneousUint8"); - -/// Non-wordsize return value. -void testReturnStruct7BytesHomogeneousUint8() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - a5 = 6; - a6 = 7; - - final result = returnStruct7BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); -} - -final returnStruct7BytesInt4ByteAligned = ffiTestFunctions.lookupFunction< - Struct7BytesInt4ByteAligned Function(Int32, Int16, Int8), - Struct7BytesInt4ByteAligned Function( - int, int, int)>("ReturnStruct7BytesInt4ByteAligned"); - -/// Non-wordsize return value. -/// With alignment rules taken into account size is 8 bytes. -void testReturnStruct7BytesInt4ByteAligned() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct7BytesInt4ByteAligned(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesInt = ffiTestFunctions.lookupFunction< - Struct8BytesInt Function(Int16, Int16, Int32), - Struct8BytesInt Function(int, int, int)>("ReturnStruct8BytesInt"); - -/// Return value in integer registers on many architectures. -void testReturnStruct8BytesInt() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct8BytesInt(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< - Struct8BytesHomogeneousFloat Function(Float, Float), - Struct8BytesHomogeneousFloat Function( - double, double)>("ReturnStruct8BytesHomogeneousFloat"); - -/// Return value in FP registers on many architectures. -void testReturnStruct8BytesHomogeneousFloat() { - double a0; - double a1; - - a0 = -1.0; - a1 = 2.0; - - final result = returnStruct8BytesHomogeneousFloat(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); -} - -final returnStruct8BytesMixed = ffiTestFunctions.lookupFunction< - Struct8BytesMixed Function(Float, Int16, Int16), - Struct8BytesMixed Function(double, int, int)>("ReturnStruct8BytesMixed"); - -/// Return value split over FP and integer register in x64. -void testReturnStruct8BytesMixed() { - double a0; - int a1; - int a2; - - a0 = -1.0; - a1 = 2; - a2 = -3; - - final result = returnStruct8BytesMixed(a0, a1, a2); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct9BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< - Struct9BytesHomogeneousUint8 Function( - Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), - Struct9BytesHomogeneousUint8 Function(int, int, int, int, int, int, int, - int, int)>("ReturnStruct9BytesHomogeneousUint8"); - -/// 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. -void testReturnStruct9BytesHomogeneousUint8() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - a5 = 6; - a6 = 7; - a7 = 8; - a8 = 9; - - final result = - returnStruct9BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); -} - -final returnStruct9BytesInt4Or8ByteAligned = ffiTestFunctions.lookupFunction< - Struct9BytesInt4Or8ByteAligned Function(Int64, Int8), - Struct9BytesInt4Or8ByteAligned Function( - int, int)>("ReturnStruct9BytesInt4Or8ByteAligned"); - -/// Return value in two integer registers on x64. -/// With alignment rules taken into account size is 12 or 16 bytes. -void testReturnStruct9BytesInt4Or8ByteAligned() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct9BytesInt4Or8ByteAligned(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct12BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< - Struct12BytesHomogeneousFloat Function(Float, Float, Float), - Struct12BytesHomogeneousFloat Function( - double, double, double)>("ReturnStruct12BytesHomogeneousFloat"); - -/// Return value in FPU registers, but does not use all registers on arm hardfp -/// and arm64. -void testReturnStruct12BytesHomogeneousFloat() { - double a0; - double a1; - double a2; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - - final result = returnStruct12BytesHomogeneousFloat(a0, a1, a2); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); -} - -final returnStruct16BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< - Struct16BytesHomogeneousFloat Function(Float, Float, Float, Float), - Struct16BytesHomogeneousFloat Function( - double, double, double, double)>("ReturnStruct16BytesHomogeneousFloat"); - -/// Return value in FPU registers on arm hardfp and arm64. -void testReturnStruct16BytesHomogeneousFloat() { - double a0; - double a1; - double a2; - double a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4.0; - - final result = returnStruct16BytesHomogeneousFloat(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); -} - -final returnStruct16BytesMixed = ffiTestFunctions.lookupFunction< - Struct16BytesMixed Function(Double, Int64), - Struct16BytesMixed Function(double, int)>("ReturnStruct16BytesMixed"); - -/// Return value split over FP and integer register in x64. -void testReturnStruct16BytesMixed() { - double a0; - int a1; - - a0 = -1.0; - a1 = 2; - - final result = returnStruct16BytesMixed(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct16BytesMixed2 = ffiTestFunctions.lookupFunction< - Struct16BytesMixed2 Function(Float, Float, Float, Int32), - Struct16BytesMixed2 Function( - double, double, double, int)>("ReturnStruct16BytesMixed2"); - -/// Return value split over FP and integer register in x64. -/// The integer register contains half float half int. -void testReturnStruct16BytesMixed2() { - double a0; - double a1; - double a2; - int a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4; - - final result = returnStruct16BytesMixed2(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.equals(a3, result.a3); -} - -final returnStruct17BytesInt = ffiTestFunctions.lookupFunction< - Struct17BytesInt Function(Int64, Int64, Int8), - Struct17BytesInt Function(int, int, int)>("ReturnStruct17BytesInt"); - -/// 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. -void testReturnStruct17BytesInt() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStruct17BytesInt(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct19BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< - Struct19BytesHomogeneousUint8 Function( - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8, - Uint8), - Struct19BytesHomogeneousUint8 Function( - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int)>("ReturnStruct19BytesHomogeneousUint8"); - -/// 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. -void testReturnStruct19BytesHomogeneousUint8() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - int a9; - int a10; - int a11; - int a12; - int a13; - int a14; - int a15; - int a16; - int a17; - int 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; - - final result = returnStruct19BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6, - a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); - Expect.equals(a9, result.a9); - Expect.equals(a10, result.a10); - Expect.equals(a11, result.a11); - Expect.equals(a12, result.a12); - Expect.equals(a13, result.a13); - Expect.equals(a14, result.a14); - Expect.equals(a15, result.a15); - Expect.equals(a16, result.a16); - Expect.equals(a17, result.a17); - Expect.equals(a18, result.a18); -} - -final returnStruct20BytesHomogeneousInt32 = ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32), - Struct20BytesHomogeneousInt32 Function( - int, int, int, int, int)>("ReturnStruct20BytesHomogeneousInt32"); - -/// Return value too big to go in cpu registers on arm64. -void testReturnStruct20BytesHomogeneousInt32() { - int a0; - int a1; - int a2; - int a3; - int a4; - - a0 = -1; - a1 = 2; - a2 = -3; - a3 = 4; - a4 = -5; - - final result = returnStruct20BytesHomogeneousInt32(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); -} - -final returnStruct20BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousFloat Function(Float, Float, Float, Float, Float), - Struct20BytesHomogeneousFloat Function(double, double, double, double, - double)>("ReturnStruct20BytesHomogeneousFloat"); - -/// Return value too big to go in FPU registers on x64, arm hardfp and arm64. -void testReturnStruct20BytesHomogeneousFloat() { - 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; - - final result = returnStruct20BytesHomogeneousFloat(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); - Expect.approxEquals(a4, result.a4); -} - -final returnStruct32BytesHomogeneousDouble = ffiTestFunctions.lookupFunction< - Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double), - Struct32BytesHomogeneousDouble Function(double, double, double, - double)>("ReturnStruct32BytesHomogeneousDouble"); - -/// Return value in FPU registers on arm64. -void testReturnStruct32BytesHomogeneousDouble() { - double a0; - double a1; - double a2; - double a3; - - a0 = -1.0; - a1 = 2.0; - a2 = -3.0; - a3 = 4.0; - - final result = returnStruct32BytesHomogeneousDouble(a0, a1, a2, a3); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); -} - -final returnStruct40BytesHomogeneousDouble = ffiTestFunctions.lookupFunction< - Struct40BytesHomogeneousDouble Function( - Double, Double, Double, Double, Double), - Struct40BytesHomogeneousDouble Function(double, double, double, double, - double)>("ReturnStruct40BytesHomogeneousDouble"); - -/// Return value too big to go in FPU registers on arm64. -void testReturnStruct40BytesHomogeneousDouble() { - 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; - - final result = returnStruct40BytesHomogeneousDouble(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); - Expect.approxEquals(a1, result.a1); - Expect.approxEquals(a2, result.a2); - Expect.approxEquals(a3, result.a3); - Expect.approxEquals(a4, result.a4); -} - -final returnStruct1024BytesHomogeneousUint64 = ffiTestFunctions.lookupFunction< - Struct1024BytesHomogeneousUint64 Function( - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64, - Uint64), - Struct1024BytesHomogeneousUint64 Function( - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int, - int)>("ReturnStruct1024BytesHomogeneousUint64"); - -/// Test 1kb struct. -void testReturnStruct1024BytesHomogeneousUint64() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - int a8; - int a9; - int a10; - int a11; - int a12; - int a13; - int a14; - int a15; - int a16; - int a17; - int a18; - int a19; - int a20; - int a21; - int a22; - int a23; - int a24; - int a25; - int a26; - int a27; - int a28; - int a29; - int a30; - int a31; - int a32; - int a33; - int a34; - int a35; - int a36; - int a37; - int a38; - int a39; - int a40; - int a41; - int a42; - int a43; - int a44; - int a45; - int a46; - int a47; - int a48; - int a49; - int a50; - int a51; - int a52; - int a53; - int a54; - int a55; - int a56; - int a57; - int a58; - int a59; - int a60; - int a61; - int a62; - int a63; - int a64; - int a65; - int a66; - int a67; - int a68; - int a69; - int a70; - int a71; - int a72; - int a73; - int a74; - int a75; - int a76; - int a77; - int a78; - int a79; - int a80; - int a81; - int a82; - int a83; - int a84; - int a85; - int a86; - int a87; - int a88; - int a89; - int a90; - int a91; - int a92; - int a93; - int a94; - int a95; - int a96; - int a97; - int a98; - int a99; - int a100; - int a101; - int a102; - int a103; - int a104; - int a105; - int a106; - int a107; - int a108; - int a109; - int a110; - int a111; - int a112; - int a113; - int a114; - int a115; - int a116; - int a117; - int a118; - int a119; - int a120; - int a121; - int a122; - int a123; - int a124; - int a125; - int a126; - int 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; - - final result = 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); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); - Expect.equals(a5, result.a5); - Expect.equals(a6, result.a6); - Expect.equals(a7, result.a7); - Expect.equals(a8, result.a8); - Expect.equals(a9, result.a9); - Expect.equals(a10, result.a10); - Expect.equals(a11, result.a11); - Expect.equals(a12, result.a12); - Expect.equals(a13, result.a13); - Expect.equals(a14, result.a14); - Expect.equals(a15, result.a15); - Expect.equals(a16, result.a16); - Expect.equals(a17, result.a17); - Expect.equals(a18, result.a18); - Expect.equals(a19, result.a19); - Expect.equals(a20, result.a20); - Expect.equals(a21, result.a21); - Expect.equals(a22, result.a22); - Expect.equals(a23, result.a23); - Expect.equals(a24, result.a24); - Expect.equals(a25, result.a25); - Expect.equals(a26, result.a26); - Expect.equals(a27, result.a27); - Expect.equals(a28, result.a28); - Expect.equals(a29, result.a29); - Expect.equals(a30, result.a30); - Expect.equals(a31, result.a31); - Expect.equals(a32, result.a32); - Expect.equals(a33, result.a33); - Expect.equals(a34, result.a34); - Expect.equals(a35, result.a35); - Expect.equals(a36, result.a36); - Expect.equals(a37, result.a37); - Expect.equals(a38, result.a38); - Expect.equals(a39, result.a39); - Expect.equals(a40, result.a40); - Expect.equals(a41, result.a41); - Expect.equals(a42, result.a42); - Expect.equals(a43, result.a43); - Expect.equals(a44, result.a44); - Expect.equals(a45, result.a45); - Expect.equals(a46, result.a46); - Expect.equals(a47, result.a47); - Expect.equals(a48, result.a48); - Expect.equals(a49, result.a49); - Expect.equals(a50, result.a50); - Expect.equals(a51, result.a51); - Expect.equals(a52, result.a52); - Expect.equals(a53, result.a53); - Expect.equals(a54, result.a54); - Expect.equals(a55, result.a55); - Expect.equals(a56, result.a56); - Expect.equals(a57, result.a57); - Expect.equals(a58, result.a58); - Expect.equals(a59, result.a59); - Expect.equals(a60, result.a60); - Expect.equals(a61, result.a61); - Expect.equals(a62, result.a62); - Expect.equals(a63, result.a63); - Expect.equals(a64, result.a64); - Expect.equals(a65, result.a65); - Expect.equals(a66, result.a66); - Expect.equals(a67, result.a67); - Expect.equals(a68, result.a68); - Expect.equals(a69, result.a69); - Expect.equals(a70, result.a70); - Expect.equals(a71, result.a71); - Expect.equals(a72, result.a72); - Expect.equals(a73, result.a73); - Expect.equals(a74, result.a74); - Expect.equals(a75, result.a75); - Expect.equals(a76, result.a76); - Expect.equals(a77, result.a77); - Expect.equals(a78, result.a78); - Expect.equals(a79, result.a79); - Expect.equals(a80, result.a80); - Expect.equals(a81, result.a81); - Expect.equals(a82, result.a82); - Expect.equals(a83, result.a83); - Expect.equals(a84, result.a84); - Expect.equals(a85, result.a85); - Expect.equals(a86, result.a86); - Expect.equals(a87, result.a87); - Expect.equals(a88, result.a88); - Expect.equals(a89, result.a89); - Expect.equals(a90, result.a90); - Expect.equals(a91, result.a91); - Expect.equals(a92, result.a92); - Expect.equals(a93, result.a93); - Expect.equals(a94, result.a94); - Expect.equals(a95, result.a95); - Expect.equals(a96, result.a96); - Expect.equals(a97, result.a97); - Expect.equals(a98, result.a98); - Expect.equals(a99, result.a99); - Expect.equals(a100, result.a100); - Expect.equals(a101, result.a101); - Expect.equals(a102, result.a102); - Expect.equals(a103, result.a103); - Expect.equals(a104, result.a104); - Expect.equals(a105, result.a105); - Expect.equals(a106, result.a106); - Expect.equals(a107, result.a107); - Expect.equals(a108, result.a108); - Expect.equals(a109, result.a109); - Expect.equals(a110, result.a110); - Expect.equals(a111, result.a111); - Expect.equals(a112, result.a112); - Expect.equals(a113, result.a113); - Expect.equals(a114, result.a114); - Expect.equals(a115, result.a115); - Expect.equals(a116, result.a116); - Expect.equals(a117, result.a117); - Expect.equals(a118, result.a118); - Expect.equals(a119, result.a119); - Expect.equals(a120, result.a120); - Expect.equals(a121, result.a121); - Expect.equals(a122, result.a122); - Expect.equals(a123, result.a123); - Expect.equals(a124, result.a124); - Expect.equals(a125, result.a125); - Expect.equals(a126, result.a126); - Expect.equals(a127, result.a127); -} - -final returnStruct3BytesPackedInt = ffiTestFunctions.lookupFunction< - Struct3BytesPackedInt Function(Int8, Int16), - Struct3BytesPackedInt Function(int, int)>("ReturnStruct3BytesPackedInt"); - -/// Small struct with mis-aligned member. -void testReturnStruct3BytesPackedInt() { - int a0; - int a1; - - a0 = -1; - a1 = 2; - - final result = returnStruct3BytesPackedInt(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); -} - -final returnStruct8BytesPackedInt = ffiTestFunctions.lookupFunction< - Struct8BytesPackedInt Function(Uint8, Uint32, Uint8, Uint8, Uint8), - Struct8BytesPackedInt Function( - int, int, int, int, int)>("ReturnStruct8BytesPackedInt"); - -/// Struct with mis-aligned member. -void testReturnStruct8BytesPackedInt() { - int a0; - int a1; - int a2; - int a3; - int a4; - - a0 = 1; - a1 = 2; - a2 = 3; - a3 = 4; - a4 = 5; - - final result = returnStruct8BytesPackedInt(a0, a1, a2, a3, a4); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); - Expect.equals(a3, result.a3); - Expect.equals(a4, result.a4); -} - -final returnStruct9BytesPackedMixed = ffiTestFunctions.lookupFunction< - Struct9BytesPackedMixed Function(Uint8, Double), - Struct9BytesPackedMixed Function( - int, double)>("ReturnStruct9BytesPackedMixed"); - -/// Struct with mis-aligned member. -/// Tests backfilling of CPU and FPU registers. -void testReturnStruct9BytesPackedMixed() { - int a0; - double a1; - - a0 = 1; - a1 = 2.0; - - final result = returnStruct9BytesPackedMixed(a0, a1); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.approxEquals(a1, result.a1); -} - -final returnUnion4BytesMixed = ffiTestFunctions.lookupFunction< - Union4BytesMixed Function(Uint32), - Union4BytesMixed Function(int)>("ReturnUnion4BytesMixed"); - -/// Returning a mixed integer/float union. -void testReturnUnion4BytesMixed() { - int a0; - - a0 = 1; - - final result = returnUnion4BytesMixed(a0); - - print("result = $result"); - - Expect.equals(a0, result.a0); -} - -final returnUnion8BytesNestedFloat = ffiTestFunctions.lookupFunction< - Union8BytesNestedFloat Function(Double), - Union8BytesNestedFloat Function(double)>("ReturnUnion8BytesNestedFloat"); - -/// Returning a floating point only union. -void testReturnUnion8BytesNestedFloat() { - double a0; - - a0 = -1.0; - - final result = returnUnion8BytesNestedFloat(a0); - - print("result = $result"); - - Expect.approxEquals(a0, result.a0); -} - -final returnUnion9BytesNestedInt = ffiTestFunctions.lookupFunction< - Union9BytesNestedInt Function(Struct8BytesInt), - Union9BytesNestedInt Function( - Struct8BytesInt)>("ReturnUnion9BytesNestedInt"); - -/// Returning a mixed-size union. -void testReturnUnion9BytesNestedInt() { - final a0Pointer = calloc(); - final Struct8BytesInt a0 = a0Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - - final result = returnUnion9BytesNestedInt(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - - calloc.free(a0Pointer); -} - -final returnUnion16BytesNestedFloat = ffiTestFunctions.lookupFunction< - Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat), - Union16BytesNestedFloat Function( - Struct8BytesHomogeneousFloat)>("ReturnUnion16BytesNestedFloat"); - -/// Returning union with homogenous floats. -void testReturnUnion16BytesNestedFloat() { - final a0Pointer = calloc(); - final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; - - a0.a0 = -1.0; - a0.a1 = 2.0; - - final result = returnUnion16BytesNestedFloat(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a0.a1, result.a0.a1); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStruct1ByteInt = ffiTestFunctions.lookupFunction< - Struct1ByteInt Function(Struct1ByteInt), - Struct1ByteInt Function( - Struct1ByteInt)>("ReturnStructArgumentStruct1ByteInt"); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed in int registers in most ABIs. -void testReturnStructArgumentStruct1ByteInt() { - final a0Pointer = calloc(); - final Struct1ByteInt a0 = a0Pointer.ref; - - a0.a0 = -1; - - final result = returnStructArgumentStruct1ByteInt(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0); - - calloc.free(a0Pointer); -} - -final returnStructArgumentInt32x8Struct1ByteInt = - ffiTestFunctions.lookupFunction< - Struct1ByteInt Function(Int32, Int32, Int32, Int32, Int32, Int32, Int32, - Int32, Struct1ByteInt), - Struct1ByteInt Function(int, int, int, int, int, int, int, int, - Struct1ByteInt)>("ReturnStructArgumentInt32x8Struct1ByteInt"); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed on stack on all ABIs. -void testReturnStructArgumentInt32x8Struct1ByteInt() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - final a8Pointer = calloc(); - final Struct1ByteInt a8 = a8Pointer.ref; - - a0 = -1; - a1 = 2; - a2 = -3; - a3 = 4; - a4 = -5; - a5 = 6; - a6 = -7; - a7 = 8; - a8.a0 = -9; - - final result = returnStructArgumentInt32x8Struct1ByteInt( - a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a8.a0, result.a0); - - calloc.free(a8Pointer); -} - -final returnStructArgumentStruct8BytesHomogeneousFloat = - ffiTestFunctions.lookupFunction< - Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat), - Struct8BytesHomogeneousFloat Function( - Struct8BytesHomogeneousFloat)>( - "ReturnStructArgumentStruct8BytesHomogeneousFloat"); - -/// Test that a struct passed in as argument can be returned. -/// Especially for ffi callbacks. -/// Struct is passed in float registers in most ABIs. -void testReturnStructArgumentStruct8BytesHomogeneousFloat() { - final a0Pointer = calloc(); - final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; - - a0.a0 = -1.0; - a0.a1 = 2.0; - - final result = returnStructArgumentStruct8BytesHomogeneousFloat(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0); - Expect.approxEquals(a0.a1, result.a1); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStruct20BytesHomogeneousInt32 = - ffiTestFunctions - .lookupFunction< - Struct20BytesHomogeneousInt32 Function( - Struct20BytesHomogeneousInt32), - Struct20BytesHomogeneousInt32 Function( - Struct20BytesHomogeneousInt32)>( - "ReturnStructArgumentStruct20BytesHomogeneousInt32"); - -/// On arm64, both argument and return value are passed in by pointer. -void testReturnStructArgumentStruct20BytesHomogeneousInt32() { - final a0Pointer = calloc(); - final Struct20BytesHomogeneousInt32 a0 = a0Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a0.a3 = 4; - a0.a4 = -5; - - final result = returnStructArgumentStruct20BytesHomogeneousInt32(a0); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0); - Expect.equals(a0.a1, result.a1); - Expect.equals(a0.a2, result.a2); - Expect.equals(a0.a3, result.a3); - Expect.equals(a0.a4, result.a4); - - calloc.free(a0Pointer); -} - -final returnStructArgumentInt32x8Struct20BytesHomogeneou = - ffiTestFunctions.lookupFunction< - Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, - Int32, Int32, Int32, Int32, Struct20BytesHomogeneousInt32), - Struct20BytesHomogeneousInt32 Function(int, int, int, int, int, int, - int, int, Struct20BytesHomogeneousInt32)>( - "ReturnStructArgumentInt32x8Struct20BytesHomogeneou"); - -/// On arm64, both argument and return value are passed in by pointer. -/// Ints exhaust registers, so that pointer is passed on stack. -void testReturnStructArgumentInt32x8Struct20BytesHomogeneou() { - int a0; - int a1; - int a2; - int a3; - int a4; - int a5; - int a6; - int a7; - final a8Pointer = calloc(); - final Struct20BytesHomogeneousInt32 a8 = a8Pointer.ref; - - 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; - - final result = returnStructArgumentInt32x8Struct20BytesHomogeneou( - a0, a1, a2, a3, a4, a5, a6, a7, a8); - - print("result = $result"); - - Expect.equals(a8.a0, result.a0); - Expect.equals(a8.a1, result.a1); - Expect.equals(a8.a2, result.a2); - Expect.equals(a8.a3, result.a3); - Expect.equals(a8.a4, result.a4); - - calloc.free(a8Pointer); -} - -final returnStructArgumentStruct8BytesInlineArrayInt = - ffiTestFunctions.lookupFunction< - Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt), - Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt)>( - "ReturnStructArgumentStruct8BytesInlineArrayInt"); - -/// Test returning struct with inline array. -void testReturnStructArgumentStruct8BytesInlineArrayInt() { - final a0Pointer = calloc(); - final Struct8BytesInlineArrayInt a0 = a0Pointer.ref; - - 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; - - final result = returnStructArgumentStruct8BytesInlineArrayInt(a0); - - print("result = $result"); - - for (int i = 0; i < 8; i++) { - Expect.equals(a0.a0[i], result.a0[i]); - } - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct16BytesHomogeneous = - ffiTestFunctions.lookupFunction< - StructStruct16BytesHomogeneousFloat2 Function( - StructStruct16BytesHomogeneousFloat2), - StructStruct16BytesHomogeneousFloat2 Function( - StructStruct16BytesHomogeneousFloat2)>( - "ReturnStructArgumentStructStruct16BytesHomogeneous"); - -/// Return value in FPU registers on arm hardfp and arm64. -void testReturnStructArgumentStructStruct16BytesHomogeneous() { - final a0Pointer = calloc(); - final StructStruct16BytesHomogeneousFloat2 a0 = a0Pointer.ref; - - a0.a0.a0 = -1.0; - a0.a1[0].a0 = 2.0; - a0.a1[1].a0 = -3.0; - a0.a2 = 4.0; - - final result = returnStructArgumentStructStruct16BytesHomogeneous(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 2; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - } - Expect.approxEquals(a0.a2, result.a2); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct32BytesHomogeneous = - ffiTestFunctions.lookupFunction< - StructStruct32BytesHomogeneousDouble2 Function( - StructStruct32BytesHomogeneousDouble2), - StructStruct32BytesHomogeneousDouble2 Function( - StructStruct32BytesHomogeneousDouble2)>( - "ReturnStructArgumentStructStruct32BytesHomogeneous"); - -/// Return value in FPU registers on arm64. -void testReturnStructArgumentStructStruct32BytesHomogeneous() { - final a0Pointer = calloc(); - final StructStruct32BytesHomogeneousDouble2 a0 = a0Pointer.ref; - - a0.a0.a0 = -1.0; - a0.a1[0].a0 = 2.0; - a0.a1[1].a0 = -3.0; - a0.a2 = 4.0; - - final result = returnStructArgumentStructStruct32BytesHomogeneous(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 2; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - } - Expect.approxEquals(a0.a2, result.a2); - - calloc.free(a0Pointer); -} - -final returnStructArgumentStructStruct16BytesMixed3 = - ffiTestFunctions.lookupFunction< - StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3), - StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3)>( - "ReturnStructArgumentStructStruct16BytesMixed3"); - -/// On x64 Linux, return value is split over FP and int registers. -void testReturnStructArgumentStructStruct16BytesMixed3() { - final a0Pointer = calloc(); - final StructStruct16BytesMixed3 a0 = a0Pointer.ref; - - 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; - - final result = returnStructArgumentStructStruct16BytesMixed3(a0); - - print("result = $result"); - - Expect.approxEquals(a0.a0.a0, result.a0.a0); - for (int i = 0; i < 1; i++) { - Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); - Expect.equals(a0.a1[i].a1, result.a1[i].a1); - Expect.equals(a0.a1[i].a2, result.a1[i].a2); - } - for (int i = 0; i < 2; i++) { - Expect.equals(a0.a2[i], result.a2[i]); - } - - calloc.free(a0Pointer); -} - -final returnStructAlignmentInt16 = ffiTestFunctions.lookupFunction< - StructAlignmentInt16 Function(Int8, Int16, Int8), - StructAlignmentInt16 Function(int, int, int)>("ReturnStructAlignmentInt16"); - -/// Test alignment and padding of 16 byte int within struct. -void testReturnStructAlignmentInt16() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt16(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStructAlignmentInt32 = ffiTestFunctions.lookupFunction< - StructAlignmentInt32 Function(Int8, Int32, Int8), - StructAlignmentInt32 Function(int, int, int)>("ReturnStructAlignmentInt32"); - -/// Test alignment and padding of 32 byte int within struct. -void testReturnStructAlignmentInt32() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt32(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStructAlignmentInt64 = ffiTestFunctions.lookupFunction< - StructAlignmentInt64 Function(Int8, Int64, Int8), - StructAlignmentInt64 Function(int, int, int)>("ReturnStructAlignmentInt64"); - -/// Test alignment and padding of 64 byte int within struct. -void testReturnStructAlignmentInt64() { - int a0; - int a1; - int a2; - - a0 = -1; - a1 = 2; - a2 = -3; - - final result = returnStructAlignmentInt64(a0, a1, a2); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1, result.a1); - Expect.equals(a2, result.a2); -} - -final returnStruct8BytesNestedInt = ffiTestFunctions.lookupFunction< - Struct8BytesNestedInt Function( - Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16), - Struct8BytesNestedInt Function(Struct4BytesHomogeneousInt16, - Struct4BytesHomogeneousInt16)>("ReturnStruct8BytesNestedInt"); - -/// Simple nested struct. -void testReturnStruct8BytesNestedInt() { - final a0Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a1.a0 = -3; - a1.a1 = 4; - - final result = returnStruct8BytesNestedInt(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct8BytesNestedFloat = ffiTestFunctions.lookupFunction< - Struct8BytesNestedFloat Function(Struct4BytesFloat, Struct4BytesFloat), - Struct8BytesNestedFloat Function( - Struct4BytesFloat, Struct4BytesFloat)>("ReturnStruct8BytesNestedFloat"); - -/// Simple nested struct with floats. -void testReturnStruct8BytesNestedFloat() { - final a0Pointer = calloc(); - final Struct4BytesFloat a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesFloat a1 = a1Pointer.ref; - - a0.a0 = -1.0; - a1.a0 = 2.0; - - final result = returnStruct8BytesNestedFloat(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a1.a0, result.a1.a0); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct8BytesNestedFloat2 = ffiTestFunctions.lookupFunction< - Struct8BytesNestedFloat2 Function(Struct4BytesFloat, Float), - Struct8BytesNestedFloat2 Function( - Struct4BytesFloat, double)>("ReturnStruct8BytesNestedFloat2"); - -/// The nesting is irregular, testing homogenous float rules on arm and arm64, -/// and the fpu register usage on x64. -void testReturnStruct8BytesNestedFloat2() { - final a0Pointer = calloc(); - final Struct4BytesFloat a0 = a0Pointer.ref; - double a1; - - a0.a0 = -1.0; - a1 = 2.0; - - final result = returnStruct8BytesNestedFloat2(a0, a1); - - print("result = $result"); - - Expect.approxEquals(a0.a0, result.a0.a0); - Expect.approxEquals(a1, result.a1); - - calloc.free(a0Pointer); -} - -final returnStruct8BytesNestedMixed = ffiTestFunctions.lookupFunction< - Struct8BytesNestedMixed Function( - Struct4BytesHomogeneousInt16, Struct4BytesFloat), - Struct8BytesNestedMixed Function(Struct4BytesHomogeneousInt16, - Struct4BytesFloat)>("ReturnStruct8BytesNestedMixed"); - -/// Simple nested struct with mixed members. -void testReturnStruct8BytesNestedMixed() { - final a0Pointer = calloc(); - final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct4BytesFloat a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a1.a0 = -3.0; - - final result = returnStruct8BytesNestedMixed(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.approxEquals(a1.a0, result.a1.a0); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct16BytesNestedInt = ffiTestFunctions.lookupFunction< - Struct16BytesNestedInt Function( - Struct8BytesNestedInt, Struct8BytesNestedInt), - Struct16BytesNestedInt Function(Struct8BytesNestedInt, - Struct8BytesNestedInt)>("ReturnStruct16BytesNestedInt"); - -/// Deeper nested struct to test recursive member access. -void testReturnStruct16BytesNestedInt() { - final a0Pointer = calloc(); - final Struct8BytesNestedInt a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct8BytesNestedInt a1 = a1Pointer.ref; - - 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; - - final result = returnStruct16BytesNestedInt(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0.a0, result.a0.a0.a0); - Expect.equals(a0.a0.a1, result.a0.a0.a1); - Expect.equals(a0.a1.a0, result.a0.a1.a0); - Expect.equals(a0.a1.a1, result.a0.a1.a1); - Expect.equals(a1.a0.a0, result.a1.a0.a0); - Expect.equals(a1.a0.a1, result.a1.a0.a1); - Expect.equals(a1.a1.a0, result.a1.a1.a0); - Expect.equals(a1.a1.a1, result.a1.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStruct32BytesNestedInt = ffiTestFunctions.lookupFunction< - Struct32BytesNestedInt Function( - Struct16BytesNestedInt, Struct16BytesNestedInt), - Struct32BytesNestedInt Function(Struct16BytesNestedInt, - Struct16BytesNestedInt)>("ReturnStruct32BytesNestedInt"); - -/// Even deeper nested struct to test recursive member access. -void testReturnStruct32BytesNestedInt() { - final a0Pointer = calloc(); - final Struct16BytesNestedInt a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final Struct16BytesNestedInt a1 = a1Pointer.ref; - - 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; - - final result = returnStruct32BytesNestedInt(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0.a0.a0, result.a0.a0.a0.a0); - Expect.equals(a0.a0.a0.a1, result.a0.a0.a0.a1); - Expect.equals(a0.a0.a1.a0, result.a0.a0.a1.a0); - Expect.equals(a0.a0.a1.a1, result.a0.a0.a1.a1); - Expect.equals(a0.a1.a0.a0, result.a0.a1.a0.a0); - Expect.equals(a0.a1.a0.a1, result.a0.a1.a0.a1); - Expect.equals(a0.a1.a1.a0, result.a0.a1.a1.a0); - Expect.equals(a0.a1.a1.a1, result.a0.a1.a1.a1); - Expect.equals(a1.a0.a0.a0, result.a1.a0.a0.a0); - Expect.equals(a1.a0.a0.a1, result.a1.a0.a0.a1); - Expect.equals(a1.a0.a1.a0, result.a1.a0.a1.a0); - Expect.equals(a1.a0.a1.a1, result.a1.a0.a1.a1); - Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); - Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); - Expect.equals(a1.a1.a1.a0, result.a1.a1.a1.a0); - Expect.equals(a1.a1.a1.a1, result.a1.a1.a1.a1); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt16 = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt16 Function( - StructAlignmentInt16, StructAlignmentInt16), - StructNestedIntStructAlignmentInt16 Function(StructAlignmentInt16, - StructAlignmentInt16)>("ReturnStructNestedIntStructAlignmentInt16"); - -/// Test alignment and padding of nested struct with 16 byte int. -void testReturnStructNestedIntStructAlignmentInt16() { - final a0Pointer = calloc(); - final StructAlignmentInt16 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt16 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt16(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt32 = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt32 Function( - StructAlignmentInt32, StructAlignmentInt32), - StructNestedIntStructAlignmentInt32 Function(StructAlignmentInt32, - StructAlignmentInt32)>("ReturnStructNestedIntStructAlignmentInt32"); - -/// Test alignment and padding of nested struct with 32 byte int. -void testReturnStructNestedIntStructAlignmentInt32() { - final a0Pointer = calloc(); - final StructAlignmentInt32 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt32 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt32(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIntStructAlignmentInt64 = - ffiTestFunctions.lookupFunction< - StructNestedIntStructAlignmentInt64 Function( - StructAlignmentInt64, StructAlignmentInt64), - StructNestedIntStructAlignmentInt64 Function(StructAlignmentInt64, - StructAlignmentInt64)>("ReturnStructNestedIntStructAlignmentInt64"); - -/// Test alignment and padding of nested struct with 64 byte int. -void testReturnStructNestedIntStructAlignmentInt64() { - final a0Pointer = calloc(); - final StructAlignmentInt64 a0 = a0Pointer.ref; - final a1Pointer = calloc(); - final StructAlignmentInt64 a1 = a1Pointer.ref; - - a0.a0 = -1; - a0.a1 = 2; - a0.a2 = -3; - a1.a0 = 4; - a1.a1 = -5; - a1.a2 = 6; - - final result = returnStructNestedIntStructAlignmentInt64(a0, a1); - - print("result = $result"); - - Expect.equals(a0.a0, result.a0.a0); - Expect.equals(a0.a1, result.a0.a1); - Expect.equals(a0.a2, result.a0.a2); - Expect.equals(a1.a0, result.a1.a0); - Expect.equals(a1.a1, result.a1.a1); - Expect.equals(a1.a2, result.a1.a2); - - calloc.free(a0Pointer); - calloc.free(a1Pointer); -} - -final returnStructNestedIrregularEvenBigger = ffiTestFunctions.lookupFunction< - StructNestedIrregularEvenBigger Function(Uint64, - StructNestedIrregularBigger, StructNestedIrregularBigger, Double), - StructNestedIrregularEvenBigger Function( - int, - StructNestedIrregularBigger, - StructNestedIrregularBigger, - double)>("ReturnStructNestedIrregularEvenBigger"); - -/// Return big irregular struct as smoke test. -void testReturnStructNestedIrregularEvenBigger() { - int a0; - final a1Pointer = calloc(); - final StructNestedIrregularBigger a1 = a1Pointer.ref; - final a2Pointer = calloc(); - final StructNestedIrregularBigger a2 = a2Pointer.ref; - 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; - - final result = returnStructNestedIrregularEvenBigger(a0, a1, a2, a3); - - print("result = $result"); - - Expect.equals(a0, result.a0); - Expect.equals(a1.a0.a0, result.a1.a0.a0); - Expect.equals(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0); - Expect.equals(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1); - Expect.approxEquals(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0); - Expect.equals(a1.a0.a2, result.a1.a0.a2); - Expect.approxEquals(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0); - Expect.approxEquals(a1.a0.a3.a1, result.a1.a0.a3.a1); - Expect.equals(a1.a0.a4, result.a1.a0.a4); - Expect.approxEquals(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0); - Expect.approxEquals(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0); - Expect.equals(a1.a0.a6, result.a1.a0.a6); - Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); - Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); - Expect.approxEquals(a1.a1.a1.a0, result.a1.a1.a1.a0); - Expect.approxEquals(a1.a2, result.a1.a2); - Expect.approxEquals(a1.a3, result.a1.a3); - Expect.equals(a2.a0.a0, result.a2.a0.a0); - Expect.equals(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0); - Expect.equals(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1); - Expect.approxEquals(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0); - Expect.equals(a2.a0.a2, result.a2.a0.a2); - Expect.approxEquals(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0); - Expect.approxEquals(a2.a0.a3.a1, result.a2.a0.a3.a1); - Expect.equals(a2.a0.a4, result.a2.a0.a4); - Expect.approxEquals(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0); - Expect.approxEquals(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0); - Expect.equals(a2.a0.a6, result.a2.a0.a6); - Expect.equals(a2.a1.a0.a0, result.a2.a1.a0.a0); - Expect.equals(a2.a1.a0.a1, result.a2.a1.a0.a1); - Expect.approxEquals(a2.a1.a1.a0, result.a2.a1.a1.a0); - Expect.approxEquals(a2.a2, result.a2.a2); - Expect.approxEquals(a2.a3, result.a2.a3); - Expect.approxEquals(a3, result.a3); - - calloc.free(a1Pointer); - calloc.free(a2Pointer); -} diff --git a/tests/ffi_2/function_structs_by_value_generated_ret_arg_leaf_test.dart b/tests/ffi_2/function_structs_by_value_generated_ret_arg_leaf_test.dart new file mode 100644 index 00000000000..9f85c7507cd --- /dev/null +++ b/tests/ffi_2/function_structs_by_value_generated_ret_arg_leaf_test.dart @@ -0,0 +1,855 @@ +// Copyright (c) 2021, 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. +// Generated by tests/ffi/generator/structs_by_value_tests_generator.dart. +// +// SharedObjects=ffi_test_functions +// VMOptions= +// VMOptions=--deterministic --optimization-counter-threshold=90 +// VMOptions=--use-slow-path +// VMOptions=--use-slow-path --stacktrace-every=100 + +// @dart = 2.9 + +import 'dart:ffi'; + +import "package:expect/expect.dart"; +import "package:ffi/ffi.dart"; + +import 'dylib_utils.dart'; + +// Reuse the compound classes. +import 'function_structs_by_value_generated_compounds.dart'; + +final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); +void main() { + for (int i = 0; i < 100; ++i) { + testReturnStructArgumentStruct1ByteIntLeaf(); + testReturnStructArgumentInt32x8Struct1ByteIntLeaf(); + testReturnStructArgumentStruct8BytesHomogeneousFloatLeaf(); + testReturnStructArgumentStruct20BytesHomogeneousInt32Leaf(); + testReturnStructArgumentInt32x8Struct20BytesHomogeneouLeaf(); + testReturnStructArgumentStruct8BytesInlineArrayIntLeaf(); + testReturnStructArgumentStructStruct16BytesHomogeneousLeaf(); + testReturnStructArgumentStructStruct32BytesHomogeneousLeaf(); + testReturnStructArgumentStructStruct16BytesMixed3Leaf(); + testReturnStructAlignmentInt16Leaf(); + testReturnStructAlignmentInt32Leaf(); + testReturnStructAlignmentInt64Leaf(); + testReturnStruct8BytesNestedIntLeaf(); + testReturnStruct8BytesNestedFloatLeaf(); + testReturnStruct8BytesNestedFloat2Leaf(); + testReturnStruct8BytesNestedMixedLeaf(); + testReturnStruct16BytesNestedIntLeaf(); + testReturnStruct32BytesNestedIntLeaf(); + testReturnStructNestedIntStructAlignmentInt16Leaf(); + testReturnStructNestedIntStructAlignmentInt32Leaf(); + testReturnStructNestedIntStructAlignmentInt64Leaf(); + testReturnStructNestedIrregularEvenBiggerLeaf(); + } +} + +final returnStructArgumentStruct1ByteIntLeaf = ffiTestFunctions.lookupFunction< + Struct1ByteInt Function(Struct1ByteInt), + Struct1ByteInt Function( + Struct1ByteInt)>("ReturnStructArgumentStruct1ByteInt", isLeaf: true); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed in int registers in most ABIs. +void testReturnStructArgumentStruct1ByteIntLeaf() { + final a0Pointer = calloc(); + final Struct1ByteInt a0 = a0Pointer.ref; + + a0.a0 = -1; + + final result = returnStructArgumentStruct1ByteIntLeaf(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0); + + calloc.free(a0Pointer); +} + +final returnStructArgumentInt32x8Struct1ByteIntLeaf = + ffiTestFunctions + .lookupFunction< + Struct1ByteInt Function(Int32, Int32, Int32, Int32, Int32, Int32, + Int32, Int32, Struct1ByteInt), + Struct1ByteInt Function( + int, int, int, int, int, int, int, int, Struct1ByteInt)>( + "ReturnStructArgumentInt32x8Struct1ByteInt", + isLeaf: true); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed on stack on all ABIs. +void testReturnStructArgumentInt32x8Struct1ByteIntLeaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + final a8Pointer = calloc(); + final Struct1ByteInt a8 = a8Pointer.ref; + + a0 = -1; + a1 = 2; + a2 = -3; + a3 = 4; + a4 = -5; + a5 = 6; + a6 = -7; + a7 = 8; + a8.a0 = -9; + + final result = returnStructArgumentInt32x8Struct1ByteIntLeaf( + a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a8.a0, result.a0); + + calloc.free(a8Pointer); +} + +final returnStructArgumentStruct8BytesHomogeneousFloatLeaf = + ffiTestFunctions.lookupFunction< + Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat), + Struct8BytesHomogeneousFloat Function( + Struct8BytesHomogeneousFloat)>( + "ReturnStructArgumentStruct8BytesHomogeneousFloat", + isLeaf: true); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed in float registers in most ABIs. +void testReturnStructArgumentStruct8BytesHomogeneousFloatLeaf() { + final a0Pointer = calloc(); + final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; + + a0.a0 = -1.0; + a0.a1 = 2.0; + + final result = returnStructArgumentStruct8BytesHomogeneousFloatLeaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0); + Expect.approxEquals(a0.a1, result.a1); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStruct20BytesHomogeneousInt32Leaf = + ffiTestFunctions + .lookupFunction< + Struct20BytesHomogeneousInt32 Function( + Struct20BytesHomogeneousInt32), + Struct20BytesHomogeneousInt32 Function( + Struct20BytesHomogeneousInt32)>( + "ReturnStructArgumentStruct20BytesHomogeneousInt32", + isLeaf: true); + +/// On arm64, both argument and return value are passed in by pointer. +void testReturnStructArgumentStruct20BytesHomogeneousInt32Leaf() { + final a0Pointer = calloc(); + final Struct20BytesHomogeneousInt32 a0 = a0Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a0.a3 = 4; + a0.a4 = -5; + + final result = returnStructArgumentStruct20BytesHomogeneousInt32Leaf(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0); + Expect.equals(a0.a1, result.a1); + Expect.equals(a0.a2, result.a2); + Expect.equals(a0.a3, result.a3); + Expect.equals(a0.a4, result.a4); + + calloc.free(a0Pointer); +} + +final returnStructArgumentInt32x8Struct20BytesHomogeneouLeaf = + ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, + Int32, Int32, Int32, Int32, Struct20BytesHomogeneousInt32), + Struct20BytesHomogeneousInt32 Function(int, int, int, int, int, int, + int, int, Struct20BytesHomogeneousInt32)>( + "ReturnStructArgumentInt32x8Struct20BytesHomogeneou", + isLeaf: true); + +/// On arm64, both argument and return value are passed in by pointer. +/// Ints exhaust registers, so that pointer is passed on stack. +void testReturnStructArgumentInt32x8Struct20BytesHomogeneouLeaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + final a8Pointer = calloc(); + final Struct20BytesHomogeneousInt32 a8 = a8Pointer.ref; + + 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; + + final result = returnStructArgumentInt32x8Struct20BytesHomogeneouLeaf( + a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a8.a0, result.a0); + Expect.equals(a8.a1, result.a1); + Expect.equals(a8.a2, result.a2); + Expect.equals(a8.a3, result.a3); + Expect.equals(a8.a4, result.a4); + + calloc.free(a8Pointer); +} + +final returnStructArgumentStruct8BytesInlineArrayIntLeaf = + ffiTestFunctions.lookupFunction< + Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt), + Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt)>( + "ReturnStructArgumentStruct8BytesInlineArrayInt", + isLeaf: true); + +/// Test returning struct with inline array. +void testReturnStructArgumentStruct8BytesInlineArrayIntLeaf() { + final a0Pointer = calloc(); + final Struct8BytesInlineArrayInt a0 = a0Pointer.ref; + + 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; + + final result = returnStructArgumentStruct8BytesInlineArrayIntLeaf(a0); + + print("result = $result"); + + for (int i = 0; i < 8; i++) { + Expect.equals(a0.a0[i], result.a0[i]); + } + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct16BytesHomogeneousLeaf = + ffiTestFunctions.lookupFunction< + StructStruct16BytesHomogeneousFloat2 Function( + StructStruct16BytesHomogeneousFloat2), + StructStruct16BytesHomogeneousFloat2 Function( + StructStruct16BytesHomogeneousFloat2)>( + "ReturnStructArgumentStructStruct16BytesHomogeneous", + isLeaf: true); + +/// Return value in FPU registers on arm hardfp and arm64. +void testReturnStructArgumentStructStruct16BytesHomogeneousLeaf() { + final a0Pointer = calloc(); + final StructStruct16BytesHomogeneousFloat2 a0 = a0Pointer.ref; + + a0.a0.a0 = -1.0; + a0.a1[0].a0 = 2.0; + a0.a1[1].a0 = -3.0; + a0.a2 = 4.0; + + final result = returnStructArgumentStructStruct16BytesHomogeneousLeaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 2; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + } + Expect.approxEquals(a0.a2, result.a2); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct32BytesHomogeneousLeaf = + ffiTestFunctions.lookupFunction< + StructStruct32BytesHomogeneousDouble2 Function( + StructStruct32BytesHomogeneousDouble2), + StructStruct32BytesHomogeneousDouble2 Function( + StructStruct32BytesHomogeneousDouble2)>( + "ReturnStructArgumentStructStruct32BytesHomogeneous", + isLeaf: true); + +/// Return value in FPU registers on arm64. +void testReturnStructArgumentStructStruct32BytesHomogeneousLeaf() { + final a0Pointer = calloc(); + final StructStruct32BytesHomogeneousDouble2 a0 = a0Pointer.ref; + + a0.a0.a0 = -1.0; + a0.a1[0].a0 = 2.0; + a0.a1[1].a0 = -3.0; + a0.a2 = 4.0; + + final result = returnStructArgumentStructStruct32BytesHomogeneousLeaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 2; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + } + Expect.approxEquals(a0.a2, result.a2); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct16BytesMixed3Leaf = + ffiTestFunctions.lookupFunction< + StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3), + StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3)>( + "ReturnStructArgumentStructStruct16BytesMixed3", + isLeaf: true); + +/// On x64 Linux, return value is split over FP and int registers. +void testReturnStructArgumentStructStruct16BytesMixed3Leaf() { + final a0Pointer = calloc(); + final StructStruct16BytesMixed3 a0 = a0Pointer.ref; + + 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; + + final result = returnStructArgumentStructStruct16BytesMixed3Leaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 1; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + Expect.equals(a0.a1[i].a1, result.a1[i].a1); + Expect.equals(a0.a1[i].a2, result.a1[i].a2); + } + for (int i = 0; i < 2; i++) { + Expect.equals(a0.a2[i], result.a2[i]); + } + + calloc.free(a0Pointer); +} + +final returnStructAlignmentInt16Leaf = ffiTestFunctions.lookupFunction< + StructAlignmentInt16 Function(Int8, Int16, Int8), + StructAlignmentInt16 Function( + int, int, int)>("ReturnStructAlignmentInt16", isLeaf: true); + +/// Test alignment and padding of 16 byte int within struct. +void testReturnStructAlignmentInt16Leaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt16Leaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStructAlignmentInt32Leaf = ffiTestFunctions.lookupFunction< + StructAlignmentInt32 Function(Int8, Int32, Int8), + StructAlignmentInt32 Function( + int, int, int)>("ReturnStructAlignmentInt32", isLeaf: true); + +/// Test alignment and padding of 32 byte int within struct. +void testReturnStructAlignmentInt32Leaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt32Leaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStructAlignmentInt64Leaf = ffiTestFunctions.lookupFunction< + StructAlignmentInt64 Function(Int8, Int64, Int8), + StructAlignmentInt64 Function( + int, int, int)>("ReturnStructAlignmentInt64", isLeaf: true); + +/// Test alignment and padding of 64 byte int within struct. +void testReturnStructAlignmentInt64Leaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt64Leaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesNestedInt Function( + Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16), + Struct8BytesNestedInt Function( + Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16)>( + "ReturnStruct8BytesNestedInt", + isLeaf: true); + +/// Simple nested struct. +void testReturnStruct8BytesNestedIntLeaf() { + final a0Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a1.a0 = -3; + a1.a1 = 4; + + final result = returnStruct8BytesNestedIntLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct8BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesNestedFloat Function(Struct4BytesFloat, Struct4BytesFloat), + Struct8BytesNestedFloat Function(Struct4BytesFloat, + Struct4BytesFloat)>("ReturnStruct8BytesNestedFloat", isLeaf: true); + +/// Simple nested struct with floats. +void testReturnStruct8BytesNestedFloatLeaf() { + final a0Pointer = calloc(); + final Struct4BytesFloat a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesFloat a1 = a1Pointer.ref; + + a0.a0 = -1.0; + a1.a0 = 2.0; + + final result = returnStruct8BytesNestedFloatLeaf(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a1.a0, result.a1.a0); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct8BytesNestedFloat2Leaf = ffiTestFunctions.lookupFunction< + Struct8BytesNestedFloat2 Function(Struct4BytesFloat, Float), + Struct8BytesNestedFloat2 Function(Struct4BytesFloat, + double)>("ReturnStruct8BytesNestedFloat2", isLeaf: true); + +/// The nesting is irregular, testing homogenous float rules on arm and arm64, +/// and the fpu register usage on x64. +void testReturnStruct8BytesNestedFloat2Leaf() { + final a0Pointer = calloc(); + final Struct4BytesFloat a0 = a0Pointer.ref; + double a1; + + a0.a0 = -1.0; + a1 = 2.0; + + final result = returnStruct8BytesNestedFloat2Leaf(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a1, result.a1); + + calloc.free(a0Pointer); +} + +final returnStruct8BytesNestedMixedLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesNestedMixed Function( + Struct4BytesHomogeneousInt16, Struct4BytesFloat), + Struct8BytesNestedMixed Function(Struct4BytesHomogeneousInt16, + Struct4BytesFloat)>("ReturnStruct8BytesNestedMixed", isLeaf: true); + +/// Simple nested struct with mixed members. +void testReturnStruct8BytesNestedMixedLeaf() { + final a0Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesFloat a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a1.a0 = -3.0; + + final result = returnStruct8BytesNestedMixedLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.approxEquals(a1.a0, result.a1.a0); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct16BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< + Struct16BytesNestedInt Function( + Struct8BytesNestedInt, Struct8BytesNestedInt), + Struct16BytesNestedInt Function(Struct8BytesNestedInt, + Struct8BytesNestedInt)>("ReturnStruct16BytesNestedInt", isLeaf: true); + +/// Deeper nested struct to test recursive member access. +void testReturnStruct16BytesNestedIntLeaf() { + final a0Pointer = calloc(); + final Struct8BytesNestedInt a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct8BytesNestedInt a1 = a1Pointer.ref; + + 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; + + final result = returnStruct16BytesNestedIntLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0.a0, result.a0.a0.a0); + Expect.equals(a0.a0.a1, result.a0.a0.a1); + Expect.equals(a0.a1.a0, result.a0.a1.a0); + Expect.equals(a0.a1.a1, result.a0.a1.a1); + Expect.equals(a1.a0.a0, result.a1.a0.a0); + Expect.equals(a1.a0.a1, result.a1.a0.a1); + Expect.equals(a1.a1.a0, result.a1.a1.a0); + Expect.equals(a1.a1.a1, result.a1.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct32BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< + Struct32BytesNestedInt Function( + Struct16BytesNestedInt, Struct16BytesNestedInt), + Struct32BytesNestedInt Function(Struct16BytesNestedInt, + Struct16BytesNestedInt)>("ReturnStruct32BytesNestedInt", isLeaf: true); + +/// Even deeper nested struct to test recursive member access. +void testReturnStruct32BytesNestedIntLeaf() { + final a0Pointer = calloc(); + final Struct16BytesNestedInt a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct16BytesNestedInt a1 = a1Pointer.ref; + + 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; + + final result = returnStruct32BytesNestedIntLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0.a0.a0, result.a0.a0.a0.a0); + Expect.equals(a0.a0.a0.a1, result.a0.a0.a0.a1); + Expect.equals(a0.a0.a1.a0, result.a0.a0.a1.a0); + Expect.equals(a0.a0.a1.a1, result.a0.a0.a1.a1); + Expect.equals(a0.a1.a0.a0, result.a0.a1.a0.a0); + Expect.equals(a0.a1.a0.a1, result.a0.a1.a0.a1); + Expect.equals(a0.a1.a1.a0, result.a0.a1.a1.a0); + Expect.equals(a0.a1.a1.a1, result.a0.a1.a1.a1); + Expect.equals(a1.a0.a0.a0, result.a1.a0.a0.a0); + Expect.equals(a1.a0.a0.a1, result.a1.a0.a0.a1); + Expect.equals(a1.a0.a1.a0, result.a1.a0.a1.a0); + Expect.equals(a1.a0.a1.a1, result.a1.a0.a1.a1); + Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); + Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); + Expect.equals(a1.a1.a1.a0, result.a1.a1.a1.a0); + Expect.equals(a1.a1.a1.a1, result.a1.a1.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt16Leaf = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt16 Function( + StructAlignmentInt16, StructAlignmentInt16), + StructNestedIntStructAlignmentInt16 Function( + StructAlignmentInt16, StructAlignmentInt16)>( + "ReturnStructNestedIntStructAlignmentInt16", + isLeaf: true); + +/// Test alignment and padding of nested struct with 16 byte int. +void testReturnStructNestedIntStructAlignmentInt16Leaf() { + final a0Pointer = calloc(); + final StructAlignmentInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt16 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt16Leaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt32Leaf = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt32 Function( + StructAlignmentInt32, StructAlignmentInt32), + StructNestedIntStructAlignmentInt32 Function( + StructAlignmentInt32, StructAlignmentInt32)>( + "ReturnStructNestedIntStructAlignmentInt32", + isLeaf: true); + +/// Test alignment and padding of nested struct with 32 byte int. +void testReturnStructNestedIntStructAlignmentInt32Leaf() { + final a0Pointer = calloc(); + final StructAlignmentInt32 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt32 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt32Leaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt64Leaf = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt64 Function( + StructAlignmentInt64, StructAlignmentInt64), + StructNestedIntStructAlignmentInt64 Function( + StructAlignmentInt64, StructAlignmentInt64)>( + "ReturnStructNestedIntStructAlignmentInt64", + isLeaf: true); + +/// Test alignment and padding of nested struct with 64 byte int. +void testReturnStructNestedIntStructAlignmentInt64Leaf() { + final a0Pointer = calloc(); + final StructAlignmentInt64 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt64 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt64Leaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIrregularEvenBiggerLeaf = + ffiTestFunctions.lookupFunction< + StructNestedIrregularEvenBigger Function(Uint64, + StructNestedIrregularBigger, StructNestedIrregularBigger, Double), + StructNestedIrregularEvenBigger Function( + int, + StructNestedIrregularBigger, + StructNestedIrregularBigger, + double)>("ReturnStructNestedIrregularEvenBigger", isLeaf: true); + +/// Return big irregular struct as smoke test. +void testReturnStructNestedIrregularEvenBiggerLeaf() { + int a0; + final a1Pointer = calloc(); + final StructNestedIrregularBigger a1 = a1Pointer.ref; + final a2Pointer = calloc(); + final StructNestedIrregularBigger a2 = a2Pointer.ref; + 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; + + final result = returnStructNestedIrregularEvenBiggerLeaf(a0, a1, a2, a3); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1.a0.a0, result.a1.a0.a0); + Expect.equals(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0); + Expect.equals(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1); + Expect.approxEquals(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0); + Expect.equals(a1.a0.a2, result.a1.a0.a2); + Expect.approxEquals(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0); + Expect.approxEquals(a1.a0.a3.a1, result.a1.a0.a3.a1); + Expect.equals(a1.a0.a4, result.a1.a0.a4); + Expect.approxEquals(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0); + Expect.approxEquals(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0); + Expect.equals(a1.a0.a6, result.a1.a0.a6); + Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); + Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); + Expect.approxEquals(a1.a1.a1.a0, result.a1.a1.a1.a0); + Expect.approxEquals(a1.a2, result.a1.a2); + Expect.approxEquals(a1.a3, result.a1.a3); + Expect.equals(a2.a0.a0, result.a2.a0.a0); + Expect.equals(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0); + Expect.equals(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1); + Expect.approxEquals(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0); + Expect.equals(a2.a0.a2, result.a2.a0.a2); + Expect.approxEquals(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0); + Expect.approxEquals(a2.a0.a3.a1, result.a2.a0.a3.a1); + Expect.equals(a2.a0.a4, result.a2.a0.a4); + Expect.approxEquals(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0); + Expect.approxEquals(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0); + Expect.equals(a2.a0.a6, result.a2.a0.a6); + Expect.equals(a2.a1.a0.a0, result.a2.a1.a0.a0); + Expect.equals(a2.a1.a0.a1, result.a2.a1.a0.a1); + Expect.approxEquals(a2.a1.a1.a0, result.a2.a1.a1.a0); + Expect.approxEquals(a2.a2, result.a2.a2); + Expect.approxEquals(a2.a3, result.a2.a3); + Expect.approxEquals(a3, result.a3); + + calloc.free(a1Pointer); + calloc.free(a2Pointer); +} diff --git a/tests/ffi_2/function_structs_by_value_generated_ret_arg_test.dart b/tests/ffi_2/function_structs_by_value_generated_ret_arg_test.dart new file mode 100644 index 00000000000..2a2bf81a8ae --- /dev/null +++ b/tests/ffi_2/function_structs_by_value_generated_ret_arg_test.dart @@ -0,0 +1,833 @@ +// 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. +// Generated by tests/ffi/generator/structs_by_value_tests_generator.dart. +// +// SharedObjects=ffi_test_functions +// VMOptions= +// VMOptions=--deterministic --optimization-counter-threshold=90 +// VMOptions=--use-slow-path +// VMOptions=--use-slow-path --stacktrace-every=100 + +// @dart = 2.9 + +import 'dart:ffi'; + +import "package:expect/expect.dart"; +import "package:ffi/ffi.dart"; + +import 'dylib_utils.dart'; + +// Reuse the compound classes. +import 'function_structs_by_value_generated_compounds.dart'; + +final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); +void main() { + for (int i = 0; i < 100; ++i) { + testReturnStructArgumentStruct1ByteInt(); + testReturnStructArgumentInt32x8Struct1ByteInt(); + testReturnStructArgumentStruct8BytesHomogeneousFloat(); + testReturnStructArgumentStruct20BytesHomogeneousInt32(); + testReturnStructArgumentInt32x8Struct20BytesHomogeneou(); + testReturnStructArgumentStruct8BytesInlineArrayInt(); + testReturnStructArgumentStructStruct16BytesHomogeneous(); + testReturnStructArgumentStructStruct32BytesHomogeneous(); + testReturnStructArgumentStructStruct16BytesMixed3(); + testReturnStructAlignmentInt16(); + testReturnStructAlignmentInt32(); + testReturnStructAlignmentInt64(); + testReturnStruct8BytesNestedInt(); + testReturnStruct8BytesNestedFloat(); + testReturnStruct8BytesNestedFloat2(); + testReturnStruct8BytesNestedMixed(); + testReturnStruct16BytesNestedInt(); + testReturnStruct32BytesNestedInt(); + testReturnStructNestedIntStructAlignmentInt16(); + testReturnStructNestedIntStructAlignmentInt32(); + testReturnStructNestedIntStructAlignmentInt64(); + testReturnStructNestedIrregularEvenBigger(); + } +} + +final returnStructArgumentStruct1ByteInt = ffiTestFunctions.lookupFunction< + Struct1ByteInt Function(Struct1ByteInt), + Struct1ByteInt Function( + Struct1ByteInt)>("ReturnStructArgumentStruct1ByteInt"); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed in int registers in most ABIs. +void testReturnStructArgumentStruct1ByteInt() { + final a0Pointer = calloc(); + final Struct1ByteInt a0 = a0Pointer.ref; + + a0.a0 = -1; + + final result = returnStructArgumentStruct1ByteInt(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0); + + calloc.free(a0Pointer); +} + +final returnStructArgumentInt32x8Struct1ByteInt = + ffiTestFunctions.lookupFunction< + Struct1ByteInt Function(Int32, Int32, Int32, Int32, Int32, Int32, Int32, + Int32, Struct1ByteInt), + Struct1ByteInt Function(int, int, int, int, int, int, int, int, + Struct1ByteInt)>("ReturnStructArgumentInt32x8Struct1ByteInt"); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed on stack on all ABIs. +void testReturnStructArgumentInt32x8Struct1ByteInt() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + final a8Pointer = calloc(); + final Struct1ByteInt a8 = a8Pointer.ref; + + a0 = -1; + a1 = 2; + a2 = -3; + a3 = 4; + a4 = -5; + a5 = 6; + a6 = -7; + a7 = 8; + a8.a0 = -9; + + final result = returnStructArgumentInt32x8Struct1ByteInt( + a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a8.a0, result.a0); + + calloc.free(a8Pointer); +} + +final returnStructArgumentStruct8BytesHomogeneousFloat = + ffiTestFunctions.lookupFunction< + Struct8BytesHomogeneousFloat Function(Struct8BytesHomogeneousFloat), + Struct8BytesHomogeneousFloat Function( + Struct8BytesHomogeneousFloat)>( + "ReturnStructArgumentStruct8BytesHomogeneousFloat"); + +/// Test that a struct passed in as argument can be returned. +/// Especially for ffi callbacks. +/// Struct is passed in float registers in most ABIs. +void testReturnStructArgumentStruct8BytesHomogeneousFloat() { + final a0Pointer = calloc(); + final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; + + a0.a0 = -1.0; + a0.a1 = 2.0; + + final result = returnStructArgumentStruct8BytesHomogeneousFloat(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0); + Expect.approxEquals(a0.a1, result.a1); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStruct20BytesHomogeneousInt32 = + ffiTestFunctions + .lookupFunction< + Struct20BytesHomogeneousInt32 Function( + Struct20BytesHomogeneousInt32), + Struct20BytesHomogeneousInt32 Function( + Struct20BytesHomogeneousInt32)>( + "ReturnStructArgumentStruct20BytesHomogeneousInt32"); + +/// On arm64, both argument and return value are passed in by pointer. +void testReturnStructArgumentStruct20BytesHomogeneousInt32() { + final a0Pointer = calloc(); + final Struct20BytesHomogeneousInt32 a0 = a0Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a0.a3 = 4; + a0.a4 = -5; + + final result = returnStructArgumentStruct20BytesHomogeneousInt32(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0); + Expect.equals(a0.a1, result.a1); + Expect.equals(a0.a2, result.a2); + Expect.equals(a0.a3, result.a3); + Expect.equals(a0.a4, result.a4); + + calloc.free(a0Pointer); +} + +final returnStructArgumentInt32x8Struct20BytesHomogeneou = + ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, + Int32, Int32, Int32, Int32, Struct20BytesHomogeneousInt32), + Struct20BytesHomogeneousInt32 Function(int, int, int, int, int, int, + int, int, Struct20BytesHomogeneousInt32)>( + "ReturnStructArgumentInt32x8Struct20BytesHomogeneou"); + +/// On arm64, both argument and return value are passed in by pointer. +/// Ints exhaust registers, so that pointer is passed on stack. +void testReturnStructArgumentInt32x8Struct20BytesHomogeneou() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + final a8Pointer = calloc(); + final Struct20BytesHomogeneousInt32 a8 = a8Pointer.ref; + + 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; + + final result = returnStructArgumentInt32x8Struct20BytesHomogeneou( + a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a8.a0, result.a0); + Expect.equals(a8.a1, result.a1); + Expect.equals(a8.a2, result.a2); + Expect.equals(a8.a3, result.a3); + Expect.equals(a8.a4, result.a4); + + calloc.free(a8Pointer); +} + +final returnStructArgumentStruct8BytesInlineArrayInt = + ffiTestFunctions.lookupFunction< + Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt), + Struct8BytesInlineArrayInt Function(Struct8BytesInlineArrayInt)>( + "ReturnStructArgumentStruct8BytesInlineArrayInt"); + +/// Test returning struct with inline array. +void testReturnStructArgumentStruct8BytesInlineArrayInt() { + final a0Pointer = calloc(); + final Struct8BytesInlineArrayInt a0 = a0Pointer.ref; + + 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; + + final result = returnStructArgumentStruct8BytesInlineArrayInt(a0); + + print("result = $result"); + + for (int i = 0; i < 8; i++) { + Expect.equals(a0.a0[i], result.a0[i]); + } + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct16BytesHomogeneous = + ffiTestFunctions.lookupFunction< + StructStruct16BytesHomogeneousFloat2 Function( + StructStruct16BytesHomogeneousFloat2), + StructStruct16BytesHomogeneousFloat2 Function( + StructStruct16BytesHomogeneousFloat2)>( + "ReturnStructArgumentStructStruct16BytesHomogeneous"); + +/// Return value in FPU registers on arm hardfp and arm64. +void testReturnStructArgumentStructStruct16BytesHomogeneous() { + final a0Pointer = calloc(); + final StructStruct16BytesHomogeneousFloat2 a0 = a0Pointer.ref; + + a0.a0.a0 = -1.0; + a0.a1[0].a0 = 2.0; + a0.a1[1].a0 = -3.0; + a0.a2 = 4.0; + + final result = returnStructArgumentStructStruct16BytesHomogeneous(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 2; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + } + Expect.approxEquals(a0.a2, result.a2); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct32BytesHomogeneous = + ffiTestFunctions.lookupFunction< + StructStruct32BytesHomogeneousDouble2 Function( + StructStruct32BytesHomogeneousDouble2), + StructStruct32BytesHomogeneousDouble2 Function( + StructStruct32BytesHomogeneousDouble2)>( + "ReturnStructArgumentStructStruct32BytesHomogeneous"); + +/// Return value in FPU registers on arm64. +void testReturnStructArgumentStructStruct32BytesHomogeneous() { + final a0Pointer = calloc(); + final StructStruct32BytesHomogeneousDouble2 a0 = a0Pointer.ref; + + a0.a0.a0 = -1.0; + a0.a1[0].a0 = 2.0; + a0.a1[1].a0 = -3.0; + a0.a2 = 4.0; + + final result = returnStructArgumentStructStruct32BytesHomogeneous(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 2; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + } + Expect.approxEquals(a0.a2, result.a2); + + calloc.free(a0Pointer); +} + +final returnStructArgumentStructStruct16BytesMixed3 = + ffiTestFunctions.lookupFunction< + StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3), + StructStruct16BytesMixed3 Function(StructStruct16BytesMixed3)>( + "ReturnStructArgumentStructStruct16BytesMixed3"); + +/// On x64 Linux, return value is split over FP and int registers. +void testReturnStructArgumentStructStruct16BytesMixed3() { + final a0Pointer = calloc(); + final StructStruct16BytesMixed3 a0 = a0Pointer.ref; + + 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; + + final result = returnStructArgumentStructStruct16BytesMixed3(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0.a0, result.a0.a0); + for (int i = 0; i < 1; i++) { + Expect.approxEquals(a0.a1[i].a0, result.a1[i].a0); + Expect.equals(a0.a1[i].a1, result.a1[i].a1); + Expect.equals(a0.a1[i].a2, result.a1[i].a2); + } + for (int i = 0; i < 2; i++) { + Expect.equals(a0.a2[i], result.a2[i]); + } + + calloc.free(a0Pointer); +} + +final returnStructAlignmentInt16 = ffiTestFunctions.lookupFunction< + StructAlignmentInt16 Function(Int8, Int16, Int8), + StructAlignmentInt16 Function(int, int, int)>("ReturnStructAlignmentInt16"); + +/// Test alignment and padding of 16 byte int within struct. +void testReturnStructAlignmentInt16() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt16(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStructAlignmentInt32 = ffiTestFunctions.lookupFunction< + StructAlignmentInt32 Function(Int8, Int32, Int8), + StructAlignmentInt32 Function(int, int, int)>("ReturnStructAlignmentInt32"); + +/// Test alignment and padding of 32 byte int within struct. +void testReturnStructAlignmentInt32() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt32(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStructAlignmentInt64 = ffiTestFunctions.lookupFunction< + StructAlignmentInt64 Function(Int8, Int64, Int8), + StructAlignmentInt64 Function(int, int, int)>("ReturnStructAlignmentInt64"); + +/// Test alignment and padding of 64 byte int within struct. +void testReturnStructAlignmentInt64() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStructAlignmentInt64(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesNestedInt = ffiTestFunctions.lookupFunction< + Struct8BytesNestedInt Function( + Struct4BytesHomogeneousInt16, Struct4BytesHomogeneousInt16), + Struct8BytesNestedInt Function(Struct4BytesHomogeneousInt16, + Struct4BytesHomogeneousInt16)>("ReturnStruct8BytesNestedInt"); + +/// Simple nested struct. +void testReturnStruct8BytesNestedInt() { + final a0Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a1.a0 = -3; + a1.a1 = 4; + + final result = returnStruct8BytesNestedInt(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct8BytesNestedFloat = ffiTestFunctions.lookupFunction< + Struct8BytesNestedFloat Function(Struct4BytesFloat, Struct4BytesFloat), + Struct8BytesNestedFloat Function( + Struct4BytesFloat, Struct4BytesFloat)>("ReturnStruct8BytesNestedFloat"); + +/// Simple nested struct with floats. +void testReturnStruct8BytesNestedFloat() { + final a0Pointer = calloc(); + final Struct4BytesFloat a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesFloat a1 = a1Pointer.ref; + + a0.a0 = -1.0; + a1.a0 = 2.0; + + final result = returnStruct8BytesNestedFloat(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a1.a0, result.a1.a0); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct8BytesNestedFloat2 = ffiTestFunctions.lookupFunction< + Struct8BytesNestedFloat2 Function(Struct4BytesFloat, Float), + Struct8BytesNestedFloat2 Function( + Struct4BytesFloat, double)>("ReturnStruct8BytesNestedFloat2"); + +/// The nesting is irregular, testing homogenous float rules on arm and arm64, +/// and the fpu register usage on x64. +void testReturnStruct8BytesNestedFloat2() { + final a0Pointer = calloc(); + final Struct4BytesFloat a0 = a0Pointer.ref; + double a1; + + a0.a0 = -1.0; + a1 = 2.0; + + final result = returnStruct8BytesNestedFloat2(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a1, result.a1); + + calloc.free(a0Pointer); +} + +final returnStruct8BytesNestedMixed = ffiTestFunctions.lookupFunction< + Struct8BytesNestedMixed Function( + Struct4BytesHomogeneousInt16, Struct4BytesFloat), + Struct8BytesNestedMixed Function(Struct4BytesHomogeneousInt16, + Struct4BytesFloat)>("ReturnStruct8BytesNestedMixed"); + +/// Simple nested struct with mixed members. +void testReturnStruct8BytesNestedMixed() { + final a0Pointer = calloc(); + final Struct4BytesHomogeneousInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct4BytesFloat a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a1.a0 = -3.0; + + final result = returnStruct8BytesNestedMixed(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.approxEquals(a1.a0, result.a1.a0); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct16BytesNestedInt = ffiTestFunctions.lookupFunction< + Struct16BytesNestedInt Function( + Struct8BytesNestedInt, Struct8BytesNestedInt), + Struct16BytesNestedInt Function(Struct8BytesNestedInt, + Struct8BytesNestedInt)>("ReturnStruct16BytesNestedInt"); + +/// Deeper nested struct to test recursive member access. +void testReturnStruct16BytesNestedInt() { + final a0Pointer = calloc(); + final Struct8BytesNestedInt a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct8BytesNestedInt a1 = a1Pointer.ref; + + 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; + + final result = returnStruct16BytesNestedInt(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0.a0, result.a0.a0.a0); + Expect.equals(a0.a0.a1, result.a0.a0.a1); + Expect.equals(a0.a1.a0, result.a0.a1.a0); + Expect.equals(a0.a1.a1, result.a0.a1.a1); + Expect.equals(a1.a0.a0, result.a1.a0.a0); + Expect.equals(a1.a0.a1, result.a1.a0.a1); + Expect.equals(a1.a1.a0, result.a1.a1.a0); + Expect.equals(a1.a1.a1, result.a1.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStruct32BytesNestedInt = ffiTestFunctions.lookupFunction< + Struct32BytesNestedInt Function( + Struct16BytesNestedInt, Struct16BytesNestedInt), + Struct32BytesNestedInt Function(Struct16BytesNestedInt, + Struct16BytesNestedInt)>("ReturnStruct32BytesNestedInt"); + +/// Even deeper nested struct to test recursive member access. +void testReturnStruct32BytesNestedInt() { + final a0Pointer = calloc(); + final Struct16BytesNestedInt a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final Struct16BytesNestedInt a1 = a1Pointer.ref; + + 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; + + final result = returnStruct32BytesNestedInt(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0.a0.a0, result.a0.a0.a0.a0); + Expect.equals(a0.a0.a0.a1, result.a0.a0.a0.a1); + Expect.equals(a0.a0.a1.a0, result.a0.a0.a1.a0); + Expect.equals(a0.a0.a1.a1, result.a0.a0.a1.a1); + Expect.equals(a0.a1.a0.a0, result.a0.a1.a0.a0); + Expect.equals(a0.a1.a0.a1, result.a0.a1.a0.a1); + Expect.equals(a0.a1.a1.a0, result.a0.a1.a1.a0); + Expect.equals(a0.a1.a1.a1, result.a0.a1.a1.a1); + Expect.equals(a1.a0.a0.a0, result.a1.a0.a0.a0); + Expect.equals(a1.a0.a0.a1, result.a1.a0.a0.a1); + Expect.equals(a1.a0.a1.a0, result.a1.a0.a1.a0); + Expect.equals(a1.a0.a1.a1, result.a1.a0.a1.a1); + Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); + Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); + Expect.equals(a1.a1.a1.a0, result.a1.a1.a1.a0); + Expect.equals(a1.a1.a1.a1, result.a1.a1.a1.a1); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt16 = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt16 Function( + StructAlignmentInt16, StructAlignmentInt16), + StructNestedIntStructAlignmentInt16 Function(StructAlignmentInt16, + StructAlignmentInt16)>("ReturnStructNestedIntStructAlignmentInt16"); + +/// Test alignment and padding of nested struct with 16 byte int. +void testReturnStructNestedIntStructAlignmentInt16() { + final a0Pointer = calloc(); + final StructAlignmentInt16 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt16 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt16(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt32 = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt32 Function( + StructAlignmentInt32, StructAlignmentInt32), + StructNestedIntStructAlignmentInt32 Function(StructAlignmentInt32, + StructAlignmentInt32)>("ReturnStructNestedIntStructAlignmentInt32"); + +/// Test alignment and padding of nested struct with 32 byte int. +void testReturnStructNestedIntStructAlignmentInt32() { + final a0Pointer = calloc(); + final StructAlignmentInt32 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt32 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt32(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIntStructAlignmentInt64 = + ffiTestFunctions.lookupFunction< + StructNestedIntStructAlignmentInt64 Function( + StructAlignmentInt64, StructAlignmentInt64), + StructNestedIntStructAlignmentInt64 Function(StructAlignmentInt64, + StructAlignmentInt64)>("ReturnStructNestedIntStructAlignmentInt64"); + +/// Test alignment and padding of nested struct with 64 byte int. +void testReturnStructNestedIntStructAlignmentInt64() { + final a0Pointer = calloc(); + final StructAlignmentInt64 a0 = a0Pointer.ref; + final a1Pointer = calloc(); + final StructAlignmentInt64 a1 = a1Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + a1.a0 = 4; + a1.a1 = -5; + a1.a2 = 6; + + final result = returnStructNestedIntStructAlignmentInt64(a0, a1); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + Expect.equals(a1.a0, result.a1.a0); + Expect.equals(a1.a1, result.a1.a1); + Expect.equals(a1.a2, result.a1.a2); + + calloc.free(a0Pointer); + calloc.free(a1Pointer); +} + +final returnStructNestedIrregularEvenBigger = ffiTestFunctions.lookupFunction< + StructNestedIrregularEvenBigger Function(Uint64, + StructNestedIrregularBigger, StructNestedIrregularBigger, Double), + StructNestedIrregularEvenBigger Function( + int, + StructNestedIrregularBigger, + StructNestedIrregularBigger, + double)>("ReturnStructNestedIrregularEvenBigger"); + +/// Return big irregular struct as smoke test. +void testReturnStructNestedIrregularEvenBigger() { + int a0; + final a1Pointer = calloc(); + final StructNestedIrregularBigger a1 = a1Pointer.ref; + final a2Pointer = calloc(); + final StructNestedIrregularBigger a2 = a2Pointer.ref; + 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; + + final result = returnStructNestedIrregularEvenBigger(a0, a1, a2, a3); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1.a0.a0, result.a1.a0.a0); + Expect.equals(a1.a0.a1.a0.a0, result.a1.a0.a1.a0.a0); + Expect.equals(a1.a0.a1.a0.a1, result.a1.a0.a1.a0.a1); + Expect.approxEquals(a1.a0.a1.a1.a0, result.a1.a0.a1.a1.a0); + Expect.equals(a1.a0.a2, result.a1.a0.a2); + Expect.approxEquals(a1.a0.a3.a0.a0, result.a1.a0.a3.a0.a0); + Expect.approxEquals(a1.a0.a3.a1, result.a1.a0.a3.a1); + Expect.equals(a1.a0.a4, result.a1.a0.a4); + Expect.approxEquals(a1.a0.a5.a0.a0, result.a1.a0.a5.a0.a0); + Expect.approxEquals(a1.a0.a5.a1.a0, result.a1.a0.a5.a1.a0); + Expect.equals(a1.a0.a6, result.a1.a0.a6); + Expect.equals(a1.a1.a0.a0, result.a1.a1.a0.a0); + Expect.equals(a1.a1.a0.a1, result.a1.a1.a0.a1); + Expect.approxEquals(a1.a1.a1.a0, result.a1.a1.a1.a0); + Expect.approxEquals(a1.a2, result.a1.a2); + Expect.approxEquals(a1.a3, result.a1.a3); + Expect.equals(a2.a0.a0, result.a2.a0.a0); + Expect.equals(a2.a0.a1.a0.a0, result.a2.a0.a1.a0.a0); + Expect.equals(a2.a0.a1.a0.a1, result.a2.a0.a1.a0.a1); + Expect.approxEquals(a2.a0.a1.a1.a0, result.a2.a0.a1.a1.a0); + Expect.equals(a2.a0.a2, result.a2.a0.a2); + Expect.approxEquals(a2.a0.a3.a0.a0, result.a2.a0.a3.a0.a0); + Expect.approxEquals(a2.a0.a3.a1, result.a2.a0.a3.a1); + Expect.equals(a2.a0.a4, result.a2.a0.a4); + Expect.approxEquals(a2.a0.a5.a0.a0, result.a2.a0.a5.a0.a0); + Expect.approxEquals(a2.a0.a5.a1.a0, result.a2.a0.a5.a1.a0); + Expect.equals(a2.a0.a6, result.a2.a0.a6); + Expect.equals(a2.a1.a0.a0, result.a2.a1.a0.a0); + Expect.equals(a2.a1.a0.a1, result.a2.a1.a0.a1); + Expect.approxEquals(a2.a1.a1.a0, result.a2.a1.a1.a0); + Expect.approxEquals(a2.a2, result.a2.a2); + Expect.approxEquals(a2.a3, result.a2.a3); + Expect.approxEquals(a3, result.a3); + + calloc.free(a1Pointer); + calloc.free(a2Pointer); +} diff --git a/tests/ffi_2/function_structs_by_value_generated_ret_leaf_test.dart b/tests/ffi_2/function_structs_by_value_generated_ret_leaf_test.dart new file mode 100644 index 00000000000..846f5b1c6e6 --- /dev/null +++ b/tests/ffi_2/function_structs_by_value_generated_ret_leaf_test.dart @@ -0,0 +1,1643 @@ +// Copyright (c) 2021, 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. +// Generated by tests/ffi/generator/structs_by_value_tests_generator.dart. +// +// SharedObjects=ffi_test_functions +// VMOptions= +// VMOptions=--deterministic --optimization-counter-threshold=90 +// VMOptions=--use-slow-path +// VMOptions=--use-slow-path --stacktrace-every=100 + +// @dart = 2.9 + +import 'dart:ffi'; + +import "package:expect/expect.dart"; +import "package:ffi/ffi.dart"; + +import 'dylib_utils.dart'; + +// Reuse the compound classes. +import 'function_structs_by_value_generated_compounds.dart'; + +final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); +void main() { + for (int i = 0; i < 100; ++i) { + testReturnStruct1ByteIntLeaf(); + testReturnStruct3BytesHomogeneousUint8Leaf(); + testReturnStruct3BytesInt2ByteAlignedLeaf(); + testReturnStruct4BytesHomogeneousInt16Leaf(); + testReturnStruct7BytesHomogeneousUint8Leaf(); + testReturnStruct7BytesInt4ByteAlignedLeaf(); + testReturnStruct8BytesIntLeaf(); + testReturnStruct8BytesHomogeneousFloatLeaf(); + testReturnStruct8BytesMixedLeaf(); + testReturnStruct9BytesHomogeneousUint8Leaf(); + testReturnStruct9BytesInt4Or8ByteAlignedLeaf(); + testReturnStruct12BytesHomogeneousFloatLeaf(); + testReturnStruct16BytesHomogeneousFloatLeaf(); + testReturnStruct16BytesMixedLeaf(); + testReturnStruct16BytesMixed2Leaf(); + testReturnStruct17BytesIntLeaf(); + testReturnStruct19BytesHomogeneousUint8Leaf(); + testReturnStruct20BytesHomogeneousInt32Leaf(); + testReturnStruct20BytesHomogeneousFloatLeaf(); + testReturnStruct32BytesHomogeneousDoubleLeaf(); + testReturnStruct40BytesHomogeneousDoubleLeaf(); + testReturnStruct1024BytesHomogeneousUint64Leaf(); + testReturnStruct3BytesPackedIntLeaf(); + testReturnStruct8BytesPackedIntLeaf(); + testReturnStruct9BytesPackedMixedLeaf(); + testReturnUnion4BytesMixedLeaf(); + testReturnUnion8BytesNestedFloatLeaf(); + testReturnUnion9BytesNestedIntLeaf(); + testReturnUnion16BytesNestedFloatLeaf(); + } +} + +final returnStruct1ByteIntLeaf = ffiTestFunctions.lookupFunction< + Struct1ByteInt Function(Int8), + Struct1ByteInt Function(int)>("ReturnStruct1ByteInt", isLeaf: true); + +/// Smallest struct with data. +void testReturnStruct1ByteIntLeaf() { + int a0; + + a0 = -1; + + final result = returnStruct1ByteIntLeaf(a0); + + print("result = $result"); + + Expect.equals(a0, result.a0); +} + +final returnStruct3BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< + Struct3BytesHomogeneousUint8 Function(Uint8, Uint8, Uint8), + Struct3BytesHomogeneousUint8 Function( + int, int, int)>("ReturnStruct3BytesHomogeneousUint8", isLeaf: true); + +/// Smaller than word size return value on all architectures. +void testReturnStruct3BytesHomogeneousUint8Leaf() { + int a0; + int a1; + int a2; + + a0 = 1; + a1 = 2; + a2 = 3; + + final result = returnStruct3BytesHomogeneousUint8Leaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct3BytesInt2ByteAlignedLeaf = ffiTestFunctions.lookupFunction< + Struct3BytesInt2ByteAligned Function(Int16, Int8), + Struct3BytesInt2ByteAligned Function( + int, int)>("ReturnStruct3BytesInt2ByteAligned", isLeaf: true); + +/// Smaller than word size return value on all architectures. +/// With alignment rules taken into account size is 4 bytes. +void testReturnStruct3BytesInt2ByteAlignedLeaf() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct3BytesInt2ByteAlignedLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct4BytesHomogeneousInt16Leaf = ffiTestFunctions.lookupFunction< + Struct4BytesHomogeneousInt16 Function(Int16, Int16), + Struct4BytesHomogeneousInt16 Function( + int, int)>("ReturnStruct4BytesHomogeneousInt16", isLeaf: true); + +/// Word size return value on 32 bit architectures.. +void testReturnStruct4BytesHomogeneousInt16Leaf() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct4BytesHomogeneousInt16Leaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct7BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< + Struct7BytesHomogeneousUint8 Function( + Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), + Struct7BytesHomogeneousUint8 Function(int, int, int, int, int, int, + int)>("ReturnStruct7BytesHomogeneousUint8", isLeaf: true); + +/// Non-wordsize return value. +void testReturnStruct7BytesHomogeneousUint8Leaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + a5 = 6; + a6 = 7; + + final result = + returnStruct7BytesHomogeneousUint8Leaf(a0, a1, a2, a3, a4, a5, a6); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); +} + +final returnStruct7BytesInt4ByteAlignedLeaf = ffiTestFunctions.lookupFunction< + Struct7BytesInt4ByteAligned Function(Int32, Int16, Int8), + Struct7BytesInt4ByteAligned Function( + int, int, int)>("ReturnStruct7BytesInt4ByteAligned", isLeaf: true); + +/// Non-wordsize return value. +/// With alignment rules taken into account size is 8 bytes. +void testReturnStruct7BytesInt4ByteAlignedLeaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct7BytesInt4ByteAlignedLeaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesIntLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesInt Function(Int16, Int16, Int32), + Struct8BytesInt Function( + int, int, int)>("ReturnStruct8BytesInt", isLeaf: true); + +/// Return value in integer registers on many architectures. +void testReturnStruct8BytesIntLeaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct8BytesIntLeaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesHomogeneousFloat Function(Float, Float), + Struct8BytesHomogeneousFloat Function( + double, double)>("ReturnStruct8BytesHomogeneousFloat", isLeaf: true); + +/// Return value in FP registers on many architectures. +void testReturnStruct8BytesHomogeneousFloatLeaf() { + double a0; + double a1; + + a0 = -1.0; + a1 = 2.0; + + final result = returnStruct8BytesHomogeneousFloatLeaf(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); +} + +final returnStruct8BytesMixedLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesMixed Function(Float, Int16, Int16), + Struct8BytesMixed Function( + double, int, int)>("ReturnStruct8BytesMixed", isLeaf: true); + +/// Return value split over FP and integer register in x64. +void testReturnStruct8BytesMixedLeaf() { + double a0; + int a1; + int a2; + + a0 = -1.0; + a1 = 2; + a2 = -3; + + final result = returnStruct8BytesMixedLeaf(a0, a1, a2); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct9BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< + Struct9BytesHomogeneousUint8 Function( + Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), + Struct9BytesHomogeneousUint8 Function(int, int, int, int, int, int, int, + int, int)>("ReturnStruct9BytesHomogeneousUint8", isLeaf: true); + +/// 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. +void testReturnStruct9BytesHomogeneousUint8Leaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + a5 = 6; + a6 = 7; + a7 = 8; + a8 = 9; + + final result = returnStruct9BytesHomogeneousUint8Leaf( + a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); +} + +final returnStruct9BytesInt4Or8ByteAlignedLeaf = + ffiTestFunctions.lookupFunction< + Struct9BytesInt4Or8ByteAligned Function(Int64, Int8), + Struct9BytesInt4Or8ByteAligned Function( + int, int)>("ReturnStruct9BytesInt4Or8ByteAligned", isLeaf: true); + +/// Return value in two integer registers on x64. +/// With alignment rules taken into account size is 12 or 16 bytes. +void testReturnStruct9BytesInt4Or8ByteAlignedLeaf() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct9BytesInt4Or8ByteAlignedLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct12BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< + Struct12BytesHomogeneousFloat Function(Float, Float, Float), + Struct12BytesHomogeneousFloat Function(double, double, + double)>("ReturnStruct12BytesHomogeneousFloat", isLeaf: true); + +/// Return value in FPU registers, but does not use all registers on arm hardfp +/// and arm64. +void testReturnStruct12BytesHomogeneousFloatLeaf() { + double a0; + double a1; + double a2; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + + final result = returnStruct12BytesHomogeneousFloatLeaf(a0, a1, a2); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); +} + +final returnStruct16BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< + Struct16BytesHomogeneousFloat Function(Float, Float, Float, Float), + Struct16BytesHomogeneousFloat Function(double, double, double, + double)>("ReturnStruct16BytesHomogeneousFloat", isLeaf: true); + +/// Return value in FPU registers on arm hardfp and arm64. +void testReturnStruct16BytesHomogeneousFloatLeaf() { + double a0; + double a1; + double a2; + double a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4.0; + + final result = returnStruct16BytesHomogeneousFloatLeaf(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); +} + +final returnStruct16BytesMixedLeaf = ffiTestFunctions.lookupFunction< + Struct16BytesMixed Function(Double, Int64), + Struct16BytesMixed Function( + double, int)>("ReturnStruct16BytesMixed", isLeaf: true); + +/// Return value split over FP and integer register in x64. +void testReturnStruct16BytesMixedLeaf() { + double a0; + int a1; + + a0 = -1.0; + a1 = 2; + + final result = returnStruct16BytesMixedLeaf(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct16BytesMixed2Leaf = ffiTestFunctions.lookupFunction< + Struct16BytesMixed2 Function(Float, Float, Float, Int32), + Struct16BytesMixed2 Function(double, double, double, + int)>("ReturnStruct16BytesMixed2", isLeaf: true); + +/// Return value split over FP and integer register in x64. +/// The integer register contains half float half int. +void testReturnStruct16BytesMixed2Leaf() { + double a0; + double a1; + double a2; + int a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4; + + final result = returnStruct16BytesMixed2Leaf(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.equals(a3, result.a3); +} + +final returnStruct17BytesIntLeaf = ffiTestFunctions.lookupFunction< + Struct17BytesInt Function(Int64, Int64, Int8), + Struct17BytesInt Function( + int, int, int)>("ReturnStruct17BytesInt", isLeaf: true); + +/// 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. +void testReturnStruct17BytesIntLeaf() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct17BytesIntLeaf(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct19BytesHomogeneousUint8Leaf = ffiTestFunctions.lookupFunction< + Struct19BytesHomogeneousUint8 Function( + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8), + Struct19BytesHomogeneousUint8 Function( + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int)>("ReturnStruct19BytesHomogeneousUint8", isLeaf: true); + +/// 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. +void testReturnStruct19BytesHomogeneousUint8Leaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + int a9; + int a10; + int a11; + int a12; + int a13; + int a14; + int a15; + int a16; + int a17; + int 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; + + final result = returnStruct19BytesHomogeneousUint8Leaf(a0, a1, a2, a3, a4, a5, + a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); + Expect.equals(a9, result.a9); + Expect.equals(a10, result.a10); + Expect.equals(a11, result.a11); + Expect.equals(a12, result.a12); + Expect.equals(a13, result.a13); + Expect.equals(a14, result.a14); + Expect.equals(a15, result.a15); + Expect.equals(a16, result.a16); + Expect.equals(a17, result.a17); + Expect.equals(a18, result.a18); +} + +final returnStruct20BytesHomogeneousInt32Leaf = ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32), + Struct20BytesHomogeneousInt32 Function(int, int, int, int, + int)>("ReturnStruct20BytesHomogeneousInt32", isLeaf: true); + +/// Return value too big to go in cpu registers on arm64. +void testReturnStruct20BytesHomogeneousInt32Leaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + + a0 = -1; + a1 = 2; + a2 = -3; + a3 = 4; + a4 = -5; + + final result = returnStruct20BytesHomogeneousInt32Leaf(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); +} + +final returnStruct20BytesHomogeneousFloatLeaf = ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousFloat Function(Float, Float, Float, Float, Float), + Struct20BytesHomogeneousFloat Function(double, double, double, double, + double)>("ReturnStruct20BytesHomogeneousFloat", isLeaf: true); + +/// Return value too big to go in FPU registers on x64, arm hardfp and arm64. +void testReturnStruct20BytesHomogeneousFloatLeaf() { + 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; + + final result = returnStruct20BytesHomogeneousFloatLeaf(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); + Expect.approxEquals(a4, result.a4); +} + +final returnStruct32BytesHomogeneousDoubleLeaf = + ffiTestFunctions.lookupFunction< + Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double), + Struct32BytesHomogeneousDouble Function(double, double, double, + double)>("ReturnStruct32BytesHomogeneousDouble", isLeaf: true); + +/// Return value in FPU registers on arm64. +void testReturnStruct32BytesHomogeneousDoubleLeaf() { + double a0; + double a1; + double a2; + double a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4.0; + + final result = returnStruct32BytesHomogeneousDoubleLeaf(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); +} + +final returnStruct40BytesHomogeneousDoubleLeaf = + ffiTestFunctions.lookupFunction< + Struct40BytesHomogeneousDouble Function( + Double, Double, Double, Double, Double), + Struct40BytesHomogeneousDouble Function(double, double, double, double, + double)>("ReturnStruct40BytesHomogeneousDouble", isLeaf: true); + +/// Return value too big to go in FPU registers on arm64. +void testReturnStruct40BytesHomogeneousDoubleLeaf() { + 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; + + final result = returnStruct40BytesHomogeneousDoubleLeaf(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); + Expect.approxEquals(a4, result.a4); +} + +final returnStruct1024BytesHomogeneousUint64Leaf = + ffiTestFunctions.lookupFunction< + Struct1024BytesHomogeneousUint64 Function( + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64), + Struct1024BytesHomogeneousUint64 Function( + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int)>("ReturnStruct1024BytesHomogeneousUint64", isLeaf: true); + +/// Test 1kb struct. +void testReturnStruct1024BytesHomogeneousUint64Leaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + int a9; + int a10; + int a11; + int a12; + int a13; + int a14; + int a15; + int a16; + int a17; + int a18; + int a19; + int a20; + int a21; + int a22; + int a23; + int a24; + int a25; + int a26; + int a27; + int a28; + int a29; + int a30; + int a31; + int a32; + int a33; + int a34; + int a35; + int a36; + int a37; + int a38; + int a39; + int a40; + int a41; + int a42; + int a43; + int a44; + int a45; + int a46; + int a47; + int a48; + int a49; + int a50; + int a51; + int a52; + int a53; + int a54; + int a55; + int a56; + int a57; + int a58; + int a59; + int a60; + int a61; + int a62; + int a63; + int a64; + int a65; + int a66; + int a67; + int a68; + int a69; + int a70; + int a71; + int a72; + int a73; + int a74; + int a75; + int a76; + int a77; + int a78; + int a79; + int a80; + int a81; + int a82; + int a83; + int a84; + int a85; + int a86; + int a87; + int a88; + int a89; + int a90; + int a91; + int a92; + int a93; + int a94; + int a95; + int a96; + int a97; + int a98; + int a99; + int a100; + int a101; + int a102; + int a103; + int a104; + int a105; + int a106; + int a107; + int a108; + int a109; + int a110; + int a111; + int a112; + int a113; + int a114; + int a115; + int a116; + int a117; + int a118; + int a119; + int a120; + int a121; + int a122; + int a123; + int a124; + int a125; + int a126; + int 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; + + final result = returnStruct1024BytesHomogeneousUint64Leaf( + 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); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); + Expect.equals(a9, result.a9); + Expect.equals(a10, result.a10); + Expect.equals(a11, result.a11); + Expect.equals(a12, result.a12); + Expect.equals(a13, result.a13); + Expect.equals(a14, result.a14); + Expect.equals(a15, result.a15); + Expect.equals(a16, result.a16); + Expect.equals(a17, result.a17); + Expect.equals(a18, result.a18); + Expect.equals(a19, result.a19); + Expect.equals(a20, result.a20); + Expect.equals(a21, result.a21); + Expect.equals(a22, result.a22); + Expect.equals(a23, result.a23); + Expect.equals(a24, result.a24); + Expect.equals(a25, result.a25); + Expect.equals(a26, result.a26); + Expect.equals(a27, result.a27); + Expect.equals(a28, result.a28); + Expect.equals(a29, result.a29); + Expect.equals(a30, result.a30); + Expect.equals(a31, result.a31); + Expect.equals(a32, result.a32); + Expect.equals(a33, result.a33); + Expect.equals(a34, result.a34); + Expect.equals(a35, result.a35); + Expect.equals(a36, result.a36); + Expect.equals(a37, result.a37); + Expect.equals(a38, result.a38); + Expect.equals(a39, result.a39); + Expect.equals(a40, result.a40); + Expect.equals(a41, result.a41); + Expect.equals(a42, result.a42); + Expect.equals(a43, result.a43); + Expect.equals(a44, result.a44); + Expect.equals(a45, result.a45); + Expect.equals(a46, result.a46); + Expect.equals(a47, result.a47); + Expect.equals(a48, result.a48); + Expect.equals(a49, result.a49); + Expect.equals(a50, result.a50); + Expect.equals(a51, result.a51); + Expect.equals(a52, result.a52); + Expect.equals(a53, result.a53); + Expect.equals(a54, result.a54); + Expect.equals(a55, result.a55); + Expect.equals(a56, result.a56); + Expect.equals(a57, result.a57); + Expect.equals(a58, result.a58); + Expect.equals(a59, result.a59); + Expect.equals(a60, result.a60); + Expect.equals(a61, result.a61); + Expect.equals(a62, result.a62); + Expect.equals(a63, result.a63); + Expect.equals(a64, result.a64); + Expect.equals(a65, result.a65); + Expect.equals(a66, result.a66); + Expect.equals(a67, result.a67); + Expect.equals(a68, result.a68); + Expect.equals(a69, result.a69); + Expect.equals(a70, result.a70); + Expect.equals(a71, result.a71); + Expect.equals(a72, result.a72); + Expect.equals(a73, result.a73); + Expect.equals(a74, result.a74); + Expect.equals(a75, result.a75); + Expect.equals(a76, result.a76); + Expect.equals(a77, result.a77); + Expect.equals(a78, result.a78); + Expect.equals(a79, result.a79); + Expect.equals(a80, result.a80); + Expect.equals(a81, result.a81); + Expect.equals(a82, result.a82); + Expect.equals(a83, result.a83); + Expect.equals(a84, result.a84); + Expect.equals(a85, result.a85); + Expect.equals(a86, result.a86); + Expect.equals(a87, result.a87); + Expect.equals(a88, result.a88); + Expect.equals(a89, result.a89); + Expect.equals(a90, result.a90); + Expect.equals(a91, result.a91); + Expect.equals(a92, result.a92); + Expect.equals(a93, result.a93); + Expect.equals(a94, result.a94); + Expect.equals(a95, result.a95); + Expect.equals(a96, result.a96); + Expect.equals(a97, result.a97); + Expect.equals(a98, result.a98); + Expect.equals(a99, result.a99); + Expect.equals(a100, result.a100); + Expect.equals(a101, result.a101); + Expect.equals(a102, result.a102); + Expect.equals(a103, result.a103); + Expect.equals(a104, result.a104); + Expect.equals(a105, result.a105); + Expect.equals(a106, result.a106); + Expect.equals(a107, result.a107); + Expect.equals(a108, result.a108); + Expect.equals(a109, result.a109); + Expect.equals(a110, result.a110); + Expect.equals(a111, result.a111); + Expect.equals(a112, result.a112); + Expect.equals(a113, result.a113); + Expect.equals(a114, result.a114); + Expect.equals(a115, result.a115); + Expect.equals(a116, result.a116); + Expect.equals(a117, result.a117); + Expect.equals(a118, result.a118); + Expect.equals(a119, result.a119); + Expect.equals(a120, result.a120); + Expect.equals(a121, result.a121); + Expect.equals(a122, result.a122); + Expect.equals(a123, result.a123); + Expect.equals(a124, result.a124); + Expect.equals(a125, result.a125); + Expect.equals(a126, result.a126); + Expect.equals(a127, result.a127); +} + +final returnStruct3BytesPackedIntLeaf = ffiTestFunctions.lookupFunction< + Struct3BytesPackedInt Function(Int8, Int16), + Struct3BytesPackedInt Function( + int, int)>("ReturnStruct3BytesPackedInt", isLeaf: true); + +/// Small struct with mis-aligned member. +void testReturnStruct3BytesPackedIntLeaf() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct3BytesPackedIntLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct8BytesPackedIntLeaf = ffiTestFunctions.lookupFunction< + Struct8BytesPackedInt Function(Uint8, Uint32, Uint8, Uint8, Uint8), + Struct8BytesPackedInt Function( + int, int, int, int, int)>("ReturnStruct8BytesPackedInt", isLeaf: true); + +/// Struct with mis-aligned member. +void testReturnStruct8BytesPackedIntLeaf() { + int a0; + int a1; + int a2; + int a3; + int a4; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + + final result = returnStruct8BytesPackedIntLeaf(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); +} + +final returnStruct9BytesPackedMixedLeaf = ffiTestFunctions.lookupFunction< + Struct9BytesPackedMixed Function(Uint8, Double), + Struct9BytesPackedMixed Function( + int, double)>("ReturnStruct9BytesPackedMixed", isLeaf: true); + +/// Struct with mis-aligned member. +/// Tests backfilling of CPU and FPU registers. +void testReturnStruct9BytesPackedMixedLeaf() { + int a0; + double a1; + + a0 = 1; + a1 = 2.0; + + final result = returnStruct9BytesPackedMixedLeaf(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.approxEquals(a1, result.a1); +} + +final returnUnion4BytesMixedLeaf = ffiTestFunctions.lookupFunction< + Union4BytesMixed Function(Uint32), + Union4BytesMixed Function(int)>("ReturnUnion4BytesMixed", isLeaf: true); + +/// Returning a mixed integer/float union. +void testReturnUnion4BytesMixedLeaf() { + int a0; + + a0 = 1; + + final result = returnUnion4BytesMixedLeaf(a0); + + print("result = $result"); + + Expect.equals(a0, result.a0); +} + +final returnUnion8BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< + Union8BytesNestedFloat Function(Double), + Union8BytesNestedFloat Function( + double)>("ReturnUnion8BytesNestedFloat", isLeaf: true); + +/// Returning a floating point only union. +void testReturnUnion8BytesNestedFloatLeaf() { + double a0; + + a0 = -1.0; + + final result = returnUnion8BytesNestedFloatLeaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); +} + +final returnUnion9BytesNestedIntLeaf = ffiTestFunctions.lookupFunction< + Union9BytesNestedInt Function(Struct8BytesInt), + Union9BytesNestedInt Function( + Struct8BytesInt)>("ReturnUnion9BytesNestedInt", isLeaf: true); + +/// Returning a mixed-size union. +void testReturnUnion9BytesNestedIntLeaf() { + final a0Pointer = calloc(); + final Struct8BytesInt a0 = a0Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + + final result = returnUnion9BytesNestedIntLeaf(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + + calloc.free(a0Pointer); +} + +final returnUnion16BytesNestedFloatLeaf = ffiTestFunctions.lookupFunction< + Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat), + Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat)>( + "ReturnUnion16BytesNestedFloat", + isLeaf: true); + +/// Returning union with homogenous floats. +void testReturnUnion16BytesNestedFloatLeaf() { + final a0Pointer = calloc(); + final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; + + a0.a0 = -1.0; + a0.a1 = 2.0; + + final result = returnUnion16BytesNestedFloatLeaf(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a0.a1, result.a0.a1); + + calloc.free(a0Pointer); +} diff --git a/tests/ffi_2/function_structs_by_value_generated_ret_test.dart b/tests/ffi_2/function_structs_by_value_generated_ret_test.dart new file mode 100644 index 00000000000..721a4e558da --- /dev/null +++ b/tests/ffi_2/function_structs_by_value_generated_ret_test.dart @@ -0,0 +1,1631 @@ +// 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. +// Generated by tests/ffi/generator/structs_by_value_tests_generator.dart. +// +// SharedObjects=ffi_test_functions +// VMOptions= +// VMOptions=--deterministic --optimization-counter-threshold=90 +// VMOptions=--use-slow-path +// VMOptions=--use-slow-path --stacktrace-every=100 + +// @dart = 2.9 + +import 'dart:ffi'; + +import "package:expect/expect.dart"; +import "package:ffi/ffi.dart"; + +import 'dylib_utils.dart'; + +// Reuse the compound classes. +import 'function_structs_by_value_generated_compounds.dart'; + +final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions"); +void main() { + for (int i = 0; i < 100; ++i) { + testReturnStruct1ByteInt(); + testReturnStruct3BytesHomogeneousUint8(); + testReturnStruct3BytesInt2ByteAligned(); + testReturnStruct4BytesHomogeneousInt16(); + testReturnStruct7BytesHomogeneousUint8(); + testReturnStruct7BytesInt4ByteAligned(); + testReturnStruct8BytesInt(); + testReturnStruct8BytesHomogeneousFloat(); + testReturnStruct8BytesMixed(); + testReturnStruct9BytesHomogeneousUint8(); + testReturnStruct9BytesInt4Or8ByteAligned(); + testReturnStruct12BytesHomogeneousFloat(); + testReturnStruct16BytesHomogeneousFloat(); + testReturnStruct16BytesMixed(); + testReturnStruct16BytesMixed2(); + testReturnStruct17BytesInt(); + testReturnStruct19BytesHomogeneousUint8(); + testReturnStruct20BytesHomogeneousInt32(); + testReturnStruct20BytesHomogeneousFloat(); + testReturnStruct32BytesHomogeneousDouble(); + testReturnStruct40BytesHomogeneousDouble(); + testReturnStruct1024BytesHomogeneousUint64(); + testReturnStruct3BytesPackedInt(); + testReturnStruct8BytesPackedInt(); + testReturnStruct9BytesPackedMixed(); + testReturnUnion4BytesMixed(); + testReturnUnion8BytesNestedFloat(); + testReturnUnion9BytesNestedInt(); + testReturnUnion16BytesNestedFloat(); + } +} + +final returnStruct1ByteInt = ffiTestFunctions.lookupFunction< + Struct1ByteInt Function(Int8), + Struct1ByteInt Function(int)>("ReturnStruct1ByteInt"); + +/// Smallest struct with data. +void testReturnStruct1ByteInt() { + int a0; + + a0 = -1; + + final result = returnStruct1ByteInt(a0); + + print("result = $result"); + + Expect.equals(a0, result.a0); +} + +final returnStruct3BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< + Struct3BytesHomogeneousUint8 Function(Uint8, Uint8, Uint8), + Struct3BytesHomogeneousUint8 Function( + int, int, int)>("ReturnStruct3BytesHomogeneousUint8"); + +/// Smaller than word size return value on all architectures. +void testReturnStruct3BytesHomogeneousUint8() { + int a0; + int a1; + int a2; + + a0 = 1; + a1 = 2; + a2 = 3; + + final result = returnStruct3BytesHomogeneousUint8(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct3BytesInt2ByteAligned = ffiTestFunctions.lookupFunction< + Struct3BytesInt2ByteAligned Function(Int16, Int8), + Struct3BytesInt2ByteAligned Function( + int, int)>("ReturnStruct3BytesInt2ByteAligned"); + +/// Smaller than word size return value on all architectures. +/// With alignment rules taken into account size is 4 bytes. +void testReturnStruct3BytesInt2ByteAligned() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct3BytesInt2ByteAligned(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct4BytesHomogeneousInt16 = ffiTestFunctions.lookupFunction< + Struct4BytesHomogeneousInt16 Function(Int16, Int16), + Struct4BytesHomogeneousInt16 Function( + int, int)>("ReturnStruct4BytesHomogeneousInt16"); + +/// Word size return value on 32 bit architectures.. +void testReturnStruct4BytesHomogeneousInt16() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct4BytesHomogeneousInt16(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct7BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< + Struct7BytesHomogeneousUint8 Function( + Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), + Struct7BytesHomogeneousUint8 Function(int, int, int, int, int, int, + int)>("ReturnStruct7BytesHomogeneousUint8"); + +/// Non-wordsize return value. +void testReturnStruct7BytesHomogeneousUint8() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + a5 = 6; + a6 = 7; + + final result = returnStruct7BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); +} + +final returnStruct7BytesInt4ByteAligned = ffiTestFunctions.lookupFunction< + Struct7BytesInt4ByteAligned Function(Int32, Int16, Int8), + Struct7BytesInt4ByteAligned Function( + int, int, int)>("ReturnStruct7BytesInt4ByteAligned"); + +/// Non-wordsize return value. +/// With alignment rules taken into account size is 8 bytes. +void testReturnStruct7BytesInt4ByteAligned() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct7BytesInt4ByteAligned(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesInt = ffiTestFunctions.lookupFunction< + Struct8BytesInt Function(Int16, Int16, Int32), + Struct8BytesInt Function(int, int, int)>("ReturnStruct8BytesInt"); + +/// Return value in integer registers on many architectures. +void testReturnStruct8BytesInt() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct8BytesInt(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct8BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< + Struct8BytesHomogeneousFloat Function(Float, Float), + Struct8BytesHomogeneousFloat Function( + double, double)>("ReturnStruct8BytesHomogeneousFloat"); + +/// Return value in FP registers on many architectures. +void testReturnStruct8BytesHomogeneousFloat() { + double a0; + double a1; + + a0 = -1.0; + a1 = 2.0; + + final result = returnStruct8BytesHomogeneousFloat(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); +} + +final returnStruct8BytesMixed = ffiTestFunctions.lookupFunction< + Struct8BytesMixed Function(Float, Int16, Int16), + Struct8BytesMixed Function(double, int, int)>("ReturnStruct8BytesMixed"); + +/// Return value split over FP and integer register in x64. +void testReturnStruct8BytesMixed() { + double a0; + int a1; + int a2; + + a0 = -1.0; + a1 = 2; + a2 = -3; + + final result = returnStruct8BytesMixed(a0, a1, a2); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct9BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< + Struct9BytesHomogeneousUint8 Function( + Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8), + Struct9BytesHomogeneousUint8 Function(int, int, int, int, int, int, int, + int, int)>("ReturnStruct9BytesHomogeneousUint8"); + +/// 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. +void testReturnStruct9BytesHomogeneousUint8() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + a5 = 6; + a6 = 7; + a7 = 8; + a8 = 9; + + final result = + returnStruct9BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6, a7, a8); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); +} + +final returnStruct9BytesInt4Or8ByteAligned = ffiTestFunctions.lookupFunction< + Struct9BytesInt4Or8ByteAligned Function(Int64, Int8), + Struct9BytesInt4Or8ByteAligned Function( + int, int)>("ReturnStruct9BytesInt4Or8ByteAligned"); + +/// Return value in two integer registers on x64. +/// With alignment rules taken into account size is 12 or 16 bytes. +void testReturnStruct9BytesInt4Or8ByteAligned() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct9BytesInt4Or8ByteAligned(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct12BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< + Struct12BytesHomogeneousFloat Function(Float, Float, Float), + Struct12BytesHomogeneousFloat Function( + double, double, double)>("ReturnStruct12BytesHomogeneousFloat"); + +/// Return value in FPU registers, but does not use all registers on arm hardfp +/// and arm64. +void testReturnStruct12BytesHomogeneousFloat() { + double a0; + double a1; + double a2; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + + final result = returnStruct12BytesHomogeneousFloat(a0, a1, a2); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); +} + +final returnStruct16BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< + Struct16BytesHomogeneousFloat Function(Float, Float, Float, Float), + Struct16BytesHomogeneousFloat Function( + double, double, double, double)>("ReturnStruct16BytesHomogeneousFloat"); + +/// Return value in FPU registers on arm hardfp and arm64. +void testReturnStruct16BytesHomogeneousFloat() { + double a0; + double a1; + double a2; + double a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4.0; + + final result = returnStruct16BytesHomogeneousFloat(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); +} + +final returnStruct16BytesMixed = ffiTestFunctions.lookupFunction< + Struct16BytesMixed Function(Double, Int64), + Struct16BytesMixed Function(double, int)>("ReturnStruct16BytesMixed"); + +/// Return value split over FP and integer register in x64. +void testReturnStruct16BytesMixed() { + double a0; + int a1; + + a0 = -1.0; + a1 = 2; + + final result = returnStruct16BytesMixed(a0, a1); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct16BytesMixed2 = ffiTestFunctions.lookupFunction< + Struct16BytesMixed2 Function(Float, Float, Float, Int32), + Struct16BytesMixed2 Function( + double, double, double, int)>("ReturnStruct16BytesMixed2"); + +/// Return value split over FP and integer register in x64. +/// The integer register contains half float half int. +void testReturnStruct16BytesMixed2() { + double a0; + double a1; + double a2; + int a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4; + + final result = returnStruct16BytesMixed2(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.equals(a3, result.a3); +} + +final returnStruct17BytesInt = ffiTestFunctions.lookupFunction< + Struct17BytesInt Function(Int64, Int64, Int8), + Struct17BytesInt Function(int, int, int)>("ReturnStruct17BytesInt"); + +/// 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. +void testReturnStruct17BytesInt() { + int a0; + int a1; + int a2; + + a0 = -1; + a1 = 2; + a2 = -3; + + final result = returnStruct17BytesInt(a0, a1, a2); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); +} + +final returnStruct19BytesHomogeneousUint8 = ffiTestFunctions.lookupFunction< + Struct19BytesHomogeneousUint8 Function( + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8, + Uint8), + Struct19BytesHomogeneousUint8 Function( + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int)>("ReturnStruct19BytesHomogeneousUint8"); + +/// 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. +void testReturnStruct19BytesHomogeneousUint8() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + int a9; + int a10; + int a11; + int a12; + int a13; + int a14; + int a15; + int a16; + int a17; + int 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; + + final result = returnStruct19BytesHomogeneousUint8(a0, a1, a2, a3, a4, a5, a6, + a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); + Expect.equals(a9, result.a9); + Expect.equals(a10, result.a10); + Expect.equals(a11, result.a11); + Expect.equals(a12, result.a12); + Expect.equals(a13, result.a13); + Expect.equals(a14, result.a14); + Expect.equals(a15, result.a15); + Expect.equals(a16, result.a16); + Expect.equals(a17, result.a17); + Expect.equals(a18, result.a18); +} + +final returnStruct20BytesHomogeneousInt32 = ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousInt32 Function(Int32, Int32, Int32, Int32, Int32), + Struct20BytesHomogeneousInt32 Function( + int, int, int, int, int)>("ReturnStruct20BytesHomogeneousInt32"); + +/// Return value too big to go in cpu registers on arm64. +void testReturnStruct20BytesHomogeneousInt32() { + int a0; + int a1; + int a2; + int a3; + int a4; + + a0 = -1; + a1 = 2; + a2 = -3; + a3 = 4; + a4 = -5; + + final result = returnStruct20BytesHomogeneousInt32(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); +} + +final returnStruct20BytesHomogeneousFloat = ffiTestFunctions.lookupFunction< + Struct20BytesHomogeneousFloat Function(Float, Float, Float, Float, Float), + Struct20BytesHomogeneousFloat Function(double, double, double, double, + double)>("ReturnStruct20BytesHomogeneousFloat"); + +/// Return value too big to go in FPU registers on x64, arm hardfp and arm64. +void testReturnStruct20BytesHomogeneousFloat() { + 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; + + final result = returnStruct20BytesHomogeneousFloat(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); + Expect.approxEquals(a4, result.a4); +} + +final returnStruct32BytesHomogeneousDouble = ffiTestFunctions.lookupFunction< + Struct32BytesHomogeneousDouble Function(Double, Double, Double, Double), + Struct32BytesHomogeneousDouble Function(double, double, double, + double)>("ReturnStruct32BytesHomogeneousDouble"); + +/// Return value in FPU registers on arm64. +void testReturnStruct32BytesHomogeneousDouble() { + double a0; + double a1; + double a2; + double a3; + + a0 = -1.0; + a1 = 2.0; + a2 = -3.0; + a3 = 4.0; + + final result = returnStruct32BytesHomogeneousDouble(a0, a1, a2, a3); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); +} + +final returnStruct40BytesHomogeneousDouble = ffiTestFunctions.lookupFunction< + Struct40BytesHomogeneousDouble Function( + Double, Double, Double, Double, Double), + Struct40BytesHomogeneousDouble Function(double, double, double, double, + double)>("ReturnStruct40BytesHomogeneousDouble"); + +/// Return value too big to go in FPU registers on arm64. +void testReturnStruct40BytesHomogeneousDouble() { + 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; + + final result = returnStruct40BytesHomogeneousDouble(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); + Expect.approxEquals(a1, result.a1); + Expect.approxEquals(a2, result.a2); + Expect.approxEquals(a3, result.a3); + Expect.approxEquals(a4, result.a4); +} + +final returnStruct1024BytesHomogeneousUint64 = ffiTestFunctions.lookupFunction< + Struct1024BytesHomogeneousUint64 Function( + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64, + Uint64), + Struct1024BytesHomogeneousUint64 Function( + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int, + int)>("ReturnStruct1024BytesHomogeneousUint64"); + +/// Test 1kb struct. +void testReturnStruct1024BytesHomogeneousUint64() { + int a0; + int a1; + int a2; + int a3; + int a4; + int a5; + int a6; + int a7; + int a8; + int a9; + int a10; + int a11; + int a12; + int a13; + int a14; + int a15; + int a16; + int a17; + int a18; + int a19; + int a20; + int a21; + int a22; + int a23; + int a24; + int a25; + int a26; + int a27; + int a28; + int a29; + int a30; + int a31; + int a32; + int a33; + int a34; + int a35; + int a36; + int a37; + int a38; + int a39; + int a40; + int a41; + int a42; + int a43; + int a44; + int a45; + int a46; + int a47; + int a48; + int a49; + int a50; + int a51; + int a52; + int a53; + int a54; + int a55; + int a56; + int a57; + int a58; + int a59; + int a60; + int a61; + int a62; + int a63; + int a64; + int a65; + int a66; + int a67; + int a68; + int a69; + int a70; + int a71; + int a72; + int a73; + int a74; + int a75; + int a76; + int a77; + int a78; + int a79; + int a80; + int a81; + int a82; + int a83; + int a84; + int a85; + int a86; + int a87; + int a88; + int a89; + int a90; + int a91; + int a92; + int a93; + int a94; + int a95; + int a96; + int a97; + int a98; + int a99; + int a100; + int a101; + int a102; + int a103; + int a104; + int a105; + int a106; + int a107; + int a108; + int a109; + int a110; + int a111; + int a112; + int a113; + int a114; + int a115; + int a116; + int a117; + int a118; + int a119; + int a120; + int a121; + int a122; + int a123; + int a124; + int a125; + int a126; + int 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; + + final result = 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); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); + Expect.equals(a5, result.a5); + Expect.equals(a6, result.a6); + Expect.equals(a7, result.a7); + Expect.equals(a8, result.a8); + Expect.equals(a9, result.a9); + Expect.equals(a10, result.a10); + Expect.equals(a11, result.a11); + Expect.equals(a12, result.a12); + Expect.equals(a13, result.a13); + Expect.equals(a14, result.a14); + Expect.equals(a15, result.a15); + Expect.equals(a16, result.a16); + Expect.equals(a17, result.a17); + Expect.equals(a18, result.a18); + Expect.equals(a19, result.a19); + Expect.equals(a20, result.a20); + Expect.equals(a21, result.a21); + Expect.equals(a22, result.a22); + Expect.equals(a23, result.a23); + Expect.equals(a24, result.a24); + Expect.equals(a25, result.a25); + Expect.equals(a26, result.a26); + Expect.equals(a27, result.a27); + Expect.equals(a28, result.a28); + Expect.equals(a29, result.a29); + Expect.equals(a30, result.a30); + Expect.equals(a31, result.a31); + Expect.equals(a32, result.a32); + Expect.equals(a33, result.a33); + Expect.equals(a34, result.a34); + Expect.equals(a35, result.a35); + Expect.equals(a36, result.a36); + Expect.equals(a37, result.a37); + Expect.equals(a38, result.a38); + Expect.equals(a39, result.a39); + Expect.equals(a40, result.a40); + Expect.equals(a41, result.a41); + Expect.equals(a42, result.a42); + Expect.equals(a43, result.a43); + Expect.equals(a44, result.a44); + Expect.equals(a45, result.a45); + Expect.equals(a46, result.a46); + Expect.equals(a47, result.a47); + Expect.equals(a48, result.a48); + Expect.equals(a49, result.a49); + Expect.equals(a50, result.a50); + Expect.equals(a51, result.a51); + Expect.equals(a52, result.a52); + Expect.equals(a53, result.a53); + Expect.equals(a54, result.a54); + Expect.equals(a55, result.a55); + Expect.equals(a56, result.a56); + Expect.equals(a57, result.a57); + Expect.equals(a58, result.a58); + Expect.equals(a59, result.a59); + Expect.equals(a60, result.a60); + Expect.equals(a61, result.a61); + Expect.equals(a62, result.a62); + Expect.equals(a63, result.a63); + Expect.equals(a64, result.a64); + Expect.equals(a65, result.a65); + Expect.equals(a66, result.a66); + Expect.equals(a67, result.a67); + Expect.equals(a68, result.a68); + Expect.equals(a69, result.a69); + Expect.equals(a70, result.a70); + Expect.equals(a71, result.a71); + Expect.equals(a72, result.a72); + Expect.equals(a73, result.a73); + Expect.equals(a74, result.a74); + Expect.equals(a75, result.a75); + Expect.equals(a76, result.a76); + Expect.equals(a77, result.a77); + Expect.equals(a78, result.a78); + Expect.equals(a79, result.a79); + Expect.equals(a80, result.a80); + Expect.equals(a81, result.a81); + Expect.equals(a82, result.a82); + Expect.equals(a83, result.a83); + Expect.equals(a84, result.a84); + Expect.equals(a85, result.a85); + Expect.equals(a86, result.a86); + Expect.equals(a87, result.a87); + Expect.equals(a88, result.a88); + Expect.equals(a89, result.a89); + Expect.equals(a90, result.a90); + Expect.equals(a91, result.a91); + Expect.equals(a92, result.a92); + Expect.equals(a93, result.a93); + Expect.equals(a94, result.a94); + Expect.equals(a95, result.a95); + Expect.equals(a96, result.a96); + Expect.equals(a97, result.a97); + Expect.equals(a98, result.a98); + Expect.equals(a99, result.a99); + Expect.equals(a100, result.a100); + Expect.equals(a101, result.a101); + Expect.equals(a102, result.a102); + Expect.equals(a103, result.a103); + Expect.equals(a104, result.a104); + Expect.equals(a105, result.a105); + Expect.equals(a106, result.a106); + Expect.equals(a107, result.a107); + Expect.equals(a108, result.a108); + Expect.equals(a109, result.a109); + Expect.equals(a110, result.a110); + Expect.equals(a111, result.a111); + Expect.equals(a112, result.a112); + Expect.equals(a113, result.a113); + Expect.equals(a114, result.a114); + Expect.equals(a115, result.a115); + Expect.equals(a116, result.a116); + Expect.equals(a117, result.a117); + Expect.equals(a118, result.a118); + Expect.equals(a119, result.a119); + Expect.equals(a120, result.a120); + Expect.equals(a121, result.a121); + Expect.equals(a122, result.a122); + Expect.equals(a123, result.a123); + Expect.equals(a124, result.a124); + Expect.equals(a125, result.a125); + Expect.equals(a126, result.a126); + Expect.equals(a127, result.a127); +} + +final returnStruct3BytesPackedInt = ffiTestFunctions.lookupFunction< + Struct3BytesPackedInt Function(Int8, Int16), + Struct3BytesPackedInt Function(int, int)>("ReturnStruct3BytesPackedInt"); + +/// Small struct with mis-aligned member. +void testReturnStruct3BytesPackedInt() { + int a0; + int a1; + + a0 = -1; + a1 = 2; + + final result = returnStruct3BytesPackedInt(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); +} + +final returnStruct8BytesPackedInt = ffiTestFunctions.lookupFunction< + Struct8BytesPackedInt Function(Uint8, Uint32, Uint8, Uint8, Uint8), + Struct8BytesPackedInt Function( + int, int, int, int, int)>("ReturnStruct8BytesPackedInt"); + +/// Struct with mis-aligned member. +void testReturnStruct8BytesPackedInt() { + int a0; + int a1; + int a2; + int a3; + int a4; + + a0 = 1; + a1 = 2; + a2 = 3; + a3 = 4; + a4 = 5; + + final result = returnStruct8BytesPackedInt(a0, a1, a2, a3, a4); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.equals(a1, result.a1); + Expect.equals(a2, result.a2); + Expect.equals(a3, result.a3); + Expect.equals(a4, result.a4); +} + +final returnStruct9BytesPackedMixed = ffiTestFunctions.lookupFunction< + Struct9BytesPackedMixed Function(Uint8, Double), + Struct9BytesPackedMixed Function( + int, double)>("ReturnStruct9BytesPackedMixed"); + +/// Struct with mis-aligned member. +/// Tests backfilling of CPU and FPU registers. +void testReturnStruct9BytesPackedMixed() { + int a0; + double a1; + + a0 = 1; + a1 = 2.0; + + final result = returnStruct9BytesPackedMixed(a0, a1); + + print("result = $result"); + + Expect.equals(a0, result.a0); + Expect.approxEquals(a1, result.a1); +} + +final returnUnion4BytesMixed = ffiTestFunctions.lookupFunction< + Union4BytesMixed Function(Uint32), + Union4BytesMixed Function(int)>("ReturnUnion4BytesMixed"); + +/// Returning a mixed integer/float union. +void testReturnUnion4BytesMixed() { + int a0; + + a0 = 1; + + final result = returnUnion4BytesMixed(a0); + + print("result = $result"); + + Expect.equals(a0, result.a0); +} + +final returnUnion8BytesNestedFloat = ffiTestFunctions.lookupFunction< + Union8BytesNestedFloat Function(Double), + Union8BytesNestedFloat Function(double)>("ReturnUnion8BytesNestedFloat"); + +/// Returning a floating point only union. +void testReturnUnion8BytesNestedFloat() { + double a0; + + a0 = -1.0; + + final result = returnUnion8BytesNestedFloat(a0); + + print("result = $result"); + + Expect.approxEquals(a0, result.a0); +} + +final returnUnion9BytesNestedInt = ffiTestFunctions.lookupFunction< + Union9BytesNestedInt Function(Struct8BytesInt), + Union9BytesNestedInt Function( + Struct8BytesInt)>("ReturnUnion9BytesNestedInt"); + +/// Returning a mixed-size union. +void testReturnUnion9BytesNestedInt() { + final a0Pointer = calloc(); + final Struct8BytesInt a0 = a0Pointer.ref; + + a0.a0 = -1; + a0.a1 = 2; + a0.a2 = -3; + + final result = returnUnion9BytesNestedInt(a0); + + print("result = $result"); + + Expect.equals(a0.a0, result.a0.a0); + Expect.equals(a0.a1, result.a0.a1); + Expect.equals(a0.a2, result.a0.a2); + + calloc.free(a0Pointer); +} + +final returnUnion16BytesNestedFloat = ffiTestFunctions.lookupFunction< + Union16BytesNestedFloat Function(Struct8BytesHomogeneousFloat), + Union16BytesNestedFloat Function( + Struct8BytesHomogeneousFloat)>("ReturnUnion16BytesNestedFloat"); + +/// Returning union with homogenous floats. +void testReturnUnion16BytesNestedFloat() { + final a0Pointer = calloc(); + final Struct8BytesHomogeneousFloat a0 = a0Pointer.ref; + + a0.a0 = -1.0; + a0.a1 = 2.0; + + final result = returnUnion16BytesNestedFloat(a0); + + print("result = $result"); + + Expect.approxEquals(a0.a0, result.a0.a0); + Expect.approxEquals(a0.a1, result.a0.a1); + + calloc.free(a0Pointer); +}