Skip to content

Commit d2b39d1

Browse files
dcharkescommit-bot@chromium.org
authored andcommitted
[cfe/ffi] asFunction/fromFunction variance in CFE + regression test
Issue: #37385 Change-Id: I0a0704f3513bf8de802e7481d813f72678837e0b Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,dart-sdk-linux-try,analyzer-win-release-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107511 Commit-Queue: Daco Harkes <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent 882a6b5 commit d2b39d1

File tree

6 files changed

+353
-19
lines changed

6 files changed

+353
-19
lines changed

pkg/vm/lib/transformations/ffi_use_sites.dart

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -344,17 +344,18 @@ class _FfiUseSiteTransformer extends FfiTransformer {
344344
}
345345

346346
void _ensureNativeTypeToDartType(
347-
DartType containerTypeArg, DartType elementType, Expression node,
347+
DartType nativeType, DartType dartType, Expression node,
348348
{bool allowStructs: false}) {
349-
final DartType shouldBeElementType =
350-
convertNativeTypeToDartType(containerTypeArg, allowStructs);
351-
if (elementType == shouldBeElementType) return;
352-
// We disable implicit downcasts, they will go away when NNBD lands.
353-
if (env.isSubtypeOf(elementType, shouldBeElementType,
354-
SubtypeCheckMode.ignoringNullabilities)) return;
349+
final DartType correspondingDartType =
350+
convertNativeTypeToDartType(nativeType, allowStructs);
351+
if (dartType == correspondingDartType) return;
352+
if (env.isSubtypeOf(correspondingDartType, dartType,
353+
SubtypeCheckMode.ignoringNullabilities)) {
354+
return;
355+
}
355356
diagnosticReporter.report(
356357
templateFfiTypeMismatch.withArguments(
357-
elementType, shouldBeElementType, containerTypeArg),
358+
dartType, correspondingDartType, nativeType),
358359
node.fileOffset,
359360
1,
360361
node.location.file);

runtime/bin/ffi_test/ffi_test_functions.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,4 +858,31 @@ DART_EXPORT int TestCallbackWrongIsolate(void (*fn)()) {
858858

859859
#endif // defined(TARGET_OS_LINUX)
860860

861+
// Receives some pointer (Pointer<NativeType> in Dart) and writes some bits.
862+
DART_EXPORT void NativeTypePointerParam(void* p) {
863+
uint8_t* p2 = reinterpret_cast<uint8_t*>(p);
864+
p2[0] = 42;
865+
}
866+
867+
// Manufactures some pointer (Pointer<NativeType> in Dart) with a bogus address.
868+
DART_EXPORT void* NativeTypePointerReturn() {
869+
uint64_t bogus_address = 0x13370000;
870+
return reinterpret_cast<void*>(bogus_address);
871+
}
872+
873+
// Passes some pointer (Pointer<NativeType> in Dart) to Dart as argument.
874+
DART_EXPORT void CallbackNativeTypePointerParam(void (*f)(void*)) {
875+
void* pointer = malloc(sizeof(int64_t));
876+
f(pointer);
877+
free(pointer);
878+
}
879+
880+
// Receives some pointer (Pointer<NativeType> in Dart) from Dart as return
881+
// value.
882+
DART_EXPORT void CallbackNativeTypePointerReturn(void* (*f)()) {
883+
void* p = f();
884+
uint8_t* p2 = reinterpret_cast<uint8_t*>(p);
885+
p2[0] = 42;
886+
}
887+
861888
} // namespace dart

tests/ffi/function_test.dart

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
// VMOptions=--write-protect-code --no-dual-map-code --stacktrace-every=100
1414
// SharedObjects=ffi_test_functions
1515

16-
library FfiTest;
17-
1816
import 'dart:ffi';
1917

2018
import 'dylib_utils.dart';
@@ -44,6 +42,7 @@ void main() {
4442
testVoidReturn();
4543
testNoArgs();
4644
testException();
45+
testLookupFunctionPointerNativeType();
4746
}
4847
}
4948

@@ -405,6 +404,17 @@ void testNoArgs() {
405404
Expect.approxEquals(1337.0, result);
406405
}
407406

