Skip to content

Commit 77dc74b

Browse files
committed
[vm/ffi] Support packed Structs
Closes: #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: #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 <[email protected]>
1 parent e7acc69 commit 77dc74b

File tree

47 files changed

+4768
-229
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+4768
-229
lines changed

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3903,6 +3903,68 @@ Message _withArgumentsFfiNotStatic(String name) {
39033903
arguments: {'name': name});
39043904
}
39053905

3906+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
3907+
const Template<Message Function(String name)> templateFfiPackedAnnotation =
3908+
const Template<Message Function(String name)>(
3909+
messageTemplate:
3910+
r"""Struct '#name' must have at most one 'Packed' annotation.""",
3911+
withArguments: _withArgumentsFfiPackedAnnotation);
3912+
3913+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
3914+
const Code<Message Function(String name)> codeFfiPackedAnnotation =
3915+
const Code<Message Function(String name)>(
3916+
"FfiPackedAnnotation",
3917+
);
3918+
3919+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
3920+
Message _withArgumentsFfiPackedAnnotation(String name) {
3921+
if (name.isEmpty) throw 'No name provided';
3922+
name = demangleMixinApplicationName(name);
3923+
return new Message(codeFfiPackedAnnotation,
3924+
message:
3925+
"""Struct '${name}' must have at most one 'Packed' annotation.""",
3926+
arguments: {'name': name});
3927+
}
3928+
3929+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
3930+
const Code<Null> codeFfiPackedAnnotationAlignment =
3931+
messageFfiPackedAnnotationAlignment;
3932+
3933+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
3934+
const MessageCode messageFfiPackedAnnotationAlignment = const MessageCode(
3935+
"FfiPackedAnnotationAlignment",
3936+
message: r"""Only packing to 1, 2, 4, 8, and 16 bytes is supported.""");
3937+
3938+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
3939+
const Template<
3940+
Message Function(
3941+
String name,
3942+
String
3943+
name2)> templateFfiPackedNestingNonPacked = const Template<
3944+
Message Function(String name, String name2)>(
3945+
messageTemplate:
3946+
r"""Nesting the non-packed or less tightly packed struct '#name' in a packed struct '#name2' is not supported.""",
3947+
withArguments: _withArgumentsFfiPackedNestingNonPacked);
3948+
3949+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
3950+
const Code<Message Function(String name, String name2)>
3951+
codeFfiPackedNestingNonPacked =
3952+
const Code<Message Function(String name, String name2)>(
3953+
"FfiPackedNestingNonPacked",
3954+
);
3955+
3956+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
3957+
Message _withArgumentsFfiPackedNestingNonPacked(String name, String name2) {
3958+
if (name.isEmpty) throw 'No name provided';
3959+
name = demangleMixinApplicationName(name);
3960+
if (name2.isEmpty) throw 'No name provided';
3961+
name2 = demangleMixinApplicationName(name2);
3962+
return new Message(codeFfiPackedNestingNonPacked,
3963+
message:
3964+
"""Nesting the non-packed or less tightly packed struct '${name}' in a packed struct '${name2}' is not supported.""",
3965+
arguments: {'name': name, 'name2': name2});
3966+
}
3967+
39063968
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
39073969
const Template<Message Function(String name)> templateFfiSizeAnnotation =
39083970
const Template<Message Function(String name)>(

pkg/front_end/lib/src/api_unstable/vm.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export '../fasta/fasta_codes.dart'
5252
LocatedMessage,
5353
messageFfiExceptionalReturnNull,
5454
messageFfiExpectedConstant,
55+
messageFfiPackedAnnotationAlignment,
5556
noLength,
5657
templateFfiDartTypeMismatch,
5758
templateFfiEmptyStruct,
@@ -64,6 +65,8 @@ export '../fasta/fasta_codes.dart'
6465
templateFfiFieldNoAnnotation,
6566
templateFfiFieldNull,
6667
templateFfiNotStatic,
68+
templateFfiPackedAnnotation,
69+
templateFfiPackedNestingNonPacked,
6770
templateFfiSizeAnnotation,
6871
templateFfiSizeAnnotationDimensions,
6972
templateFfiStructGeneric,

pkg/front_end/messages.status

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ FfiFieldInitializer/analyzerCode: Fail
329329
FfiFieldNoAnnotation/analyzerCode: Fail
330330
FfiFieldNull/analyzerCode: Fail
331331
FfiNotStatic/analyzerCode: Fail
332+
FfiPackedAnnotation/analyzerCode: Fail
333+
FfiPackedAnnotationAlignment/analyzerCode: Fail
334+
FfiPackedNestingNonPacked/analyzerCode: Fail
332335
FfiSizeAnnotation/analyzerCode: Fail
333336
FfiSizeAnnotationDimensions/analyzerCode: Fail
334337
FfiStructAnnotation/analyzerCode: Fail

pkg/front_end/messages.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4279,6 +4279,21 @@ FfiExtendsOrImplementsSealedClass:
42794279
template: "Class '#name' cannot be extended or implemented."
42804280
external: test/ffi_test.dart
42814281

4282+
FfiPackedAnnotation:
4283+
# Used by dart:ffi
4284+
template: "Struct '#name' must have at most one 'Packed' annotation."
4285+
external: test/ffi_test.dart
4286+
4287+
FfiPackedAnnotationAlignment:
4288+
# Used by dart:ffi
4289+
template: "Only packing to 1, 2, 4, 8, and 16 bytes is supported."
4290+
external: test/ffi_test.dart
4291+
4292+
FfiPackedNestingNonPacked:
4293+
# Used by dart:ffi
4294+
template: "Nesting the non-packed or less tightly packed struct '#name' in a packed struct '#name2' is not supported."
4295+
external: test/ffi_test.dart
4296+
42824297
FfiSizeAnnotation:
42834298
# Used by dart:ffi
42844299
template: "Field '#name' must have exactly one 'Array' annotation."

pkg/front_end/test/spell_checking_list_common.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,6 +2113,8 @@ owner
21132113
package
21142114
packaged
21152115
packages
2116+
packed
2117+
packing
21162118
pad
21172119
padded
21182120
padding
@@ -3042,6 +3044,7 @@ throws
30423044
thumb
30433045
thunk
30443046
thus
3047+
tightly
30453048
time
30463049
timeline
30473050
times

pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import "dart:ffi" as ffi;
66
import "dart:ffi";
77
import "package:ffi/ffi.dart";
88

9-
@#C6
9+
@#C7
1010
class Coordinate extends ffi::Struct {
11-
static final field core::int* #sizeOf = (#C9).{core::List::[]}(ffi::_abi());
11+
static final field core::int* #sizeOf = (#C10).{core::List::[]}(ffi::_abi());
1212
@#C12
1313
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
1414
: super ffi::Struct::_fromPointer(#pointer)
@@ -51,14 +51,14 @@ constants {
5151
#C2 = TypeLiteralConstant(ffi::Double)
5252
#C3 = TypeLiteralConstant(ffi::Pointer<ffi::NativeType>)
5353
#C4 = <core::Type>[#C2, #C2, #C3]
54-
#C5 = ffi::_FfiStructLayout {fieldTypes:#C4}
55-
#C6 = core::pragma {name:#C1, options:#C5}
56-
#C7 = 24
57-
#C8 = 20
58-
#C9 = <core::int*>[#C7, #C8, #C7]
59-
#C10 = "vm:entry-point"
60-
#C11 = null
61-
#C12 = core::pragma {name:#C10, options:#C11}
54+
#C5 = null
55+
#C6 = ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
56+
#C7 = core::pragma {name:#C1, options:#C6}
57+
#C8 = 24
58+
#C9 = 20
59+
#C10 = <core::int*>[#C8, #C9, #C8]
60+
#C11 = "vm:entry-point"
61+
#C12 = core::pragma {name:#C11, options:#C5}
6262
#C13 = 0
6363
#C14 = <core::int*>[#C13, #C13, #C13]
6464
#C15 = 8

pkg/front_end/testcases/incremental/ffi_01.yaml.world.1.expect

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {
33

44
import "dart:ffi";
55

6-
@#C6
6+
@#C7
77
class Coordinate extends dart.ffi::Struct {
8-
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
8+
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
99
@#C12
1010
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
1111
: super dart.ffi::Struct::_fromPointer(#pointer)
@@ -54,14 +54,14 @@ constants {
5454
#C2 = TypeLiteralConstant(dart.ffi::Double)
5555
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
5656
#C4 = <dart.core::Type>[#C2, #C2, #C3]
57-
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
58-
#C6 = dart.core::pragma {name:#C1, options:#C5}
59-
#C7 = 24
60-
#C8 = 20
61-
#C9 = <dart.core::int*>[#C7, #C8, #C7]
62-
#C10 = "vm:entry-point"
63-
#C11 = null
64-
#C12 = dart.core::pragma {name:#C10, options:#C11}
57+
#C5 = null
58+
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
59+
#C7 = dart.core::pragma {name:#C1, options:#C6}
60+
#C8 = 24
61+
#C9 = 20
62+
#C10 = <dart.core::int*>[#C8, #C9, #C8]
63+
#C11 = "vm:entry-point"
64+
#C12 = dart.core::pragma {name:#C11, options:#C5}
6565
#C13 = 0
6666
#C14 = <dart.core::int*>[#C13, #C13, #C13]
6767
#C15 = 8

pkg/front_end/testcases/incremental/ffi_01.yaml.world.2.expect

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {
33

44
import "dart:ffi";
55

6-
@#C6
6+
@#C7
77
class Coordinate extends dart.ffi::Struct {
8-
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
8+
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
99
@#C12
1010
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
1111
: super dart.ffi::Struct::_fromPointer(#pointer)
@@ -58,14 +58,14 @@ constants {
5858
#C2 = TypeLiteralConstant(dart.ffi::Double)
5959
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
6060
#C4 = <dart.core::Type>[#C2, #C2, #C3]
61-
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
62-
#C6 = dart.core::pragma {name:#C1, options:#C5}
63-
#C7 = 24
64-
#C8 = 20
65-
#C9 = <dart.core::int*>[#C7, #C8, #C7]
66-
#C10 = "vm:entry-point"
67-
#C11 = null
68-
#C12 = dart.core::pragma {name:#C10, options:#C11}
61+
#C5 = null
62+
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
63+
#C7 = dart.core::pragma {name:#C1, options:#C6}
64+
#C8 = 24
65+
#C9 = 20
66+
#C10 = <dart.core::int*>[#C8, #C9, #C8]
67+
#C11 = "vm:entry-point"
68+
#C12 = dart.core::pragma {name:#C11, options:#C5}
6969
#C13 = 0
7070
#C14 = <dart.core::int*>[#C13, #C13, #C13]
7171
#C15 = 8

pkg/front_end/testcases/incremental/ffi_02.yaml.world.1.expect

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {
33

44
import "dart:ffi";
55

6-
@#C6
6+
@#C7
77
class Coordinate extends dart.ffi::Struct {
8-
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
8+
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
99
@#C12
1010
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
1111
: super dart.ffi::Struct::_fromPointer(#pointer)
@@ -55,14 +55,14 @@ constants {
5555
#C2 = TypeLiteralConstant(dart.ffi::Double)
5656
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
5757
#C4 = <dart.core::Type>[#C2, #C2, #C3]
58-
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
59-
#C6 = dart.core::pragma {name:#C1, options:#C5}
60-
#C7 = 24
61-
#C8 = 20
62-
#C9 = <dart.core::int*>[#C7, #C8, #C7]
63-
#C10 = "vm:entry-point"
64-
#C11 = null
65-
#C12 = dart.core::pragma {name:#C10, options:#C11}
58+
#C5 = null
59+
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
60+
#C7 = dart.core::pragma {name:#C1, options:#C6}
61+
#C8 = 24
62+
#C9 = 20
63+
#C10 = <dart.core::int*>[#C8, #C9, #C8]
64+
#C11 = "vm:entry-point"
65+
#C12 = dart.core::pragma {name:#C11, options:#C5}
6666
#C13 = 0
6767
#C14 = <dart.core::int*>[#C13, #C13, #C13]
6868
#C15 = 8

pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.1.expect

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {
33

44
import "dart:ffi";
55

6-
@#C6
6+
@#C7
77
class Coordinate extends dart.ffi::Struct {
8-
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
8+
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
99
@#C12
1010
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
1111
: super dart.ffi::Struct::_fromPointer(#pointer)
@@ -54,14 +54,14 @@ constants {
5454
#C2 = TypeLiteralConstant(dart.ffi::Double)
5555
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
5656
#C4 = <dart.core::Type>[#C2, #C2, #C3]
57-
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
58-
#C6 = dart.core::pragma {name:#C1, options:#C5}
59-
#C7 = 24
60-
#C8 = 20
61-
#C9 = <dart.core::int*>[#C7, #C8, #C7]
62-
#C10 = "vm:entry-point"
63-
#C11 = null
64-
#C12 = dart.core::pragma {name:#C10, options:#C11}
57+
#C5 = null
58+
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
59+
#C7 = dart.core::pragma {name:#C1, options:#C6}
60+
#C8 = 24
61+
#C9 = 20
62+
#C10 = <dart.core::int*>[#C8, #C9, #C8]
63+
#C11 = "vm:entry-point"
64+
#C12 = dart.core::pragma {name:#C11, options:#C5}
6565
#C13 = 0
6666
#C14 = <dart.core::int*>[#C13, #C13, #C13]
6767
#C15 = 8

pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.2.expect

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {
33

44
import "dart:ffi";
55

6-
@#C6
6+
@#C7
77
class Coordinate extends dart.ffi::Struct {
8-
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
8+
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
99
@#C12
1010
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
1111
: super dart.ffi::Struct::_fromPointer(#pointer)
@@ -55,14 +55,14 @@ constants {
5555
#C2 = TypeLiteralConstant(dart.ffi::Double)
5656
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
5757
#C4 = <dart.core::Type>[#C2, #C2, #C3]
58-
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
59-
#C6 = dart.core::pragma {name:#C1, options:#C5}
60-
#C7 = 24
61-
#C8 = 20
62-
#C9 = <dart.core::int*>[#C7, #C8, #C7]
63-
#C10 = "vm:entry-point"
64-
#C11 = null
65-
#C12 = dart.core::pragma {name:#C10, options:#C11}
58+
#C5 = null
59+
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
60+
#C7 = dart.core::pragma {name:#C1, options:#C6}
61+
#C8 = 24
62+
#C9 = 20
63+
#C10 = <dart.core::int*>[#C8, #C9, #C8]
64+
#C11 = "vm:entry-point"
65+
#C12 = dart.core::pragma {name:#C11, options:#C5}
6666
#C13 = 0
6767
#C14 = <dart.core::int*>[#C13, #C13, #C13]
6868
#C15 = 8

pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.3.expect

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ library from "org-dartlang-test:///lib.dart" as lib {
33

44
import "dart:ffi";
55

6-
@#C6
6+
@#C7
77
class Coordinate extends dart.ffi::Struct {
8-
static final field dart.core::int* #sizeOf = (#C9).{dart.core::List::[]}(dart.ffi::_abi());
8+
static final field dart.core::int* #sizeOf = (#C10).{dart.core::List::[]}(dart.ffi::_abi());
99
@#C12
1010
constructor #fromTypedDataBase(dynamic #pointer) → dynamic
1111
: super dart.ffi::Struct::_fromPointer(#pointer)
@@ -56,14 +56,14 @@ constants {
5656
#C2 = TypeLiteralConstant(dart.ffi::Double)
5757
#C3 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
5858
#C4 = <dart.core::Type>[#C2, #C2, #C3]
59-
#C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C4}
60-
#C6 = dart.core::pragma {name:#C1, options:#C5}
61-
#C7 = 24
62-
#C8 = 20
63-
#C9 = <dart.core::int*>[#C7, #C8, #C7]
64-
#C10 = "vm:entry-point"
65-
#C11 = null
66-
#C12 = dart.core::pragma {name:#C10, options:#C11}
59+
#C5 = null
60+
#C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
61+
#C7 = dart.core::pragma {name:#C1, options:#C6}
62+
#C8 = 24
63+
#C9 = 20
64+
#C10 = <dart.core::int*>[#C8, #C9, #C8]
65+
#C11 = "vm:entry-point"
66+
#C12 = dart.core::pragma {name:#C11, options:#C5}
6767
#C13 = 0
6868
#C14 = <dart.core::int*>[#C13, #C13, #C13]
6969
#C15 = 8

0 commit comments

Comments
 (0)