[vm/ffi] Fix sign extension for small int arguments on x64 Linux/MacOS
Sign extension of small integers is not symmetric between register arguments and register return values.
On Linux/MacOS x64, the caller is responsible for both the arguments and return value.
Previous tests only tested equality, which tests the equality of the lowest byte. However, when printing or using the small ints arithmetic all 4 bytes are used. The new tests pass back the number in a different format.
The callback tests test the number in Dart, so they did not suffer from implicit conversions. (TestTakeMaxUint8x10 in runtime/bin/ffi_test/ffi_test_functions.cc and tests/ffi_2/function_callbacks_test.dart.)
Fixes: https://github.com/dart-lang/sdk/issues/40537
Change-Id: I6a57cb7cb43206926eb101a66e3b2abfacec72a0
Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-abi-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134825
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 17:05:14 +00:00
|
|
|
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
|
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
//
|
|
|
|
// Truncation and sign extension of small ints, tested with something else than
|
|
|
|
// equality.
|
|
|
|
//
|
|
|
|
// SharedObjects=ffi_test_functions
|
|
|
|
|
2021-04-26 17:58:57 +00:00
|
|
|
// @dart = 2.9
|
|
|
|
|
[vm/ffi] Fix sign extension for small int arguments on x64 Linux/MacOS
Sign extension of small integers is not symmetric between register arguments and register return values.
On Linux/MacOS x64, the caller is responsible for both the arguments and return value.
Previous tests only tested equality, which tests the equality of the lowest byte. However, when printing or using the small ints arithmetic all 4 bytes are used. The new tests pass back the number in a different format.
The callback tests test the number in Dart, so they did not suffer from implicit conversions. (TestTakeMaxUint8x10 in runtime/bin/ffi_test/ffi_test_functions.cc and tests/ffi_2/function_callbacks_test.dart.)
Fixes: https://github.com/dart-lang/sdk/issues/40537
Change-Id: I6a57cb7cb43206926eb101a66e3b2abfacec72a0
Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,app-kernel-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-kernel-precomp-linux-debug-x64-try,vm-dartkb-linux-release-x64-abi-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,dart-sdk-linux-try,analyzer-analysis-server-linux-try,analyzer-linux-release-try,front-end-linux-release-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-mac-debug-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134825
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2020-02-10 17:05:14 +00:00
|
|
|
import 'dart:ffi';
|
|
|
|
|
|
|
|
import "package:expect/expect.dart";
|
|
|
|
|
|
|
|
import "dylib_utils.dart";
|
|
|
|
|
|
|
|
main() {
|
|
|
|
variant1Negative();
|
|
|
|
variant1Positive();
|
|
|
|
variant2Negative();
|
|
|
|
variant2Positive();
|
|
|
|
variant3Negative();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// `return x == 249 ? 1 : 0`.
|
|
|
|
///
|
|
|
|
/// This doesn't catch the error.
|
|
|
|
final regress40537 = ffiTestFunctions
|
|
|
|
.lookupFunction<IntPtr Function(Uint8), int Function(int)>("Regress40537");
|
|
|
|
|
|
|
|
variant1Negative() {
|
|
|
|
// 0xF9 = -7 in 2s complement.
|
|
|
|
// 0xF9 = 249 in unsinged.
|
|
|
|
final result = regress40537(-7);
|
|
|
|
print(result);
|
|
|
|
Expect.equals(1, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
variant1Positive() {
|
|
|
|
// 0xF9 = 249 in unsinged.
|
|
|
|
final result = regress40537(0xFFFFFFF9);
|
|
|
|
print(result);
|
|
|
|
Expect.equals(1, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// `return x`.
|
|
|
|
///
|
|
|
|
/// This does.
|
|
|
|
final regress40537Variant2 =
|
|
|
|
ffiTestFunctions.lookupFunction<IntPtr Function(Uint8), int Function(int)>(
|
|
|
|
"Regress40537Variant2");
|
|
|
|
|
|
|
|
variant2Negative() {
|
|
|
|
// The 32 bit representation of -7 is 0xFFFFFFF9.
|
|
|
|
// Only the lowest byte, 0xF9, should be interpreted by calling convention,
|
|
|
|
// or it should be truncated and zero extended before calling.
|
|
|
|
final result = regress40537Variant2(-7);
|
|
|
|
print(result);
|
|
|
|
Expect.equals(249, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
variant2Positive() {
|
|
|
|
// Only the lowest byte, 0xF9, should be interpreted by calling convention,
|
|
|
|
// or it should be truncated and zero extended before calling.
|
|
|
|
final result = regress40537Variant2(0xFFFFFFF9);
|
|
|
|
print(result);
|
|
|
|
Expect.equals(249, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// `return x`.
|
|
|
|
final regress40537Variant3 =
|
|
|
|
ffiTestFunctions.lookupFunction<Uint8 Function(IntPtr), int Function(int)>(
|
|
|
|
"Regress40537Variant3");
|
|
|
|
|
|
|
|
variant3Negative() {
|
|
|
|
// This really passes -7 its intptr_t.
|
|
|
|
final result = regress40537Variant3(-7);
|
|
|
|
print(result);
|
|
|
|
Expect.equals(249, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
|