From 045b9c171500a6c4830df6756f608dcfe1653a26 Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Thu, 27 Jan 2022 13:09:01 +0000 Subject: [PATCH] Reland "[vm/ffi] Add common C types" We're adding these types to `dart:ffi` rather than `package:ffi` so that they can be used with `FfiNative`s. Adds `NativeType`s for the following C types: * unsigned char * signed char * short * unsigned short * int * unsigned int * long * unsigned long * long long * unsigned long long * uintptr_t * size_t * wchar_t Because the C standard only defines minimum sizes for many of these types, future platforms might diverge from the typical size even if all platforms currently agree on a size. To avoid having to reification later, we define all types as AbiSpecificIntegers rather than typedefs, even if all current target platforms agree on the size. Closes: https://github.com/dart-lang/sdk/issues/36140 TEST=tests/ffi/c_types_test.dart Original patch in patchset 1. * Removes `Char` for now until package:win32 has rolled to 2.3.8 in Flutter. https://pub.dev/packages/win32/versions/2.3.8/changelog https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8824468064587445729/+/u/Android_Views_Integration_Tests/stdout * Adds `c_type.dart` in `ffi_source.gni` which should fix `IntPtr` missing when analyzing `path_provider_linux`. (However, I was unable to reproduce the issue locally.) https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8824468064571399025/+/u/run_test.dart_for_flutter_plugins_shard_and_subshard_analyze/test_stdout `/tmp/flutter_plugins.KZMNMC/packages/path_provider/path_provider_linux$ ~/flt/engine/src/out/host_debug/dart-sdk/bin/dart analyze --fatal-infos` Change-Id: I89130cccba285fc9c483bb53f5710a302f2b104f Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm64c-try,vm-ffi-android-debug-arm-try,vm-canary-linux-debug-try,vm-fuchsia-release-x64-try,vm-kernel-gcc-linux-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-mac-debug-x64-try,vm-kernel-mac-release-arm64-try,vm-kernel-nnbd-win-release-ia32-try,vm-kernel-nnbd-win-release-x64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-win-release-x64-try,flutter-analyze-try,flutter-engine-linux-try,flutter-frontend-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/229156 Reviewed-by: Martin Kustermann Commit-Queue: Daco Harkes --- benchmarks/FfiMemory/dart/FfiMemory.dart | 30 -- benchmarks/FfiMemory/dart2/FfiMemory.dart | 30 -- .../general/ffi_sample.dart.weak.expect | 2 +- .../ffi_sample.dart.weak.modular.expect | 2 +- .../ffi_sample.dart.weak.transformed.expect | 2 +- ..._outline_change_50_ffi.yaml.world.1.expect | 30 +- ..._outline_change_50_ffi.yaml.world.2.expect | 30 +- .../nnbd/ffi_sample.dart.strong.expect | 2 +- .../ffi_sample.dart.strong.transformed.expect | 2 +- .../nnbd/ffi_sample.dart.weak.expect | 2 +- .../nnbd/ffi_sample.dart.weak.modular.expect | 2 +- .../ffi_sample.dart.weak.transformed.expect | 2 +- ...ffi_struct_inline_array.dart.strong.expect | 2 +- ...nline_array.dart.strong.transformed.expect | 2 +- .../ffi_struct_inline_array.dart.weak.expect | 2 +- ...ruct_inline_array.dart.weak.modular.expect | 2 +- ..._inline_array.dart.weak.transformed.expect | 2 +- ...array_multi_dimensional.dart.strong.expect | 2 +- ...dimensional.dart.strong.transformed.expect | 2 +- ...e_array_multi_dimensional.dart.weak.expect | 2 +- ...multi_dimensional.dart.weak.modular.expect | 2 +- ...i_dimensional.dart.weak.transformed.expect | 2 +- runtime/bin/ffi_test/ffi_test_functions.cc | 43 +- .../vm/lib/ffi_native_type_patch.dart | 5 - sdk/lib/ffi/abi_specific.dart | 8 +- sdk/lib/ffi/c_type.dart | 503 ++++++++++++++++++ sdk/lib/ffi/ffi.dart | 1 + sdk/lib/ffi/ffi_sources.gni | 1 + sdk/lib/ffi/native_type.dart | 30 -- tests/ffi/abi_specific_int_test.dart | 2 - tests/ffi/abi_specific_ints.dart | 145 ----- tests/ffi/c_types_test.dart | 149 ++++-- ...backs_structs_by_value_generated_test.dart | 3 - ..._structs_by_value_generated_compounds.dart | 3 - ..._structs_by_value_generated_leaf_test.dart | 3 - ...ction_structs_by_value_generated_test.dart | 3 - .../structs_by_value_tests_generator.dart | 6 - tests/ffi_2/abi_specific_int_test.dart | 2 - tests/ffi_2/abi_specific_ints.dart | 132 ----- tests/ffi_2/c_types_test.dart | 148 +++++- ...backs_structs_by_value_generated_test.dart | 3 - ..._structs_by_value_generated_compounds.dart | 3 - ..._structs_by_value_generated_leaf_test.dart | 3 - ...ction_structs_by_value_generated_test.dart | 3 - 44 files changed, 861 insertions(+), 494 deletions(-) create mode 100644 sdk/lib/ffi/c_type.dart delete mode 100644 tests/ffi/abi_specific_ints.dart delete mode 100644 tests/ffi_2/abi_specific_ints.dart diff --git a/benchmarks/FfiMemory/dart/FfiMemory.dart b/benchmarks/FfiMemory/dart/FfiMemory.dart index 881eff2d3d7..6178f24fd34 100644 --- a/benchmarks/FfiMemory/dart/FfiMemory.dart +++ b/benchmarks/FfiMemory/dart/FfiMemory.dart @@ -15,36 +15,6 @@ import 'dart:typed_data'; import 'package:ffi/ffi.dart'; import 'package:benchmark_harness/benchmark_harness.dart'; -/// Represents a native unsigned pointer-sized integer in C. -/// -/// [UintPtr] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint32(), - Abi.androidArm64: Uint64(), - Abi.androidIA32: Uint32(), - Abi.androidX64: Uint64(), - Abi.fuchsiaArm64: Uint64(), - Abi.fuchsiaX64: Uint64(), - Abi.iosArm: Uint32(), - Abi.iosArm64: Uint64(), - Abi.iosX64: Uint64(), - Abi.linuxArm: Uint32(), - Abi.linuxArm64: Uint64(), - Abi.linuxIA32: Uint32(), - Abi.linuxX64: Uint64(), - Abi.linuxRiscv32: Uint32(), - Abi.linuxRiscv64: Uint64(), - Abi.macosArm64: Uint64(), - Abi.macosX64: Uint64(), - Abi.windowsArm64: Uint64(), - Abi.windowsIA32: Uint32(), - Abi.windowsX64: Uint64(), -}) -class UintPtr extends AbiSpecificInteger { - const UintPtr(); -} - // // Pointer store. // diff --git a/benchmarks/FfiMemory/dart2/FfiMemory.dart b/benchmarks/FfiMemory/dart2/FfiMemory.dart index 86f7e1f90ab..b3a6cf9d099 100644 --- a/benchmarks/FfiMemory/dart2/FfiMemory.dart +++ b/benchmarks/FfiMemory/dart2/FfiMemory.dart @@ -17,36 +17,6 @@ import 'dart:typed_data'; import 'package:ffi/ffi.dart'; import 'package:benchmark_harness/benchmark_harness.dart'; -/// Represents a native unsigned pointer-sized integer in C. -/// -/// [UintPtr] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint32(), - Abi.androidArm64: Uint64(), - Abi.androidIA32: Uint32(), - Abi.androidX64: Uint64(), - Abi.fuchsiaArm64: Uint64(), - Abi.fuchsiaX64: Uint64(), - Abi.iosArm: Uint32(), - Abi.iosArm64: Uint64(), - Abi.iosX64: Uint64(), - Abi.linuxArm: Uint32(), - Abi.linuxArm64: Uint64(), - Abi.linuxIA32: Uint32(), - Abi.linuxX64: Uint64(), - Abi.linuxRiscv32: Uint32(), - Abi.linuxRiscv64: Uint64(), - Abi.macosArm64: Uint64(), - Abi.macosX64: Uint64(), - Abi.windowsArm64: Uint64(), - Abi.windowsIA32: Uint32(), - Abi.windowsX64: Uint64(), -}) -class UintPtr extends AbiSpecificInteger { - const UintPtr(); -} - // // Pointer store. // diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.weak.expect b/pkg/front_end/testcases/general/ffi_sample.dart.weak.expect index 8c513a44aaf..d92782a30a5 100644 --- a/pkg/front_end/testcases/general/ffi_sample.dart.weak.expect +++ b/pkg/front_end/testcases/general/ffi_sample.dart.weak.expect @@ -40,7 +40,7 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_sample.dart: -- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:144:9) +- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9) - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9) - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.weak.modular.expect b/pkg/front_end/testcases/general/ffi_sample.dart.weak.modular.expect index 8c513a44aaf..d92782a30a5 100644 --- a/pkg/front_end/testcases/general/ffi_sample.dart.weak.modular.expect +++ b/pkg/front_end/testcases/general/ffi_sample.dart.weak.modular.expect @@ -40,7 +40,7 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_sample.dart: -- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:144:9) +- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9) - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9) - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect b/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect index ae497d5a5fa..0765c4c028c 100644 --- a/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect +++ b/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect @@ -74,7 +74,7 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_sample.dart: -- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:144:9) +- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9) - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9) - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect index 6c37a20df30..cf7f4015200 100644 --- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect +++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect @@ -63,6 +63,7 @@ additionalExports = (ffi::nullptr, ffi::FloatArray, ffi::FloatPointer, ffi::Handle, + ffi::Int, ffi::Int16, ffi::Int16Array, ffi::Int16Pointer, @@ -76,6 +77,8 @@ additionalExports = (ffi::nullptr, ffi::Int8Array, ffi::Int8Pointer, ffi::IntPtr, + ffi::Long, + ffi::LongLong, ffi::NativeApi, ffi::NativeFunction, ffi::NativeFunctionPointer, @@ -86,6 +89,9 @@ additionalExports = (ffi::nullptr, ffi::Pointer, ffi::PointerArray, ffi::PointerPointer, + ffi::Short, + ffi::SignedChar, + ffi::Size, ffi::Struct, ffi::StructArray, ffi::StructPointer, @@ -101,11 +107,18 @@ additionalExports = (ffi::nullptr, ffi::Uint8, ffi::Uint8Array, ffi::Uint8Pointer, + ffi::UintPtr, ffi::Union, ffi::UnionArray, ffi::UnionPointer, + ffi::UnsignedChar, + ffi::UnsignedInt, + ffi::UnsignedLong, + ffi::UnsignedLongLong, + ffi::UnsignedShort, ffi::Unsized, - ffi::Void) + ffi::Void, + ffi::WChar) export "org-dartlang-test:///lib3.dart"; @@ -139,6 +152,7 @@ additionalExports = (ffi::nullptr, ffi::FloatArray, ffi::FloatPointer, ffi::Handle, + ffi::Int, ffi::Int16, ffi::Int16Array, ffi::Int16Pointer, @@ -152,6 +166,8 @@ additionalExports = (ffi::nullptr, ffi::Int8Array, ffi::Int8Pointer, ffi::IntPtr, + ffi::Long, + ffi::LongLong, ffi::NativeApi, ffi::NativeFunction, ffi::NativeFunctionPointer, @@ -162,6 +178,9 @@ additionalExports = (ffi::nullptr, ffi::Pointer, ffi::PointerArray, ffi::PointerPointer, + ffi::Short, + ffi::SignedChar, + ffi::Size, ffi::Struct, ffi::StructArray, ffi::StructPointer, @@ -177,11 +196,18 @@ additionalExports = (ffi::nullptr, ffi::Uint8, ffi::Uint8Array, ffi::Uint8Pointer, + ffi::UintPtr, ffi::Union, ffi::UnionArray, ffi::UnionPointer, + ffi::UnsignedChar, + ffi::UnsignedInt, + ffi::UnsignedLong, + ffi::UnsignedLongLong, + ffi::UnsignedShort, ffi::Unsized, - ffi::Void) + ffi::Void, + ffi::WChar) export "dart:ffi"; diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect index e7c047a37ce..cb6c619438c 100644 --- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect +++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect @@ -63,6 +63,7 @@ additionalExports = (ffi::nullptr, ffi::FloatArray, ffi::FloatPointer, ffi::Handle, + ffi::Int, ffi::Int16, ffi::Int16Array, ffi::Int16Pointer, @@ -76,6 +77,8 @@ additionalExports = (ffi::nullptr, ffi::Int8Array, ffi::Int8Pointer, ffi::IntPtr, + ffi::Long, + ffi::LongLong, ffi::NativeApi, ffi::NativeFunction, ffi::NativeFunctionPointer, @@ -86,6 +89,9 @@ additionalExports = (ffi::nullptr, ffi::Pointer, ffi::PointerArray, ffi::PointerPointer, + ffi::Short, + ffi::SignedChar, + ffi::Size, ffi::Struct, ffi::StructArray, ffi::StructPointer, @@ -101,11 +107,18 @@ additionalExports = (ffi::nullptr, ffi::Uint8, ffi::Uint8Array, ffi::Uint8Pointer, + ffi::UintPtr, ffi::Union, ffi::UnionArray, ffi::UnionPointer, + ffi::UnsignedChar, + ffi::UnsignedInt, + ffi::UnsignedLong, + ffi::UnsignedLongLong, + ffi::UnsignedShort, ffi::Unsized, - ffi::Void) + ffi::Void, + ffi::WChar) export "org-dartlang-test:///lib3.dart"; @@ -139,6 +152,7 @@ additionalExports = (ffi::nullptr, ffi::FloatArray, ffi::FloatPointer, ffi::Handle, + ffi::Int, ffi::Int16, ffi::Int16Array, ffi::Int16Pointer, @@ -152,6 +166,8 @@ additionalExports = (ffi::nullptr, ffi::Int8Array, ffi::Int8Pointer, ffi::IntPtr, + ffi::Long, + ffi::LongLong, ffi::NativeApi, ffi::NativeFunction, ffi::NativeFunctionPointer, @@ -162,6 +178,9 @@ additionalExports = (ffi::nullptr, ffi::Pointer, ffi::PointerArray, ffi::PointerPointer, + ffi::Short, + ffi::SignedChar, + ffi::Size, ffi::Struct, ffi::StructArray, ffi::StructPointer, @@ -177,11 +196,18 @@ additionalExports = (ffi::nullptr, ffi::Uint8, ffi::Uint8Array, ffi::Uint8Pointer, + ffi::UintPtr, ffi::Union, ffi::UnionArray, ffi::UnionPointer, + ffi::UnsignedChar, + ffi::UnsignedInt, + ffi::UnsignedLong, + ffi::UnsignedLongLong, + ffi::UnsignedShort, ffi::Unsized, - ffi::Void) + ffi::Void, + ffi::WChar) export "dart:ffi"; diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.expect index 35dda106cf7..b190b3a9c29 100644 --- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.expect +++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.expect @@ -34,7 +34,7 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_sample.dart: -- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:144:9) +- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9) - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9) - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect index 02dfd2a915f..fccf63463e3 100644 --- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.strong.transformed.expect @@ -65,7 +65,7 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_sample.dart: -- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:144:9) +- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9) - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9) - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.expect index 35dda106cf7..b190b3a9c29 100644 --- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.expect +++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.expect @@ -34,7 +34,7 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_sample.dart: -- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:144:9) +- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9) - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9) - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.modular.expect index 35dda106cf7..b190b3a9c29 100644 --- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.modular.expect +++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.modular.expect @@ -34,7 +34,7 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_sample.dart: -- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:144:9) +- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9) - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9) - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect index 02dfd2a915f..fccf63463e3 100644 --- a/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect +++ b/pkg/front_end/testcases/nnbd/ffi_sample.dart.weak.transformed.expect @@ -65,7 +65,7 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_sample.dart: -- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:144:9) +- Double. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:114:9) - _NativeDouble. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:34:9) - NativeType. (from org-dartlang-sdk:///sdk/lib/ffi/native_type.dart:12:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect index 0db513dff49..4d771b3fe31 100644 --- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect +++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.expect @@ -25,5 +25,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_struct_inline_array.dart: -- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9) +- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect index 525cfd922bd..f3903c0958c 100644 --- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.strong.transformed.expect @@ -52,5 +52,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_struct_inline_array.dart: -- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9) +- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect index e6c0f958734..e179ab5d07d 100644 --- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect +++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.expect @@ -25,5 +25,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_struct_inline_array.dart: -- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9) +- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect index e6c0f958734..e179ab5d07d 100644 --- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect +++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.modular.expect @@ -25,5 +25,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_struct_inline_array.dart: -- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9) +- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect index b38ad344607..24cfa9601b1 100644 --- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect +++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array.dart.weak.transformed.expect @@ -52,5 +52,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_struct_inline_array.dart: -- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9) +- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect index 0e058b10c06..dd7fa306a70 100644 --- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect +++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.expect @@ -33,5 +33,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart: -- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9) +- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect index ecf21c080b3..a16945b05a6 100644 --- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.strong.transformed.expect @@ -84,5 +84,5 @@ Extra constant evaluation: evaluated: 110, effectively constant: 2 Constructor coverage from constants: org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart: -- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9) +- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect index 5e4b756023e..be09548d6b9 100644 --- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect +++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.expect @@ -33,5 +33,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart: -- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9) +- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect index 5e4b756023e..be09548d6b9 100644 --- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect +++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.modular.expect @@ -33,5 +33,5 @@ constants { Constructor coverage from constants: org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart: -- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9) +- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect index a9ba39c9ed8..a83a86b7e37 100644 --- a/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect +++ b/pkg/front_end/testcases/nnbd/ffi_struct_inline_array_multi_dimensional.dart.weak.transformed.expect @@ -84,5 +84,5 @@ Extra constant evaluation: evaluated: 110, effectively constant: 2 Constructor coverage from constants: org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart: -- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:138:9) +- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:139:9) - Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9) diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc index dd5e41fdb7a..1545f8ee8bc 100644 --- a/runtime/bin/ffi_test/ffi_test_functions.cc +++ b/runtime/bin/ffi_test/ffi_test_functions.cc @@ -1138,27 +1138,36 @@ DART_EXPORT uint64_t SizeOfStruct3BytesPackedInt() { typedef intptr_t ssize_t; #endif -#define DEFINE_SIZE_OF(type_modifier, type) \ - DART_EXPORT uint64_t FfiSizeOf_##type_modifier##_##type() { \ - return sizeof(type_modifier type); \ +#define DEFINE_SIZE_OF_AND_SIGN_OF(type_modifier, type, type2) \ + DART_EXPORT uint64_t FfiSizeOf_##type_modifier##_##type##_##type2() { \ + return sizeof(type_modifier type type2); \ + } \ + \ + DART_EXPORT uint64_t FfiSignOf_##type_modifier##_##type##_##type2() { \ + return std::numeric_limits::is_signed; \ } -#define SIZES(F) \ - F(, intptr_t) \ - F(, uintptr_t) \ - F(, int) \ - F(unsigned, int) \ - F(, long) /* NOLINT */ \ - F(unsigned, long) /* NOLINT */ \ - F(, wchar_t) \ - F(, size_t) \ - F(, ssize_t) \ - F(, off_t) +#define TYPES(F) \ + F(, char, ) /* NOLINT */ \ + F(signed, char, ) /* NOLINT */ \ + F(unsigned, char, ) /* NOLINT */ \ + F(, short, ) /* NOLINT */ \ + F(unsigned, short, ) /* NOLINT */ \ + F(, int, ) /* NOLINT */ \ + F(unsigned, int, ) /* NOLINT */ \ + F(, long, ) /* NOLINT */ \ + F(unsigned, long, ) /* NOLINT */ \ + F(, long, long) /* NOLINT */ \ + F(unsigned, long, long) /* NOLINT */ \ + F(, intptr_t, ) /* NOLINT */ \ + F(, uintptr_t, ) /* NOLINT */ \ + F(, size_t, ) /* NOLINT */ \ + F(, wchar_t, ) /* NOLINT */ -SIZES(DEFINE_SIZE_OF) +TYPES(DEFINE_SIZE_OF_AND_SIGN_OF) -#undef DEFINE_SIZE_OF -#undef SIZES +#undef DEFINE_SIZE_OF_AND_SIGN_OF +#undef TYPES DART_EXPORT int64_t WCharMinValue() { return WCHAR_MIN; diff --git a/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart b/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart index 92e23c1cf18..ca47a83cba4 100644 --- a/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart +++ b/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart @@ -55,11 +55,6 @@ class Uint32 extends _NativeInteger {} @pragma("vm:entry-point") class Uint64 extends _NativeInteger {} -// TODO(http://dartbug.com/47938): Implement as AbiSpecificInteger. -@patch -@pragma("vm:entry-point") -class IntPtr extends _NativeInteger {} - @patch @pragma("vm:entry-point") class Float extends _NativeDouble {} diff --git a/sdk/lib/ffi/abi_specific.dart b/sdk/lib/ffi/abi_specific.dart index d84f74eea2c..a41308c44be 100644 --- a/sdk/lib/ffi/abi_specific.dart +++ b/sdk/lib/ffi/abi_specific.dart @@ -13,10 +13,12 @@ part of dart.ffi; /// For example: /// /// ``` -/// /// Represents a `uintptr_t` in C. +/// /// The C `uintptr_t` type. /// /// -/// /// [UintPtr] is not constructible in the Dart code and serves purely as -/// /// marker in type signatures. +/// /// The [UintPtr] type is a native type, and should not be constructed in +/// /// Dart code. +/// /// It occurs only in native type signatures and as annotation on [Struct] +/// /// and [Union] fields. /// @AbiSpecificIntegerMapping({ /// Abi.androidArm: Uint32(), /// Abi.androidArm64: Uint64(), diff --git a/sdk/lib/ffi/c_type.dart b/sdk/lib/ffi/c_type.dart new file mode 100644 index 00000000000..b1bc7643c19 --- /dev/null +++ b/sdk/lib/ffi/c_type.dart @@ -0,0 +1,503 @@ +// Copyright (c) 2022, 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 library defines [NativeType]s for common C types. +/// +/// Many C types only define a minimal size in the C standard, but they are +/// consistent per [Abi]. Therefore we use [AbiSpecificInteger]s to define +/// these C types in this library. +part of dart.ffi; + +/// The C `signed char` type. +/// +/// Typically a signed 8-bit integer. +/// For a guaranteed 8-bit integer, use [Int8] with the C `int8_t` type. +/// For an `unsigned char`, use [UnsignedChar]. +/// +/// The [SignedChar] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int8(), + Abi.androidArm64: Int8(), + Abi.androidIA32: Int8(), + Abi.androidX64: Int8(), + Abi.fuchsiaArm64: Int8(), + Abi.fuchsiaX64: Int8(), + Abi.iosArm: Int8(), + Abi.iosArm64: Int8(), + Abi.iosX64: Int8(), + Abi.linuxArm: Int8(), + Abi.linuxArm64: Int8(), + Abi.linuxIA32: Int8(), + Abi.linuxX64: Int8(), + Abi.linuxRiscv32: Int8(), + Abi.linuxRiscv64: Int8(), + Abi.macosArm64: Int8(), + Abi.macosX64: Int8(), + Abi.windowsArm64: Int8(), + Abi.windowsIA32: Int8(), + Abi.windowsX64: Int8(), +}) +class SignedChar extends AbiSpecificInteger { + const SignedChar(); +} + +/// The C `unsigned char` type. +/// +/// Typically an unsigned 8-bit integer. +/// For a guaranteed 8-bit integer, use [Uint8] with the C `uint8_t` type. +/// For a `signed char`, use [SignedChar]. +/// +/// The [UnsignedChar] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint8(), + Abi.androidArm64: Uint8(), + Abi.androidIA32: Uint8(), + Abi.androidX64: Uint8(), + Abi.fuchsiaArm64: Uint8(), + Abi.fuchsiaX64: Uint8(), + Abi.iosArm: Uint8(), + Abi.iosArm64: Uint8(), + Abi.iosX64: Uint8(), + Abi.linuxArm: Uint8(), + Abi.linuxArm64: Uint8(), + Abi.linuxIA32: Uint8(), + Abi.linuxX64: Uint8(), + Abi.linuxRiscv32: Uint8(), + Abi.linuxRiscv64: Uint8(), + Abi.macosArm64: Uint8(), + Abi.macosX64: Uint8(), + Abi.windowsArm64: Uint8(), + Abi.windowsIA32: Uint8(), + Abi.windowsX64: Uint8(), +}) +class UnsignedChar extends AbiSpecificInteger { + const UnsignedChar(); +} + +/// The C `short` type. +/// +/// Typically a signed 16-bit integer. +/// For a guaranteed 16-bit integer, use [Int16] with the C `int16_t` type. +/// For an `unsigned short`, use [UnsignedShort]. +/// +/// The [Short] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int16(), + Abi.androidArm64: Int16(), + Abi.androidIA32: Int16(), + Abi.androidX64: Int16(), + Abi.fuchsiaArm64: Int16(), + Abi.fuchsiaX64: Int16(), + Abi.iosArm: Int16(), + Abi.iosArm64: Int16(), + Abi.iosX64: Int16(), + Abi.linuxArm: Int16(), + Abi.linuxArm64: Int16(), + Abi.linuxIA32: Int16(), + Abi.linuxX64: Int16(), + Abi.linuxRiscv32: Int16(), + Abi.linuxRiscv64: Int16(), + Abi.macosArm64: Int16(), + Abi.macosX64: Int16(), + Abi.windowsArm64: Int16(), + Abi.windowsIA32: Int16(), + Abi.windowsX64: Int16(), +}) +class Short extends AbiSpecificInteger { + const Short(); +} + +/// The C `unsigned short` type. +/// +/// Typically an unsigned 16-bit integer. +/// For a guaranteed 16-bit integer, use [Uint16] with the C `uint16_t` type. +/// For a signed `short`, use [Short]. +/// +/// The [UnsignedShort] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint16(), + Abi.androidArm64: Uint16(), + Abi.androidIA32: Uint16(), + Abi.androidX64: Uint16(), + Abi.fuchsiaArm64: Uint16(), + Abi.fuchsiaX64: Uint16(), + Abi.iosArm: Uint16(), + Abi.iosArm64: Uint16(), + Abi.iosX64: Uint16(), + Abi.linuxArm: Uint16(), + Abi.linuxArm64: Uint16(), + Abi.linuxIA32: Uint16(), + Abi.linuxX64: Uint16(), + Abi.linuxRiscv32: Uint16(), + Abi.linuxRiscv64: Uint16(), + Abi.macosArm64: Uint16(), + Abi.macosX64: Uint16(), + Abi.windowsArm64: Uint16(), + Abi.windowsIA32: Uint16(), + Abi.windowsX64: Uint16(), +}) +class UnsignedShort extends AbiSpecificInteger { + const UnsignedShort(); +} + +/// The C `int` type. +/// +/// Typically a signed 32-bit integer. +/// For a guaranteed 32-bit integer, use [Int32] with the C `int32_t` type. +/// For an `unsigned int`, use [UnsignedInt]. +/// +/// The [Int] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int32(), + Abi.androidArm64: Int32(), + Abi.androidIA32: Int32(), + Abi.androidX64: Int32(), + Abi.fuchsiaArm64: Int32(), + Abi.fuchsiaX64: Int32(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int32(), + Abi.iosX64: Int32(), + Abi.linuxArm: Int32(), + Abi.linuxArm64: Int32(), + Abi.linuxIA32: Int32(), + Abi.linuxX64: Int32(), + Abi.linuxRiscv32: Int32(), + Abi.linuxRiscv64: Int32(), + Abi.macosArm64: Int32(), + Abi.macosX64: Int32(), + Abi.windowsArm64: Int32(), + Abi.windowsIA32: Int32(), + Abi.windowsX64: Int32(), +}) +class Int extends AbiSpecificInteger { + const Int(); +} + +/// The C `unsigned int` type. +/// +/// Typically an unsigned 32-bit integer. +/// For a guaranteed 32-bit integer, use [Uint32] with the C `uint32_t` type. +/// For a signed `int`, use [Int]. +/// +/// The [UnsignedInt] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint32(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint32(), + Abi.fuchsiaArm64: Uint32(), + Abi.fuchsiaX64: Uint32(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint32(), + Abi.iosX64: Uint32(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint32(), + Abi.linuxIA32: Uint32(), + Abi.linuxX64: Uint32(), + Abi.linuxRiscv32: Uint32(), + Abi.linuxRiscv64: Uint32(), + Abi.macosArm64: Uint32(), + Abi.macosX64: Uint32(), + Abi.windowsArm64: Uint32(), + Abi.windowsIA32: Uint32(), + Abi.windowsX64: Uint32(), +}) +class UnsignedInt extends AbiSpecificInteger { + const UnsignedInt(); +} + +/// The C `long int`, aka. `long`, type. +/// +/// Typically a signed 32- or 64-bit integer. +/// For a guaranteed 32-bit integer, use [Int32] with the C `int32_t` type. +/// For a guaranteed 64-bit integer, use [Int64] with the C `int64_t` type. +/// For an `unsigned long`, use [UnsignedLong]. +/// +/// The [Long] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int32(), + Abi.androidArm64: Int64(), + Abi.androidIA32: Int32(), + Abi.androidX64: Int64(), + Abi.fuchsiaArm64: Int64(), + Abi.fuchsiaX64: Int64(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int64(), + Abi.iosX64: Int64(), + Abi.linuxArm: Int32(), + Abi.linuxArm64: Int64(), + Abi.linuxIA32: Int32(), + Abi.linuxX64: Int64(), + Abi.linuxRiscv32: Int32(), + Abi.linuxRiscv64: Int64(), + Abi.macosArm64: Int64(), + Abi.macosX64: Int64(), + Abi.windowsArm64: Int32(), + Abi.windowsIA32: Int32(), + Abi.windowsX64: Int32(), +}) +class Long extends AbiSpecificInteger { + const Long(); +} + +/// The C `unsigned long int`, aka. `unsigned long`, type. +/// +/// Typically an unsigned 32- or 64-bit integer. +/// For a guaranteed 32-bit integer, use [Uint32] with the C `uint32_t` type. +/// For a guaranteed 64-bit integer, use [Uint64] with the C `uint64_t` type. +/// For a signed `long`, use [Long]. +/// +/// The [UnsignedLong] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint64(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint64(), + Abi.linuxIA32: Uint32(), + Abi.linuxX64: Uint64(), + Abi.linuxRiscv32: Uint32(), + Abi.linuxRiscv64: Uint64(), + Abi.macosArm64: Uint64(), + Abi.macosX64: Uint64(), + Abi.windowsArm64: Uint32(), + Abi.windowsIA32: Uint32(), + Abi.windowsX64: Uint32(), +}) +class UnsignedLong extends AbiSpecificInteger { + const UnsignedLong(); +} + +/// The C `long long` type. +/// +/// Typically a signed 64-bit integer. +/// For a guaranteed 64-bit integer, use [Int64] with the C `int64_t` type. +/// For an `unsigned long long`, use [UnsignedLongLong]. +/// +/// The [LongLong] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int64(), + Abi.androidArm64: Int64(), + Abi.androidIA32: Int64(), + Abi.androidX64: Int64(), + Abi.fuchsiaArm64: Int64(), + Abi.fuchsiaX64: Int64(), + Abi.iosArm: Int64(), + Abi.iosArm64: Int64(), + Abi.iosX64: Int64(), + Abi.linuxArm: Int64(), + Abi.linuxArm64: Int64(), + Abi.linuxIA32: Int64(), + Abi.linuxX64: Int64(), + Abi.linuxRiscv32: Int64(), + Abi.linuxRiscv64: Int64(), + Abi.macosArm64: Int64(), + Abi.macosX64: Int64(), + Abi.windowsArm64: Int64(), + Abi.windowsIA32: Int64(), + Abi.windowsX64: Int64(), +}) +class LongLong extends AbiSpecificInteger { + const LongLong(); +} + +/// The C `unsigned long long` type. +/// +/// Typically an unsigned 64-bit integer. +/// For a guaranteed 64-bit integer, use [Uint64] with the C `uint64_t` type. +/// For a signed `long long`, use [LongLong]. +/// +/// The [UnsignedLongLong] type is a native type, and should not be constructed +/// in Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint64(), + Abi.androidArm64: Uint64(), + Abi.androidIA32: Uint64(), + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), + Abi.iosArm: Uint64(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), + Abi.linuxArm: Uint64(), + Abi.linuxArm64: Uint64(), + Abi.linuxIA32: Uint64(), + Abi.linuxX64: Uint64(), + Abi.linuxRiscv32: Uint64(), + Abi.linuxRiscv64: Uint64(), + Abi.macosArm64: Uint64(), + Abi.macosX64: Uint64(), + Abi.windowsArm64: Uint64(), + Abi.windowsIA32: Uint64(), + Abi.windowsX64: Uint64(), +}) +class UnsignedLongLong extends AbiSpecificInteger { + const UnsignedLongLong(); +} + +/// The C `intptr_t` type. +/// +/// The [IntPtr] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Int32(), + Abi.androidArm64: Int64(), + Abi.androidIA32: Int32(), + Abi.androidX64: Int64(), + Abi.fuchsiaArm64: Int64(), + Abi.fuchsiaX64: Int64(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int64(), + Abi.iosX64: Int64(), + Abi.linuxArm: Int32(), + Abi.linuxArm64: Int64(), + Abi.linuxIA32: Int32(), + Abi.linuxX64: Int64(), + Abi.linuxRiscv32: Int32(), + Abi.linuxRiscv64: Int64(), + Abi.macosArm64: Int64(), + Abi.macosX64: Int64(), + Abi.windowsArm64: Int64(), + Abi.windowsIA32: Int32(), + Abi.windowsX64: Int64(), +}) +class IntPtr extends AbiSpecificInteger { + const IntPtr(); +} + +/// The C `uintptr_t` type. +/// +/// The [UintPtr] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint64(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint64(), + Abi.linuxIA32: Uint32(), + Abi.linuxX64: Uint64(), + Abi.linuxRiscv32: Uint32(), + Abi.linuxRiscv64: Uint64(), + Abi.macosArm64: Uint64(), + Abi.macosX64: Uint64(), + Abi.windowsArm64: Uint64(), + Abi.windowsIA32: Uint32(), + Abi.windowsX64: Uint64(), +}) +class UintPtr extends AbiSpecificInteger { + const UintPtr(); +} + +/// The C `size_t` type. +/// +/// The [Size] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint64(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint64(), + Abi.fuchsiaArm64: Uint64(), + Abi.fuchsiaX64: Uint64(), + Abi.iosArm: Uint32(), + Abi.iosArm64: Uint64(), + Abi.iosX64: Uint64(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint64(), + Abi.linuxIA32: Uint32(), + Abi.linuxX64: Uint64(), + Abi.linuxRiscv32: Uint32(), + Abi.linuxRiscv64: Uint64(), + Abi.macosArm64: Uint64(), + Abi.macosX64: Uint64(), + Abi.windowsArm64: Uint64(), + Abi.windowsIA32: Uint32(), + Abi.windowsX64: Uint64(), +}) +class Size extends AbiSpecificInteger { + const Size(); +} + +/// The C `wchar_t` type. +/// +/// The signedness of `wchar_t` is undefined in C. Here, it is exposed as the +/// defaults on the tested [Abi]s. +/// +/// The [WChar] type is a native type, and should not be constructed in +/// Dart code. +/// It occurs only in native type signatures and as annotation on [Struct] and +/// [Union] fields. +@AbiSpecificIntegerMapping({ + Abi.androidArm: Uint32(), + Abi.androidArm64: Uint32(), + Abi.androidIA32: Uint32(), + Abi.androidX64: Uint32(), + Abi.fuchsiaArm64: Uint32(), + Abi.fuchsiaX64: Int32(), + Abi.iosArm: Int32(), + Abi.iosArm64: Int32(), + Abi.iosX64: Int32(), + Abi.linuxArm: Uint32(), + Abi.linuxArm64: Uint32(), + Abi.linuxIA32: Int32(), + Abi.linuxX64: Int32(), + Abi.linuxRiscv32: Uint32(), + Abi.linuxRiscv64: Uint32(), + Abi.macosArm64: Int32(), + Abi.macosX64: Int32(), + Abi.windowsArm64: Uint16(), + Abi.windowsIA32: Uint16(), + Abi.windowsX64: Uint16(), +}) +class WChar extends AbiSpecificInteger { + const WChar(); +} diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart index b1d53a68616..9a7afe26464 100644 --- a/sdk/lib/ffi/ffi.dart +++ b/sdk/lib/ffi/ffi.dart @@ -20,6 +20,7 @@ part 'abi_specific.dart'; part 'native_type.dart'; part 'allocation.dart'; part 'annotations.dart'; +part 'c_type.dart'; part 'dynamic_library.dart'; part 'struct.dart'; part 'union.dart'; diff --git a/sdk/lib/ffi/ffi_sources.gni b/sdk/lib/ffi/ffi_sources.gni index b725fe02eab..419736958b8 100644 --- a/sdk/lib/ffi/ffi_sources.gni +++ b/sdk/lib/ffi/ffi_sources.gni @@ -10,6 +10,7 @@ ffi_sdk_sources = [ "abi_specific.dart", "allocation.dart", "annotations.dart", + "c_type.dart", "dynamic_library.dart", "native_type.dart", "struct.dart", diff --git a/sdk/lib/ffi/native_type.dart b/sdk/lib/ffi/native_type.dart index dbbea7c85fc..55a9f6d5246 100644 --- a/sdk/lib/ffi/native_type.dart +++ b/sdk/lib/ffi/native_type.dart @@ -98,36 +98,6 @@ class Uint64 extends _NativeInteger { const Uint64(); } -/// Represents a native pointer-sized integer in C. -/// -/// [IntPtr] is not constructible in the Dart code and serves purely as marker -/// in type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Int32(), - Abi.androidArm64: Int64(), - Abi.androidIA32: Int32(), - Abi.androidX64: Int64(), - Abi.fuchsiaArm64: Int64(), - Abi.fuchsiaX64: Int64(), - Abi.iosArm: Int32(), - Abi.iosArm64: Int64(), - Abi.iosX64: Int64(), - Abi.linuxArm: Int32(), - Abi.linuxArm64: Int64(), - Abi.linuxIA32: Int32(), - Abi.linuxX64: Int64(), - Abi.linuxRiscv32: Int32(), - Abi.linuxRiscv64: Int64(), - Abi.macosArm64: Int64(), - Abi.macosX64: Int64(), - Abi.windowsArm64: Int64(), - Abi.windowsIA32: Int32(), - Abi.windowsX64: Int64(), -}) -class IntPtr extends AbiSpecificInteger { - const IntPtr(); -} - /// Represents a native 32 bit float in C. /// /// [Float] is not constructible in the Dart code and serves purely as marker diff --git a/tests/ffi/abi_specific_int_test.dart b/tests/ffi/abi_specific_int_test.dart index 266655cce6d..cea45b146d8 100644 --- a/tests/ffi/abi_specific_int_test.dart +++ b/tests/ffi/abi_specific_int_test.dart @@ -8,8 +8,6 @@ import 'dart:io'; import 'package:expect/expect.dart'; import 'package:ffi/ffi.dart'; -import 'abi_specific_ints.dart'; - void main() { testSizeOf(); testStoreLoad(); diff --git a/tests/ffi/abi_specific_ints.dart b/tests/ffi/abi_specific_ints.dart deleted file mode 100644 index c0cd3f05026..00000000000 --- a/tests/ffi/abi_specific_ints.dart +++ /dev/null @@ -1,145 +0,0 @@ -// 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. - -import 'dart:ffi'; - -// TODO(dacoharkes): These should move to `package:ffi`. - -// `int` in C. -typedef Int = Int32; - -// `unsigned int` in C. -typedef UnsignedInt = Uint32; - -// `size_t` in C. -typedef Size = UintPtr; - -// `ssize_t` in C. -typedef SSize = IntPtr; - -// `off_t` in C. -typedef Off = Long; - -/// Represents a native unsigned pointer-sized integer in C. -/// -/// [UintPtr] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint32(), - Abi.androidArm64: Uint64(), - Abi.androidIA32: Uint32(), - Abi.androidX64: Uint64(), - Abi.fuchsiaArm64: Uint64(), - Abi.fuchsiaX64: Uint64(), - Abi.iosArm: Uint32(), - Abi.iosArm64: Uint64(), - Abi.iosX64: Uint64(), - Abi.linuxArm: Uint32(), - Abi.linuxArm64: Uint64(), - Abi.linuxIA32: Uint32(), - Abi.linuxX64: Uint64(), - Abi.linuxRiscv32: Uint32(), - Abi.linuxRiscv64: Uint64(), - Abi.macosArm64: Uint64(), - Abi.macosX64: Uint64(), - Abi.windowsArm64: Uint64(), - Abi.windowsIA32: Uint32(), - Abi.windowsX64: Uint64(), -}) -class UintPtr extends AbiSpecificInteger { - const UintPtr(); -} - -/// `long` in C. -/// -/// [Long] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Int32(), - Abi.androidArm64: Int64(), - Abi.androidIA32: Int32(), - Abi.androidX64: Int64(), - Abi.fuchsiaArm64: Int64(), - Abi.fuchsiaX64: Int64(), - Abi.iosArm: Int32(), - Abi.iosArm64: Int64(), - Abi.iosX64: Int64(), - Abi.linuxArm: Int32(), - Abi.linuxArm64: Int64(), - Abi.linuxIA32: Int32(), - Abi.linuxX64: Int64(), - Abi.linuxRiscv32: Int32(), - Abi.linuxRiscv64: Int64(), - Abi.macosArm64: Int64(), - Abi.macosX64: Int64(), - Abi.windowsArm64: Int32(), - Abi.windowsIA32: Int32(), - Abi.windowsX64: Int32(), -}) -class Long extends AbiSpecificInteger { - const Long(); -} - -/// `unsigned long` in C. -/// -/// [UnsignedLong] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint32(), - Abi.androidArm64: Uint64(), - Abi.androidIA32: Uint32(), - Abi.androidX64: Uint64(), - Abi.fuchsiaArm64: Uint64(), - Abi.fuchsiaX64: Uint64(), - Abi.iosArm: Uint32(), - Abi.iosArm64: Uint64(), - Abi.iosX64: Uint64(), - Abi.linuxArm: Uint32(), - Abi.linuxArm64: Uint64(), - Abi.linuxIA32: Uint32(), - Abi.linuxX64: Uint64(), - Abi.linuxRiscv32: Uint32(), - Abi.linuxRiscv64: Uint64(), - Abi.macosArm64: Uint64(), - Abi.macosX64: Uint64(), - Abi.windowsArm64: Uint32(), - Abi.windowsIA32: Uint32(), - Abi.windowsX64: Uint32(), -}) -class UnsignedLong extends AbiSpecificInteger { - const UnsignedLong(); -} - -/// `wchar_t` in C. -/// -/// The signedness of `wchar_t` is undefined in C. Here, it is exposed as an -/// unsigned integer. -/// -/// [WChar] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint32(), - Abi.androidArm64: Uint32(), - Abi.androidIA32: Uint32(), - Abi.androidX64: Uint32(), - Abi.fuchsiaArm64: Uint32(), - Abi.fuchsiaX64: Uint32(), - Abi.iosArm: Uint32(), - Abi.iosArm64: Uint32(), - Abi.iosX64: Uint32(), - Abi.linuxArm: Uint32(), - Abi.linuxArm64: Uint32(), - Abi.linuxIA32: Uint32(), - Abi.linuxX64: Uint32(), - Abi.linuxRiscv32: Uint32(), - Abi.linuxRiscv64: Uint32(), - Abi.macosArm64: Uint32(), - Abi.macosX64: Uint32(), - Abi.windowsArm64: Uint16(), - Abi.windowsIA32: Uint16(), - Abi.windowsX64: Uint16(), -}) -class WChar extends AbiSpecificInteger { - const WChar(); -} diff --git a/tests/ffi/c_types_test.dart b/tests/ffi/c_types_test.dart index d423c2c0390..c132f3b564f 100644 --- a/tests/ffi/c_types_test.dart +++ b/tests/ffi/c_types_test.dart @@ -7,11 +7,11 @@ // SharedObjects=ffi_test_functions import 'dart:ffi'; - -import "package:expect/expect.dart"; import 'dart:io' show Platform; -import 'abi_specific_ints.dart'; +import 'package:expect/expect.dart'; +import 'package:ffi/ffi.dart'; + import 'ffi_test_helpers.dart'; void main() { @@ -20,62 +20,156 @@ void main() { testIntAssumptions(); testSizeTAssumptions(); testLongAssumptions(); - testOffTAssumptions(); testWCharTAssumptions(); } class CType { final int ffiSize; + final int Function(Pointer)? ffiLoad; final String modifier; final String type; + final String type2; - CType(this.ffiSize, this.type, [this.modifier = ""]); + CType(this.ffiSize, this.type, + {this.type2 = '', this.modifier = '', this.ffiLoad}); - String get cRepresentation => "$modifier $type".trim(); + String get cRepresentation => '$modifier $type $type2'.trim(); - String get _getSizeName => "FfiSizeOf_$modifier\_$type"; + String get _getSizeName => 'FfiSizeOf_$modifier\_$type\_$type2'; + + String get _getSignName => 'FfiSignOf_$modifier\_$type\_$type2'; int Function() get sizeFunction => ffiTestFunctions .lookupFunction(_getSizeName); + int Function() get signFunction => ffiTestFunctions + .lookupFunction(_getSignName); + int get size => sizeFunction(); + bool get isSigned => signFunction() != 0; + + bool? get ffiIsSigned { + final ffiLoad_ = ffiLoad; + if (ffiLoad_ == null) { + return null; + } + assert(size < 8); + return using((Arena arena) { + final p = arena()..value = -1; + return ffiLoad_(p) < 0; + }); + } + String toString() => cRepresentation; } -final intptr_t = CType(sizeOf(), "intptr_t"); -final uintptr_t = CType(sizeOf(), "uintptr_t"); -final int_ = CType(sizeOf(), "int"); -final uint = CType(sizeOf(), "int", "unsigned"); -final long = CType(sizeOf(), "long"); -final ulong = CType(sizeOf(), "long", "unsigned"); -final wchar_t = CType(sizeOf(), "wchar_t"); -final size_t = CType(sizeOf(), "size_t"); -final ssize_t = CType(sizeOf(), "ssize_t"); -final off_t = CType(sizeOf(), "off_t"); +final uchar = CType( + sizeOf(), + 'char', + modifier: 'unsigned', + ffiLoad: (Pointer p) => p.cast().value, +); +final schar = CType( + sizeOf(), + 'char', + modifier: 'signed', + ffiLoad: (Pointer p) => p.cast().value, +); +final short = CType( + sizeOf(), + 'short', + ffiLoad: (Pointer p) => p.cast().value, +); +final ushort = CType( + sizeOf(), + 'short', + modifier: 'unsigned', + ffiLoad: (Pointer p) => p.cast().value, +); +final int_ = CType( + sizeOf(), + 'int', + ffiLoad: (Pointer p) => p.cast().value, +); +final uint = CType( + sizeOf(), + 'int', + modifier: 'unsigned', + ffiLoad: (Pointer p) => p.cast().value, +); +final long = CType( + sizeOf(), + 'long', +); +final ulong = CType( + sizeOf(), + 'long', + modifier: 'unsigned', +); +final longlong = CType( + sizeOf(), + 'long', + type2: 'long', +); +final ulonglong = CType( + sizeOf(), + 'long', + type2: 'long', + modifier: 'unsigned', +); +final intptr_t = CType( + sizeOf(), + 'intptr_t', +); +final uintptr_t = CType( + sizeOf(), + 'uintptr_t', +); +final size_t = CType( + sizeOf(), + 'size_t', +); +final wchar_t = CType( + sizeOf(), + 'wchar_t', + ffiLoad: (Pointer p) => p.cast().value, +); final cTypes = [ - intptr_t, - uintptr_t, + uchar, + schar, + short, + ushort, int_, uint, long, ulong, - wchar_t, + longlong, + ulonglong, + intptr_t, + uintptr_t, size_t, - ssize_t, - off_t + wchar_t, ]; void printSizes() { cTypes.forEach((element) { - print("${element.cRepresentation.padRight(20)}: ${element.size}"); + final cName = element.cRepresentation.padRight(20); + final size = element.size; + final signed = element.isSigned ? 'signed' : 'unsigned'; + print('$cName: $size $signed'); }); } void testSizes() { cTypes.forEach((element) { + print(element); Expect.equals(element.size, element.ffiSize); + final ffiIsSigned = element.ffiIsSigned; + if (ffiIsSigned != null) { + Expect.equals(element.isSigned, ffiIsSigned); + } }); } @@ -86,7 +180,6 @@ void testIntAssumptions() { void testSizeTAssumptions() { Expect.equals(intptr_t.size, size_t.size); - Expect.equals(intptr_t.size, ssize_t.size); } void testLongAssumptions() { @@ -99,13 +192,9 @@ void testLongAssumptions() { } } -void testOffTAssumptions() { - Expect.equals(long.size, off_t.size); -} - void testWCharTAssumptions() { - final bool isSigned = wCharMinValue() != 0; - print("wchar_t isSigned $isSigned"); + final bool isSigned = wchar_t.isSigned; + print('wchar_t isSigned $isSigned'); if (Platform.isWindows) { Expect.equals(2, wchar_t.size); if (isSigned) { diff --git a/tests/ffi/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart index 2276d2f01e6..2fbccd18f63 100644 --- a/tests/ffi/function_callbacks_structs_by_value_generated_test.dart +++ b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart @@ -16,9 +16,6 @@ import 'dart:ffi'; import "package:expect/expect.dart"; import "package:ffi/ffi.dart"; -// Reuse the AbiSpecificInts. -import 'abi_specific_ints.dart'; - import 'callback_tests_utils.dart'; import 'dylib_utils.dart'; diff --git a/tests/ffi/function_structs_by_value_generated_compounds.dart b/tests/ffi/function_structs_by_value_generated_compounds.dart index 439e9a349b7..666ef20e1d9 100644 --- a/tests/ffi/function_structs_by_value_generated_compounds.dart +++ b/tests/ffi/function_structs_by_value_generated_compounds.dart @@ -7,9 +7,6 @@ import 'dart:ffi'; -// Reuse the AbiSpecificInts. -import 'abi_specific_ints.dart'; - class Struct1ByteBool extends Struct { @Bool() external bool a0; diff --git a/tests/ffi/function_structs_by_value_generated_leaf_test.dart b/tests/ffi/function_structs_by_value_generated_leaf_test.dart index 283faad9d6a..770441739da 100644 --- a/tests/ffi/function_structs_by_value_generated_leaf_test.dart +++ b/tests/ffi/function_structs_by_value_generated_leaf_test.dart @@ -16,9 +16,6 @@ import 'dart:ffi'; import "package:expect/expect.dart"; import "package:ffi/ffi.dart"; -// Reuse the AbiSpecificInts. -import 'abi_specific_ints.dart'; - import 'dylib_utils.dart'; // Reuse the compound classes. diff --git a/tests/ffi/function_structs_by_value_generated_test.dart b/tests/ffi/function_structs_by_value_generated_test.dart index 1f4c5d3df7a..897472cd2d7 100644 --- a/tests/ffi/function_structs_by_value_generated_test.dart +++ b/tests/ffi/function_structs_by_value_generated_test.dart @@ -16,9 +16,6 @@ import 'dart:ffi'; import "package:expect/expect.dart"; import "package:ffi/ffi.dart"; -// Reuse the AbiSpecificInts. -import 'abi_specific_ints.dart'; - import 'dylib_utils.dart'; // Reuse the compound classes. diff --git a/tests/ffi/generator/structs_by_value_tests_generator.dart b/tests/ffi/generator/structs_by_value_tests_generator.dart index 4c260b9d6b8..3a18095d500 100644 --- a/tests/ffi/generator/structs_by_value_tests_generator.dart +++ b/tests/ffi/generator/structs_by_value_tests_generator.dart @@ -922,8 +922,6 @@ $dartVersion import 'dart:ffi'; -// Reuse the AbiSpecificInts. -import 'abi_specific_ints.dart'; """; } @@ -967,8 +965,6 @@ import 'dart:ffi'; import "package:expect/expect.dart"; import "package:ffi/ffi.dart"; -// Reuse the AbiSpecificInts. -import 'abi_specific_ints.dart'; import 'dylib_utils.dart'; @@ -1029,8 +1025,6 @@ import 'dart:ffi'; import "package:expect/expect.dart"; import "package:ffi/ffi.dart"; -// Reuse the AbiSpecificInts. -import 'abi_specific_ints.dart'; import 'callback_tests_utils.dart'; diff --git a/tests/ffi_2/abi_specific_int_test.dart b/tests/ffi_2/abi_specific_int_test.dart index 152c159034c..57daa3f3cf0 100644 --- a/tests/ffi_2/abi_specific_int_test.dart +++ b/tests/ffi_2/abi_specific_int_test.dart @@ -10,8 +10,6 @@ import 'dart:io'; import 'package:expect/expect.dart'; import 'package:ffi/ffi.dart'; -import 'abi_specific_ints.dart'; - void main() { testSizeOf(); testStoreLoad(); diff --git a/tests/ffi_2/abi_specific_ints.dart b/tests/ffi_2/abi_specific_ints.dart deleted file mode 100644 index c1d830251a2..00000000000 --- a/tests/ffi_2/abi_specific_ints.dart +++ /dev/null @@ -1,132 +0,0 @@ -// 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. - -// @dart = 2.9 - -import 'dart:ffi'; - -// TODO(dacoharkes): These should move to `package:ffi`. - -/// Represents a native unsigned pointer-sized integer in C. -/// -/// [UintPtr] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint32(), - Abi.androidArm64: Uint64(), - Abi.androidIA32: Uint32(), - Abi.androidX64: Uint64(), - Abi.fuchsiaArm64: Uint64(), - Abi.fuchsiaX64: Uint64(), - Abi.iosArm: Uint32(), - Abi.iosArm64: Uint64(), - Abi.iosX64: Uint64(), - Abi.linuxArm: Uint32(), - Abi.linuxArm64: Uint64(), - Abi.linuxIA32: Uint32(), - Abi.linuxX64: Uint64(), - Abi.linuxRiscv32: Uint32(), - Abi.linuxRiscv64: Uint64(), - Abi.macosArm64: Uint64(), - Abi.macosX64: Uint64(), - Abi.windowsArm64: Uint64(), - Abi.windowsIA32: Uint32(), - Abi.windowsX64: Uint64(), -}) -class UintPtr extends AbiSpecificInteger { - const UintPtr(); -} - -/// `long` in C. -/// -/// [Long] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Int32(), - Abi.androidArm64: Int64(), - Abi.androidIA32: Int32(), - Abi.androidX64: Int64(), - Abi.fuchsiaArm64: Int64(), - Abi.fuchsiaX64: Int64(), - Abi.iosArm: Int32(), - Abi.iosArm64: Int64(), - Abi.iosX64: Int64(), - Abi.linuxArm: Int32(), - Abi.linuxArm64: Int64(), - Abi.linuxIA32: Int32(), - Abi.linuxX64: Int64(), - Abi.linuxRiscv32: Int32(), - Abi.linuxRiscv64: Int64(), - Abi.macosArm64: Int64(), - Abi.macosX64: Int64(), - Abi.windowsArm64: Int32(), - Abi.windowsIA32: Int32(), - Abi.windowsX64: Int32(), -}) -class Long extends AbiSpecificInteger { - const Long(); -} - -/// `unsigned long` in C. -/// -/// [UnsignedLong] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint32(), - Abi.androidArm64: Uint64(), - Abi.androidIA32: Uint32(), - Abi.androidX64: Uint64(), - Abi.fuchsiaArm64: Uint64(), - Abi.fuchsiaX64: Uint64(), - Abi.iosArm: Uint32(), - Abi.iosArm64: Uint64(), - Abi.iosX64: Uint64(), - Abi.linuxArm: Uint32(), - Abi.linuxArm64: Uint64(), - Abi.linuxIA32: Uint32(), - Abi.linuxX64: Uint64(), - Abi.linuxRiscv32: Uint32(), - Abi.linuxRiscv64: Uint64(), - Abi.macosArm64: Uint64(), - Abi.macosX64: Uint64(), - Abi.windowsArm64: Uint32(), - Abi.windowsIA32: Uint32(), - Abi.windowsX64: Uint32(), -}) -class UnsignedLong extends AbiSpecificInteger { - const UnsignedLong(); -} - -/// `wchar_t` in C. -/// -/// The signedness of `wchar_t` is undefined in C. Here, it is exposed as an -/// unsigned integer. -/// -/// [WChar] is not constructible in the Dart code and serves purely as marker in -/// type signatures. -@AbiSpecificIntegerMapping({ - Abi.androidArm: Uint32(), - Abi.androidArm64: Uint32(), - Abi.androidIA32: Uint32(), - Abi.androidX64: Uint32(), - Abi.fuchsiaArm64: Uint32(), - Abi.fuchsiaX64: Uint32(), - Abi.iosArm: Uint32(), - Abi.iosArm64: Uint32(), - Abi.iosX64: Uint32(), - Abi.linuxArm: Uint32(), - Abi.linuxArm64: Uint32(), - Abi.linuxIA32: Uint32(), - Abi.linuxX64: Uint32(), - Abi.linuxRiscv32: Uint32(), - Abi.linuxRiscv64: Uint32(), - Abi.macosArm64: Uint32(), - Abi.macosX64: Uint32(), - Abi.windowsArm64: Uint16(), - Abi.windowsIA32: Uint16(), - Abi.windowsX64: Uint16(), -}) -class WChar extends AbiSpecificInteger { - const WChar(); -} diff --git a/tests/ffi_2/c_types_test.dart b/tests/ffi_2/c_types_test.dart index fa762bdf7ba..032853ce43b 100644 --- a/tests/ffi_2/c_types_test.dart +++ b/tests/ffi_2/c_types_test.dart @@ -9,65 +9,181 @@ // @dart = 2.9 import 'dart:ffi'; - -import "package:expect/expect.dart"; import 'dart:io' show Platform; -import 'abi_specific_ints.dart'; +import 'package:expect/expect.dart'; +import 'package:ffi/ffi.dart'; + import 'ffi_test_helpers.dart'; void main() { printSizes(); testSizes(); + testIntAssumptions(); + testSizeTAssumptions(); testLongAssumptions(); testWCharTAssumptions(); } class CType { final int ffiSize; + final int Function(Pointer) ffiLoad; final String modifier; final String type; + final String type2; - CType(this.ffiSize, this.type, [this.modifier = ""]); + CType(this.ffiSize, this.type, + {this.type2 = '', this.modifier = '', this.ffiLoad}); - String get cRepresentation => "$modifier $type".trim(); + String get cRepresentation => '$modifier $type $type2'.trim(); - String get _getSizeName => "FfiSizeOf_$modifier\_$type"; + String get _getSizeName => 'FfiSizeOf_$modifier\_$type\_$type2'; + + String get _getSignName => 'FfiSignOf_$modifier\_$type\_$type2'; int Function() get sizeFunction => ffiTestFunctions .lookupFunction(_getSizeName); + int Function() get signFunction => ffiTestFunctions + .lookupFunction(_getSignName); + int get size => sizeFunction(); + bool get isSigned => signFunction() != 0; + + bool get ffiIsSigned { + final ffiLoad_ = ffiLoad; + if (ffiLoad_ == null) { + return null; + } + assert(size < 8); + return using((Arena arena) { + final p = arena()..value = -1; + return ffiLoad_(p) < 0; + }); + } + String toString() => cRepresentation; } -final intptr_t = CType(sizeOf(), "intptr_t"); -final uintptr_t = CType(sizeOf(), "uintptr_t"); -final long = CType(sizeOf(), "long"); -final ulong = CType(sizeOf(), "long", "unsigned"); -final wchar_t = CType(sizeOf(), "wchar_t"); +final uchar = CType( + sizeOf(), + 'char', + modifier: 'unsigned', + ffiLoad: (Pointer p) => p.cast().value, +); +final schar = CType( + sizeOf(), + 'char', + modifier: 'signed', + ffiLoad: (Pointer p) => p.cast().value, +); +final short = CType( + sizeOf(), + 'short', + ffiLoad: (Pointer p) => p.cast().value, +); +final ushort = CType( + sizeOf(), + 'short', + modifier: 'unsigned', + ffiLoad: (Pointer p) => p.cast().value, +); +final int_ = CType( + sizeOf(), + 'int', + ffiLoad: (Pointer p) => p.cast().value, +); +final uint = CType( + sizeOf(), + 'int', + modifier: 'unsigned', + ffiLoad: (Pointer p) => p.cast().value, +); +final long = CType( + sizeOf(), + 'long', +); +final ulong = CType( + sizeOf(), + 'long', + modifier: 'unsigned', +); +final longlong = CType( + sizeOf(), + 'long', + type2: 'long', +); +final ulonglong = CType( + sizeOf(), + 'long', + type2: 'long', + modifier: 'unsigned', +); +final intptr_t = CType( + sizeOf(), + 'intptr_t', +); +final uintptr_t = CType( + sizeOf(), + 'uintptr_t', +); +final size_t = CType( + sizeOf(), + 'size_t', +); +final wchar_t = CType( + sizeOf(), + 'wchar_t', + ffiLoad: (Pointer p) => p.cast().value, +); final cTypes = [ - intptr_t, - uintptr_t, + uchar, + schar, + short, + ushort, + int_, + uint, long, ulong, + longlong, + ulonglong, + intptr_t, + uintptr_t, + size_t, wchar_t, ]; void printSizes() { cTypes.forEach((element) { - print("${element.cRepresentation.padRight(20)}: ${element.size}"); + final cName = element.cRepresentation.padRight(20); + final size = element.size; + final signed = element.isSigned ? 'signed' : 'unsigned'; + print('$cName: $size $signed'); }); } void testSizes() { cTypes.forEach((element) { + print(element); Expect.equals(element.size, element.ffiSize); + final ffiIsSigned = element.ffiIsSigned; + if (ffiIsSigned != null) { + Expect.equals(element.isSigned, ffiIsSigned); + } }); } +void testIntAssumptions() { + Expect.equals(4, int_.size); + Expect.equals(4, uint.size); +} + +void testSizeTAssumptions() { + Expect.equals(intptr_t.size, size_t.size); +} + void testLongAssumptions() { if (Platform.isWindows) { Expect.equals(4, long.size); @@ -79,8 +195,8 @@ void testLongAssumptions() { } void testWCharTAssumptions() { - final bool isSigned = wCharMinValue() != 0; - print("wchar_t isSigned $isSigned"); + final bool isSigned = wchar_t.isSigned; + print('wchar_t isSigned $isSigned'); if (Platform.isWindows) { Expect.equals(2, wchar_t.size); if (isSigned) { diff --git a/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart index f4100fbf115..b890cbc1c5b 100644 --- a/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart +++ b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart @@ -18,9 +18,6 @@ import 'dart:ffi'; import "package:expect/expect.dart"; import "package:ffi/ffi.dart"; -// Reuse the AbiSpecificInts. -import 'abi_specific_ints.dart'; - import 'callback_tests_utils.dart'; import 'dylib_utils.dart'; diff --git a/tests/ffi_2/function_structs_by_value_generated_compounds.dart b/tests/ffi_2/function_structs_by_value_generated_compounds.dart index 69081770c04..cd3fdf1800d 100644 --- a/tests/ffi_2/function_structs_by_value_generated_compounds.dart +++ b/tests/ffi_2/function_structs_by_value_generated_compounds.dart @@ -9,9 +9,6 @@ import 'dart:ffi'; -// Reuse the AbiSpecificInts. -import 'abi_specific_ints.dart'; - class Struct1ByteBool extends Struct { @Bool() bool a0; diff --git a/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart b/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart index 7c642963cbc..8c010567d92 100644 --- a/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart +++ b/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart @@ -18,9 +18,6 @@ import 'dart:ffi'; import "package:expect/expect.dart"; import "package:ffi/ffi.dart"; -// Reuse the AbiSpecificInts. -import 'abi_specific_ints.dart'; - import 'dylib_utils.dart'; // Reuse the compound classes. diff --git a/tests/ffi_2/function_structs_by_value_generated_test.dart b/tests/ffi_2/function_structs_by_value_generated_test.dart index ef24ad2ce7a..6329287ff76 100644 --- a/tests/ffi_2/function_structs_by_value_generated_test.dart +++ b/tests/ffi_2/function_structs_by_value_generated_test.dart @@ -18,9 +18,6 @@ import 'dart:ffi'; import "package:expect/expect.dart"; import "package:ffi/ffi.dart"; -// Reuse the AbiSpecificInts. -import 'abi_specific_ints.dart'; - import 'dylib_utils.dart'; // Reuse the compound classes.