407+
typedef NativeTypeNFT = Pointer<NativeType> Function(
408+
Pointer<Pointer<NativeType>>, Int8);
409+
typedef NativeTypeFT = Pointer<NativeType> Function(
410+
Pointer<Pointer<NativeType>>, int);
411+
412+
void testLookupFunctionPointerNativeType() {
413+
// The function signature does not match up, but that does not matter since
414+
// this test does not use the trampoline.
415+
ffiTestFunctions.lookupFunction<NativeTypeNFT, NativeTypeFT>("LargePointer");
416+
}
417+
408418
// Throw an exception from within the trampoline and collect a stacktrace
409419
// include its frame.
410420
void testException() {

tests/ffi/static_checks_test.dart

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ void main() {
4242
testLookupFunctionGeneric2();
4343
testLookupFunctionWrongNativeFunctionSignature();
4444
testLookupFunctionTypeMismatch();
45-
testLookupFunctionPointerNativeType();
4645
testNativeFunctionSignatureInvalidReturn();
4746
testNativeFunctionSignatureInvalidParam();
4847
testNativeFunctionSignatureInvalidOptionalNamed();
@@ -289,14 +288,6 @@ void testLookupFunctionTypeMismatch() {
289288
l.lookupFunction<NativeDoubleUnOp, IntUnOp>("cos"); //# 18: compile-time error
290289
}
291290

292-
typedef NativeTypeNFT = Pointer<NativeType> Function(Pointer<Pointer<NativeType>>, Int8);
293-
typedef NativeTypeFT = Pointer<NativeType> Function(Pointer<Pointer<NativeType>>, int);
294-
295-
void testLookupFunctionPointerNativeType() {
296-
final DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
297-
l.lookupFunction<NativeTypeNFT, NativeTypeFT>("LargePointer"); //# 19: ok
298-
}
299-
300291
// TODO(dacoharkes): make the next 4 test compile errors
301292
typedef Invalid1 = int Function(Int8);
302293
typedef Invalid2 = Int8 Function(int);
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
//
5+
// SharedObjects=ffi_test_functions
6+
7+
import 'dart:ffi';
8+
9+
import 'dylib_utils.dart';
10+
11+
// ============================================
12+
// Tests checks on Dart to native (asFunction).
13+
// ============================================
14+
15+
typedef Int64PointerParamOpDart = void Function(Pointer<Int64>);
16+
typedef Int64PointerParamOp = Void Function(Pointer<Int64>);
17+
typedef Int64PointerReturnOp = Pointer<Int64> Function();
18+
typedef NaTyPointerReturnOp = Pointer<NativeType> Function();
19+
20+
final paramOpName = "NativeTypePointerParam";
21+
final returnOpName = "NativeTypePointerReturn";
22+
23+
final DynamicLibrary ffiTestFunctions =
24+
dlopenPlatformSpecific("ffi_test_functions");
25+
26+
final p1 =
27+
ffiTestFunctions.lookup<NativeFunction<Int64PointerParamOp>>(paramOpName);
28+
final nonInvariantBinding1 = //# 1: compile-time error
29+
p1.asFunction<NaTyPointerParamOpDart>(); //# 1: continued
30+
31+
final p2 =
32+
ffiTestFunctions.lookup<NativeFunction<NaTyPointerReturnOp>>(returnOpName);
33+
final nonInvariantBinding2 = //# 2: compile-time error
34+
p2.asFunction<Int64PointerReturnOp>(); //# 2: continued
35+
36+
final p3 = Pointer<
37+
NativeFunction<
38+
Pointer<NativeFunction<Pointer<NativeType> Function()>>
39+
Function()>>.fromAddress(0x1234);
40+
final f3 = p3 //# 10: compile-time error
41+
.asFunction< //# 10: continued
42+
Pointer< //# 10: continued
43+
NativeFunction< //# 10: continued
44+
Pointer<Int8> Function()>> //# 10: continued
45+
Function()>(); //# 10: continued
46+
47+
// ===========================================================
48+
// Test check on callbacks from native to Dart (fromFunction).
49+
// ===========================================================
50+
51+
void naTyPointerParamOp(Pointer<NativeType> p) {
52+
final Pointer<Int8> asInt8 = p.cast();
53+
asInt8.value = 42;
54+
}
55+
56+
Pointer<Int64> int64PointerReturnOp() {
57+
return Pointer.fromAddress(0x13370000);
58+
}
59+
60+
final implictDowncast1 = //# 3: compile-time error
61+
Pointer.fromFunction<Int64PointerParamOp>(//# 3: continued
62+
naTyPointerParamOp); //# 3: continued
63+
final implictDowncast2 = //# 4: compile-time error
64+
Pointer.fromFunction<NaTyPointerReturnOp>(//# 4: continued
65+
int64PointerReturnOp); //# 4: continued
66+
67+
void main() {}

0 commit comments

Comments
 (0)