dart-sdk/tests/ffi_2/function_callbacks_test.dart
Alexander Markov a7f7c0c5ac [vm] Support serialization of FFI callbacks in IL serialization
TEST=tests/ffi/function_callbacks_test.dart
TEST=Manual run of vm-kernel-precomp-linux-debug-x64-try with --test_il_serialization enabled.

Issue: https://github.com/dart-lang/sdk/issues/43299
Change-Id: Ia57021d9091e8a80de3645cb4723ebdbb5a3d33d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/256371
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2022-08-26 17:37:21 +00:00

236 lines
6.6 KiB
Dart

// Copyright (c) 2019, 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
// Dart test program for testing dart:ffi function pointers with callbacks.
//
// VMOptions=--stacktrace-every=100
// VMOptions=--write-protect-code --no-dual-map-code
// VMOptions=--write-protect-code --no-dual-map-code --stacktrace-every=100
// VMOptions=--use-slow-path
// VMOptions=--use-slow-path --stacktrace-every=100
// VMOptions=--use-slow-path --write-protect-code --no-dual-map-code
// VMOptions=--use-slow-path --write-protect-code --no-dual-map-code --stacktrace-every=100
// VMOptions=--dwarf_stack_traces --no-retain_function_objects --no-retain_code_objects
// VMOptions=--test_il_serialization
// SharedObjects=ffi_test_functions
import 'dart:ffi';
import 'callback_tests_utils.dart';
typedef SimpleAdditionType = Int32 Function(Int32, Int32);
int simpleAddition(int x, int y) {
print("simpleAddition($x, $y)");
return x + y;
}
class Foo {
static int simpleAddition(int x, int y) {
print("Foo.simpleAddition($x, $y)");
return x + y;
}
}
typedef IntComputationType = Int64 Function(Int8, Int16, Int32, Int64);
int intComputation(int a, int b, int c, int d) {
print("intComputation($a, $b, $c, $d)");
return d - c + b - a;
}
typedef UintComputationType = Uint64 Function(Uint8, Uint16, Uint32, Uint64);
int uintComputation(int a, int b, int c, int d) {
print("uintComputation($a, $b, $c, $d)");
return d - c + b - a;
}
typedef SimpleMultiplyType = Double Function(Double);
double simpleMultiply(double x) {
print("simpleMultiply($x)");
return x * 1.337;
}
typedef SimpleMultiplyFloatType = Float Function(Float);
double simpleMultiplyFloat(double x) {
print("simpleMultiplyFloat($x)");
return x * 1.337;
}
typedef ManyIntsType = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr, IntPtr,
IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
int manyInts(
int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
print("manyInts($a, $b, $c, $d, $e, $f, $g, $h, $i, $j");
return a + b + c + d + e + f + g + h + i + j;
}
typedef ManyDoublesType = Double Function(Double, Double, Double, Double,
Double, Double, Double, Double, Double, Double);
double manyDoubles(double a, double b, double c, double d, double e, double f,
double g, double h, double i, double j) {
print("manyDoubles($a, $b, $c, $d, $e, $f, $g, $h, $i, $j");
return a + b + c + d + e + f + g + h + i + j;
}
typedef ManyArgsType = Double Function(
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double,
IntPtr,
Float,
IntPtr,
Double);
double manyArgs(
int _1,
double _2,
int _3,
double _4,
int _5,
double _6,
int _7,
double _8,
int _9,
double _10,
int _11,
double _12,
int _13,
double _14,
int _15,
double _16,
int _17,
double _18,
int _19,
double _20) {
print("manyArgs( $_1, $_2, $_3, $_4, $_5, $_6, $_7, $_8, $_9, $_10," +
"$_11, $_12, $_13, $_14, $_15, $_16, $_17, $_18, $_19, $_20)");
return _1 +
_2 +
_3 +
_4 +
_5 +
_6 +
_7 +
_8 +
_9 +
_10 +
_11 +
_12 +
_13 +
_14 +
_15 +
_16 +
_17 +
_18 +
_19 +
_20;
}
typedef StoreType = Pointer<Int64> Function(Pointer<Int64>);
Pointer<Int64> store(Pointer<Int64> ptr) => ptr.elementAt(1)..value = 1337;
typedef NullPointersType = Pointer<Int64> Function(Pointer<Int64>);
Pointer<Int64> nullPointers(Pointer<Int64> ptr) => ptr.elementAt(1);
typedef ReturnVoid = Void Function();
void returnVoid() {}
void throwException() {
throw "Exception.";
}
typedef ThrowExceptionInt = IntPtr Function();
int throwExceptionInt() {
throw "Exception.";
}
typedef ThrowExceptionDouble = Double Function();
double throwExceptionDouble() {
throw "Exception.";
}
typedef ThrowExceptionPointer = Pointer<Void> Function();
Pointer<Void> throwExceptionPointer() {
throw "Exception.";
}
typedef TakeMaxUint8x10Type = IntPtr Function(
Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8, Uint8);
int takeMaxUint8x10(
int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
print("takeMaxUint8x10($a, $b, $c, $d, $e, $f, $g, $h, $i, $j)");
return a == 0xff &&
b == 0xff &&
c == 0xff &&
d == 0xff &&
e == 0xff &&
f == 0xff &&
g == 0xff &&
h == 0xff &&
i == 0xff &&
j == 0xff
? 1
: 0;
}
typedef ReturnMaxUint8Type = Uint8 Function();
int returnMaxUint8() {
return 0xff;
}
int returnMaxUint8v2() {
return 0xabcff;
}
final testcases = [
CallbackTest("SimpleAddition",
Pointer.fromFunction<SimpleAdditionType>(simpleAddition, 0)),
CallbackTest("SimpleAddition",
Pointer.fromFunction<SimpleAdditionType>(Foo.simpleAddition, 0)),
CallbackTest("IntComputation",
Pointer.fromFunction<IntComputationType>(intComputation, 0)),
CallbackTest("UintComputation",
Pointer.fromFunction<UintComputationType>(uintComputation, 0)),
CallbackTest("SimpleMultiply",
Pointer.fromFunction<SimpleMultiplyType>(simpleMultiply, 0.0)),
CallbackTest("SimpleMultiplyFloat",
Pointer.fromFunction<SimpleMultiplyFloatType>(simpleMultiplyFloat, 0.0)),
CallbackTest("ManyInts", Pointer.fromFunction<ManyIntsType>(manyInts, 0)),
CallbackTest(
"ManyDoubles", Pointer.fromFunction<ManyDoublesType>(manyDoubles, 0.0)),
CallbackTest("ManyArgs", Pointer.fromFunction<ManyArgsType>(manyArgs, 0.0)),
CallbackTest("Store", Pointer.fromFunction<StoreType>(store)),
CallbackTest(
"NullPointers", Pointer.fromFunction<NullPointersType>(nullPointers)),
CallbackTest("ReturnVoid", Pointer.fromFunction<ReturnVoid>(returnVoid)),
CallbackTest("ThrowExceptionDouble",
Pointer.fromFunction<ThrowExceptionDouble>(throwExceptionDouble, 42.0)),
CallbackTest("ThrowExceptionPointer",
Pointer.fromFunction<ThrowExceptionPointer>(throwExceptionPointer)),
CallbackTest("ThrowException",
Pointer.fromFunction<ThrowExceptionInt>(throwExceptionInt, 42)),
CallbackTest("TakeMaxUint8x10",
Pointer.fromFunction<TakeMaxUint8x10Type>(takeMaxUint8x10, 0)),
CallbackTest("ReturnMaxUint8",
Pointer.fromFunction<ReturnMaxUint8Type>(returnMaxUint8, 0)),
CallbackTest("ReturnMaxUint8",
Pointer.fromFunction<ReturnMaxUint8Type>(returnMaxUint8v2, 0)),
];
void main() {
testcases.forEach((t) => t.run());
}