dart-sdk/tests/ffi/address_of_struct_generated_test.dart
Daco Harkes 4b66657b98 [vm/ffi] address of operator for FFI leaf calls
During FFI leaf calls, the Dart GC will not run. This means that we
can pass pointers into `TypedData` to FFI calls that take `Pointer`
arguments.

After this CL, we have three types of arguments that can flow into
`Pointer` argument in an FFI call:
* `Pointer`.
* `TypedData`: Any typed data including views.
* `_Compound`: A TypedData/Pointer and an offset in bytes.

The is only possible for `@Native external` functions, `asFunction`
does not support passing in `TypedData`. (See related GitHub issues
for discussion. TLDR: FFIgen should generate bindings without config.)

`.address` expressions on `TypedData` and `Array` elements do _not_
introduce bounds checks, even though `TypedData` and `Array` have
bounds information. E.g. `ffiNative(Uint8List(10)[20].address)` does
not throw.

Implementation details:

The CFE analyzes call-sites to `@Native external` functions. If the
arguments are `.address` expressions, it transforms the call site to
pass the compound or `TypedData`. If an additional offset needs to be
applied, the CFE constructs a new `_Compound` with the correct offset
in bytes.

The CFE then also creates a new `@Native external` function which have
`TypedData`s and `_Compound`s parameters. To avoid name clashes, these
functions are postfixed with `#` and `P`, `T`, or `C` for each Pointer
parameter.

TEST=pkg/vm/testcases/transformations/ffi/address_of_*

In the VM, `TypedData` arguments are passed as tagged values, and the
address is loaded inside the `FfiCallInstr`. `_Compound` arguments
turn into two IL definitions, one for the `TypedDataBase` (tagged),
and one for the offset in bytes (unboxed). The address is then loaded
inside the `FfiCallInstr` and the offset in bytes is applied.

Adding the offset in bytes required an extra temp register for ia32.
Also, it uncovered that the temp register in arm32 was conflicting
with the argument registers. However, TMP should suffice instead.

TEST=tests/ffi/address_of_array_generated_test.dart
TEST=tests/ffi/address_of_struct_generated_test.dart
TEST=tests/ffi/address_of_typeddata_generated_test.dart

Closes: https://github.com/dart-lang/sdk/issues/44589
Closes: https://github.com/dart-lang/sdk/issues/54771

CoreLibraryReviewExempt: VM only, unsupported in dart2wasm
Change-Id: I01fb428cfd6f9096a34689c2819c124a8003cb6b
Cq-Include-Trybots: dart/try:vm-aot-android-release-arm64c-try,vm-aot-android-release-arm_x64-try,vm-aot-linux-debug-x64-try,vm-aot-linux-debug-x64c-try,vm-aot-mac-release-arm64-try,vm-aot-mac-release-x64-try,vm-aot-obfuscate-linux-release-x64-try,vm-aot-optimization-level-linux-release-x64-try,vm-aot-win-debug-arm64-try,vm-aot-win-debug-x64c-try,vm-aot-win-release-x64-try,vm-appjit-linux-debug-x64-try,vm-asan-linux-release-x64-try,vm-checked-mac-release-arm64-try,vm-eager-optimization-linux-release-ia32-try,vm-eager-optimization-linux-release-x64-try,vm-ffi-android-debug-arm64c-try,vm-ffi-qemu-linux-release-arm-try,vm-ffi-qemu-linux-release-riscv64-try,vm-linux-debug-ia32-try,vm-linux-debug-x64-try,vm-linux-debug-x64c-try,vm-mac-debug-arm64-try,vm-mac-debug-x64-try,vm-msan-linux-release-x64-try,vm-reload-linux-debug-x64-try,vm-reload-rollback-linux-debug-x64-try,vm-ubsan-linux-release-x64-try,vm-win-debug-arm64-try,vm-win-debug-x64-try,vm-win-debug-x64c-try,vm-win-release-ia32-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/360882
Reviewed-by: Jens Johansen <jensj@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Tess Strickland <sstrickl@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
2024-04-25 10:06:16 +00:00

1119 lines
25 KiB
Dart

