Skip to content

Commit

Permalink
[vm/ffi] Support packed Structs
Browse files Browse the repository at this point in the history
Closes: dart-lang#38158

This CL implements unaligned access for float/double on arm32, but does
not expose it in an API. Rather it only uses these loads/stores inside
the getters and setters of packed structs.
Bug: dart-lang#45009

Besides unaligned access for float/double, this CL is mostly a CFE
change. The only VM change is reading the packing in the
`_FfiStructLayout` annotation.

The implementation of using the packing in the VM, and analyzer changes
have landed separately in earlier CLs.

tools/test.py ffi ffi_2
TEST=tests/ffi(_2)/(.*)by_value_(*.)_test.dart

Change-Id: Ic3106ecc626d2e30674a49bf03f65ae12d2b3502
Cq-Include-Trybots: luci.dart.try:dart-sdk-linux-try,dart-sdk-mac-try,dart-sdk-win-try,vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-mac-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-mac-release-x64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-win-release-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-msan-linux-release-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-android-release-arm_x64-try,analyzer-analysis-server-linux-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/186143
Reviewed-by: Aske Simon Christensen <askesc@google.com>
  • Loading branch information
dcharkes committed Mar 19, 2021
1 parent e7acc69 commit 77dc74b
Show file tree
Hide file tree
Showing 47 changed files with 4,768 additions and 229 deletions.
62 changes: 62 additions & 0 deletions pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3903,6 +3903,68 @@ Message _withArgumentsFfiNotStatic(String name) {
arguments: {'name': name});
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)> templateFfiPackedAnnotation =
const Template<Message Function(String name)>(
messageTemplate:
r"""Struct '#name' must have at most one 'Packed' annotation.""",
withArguments: _withArgumentsFfiPackedAnnotation);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name)> codeFfiPackedAnnotation =
const Code<Message Function(String name)>(
"FfiPackedAnnotation",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsFfiPackedAnnotation(String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(codeFfiPackedAnnotation,
message:
"""Struct '${name}' must have at most one 'Packed' annotation.""",
arguments: {'name': name});
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeFfiPackedAnnotationAlignment =
messageFfiPackedAnnotationAlignment;

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageFfiPackedAnnotationAlignment = const MessageCode(
"FfiPackedAnnotationAlignment",
message: r"""Only packing to 1, 2, 4, 8, and 16 bytes is supported.""");

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
String name,
String
name2)> templateFfiPackedNestingNonPacked = const Template<
Message Function(String name, String name2)>(
messageTemplate:
r"""Nesting the non-packed or less tightly packed struct '#name' in a packed struct '#name2' is not supported.""",
withArguments: _withArgumentsFfiPackedNestingNonPacked);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name, String name2)>
codeFfiPackedNestingNonPacked =
const Code<Message Function(String name, String name2)>(
"FfiPackedNestingNonPacked",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsFfiPackedNestingNonPacked(String name, String name2) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
if (name2.isEmpty) throw 'No name provided';
name2 = demangleMixinApplicationName(name2);
return new Message(codeFfiPackedNestingNonPacked,
message:
"""Nesting the non-packed or less tightly packed struct '${name}' in a packed struct '${name2}' is not supported.""",
arguments: {'name': name, 'name2': name2});
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)> templateFfiSizeAnnotation =
const Template<Message Function(String name)>(
Expand Down
3 changes: 3 additions & 0 deletions pkg/front_end/lib/src/api_unstable/vm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export '../fasta/fasta_codes.dart'
LocatedMessage,
messageFfiExceptionalReturnNull,
messageFfiExpectedConstant,
messageFfiPackedAnnotationAlignment,
noLength,
templateFfiDartTypeMismatch,
templateFfiEmptyStruct,
Expand All @@ -64,6 +65,8 @@ export '../fasta/fasta_codes.dart'
templateFfiFieldNoAnnotation,
templateFfiFieldNull,
templateFfiNotStatic,
templateFfiPackedAnnotation,
templateFfiPackedNestingNonPacked,
templateFfiSizeAnnotation,
templateFfiSizeAnnotationDimensions,
templateFfiStructGeneric,
Expand Down
3 changes: 3 additions & 0 deletions pkg/front_end/messages.status
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,9 @@ FfiFieldInitializer/analyzerCode: Fail
FfiFieldNoAnnotation/analyzerCode: Fail
FfiFieldNull/analyzerCode: Fail
FfiNotStatic/analyzerCode: Fail
FfiPackedAnnotation/analyzerCode: Fail
FfiPackedAnnotationAlignment/analyzerCode: Fail
FfiPackedNestingNonPacked/analyzerCode: Fail
FfiSizeAnnotation/analyzerCode: Fail
FfiSizeAnnotationDimensions/analyzerCode: Fail
FfiStructAnnotation/analyzerCode: Fail
Expand Down
15 changes: 15 additions & 0 deletions pkg/front_end/messages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4279,6 +4279,21 @@ FfiExtendsOrImplementsSealedClass:
template: "Class '#name' cannot be extended or implemented."
external: test/ffi_test.dart

FfiPackedAnnotation:
# Used by dart:ffi
template: "Struct '#name' must have at most one 'Packed' annotation."
external: test/ffi_test.dart

FfiPackedAnnotationAlignment:
# Used by dart:ffi
template: "Only packing to 1, 2, 4, 8, and 16 bytes is supported."
external: test/ffi_test.dart

FfiPackedNestingNonPacked:
# Used by dart:ffi
template: "Nesting the non-packed or less tightly packed struct '#name' in a packed struct '#name2' is not supported."
external: test/ffi_test.dart

FfiSizeAnnotation:
# Used by dart:ffi
template: "Field '#name' must have exactly one 'Array' annotation."
Expand Down
3 changes: 3 additions & 0 deletions pkg/front_end/test/spell_checking_list_common.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,8 @@ owner
package
packaged
packages
packed
packing
pad
padded
padding
Expand Down Expand Up @@ -3042,6 +3044,7 @@ throws
thumb
thunk
thus
tightly
time
timeline
times
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import "dart:ffi" as ffi;
import "dart:ffi";
import "package:ffi/ffi.dart";

@#C6
@#C7
class Coordinate extends ffi::Struct {
static final field core::int* #sizeOf = (#C9).{core::List::[]}(ffi::_abi());
static final field core::int* #sizeOf = (#C10).{core::List::[]}(ffi::_abi());
@#C12
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
: super ffi::Struct::_fromPointer(#pointer)
Expand Down Expand Up @@ -51,14 +51,14 @@ constants {
#C2 = TypeLiteralConstant(ffi::Double)
#C3 = TypeLiteralConstant(ffi::Pointer<ffi::NativeType>)
#C4 = <core::Type>[#C2, #C2, #C3]
#C5 = ffi::_FfiStructLayout {fieldTypes:#C4}
#C6 = core::pragma {name:#C1, options:#C5}
#C7 = 24
#C8 = 20
#C9 = <core::int*>[#C7, #C8, #C7]
#C10 = "vm:entry-point"
#C11 = null
#C12 = core::pragma {name:#C10, options:#C11}
#C5 = null
#C6 = ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
#C7 = core::pragma {name:#C1, options:#C6}
#C8 = 24
#C9 = 20
#C10 = <core::int*>[#C8, #C9, #C8]
#C11 = "vm:entry-point"
#C12 = core::pragma {name:#C11, options:#C5}
#C13 = 0
#C14 = <core::int*>[#C13, #C13, #C13]
#C15 = 8
Expand Down
20 changes: 10 additions & 10 deletions pkg/front_end/testcases/incremental/ffi_01.yaml.world.1.expect
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {

import "dart:ffi";

@#C6
@#C7
class Coordinate extends dart.ffi::Struct {
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
@#C12
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
: super dart.ffi::Struct::_fromPointer(#pointer)
Expand Down Expand Up @@ -54,14 +54,14 @@ constants {
#C2 = TypeLiteralConstant(dart.ffi::Double)
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
#C4 = <dart.core::Type>[#C2, #C2, #C3]
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
#C6 = dart.core::pragma {name:#C1, options:#C5}
#C7 = 24
#C8 = 20
#C9 = <dart.core::int*>[#C7, #C8, #C7]
#C10 = "vm:entry-point"
#C11 = null
#C12 = dart.core::pragma {name:#C10, options:#C11}
#C5 = null
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
#C7 = dart.core::pragma {name:#C1, options:#C6}
#C8 = 24
#C9 = 20
#C10 = <dart.core::int*>[#C8, #C9, #C8]
#C11 = "vm:entry-point"
#C12 = dart.core::pragma {name:#C11, options:#C5}
#C13 = 0
#C14 = <dart.core::int*>[#C13, #C13, #C13]
#C15 = 8
Expand Down
20 changes: 10 additions & 10 deletions pkg/front_end/testcases/incremental/ffi_01.yaml.world.2.expect
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {

import "dart:ffi";

@#C6
@#C7
class Coordinate extends dart.ffi::Struct {
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
@#C12
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
: super dart.ffi::Struct::_fromPointer(#pointer)
Expand Down Expand Up @@ -58,14 +58,14 @@ constants {
#C2 = TypeLiteralConstant(dart.ffi::Double)
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
#C4 = <dart.core::Type>[#C2, #C2, #C3]
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
#C6 = dart.core::pragma {name:#C1, options:#C5}
#C7 = 24
#C8 = 20
#C9 = <dart.core::int*>[#C7, #C8, #C7]
#C10 = "vm:entry-point"
#C11 = null
#C12 = dart.core::pragma {name:#C10, options:#C11}
#C5 = null
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
#C7 = dart.core::pragma {name:#C1, options:#C6}
#C8 = 24
#C9 = 20
#C10 = <dart.core::int*>[#C8, #C9, #C8]
#C11 = "vm:entry-point"
#C12 = dart.core::pragma {name:#C11, options:#C5}
#C13 = 0
#C14 = <dart.core::int*>[#C13, #C13, #C13]
#C15 = 8
Expand Down
20 changes: 10 additions & 10 deletions pkg/front_end/testcases/incremental/ffi_02.yaml.world.1.expect
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {

import "dart:ffi";

@#C6
@#C7
class Coordinate extends dart.ffi::Struct {
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
@#C12
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
: super dart.ffi::Struct::_fromPointer(#pointer)
Expand Down Expand Up @@ -55,14 +55,14 @@ constants {
#C2 = TypeLiteralConstant(dart.ffi::Double)
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
#C4 = <dart.core::Type>[#C2, #C2, #C3]
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
#C6 = dart.core::pragma {name:#C1, options:#C5}
#C7 = 24
#C8 = 20
#C9 = <dart.core::int*>[#C7, #C8, #C7]
#C10 = "vm:entry-point"
#C11 = null
#C12 = dart.core::pragma {name:#C10, options:#C11}
#C5 = null
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
#C7 = dart.core::pragma {name:#C1, options:#C6}
#C8 = 24
#C9 = 20
#C10 = <dart.core::int*>[#C8, #C9, #C8]
#C11 = "vm:entry-point"
#C12 = dart.core::pragma {name:#C11, options:#C5}
#C13 = 0
#C14 = <dart.core::int*>[#C13, #C13, #C13]
#C15 = 8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {

import "dart:ffi";

@#C6
@#C7
class Coordinate extends dart.ffi::Struct {
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
@#C12
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
: super dart.ffi::Struct::_fromPointer(#pointer)
Expand Down Expand Up @@ -54,14 +54,14 @@ constants {
#C2 = TypeLiteralConstant(dart.ffi::Double)
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
#C4 = <dart.core::Type>[#C2, #C2, #C3]
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
#C6 = dart.core::pragma {name:#C1, options:#C5}
#C7 = 24
#C8 = 20
#C9 = <dart.core::int*>[#C7, #C8, #C7]
#C10 = "vm:entry-point"
#C11 = null
#C12 = dart.core::pragma {name:#C10, options:#C11}
#C5 = null
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
#C7 = dart.core::pragma {name:#C1, options:#C6}
#C8 = 24
#C9 = 20
#C10 = <dart.core::int*>[#C8, #C9, #C8]
#C11 = "vm:entry-point"
#C12 = dart.core::pragma {name:#C11, options:#C5}
#C13 = 0
#C14 = <dart.core::int*>[#C13, #C13, #C13]
#C15 = 8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {

import "dart:ffi";

@#C6
@#C7
class Coordinate extends dart.ffi::Struct {
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
@#C12
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
: super dart.ffi::Struct::_fromPointer(#pointer)
Expand Down Expand Up @@ -55,14 +55,14 @@ constants {
#C2 = TypeLiteralConstant(dart.ffi::Double)
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
#C4 = <dart.core::Type>[#C2, #C2, #C3]
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
#C6 = dart.core::pragma {name:#C1, options:#C5}
#C7 = 24
#C8 = 20
#C9 = <dart.core::int*>[#C7, #C8, #C7]
#C10 = "vm:entry-point"
#C11 = null
#C12 = dart.core::pragma {name:#C10, options:#C11}
#C5 = null
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
#C7 = dart.core::pragma {name:#C1, options:#C6}
#C8 = 24
#C9 = 20
#C10 = <dart.core::int*>[#C8, #C9, #C8]
#C11 = "vm:entry-point"
#C12 = dart.core::pragma {name:#C11, options:#C5}
#C13 = 0
#C14 = <dart.core::int*>[#C13, #C13, #C13]
#C15 = 8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {

import "dart:ffi";

@#C6
@#C7
class Coordinate extends dart.ffi::Struct {
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
@#C12
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
: super dart.ffi::Struct::_fromPointer(#pointer)
Expand Down Expand Up @@ -56,14 +56,14 @@ constants {
#C2 = TypeLiteralConstant(dart.ffi::Double)
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
#C4 = <dart.core::Type>[#C2, #C2, #C3]
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
#C6 = dart.core::pragma {name:#C1, options:#C5}
#C7 = 24
#C8 = 20
#C9 = <dart.core::int*>[#C7, #C8, #C7]
#C10 = "vm:entry-point"
#C11 = null
#C12 = dart.core::pragma {name:#C10, options:#C11}
#C5 = null
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
#C7 = dart.core::pragma {name:#C1, options:#C6}
#C8 = 24
#C9 = 20
#C10 = <dart.core::int*>[#C8, #C9, #C8]
#C11 = "vm:entry-point"
#C12 = dart.core::pragma {name:#C11, options:#C5}
#C13 = 0
#C14 = <dart.core::int*>[#C13, #C13, #C13]
#C15 = 8
Expand Down
Loading

0 comments on commit 77dc74b

Please sign in to comment.