// Copyright (c) 2024, 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/address_of_test_generator.dart.
//
// SharedObjects=ffi_test_functions
// VMOptions=
// VMOptions=--deterministic --optimization-counter-threshold=90
// VMOptions=--use-slow-path
// VMOptions=--use-slow-path --stacktrace-every=100
// ignore_for_file: unused_import
import 'dart:ffi';
import 'dart:typed_data';
import 'package:expect/expect.dart';
import 'address_of_generated_shared.dart';
import 'address_of_shared.dart';
import 'dylib_utils.dart';
final ffiTestFunctions = dlopenPlatformSpecific('ffi_test_functions');
void main() {
// Force dlopen so @Native lookups in DynamicLibrary.process() succeed.
dlopenGlobalPlatformSpecific('ffi_test_functions');
for (int i = 0; i < 100; ++i) {
testAddressOfInt8StructField();
testAddressOfInt16StructField();
testAddressOfInt32StructField();
testAddressOfInt64StructField();
testAddressOfUint8StructField();
testAddressOfUint16StructField();
testAddressOfUint32StructField();
testAddressOfUint64StructField();
testAddressOfFloatStructField();
testAddressOfDoubleStructField();
testAddressOfBoolStructField();
testAddressOfStructPointerMany();
}
}
final class Int8Struct extends Struct {
@Int8()
external int a0;
@Int8()
external int a1;
@Int8()
external int a2;
@Int8()
external int a3;
@Int8()
external int a4;
@Int8()
external int a5;
@Int8()
external int a6;
@Int8()
external int a7;
@Int8()
external int a8;
@Int8()
external int a9;
@Int8()
external int a10;
@Int8()
external int a11;
@Int8()
external int a12;
@Int8()
external int a13;
@Int8()
external int a14;
@Int8()
external int a15;
@Int8()
external int a16;
@Int8()
external int a17;
@Int8()
external int a18;
@Int8()
external int a19;
}
Int8Struct makeInt8Struct(int length) {
assert(length == 20);
final typedData = makeInt8List(length);
final struct = Struct.create<Int8Struct>(typedData);
return struct;
}
void testAddressOfInt8StructField() {
const length = 20;
final struct = makeInt8Struct(length);
final expectedResult = makeExpectedResultInt8(0, length);
final result = takeInt8PointerMany(
struct.a0.address,
struct.a1.address,
struct.a2.address,
struct.a3.address,
struct.a4.address,
struct.a5.address,
struct.a6.address,
struct.a7.address,
struct.a8.address,
struct.a9.address,
struct.a10.address,
struct.a11.address,
struct.a12.address,
struct.a13.address,
struct.a14.address,
struct.a15.address,
struct.a16.address,
struct.a17.address,
struct.a18.address,
struct.a19.address,
);
Expect.equals(expectedResult, result);
}
final class Int16Struct extends Struct {
@Int16()
external int a0;
@Int16()
external int a1;
@Int16()
external int a2;
@Int16()
external int a3;
@Int16()
external int a4;
@Int16()
external int a5;
@Int16()
external int a6;
@Int16()
external int a7;
@Int16()
external int a8;
@Int16()
external int a9;
@Int16()
external int a10;
@Int16()
external int a11;
@Int16()
external int a12;
@Int16()
external int a13;
@Int16()
external int a14;
@Int16()
external int a15;
@Int16()
external int a16;
@Int16()
external int a17;
@Int16()
external int a18;
@Int16()
external int a19;
}
Int16Struct makeInt16Struct(int length) {
assert(length == 20);
final typedData = makeInt16List(length);
final struct = Struct.create<Int16Struct>(typedData);
return struct;
}
void testAddressOfInt16StructField() {
const length = 20;
final struct = makeInt16Struct(length);
final expectedResult = makeExpectedResultInt16(0, length);
final result = takeInt16PointerMany(
struct.a0.address,
struct.a1.address,
struct.a2.address,
struct.a3.address,
struct.a4.address,
struct.a5.address,
struct.a6.address,
struct.a7.address,
struct.a8.address,
struct.a9.address,
struct.a10.address,
struct.a11.address,
struct.a12.address,
struct.a13.address,
struct.a14.address,
struct.a15.address,
struct.a16.address,
struct.a17.address,
struct.a18.address,
struct.a19.address,
);
Expect.equals(expectedResult, result);
}
final class Int32Struct extends Struct {
@Int32()
external int a0;
@Int32()
external int a1;
@Int32()
external int a2;
@Int32()
external int a3;
@Int32()
external int a4;
@Int32()
external int a5;
@Int32()
external int a6;
@Int32()
external int a7;
@Int32()
external int a8;
@Int32()
external int a9;
@Int32()
external int a10;
@Int32()
external int a11;
@Int32()
external int a12;
@Int32()
external int a13;
@Int32()
external int a14;
@Int32()
external int a15;
@Int32()
external int a16;
@Int32()
external int a17;
@Int32()
external int a18;
@Int32()
external int a19;
}
Int32Struct makeInt32Struct(int length) {
assert(length == 20);
final typedData = makeInt32List(length);
final struct = Struct.create<Int32Struct>(typedData);
return struct;
}
void testAddressOfInt32StructField() {
const length = 20;
final struct = makeInt32Struct(length);
final expectedResult = makeExpectedResultInt32(0, length);
final result = takeInt32PointerMany(
struct.a0.address,
struct.a1.address,
struct.a2.address,
struct.a3.address,
struct.a4.address,
struct.a5.address,
struct.a6.address,
struct.a7.address,
struct.a8.address,
struct.a9.address,
struct.a10.address,
struct.a11.address,
struct.a12.address,
struct.a13.address,
struct.a14.address,
struct.a15.address,
struct.a16.address,
struct.a17.address,
struct.a18.address,
struct.a19.address,
);
Expect.equals(expectedResult, result);
}
final class Int64Struct extends Struct {
@Int64()
external int a0;
@Int64()
external int a1;
@Int64()
external int a2;
@Int64()
external int a3;
@Int64()
external int a4;
@Int64()
external int a5;
@Int64()
external int a6;
@Int64()
external int a7;
@Int64()
external int a8;
@Int64()
external int a9;
@Int64()
external int a10;
@Int64()
external int a11;
@Int64()
external int a12;
@Int64()
external int a13;
@Int64()
external int a14;
@Int64()
external int a15;
@Int64()
external int a16;
@Int64()
external int a17;
@Int64()
external int a18;
@Int64()
external int a19;
}
Int64Struct makeInt64Struct(int length) {
assert(length == 20);
final typedData = makeInt64List(length);
final struct = Struct.create<Int64Struct>(typedData);
return struct;
}
void testAddressOfInt64StructField() {
const length = 20;
final struct = makeInt64Struct(length);
final expectedResult = makeExpectedResultInt64(0, length);
final result = takeInt64PointerMany(
struct.a0.address,
struct.a1.address,
struct.a2.address,
struct.a3.address,
struct.a4.address,
struct.a5.address,
struct.a6.address,
struct.a7.address,
struct.a8.address,
struct.a9.address,
struct.a10.address,
struct.a11.address,
struct.a12.address,
struct.a13.address,
struct.a14.address,
struct.a15.address,
struct.a16.address,
struct.a17.address,
struct.a18.address,
struct.a19.address,
);
Expect.equals(expectedResult, result);
}
final class Uint8Struct extends Struct {
@Uint8()
external int a0;
@Uint8()
external int a1;
@Uint8()
external int a2;
@Uint8()
external int a3;
@Uint8()
external int a4;
@Uint8()
external int a5;
@Uint8()
external int a6;
@Uint8()
external int a7;
@Uint8()
external int a8;
@Uint8()
external int a9;
@Uint8()
external int a10;
@Uint8()
external int a11;
@Uint8()
external int a12;
@Uint8()
external int a13;
@Uint8()
external int a14;
@Uint8()
external int a15;
@Uint8()
external int a16;
@Uint8()
external int a17;
@Uint8()
external int a18;
@Uint8()
external int a19;
}
Uint8Struct makeUint8Struct(int length) {
assert(length == 20);
final typedData = makeUint8List(length);
final struct = Struct.create<Uint8Struct>(typedData);
return struct;
}
void testAddressOfUint8StructField() {
const length = 20;
final struct = makeUint8Struct(length);
final expectedResult = makeExpectedResultUint8(0, length);
final result = takeUint8PointerMany(
struct.a0.address,
struct.a1.address,
struct.a2.address,
struct.a3.address,
struct.a4.address,
struct.a5.address,
struct.a6.address,
struct.a7.address,
struct.a8.address,
struct.a9.address,
struct.a10.address,
struct.a11.address,
struct.a12.address,
struct.a13.address,
struct.a14.address,
struct.a15.address,
struct.a16.address,
struct.a17.address,
struct.a18.address,
struct.a19.address,
);
Expect.equals(expectedResult, result);
}
final class Uint16Struct extends Struct {
@Uint16()
external int a0;
@Uint16()
external int a1;
@Uint16()
external int a2;
@Uint16()
external int a3;
@Uint16()
external int a4;
@Uint16()
external int a5;
@Uint16()
external int a6;
@Uint16()
external int a7;
@Uint16()
external int a8;
@Uint16()
external int a9;
@Uint16()
external int a10;
@Uint16()
external int a11;
@Uint16()
external int a12;
@Uint16()
external int a13;
@Uint16()
external int a14;
@Uint16()
external int a15;
@Uint16()
external int a16;
@Uint16()
external int a17;
@Uint16()
external int a18;
@Uint16()
external int a19;
}
Uint16Struct makeUint16Struct(int length) {
assert(length == 20);
final typedData = makeUint16List(length);
final struct = Struct.create<Uint16Struct>(typedData);
return struct;
}
void testAddressOfUint16StructField() {
const length = 20;
final struct = makeUint16Struct(length);
final expectedResult = makeExpectedResultUint16(0, length);
final result = takeUint16PointerMany(
struct.a0.address,
struct.a1.address,
struct.a2.address,
struct.a3.address,
struct.a4.address,
struct.a5.address,
struct.a6.address,
struct.a7.address,
struct.a8.address,
struct.a9.address,
struct.a10.address,
struct.a11.address,
struct.a12.address,
struct.a13.address,
struct.a14.address,
struct.a15.address,
struct.a16.address,
struct.a17.address,
struct.a18.address,
struct.a19.address,
);
Expect.equals(expectedResult, result);
}
final class Uint32Struct extends Struct {
@Uint32()
external int a0;
@Uint32()
external int a1;
@Uint32()
external int a2;
@Uint32()
external int a3;
@Uint32()
external int a4;
@Uint32()
external int a5;
@Uint32()
external int a6;
@Uint32()
external int a7;
@Uint32()
external int a8;
@Uint32()
external int a9;
@Uint32()
external int a10;
@Uint32()
external int a11;
@Uint32()
external int a12;
@Uint32()
external int a13;
@Uint32()
external int a14;
@Uint32()
external int a15;
@Uint32()
external int a16;
@Uint32()
external int a17;
@Uint32()
external int a18;
@Uint32()
external int a19;
}
Uint32Struct makeUint32Struct(int length) {
assert(length == 20);
final typedData = makeUint32List(length);
final struct = Struct.create<Uint32Struct>(typedData);
return struct;
}
void testAddressOfUint32StructField() {
const length = 20;
final struct = makeUint32Struct(length);
final expectedResult = makeExpectedResultUint32(0, length);
final result = takeUint32PointerMany(
struct.a0.address,
struct.a1.address,
struct.a2.address,
struct.a3.address,
struct.a4.address,
struct.a5.address,
struct.a6.address,
struct.a7.address,
struct.a8.address,
struct.a9.address,
struct.a10.address,
struct.a11.address,
struct.a12.address,
struct.a13.address,
struct.a14.address,
struct.a15.address,
struct.a16.address,
struct.a17.address,
struct.a18.address,
struct.a19.address,
);
Expect.equals(expectedResult, result);
}
final class Uint64Struct extends Struct {
@Uint64()
external int a0;
@Uint64()
external int a1;
@Uint64()
external int a2;
@Uint64()
external int a3;
@Uint64()
external int a4;
@Uint64()
external int a5;
@Uint64()
external int a6;
@Uint64()
external int a7;
@Uint64()
external int a8;
@Uint64()
external int a9;
@Uint64()
external int a10;
@Uint64()
external int a11;
@Uint64()
external int a12;
@Uint64()
external int a13;
@Uint64()
external int a14;
@Uint64()
external int a15;
@Uint64()
external int a16;
@Uint64()
external int a17;
@Uint64()
external int a18;
@Uint64()
external int a19;
}
Uint64Struct makeUint64Struct(int length) {
assert(length == 20);
final typedData = makeUint64List(length);
final struct = Struct.create<Uint64Struct>(typedData);
return struct;
}
void testAddressOfUint64StructField() {
const length = 20;
final struct = makeUint64Struct(length);
final expectedResult = makeExpectedResultUint64(0, length);
final result = takeUint64PointerMany(
struct.a0.address,
struct.a1.address,
struct.a2.address,
struct.a3.address,
struct.a4.address,
struct.a5.address,
struct.a6.address,
struct.a7.address,
struct.a8.address,
struct.a9.address,
struct.a10.address,
struct.a11.address,
struct.a12.address,
struct.a13.address,
struct.a14.address,
struct.a15.address,
struct.a16.address,
struct.a17.address,
struct.a18.address,
struct.a19.address,
);
Expect.equals(expectedResult, result);
}
final class FloatStruct extends Struct {
@Float()
external double a0;
@Float()
external double a1;
@Float()
external double a2;
@Float()
external double a3;
@Float()
external double a4;
@Float()
external double a5;
@Float()
external double a6;
@Float()
external double a7;
@Float()
external double a8;
@Float()
external double a9;
@Float()
external double a10;
@Float()
external double a11;
@Float()
external double a12;
@Float()
external double a13;
@Float()
external double a14;
@Float()
external double a15;
@Float()
external double a16;
@Float()
external double a17;
@Float()
external double a18;
@Float()
external double a19;
}
FloatStruct makeFloatStruct(int length) {
assert(length == 20);
final typedData = makeFloat32List(length);
final struct = Struct.create<FloatStruct>(typedData);
return struct;
}
void testAddressOfFloatStructField() {
const length = 20;
final struct = makeFloatStruct(length);
final expectedResult = makeExpectedResultFloat(0, length);
final result = takeFloatPointerMany(
struct.a0.address,
struct.a1.address,
struct.a2.address,
struct.a3.address,
struct.a4.address,
struct.a5.address,
struct.a6.address,
struct.a7.address,
struct.a8.address,
struct.a9.address,
struct.a10.address,
struct.a11.address,
struct.a12.address,
struct.a13.address,
struct.a14.address,
struct.a15.address,
struct.a16.address,
struct.a17.address,
struct.a18.address,
struct.a19.address,
);
Expect.approxEquals(expectedResult, result);
}
final class DoubleStruct extends Struct {
@Double()
external double a0;
@Double()
external double a1;
@Double()
external double a2;
@Double()
external double a3;
@Double()
external double a4;
@Double()
external double a5;
@Double()
external double a6;
@Double()
external double a7;
@Double()
external double a8;
@Double()
external double a9;
@Double()
external double a10;
@Double()
external double a11;
@Double()
external double a12;
@Double()
external double a13;
@Double()
external double a14;
@Double()
external double a15;
@Double()
external double a16;
@Double()
external double a17;
@Double()
external double a18;
@Double()
external double a19;
}
DoubleStruct makeDoubleStruct(int length) {
assert(length == 20);
final typedData = makeFloat64List(length);
final struct = Struct.create<DoubleStruct>(typedData);
return struct;
}
void testAddressOfDoubleStructField() {
const length = 20;
final struct = makeDoubleStruct(length);
final expectedResult = makeExpectedResultDouble(0, length);
final result = takeDoublePointerMany(
struct.a0.address,
struct.a1.address,
struct.a2.address,
struct.a3.address,
struct.a4.address,
struct.a5.address,
struct.a6.address,
struct.a7.address,
struct.a8.address,
struct.a9.address,
struct.a10.address,
struct.a11.address,
struct.a12.address,
struct.a13.address,
struct.a14.address,
struct.a15.address,
struct.a16.address,
struct.a17.address,
struct.a18.address,
struct.a19.address,
);
Expect.approxEquals(expectedResult, result);
}
final class BoolStruct extends Struct {
@Bool()
external bool a0;
@Bool()
external bool a1;
@Bool()
external bool a2;
@Bool()
external bool a3;
@Bool()
external bool a4;
@Bool()
external bool a5;
@Bool()
external bool a6;
@Bool()
external bool a7;
@Bool()
external bool a8;
@Bool()
external bool a9;
@Bool()
external bool a10;
@Bool()
external bool a11;
@Bool()
external bool a12;
@Bool()
external bool a13;
@Bool()
external bool a14;
@Bool()
external bool a15;
@Bool()
external bool a16;
@Bool()
external bool a17;
@Bool()
external bool a18;
@Bool()
external bool a19;
}
BoolStruct makeBoolStruct(int length) {
assert(length == 20);
final typedData = makeBoolList(length);
final struct = Struct.create<BoolStruct>(typedData);
return struct;
}
void testAddressOfBoolStructField() {
const length = 20;
final struct = makeBoolStruct(length);
final expectedResult = makeExpectedResultBool(0, length);
final result = takeBoolPointerMany(
struct.a0.address,
struct.a1.address,
struct.a2.address,
struct.a3.address,
struct.a4.address,
struct.a5.address,
struct.a6.address,
struct.a7.address,
struct.a8.address,
struct.a9.address,
struct.a10.address,
struct.a11.address,
struct.a12.address,
struct.a13.address,
struct.a14.address,
struct.a15.address,
struct.a16.address,
struct.a17.address,
struct.a18.address,
struct.a19.address,
);
Expect.equals(expectedResult, result);
}
final class Struct2BytesInt extends Struct {
@Int16()
external int a0;
String toString() => "(${a0})";
}
@Native<
Int16 Function(
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
Pointer<Struct2BytesInt>,
)>(symbol: 'TakeStruct2BytesIntPointerMany', isLeaf: true)
external int takeStruct2BytesIntPointerMany(
Pointer<Struct2BytesInt> pointer0,
Pointer<Struct2BytesInt> pointer1,
Pointer<Struct2BytesInt> pointer2,
Pointer<Struct2BytesInt> pointer3,
Pointer<Struct2BytesInt> pointer4,
Pointer<Struct2BytesInt> pointer5,
Pointer<Struct2BytesInt> pointer6,
Pointer<Struct2BytesInt> pointer7,
Pointer<Struct2BytesInt> pointer8,
Pointer<Struct2BytesInt> pointer9,
Pointer<Struct2BytesInt> pointer10,
Pointer<Struct2BytesInt> pointer11,
Pointer<Struct2BytesInt> pointer12,
Pointer<Struct2BytesInt> pointer13,
Pointer<Struct2BytesInt> pointer14,
Pointer<Struct2BytesInt> pointer15,
Pointer<Struct2BytesInt> pointer16,
Pointer<Struct2BytesInt> pointer17,
Pointer<Struct2BytesInt> pointer18,
Pointer<Struct2BytesInt> pointer19,
);
void testAddressOfStructPointerMany() {
const length = 20;
final typedData = makeInt16List(length);
final struct0 = Struct.create<Struct2BytesInt>(typedData, 0);
final struct1 = Struct.create<Struct2BytesInt>(typedData, 1);
final struct2 = Struct.create<Struct2BytesInt>(typedData, 2);
final struct3 = Struct.create<Struct2BytesInt>(typedData, 3);
final struct4 = Struct.create<Struct2BytesInt>(typedData, 4);
final struct5 = Struct.create<Struct2BytesInt>(typedData, 5);
final struct6 = Struct.create<Struct2BytesInt>(typedData, 6);
final struct7 = Struct.create<Struct2BytesInt>(typedData, 7);
final struct8 = Struct.create<Struct2BytesInt>(typedData, 8);
final struct9 = Struct.create<Struct2BytesInt>(typedData, 9);
final struct10 = Struct.create<Struct2BytesInt>(typedData, 10);
final struct11 = Struct.create<Struct2BytesInt>(typedData, 11);
final struct12 = Struct.create<Struct2BytesInt>(typedData, 12);
final struct13 = Struct.create<Struct2BytesInt>(typedData, 13);
final struct14 = Struct.create<Struct2BytesInt>(typedData, 14);
final struct15 = Struct.create<Struct2BytesInt>(typedData, 15);
final struct16 = Struct.create<Struct2BytesInt>(typedData, 16);
final struct17 = Struct.create<Struct2BytesInt>(typedData, 17);
final struct18 = Struct.create<Struct2BytesInt>(typedData, 18);
final struct19 = Struct.create<Struct2BytesInt>(typedData, 19);
final expectedResult = makeExpectedResultInt16(0, length);
final result = takeStruct2BytesIntPointerMany(
struct0.address,
struct1.address,
struct2.address,
struct3.address,
struct4.address,
struct5.address,
struct6.address,
struct7.address,
struct8.address,
struct9.address,
struct10.address,
struct11.address,
struct12.address,
struct13.address,
struct14.address,
struct15.address,
struct16.address,
struct17.address,
struct18.address,
struct19.address,
);
Expect.equals(expectedResult, result);
}
final class Union2BytesInt extends Union {
@Int16()
external int a0;
String toString() => "(${a0})";
}
@Native<
Int16 Function(
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
Pointer<Union2BytesInt>,
)>(symbol: 'TakeUnion2BytesIntPointerMany', isLeaf: true)
external int takeUnion2BytesIntPointerMany(
Pointer<Union2BytesInt> pointer0,
Pointer<Union2BytesInt> pointer1,
Pointer<Union2BytesInt> pointer2,
Pointer<Union2BytesInt> pointer3,
Pointer<Union2BytesInt> pointer4,
Pointer<Union2BytesInt> pointer5,
Pointer<Union2BytesInt> pointer6,
Pointer<Union2BytesInt> pointer7,
Pointer<Union2BytesInt> pointer8,
Pointer<Union2BytesInt> pointer9,
Pointer<Union2BytesInt> pointer10,
Pointer<Union2BytesInt> pointer11,
Pointer<Union2BytesInt> pointer12,
Pointer<Union2BytesInt> pointer13,
Pointer<Union2BytesInt> pointer14,
Pointer<Union2BytesInt> pointer15,
Pointer<Union2BytesInt> pointer16,
Pointer<Union2BytesInt> pointer17,
Pointer<Union2BytesInt> pointer18,
Pointer<Union2BytesInt> pointer19,
);
void testAddressOfUnionPointerMany() {
const length = 20;
final typedData = makeInt16List(length);
final struct0 = Union.create<Union2BytesInt>(typedData, 0);
final struct1 = Union.create<Union2BytesInt>(typedData, 1);
final struct2 = Union.create<Union2BytesInt>(typedData, 2);
final struct3 = Union.create<Union2BytesInt>(typedData, 3);
final struct4 = Union.create<Union2BytesInt>(typedData, 4);
final struct5 = Union.create<Union2BytesInt>(typedData, 5);
final struct6 = Union.create<Union2BytesInt>(typedData, 6);
final struct7 = Union.create<Union2BytesInt>(typedData, 7);
final struct8 = Union.create<Union2BytesInt>(typedData, 8);
final struct9 = Union.create<Union2BytesInt>(typedData, 9);
final struct10 = Union.create<Union2BytesInt>(typedData, 10);
final struct11 = Union.create<Union2BytesInt>(typedData, 11);
final struct12 = Union.create<Union2BytesInt>(typedData, 12);
final struct13 = Union.create<Union2BytesInt>(typedData, 13);
final struct14 = Union.create<Union2BytesInt>(typedData, 14);
final struct15 = Union.create<Union2BytesInt>(typedData, 15);
final struct16 = Union.create<Union2BytesInt>(typedData, 16);
final struct17 = Union.create<Union2BytesInt>(typedData, 17);
final struct18 = Union.create<Union2BytesInt>(typedData, 18);
final struct19 = Union.create<Union2BytesInt>(typedData, 19);
final expectedResult = makeExpectedResultInt16(0, length);
final result = takeUnion2BytesIntPointerMany(
struct0.address,
struct1.address,
struct2.address,
struct3.address,
struct4.address,
struct5.address,
struct6.address,
struct7.address,
struct8.address,
struct9.address,
struct10.address,
struct11.address,
struct12.address,
struct13.address,
struct14.address,
struct15.address,
struct16.address,
struct17.address,
struct18.address,
struct19.address,
);
Expect.equals(expectedResult, result);
}