Skip to content

Commit

Permalink
[vm/ffi] Support Unions
Browse files Browse the repository at this point in the history
Closes: #38491

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

Change-Id: I6d29f7e3c3046cda4a15c9b42063c66b064787be
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,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-linux-debug-x64c-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194420
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
  • Loading branch information
dcharkes authored and commit-bot@chromium.org committed Apr 15, 2021
1 parent b5c63ce commit 8a2b7bb
Show file tree
Hide file tree
Showing 43 changed files with 5,005 additions and 432 deletions.
69 changes: 39 additions & 30 deletions pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3735,26 +3735,30 @@ const MessageCode messageFastaUsageShort =

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(String name)> templateFfiEmptyStruct = const Template<
Message Function(String name)>(
Message Function(
String string,
String
name)> templateFfiEmptyStruct = const Template<
Message Function(String string, String name)>(
messageTemplate:
r"""Struct '#name' is empty. Empty structs are undefined behavior.""",
r"""#string '#name' is empty. Empty structs and unions are undefined behavior.""",
withArguments: _withArgumentsFfiEmptyStruct);

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

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsFfiEmptyStruct(String name) {
Message _withArgumentsFfiEmptyStruct(String string, String name) {
if (string.isEmpty) throw 'No string provided';
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(codeFfiEmptyStruct,
message:
"""Struct '${name}' is empty. Empty structs are undefined behavior.""",
arguments: {'name': name});
"""${string} '${name}' is empty. Empty structs and unions are undefined behavior.""",
arguments: {'string': string, 'name': name});
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Expand Down Expand Up @@ -3802,7 +3806,7 @@ const Template<
Message Function(String name)> templateFfiFieldAnnotation = const Template<
Message Function(String name)>(
messageTemplate:
r"""Field '#name' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields.""",
r"""Field '#name' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs and Unions cannot have regular Dart fields.""",
withArguments: _withArgumentsFfiFieldAnnotation);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Expand All @@ -3817,33 +3821,36 @@ Message _withArgumentsFfiFieldAnnotation(String name) {
name = demangleMixinApplicationName(name);
return new Message(codeFfiFieldAnnotation,
message:
"""Field '${name}' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields.""",
"""Field '${name}' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs and Unions cannot have regular Dart fields.""",
arguments: {'name': name});
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name, List<String> _names)>
templateFfiFieldCyclic =
const Template<Message Function(String name, List<String> _names)>(
messageTemplate: r"""Struct '#name' contains itself. Cycle elements:
const Template<
Message Function(String string, String name, List<String> _names)>
templateFfiFieldCyclic = const Template<
Message Function(String string, String name, List<String> _names)>(
messageTemplate: r"""#string '#name' contains itself. Cycle elements:
#names""", withArguments: _withArgumentsFfiFieldCyclic);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name, List<String> _names)>
codeFfiFieldCyclic =
const Code<Message Function(String name, List<String> _names)>(
const Code<Message Function(String string, String name, List<String> _names)>
codeFfiFieldCyclic = const Code<
Message Function(String string, String name, List<String> _names)>(
"FfiFieldCyclic",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsFfiFieldCyclic(String name, List<String> _names) {
Message _withArgumentsFfiFieldCyclic(
String string, String name, List<String> _names) {
if (string.isEmpty) throw 'No string provided';
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
if (_names.isEmpty) throw 'No names provided';
String names = itemizeNames(_names);
return new Message(codeFfiFieldCyclic,
message: """Struct '${name}' contains itself. Cycle elements:
${names}""", arguments: {'name': name, 'names': _names});
message: """${string} '${name}' contains itself. Cycle elements:
${names}""", arguments: {'string': string, 'name': name, 'names': _names});
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Expand Down Expand Up @@ -3904,7 +3911,7 @@ const Template<
Message Function(String name)> templateFfiFieldNull = const Template<
Message Function(String name)>(
messageTemplate:
r"""Field '#name' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct`.""",
r"""Field '#name' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct` or `Union`.""",
withArguments: _withArgumentsFfiFieldNull);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Expand All @@ -3919,7 +3926,7 @@ Message _withArgumentsFfiFieldNull(String name) {
name = demangleMixinApplicationName(name);
return new Message(codeFfiFieldNull,
message:
"""Field '${name}' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct`.""",
"""Field '${name}' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct` or `Union`.""",
arguments: {'name': name});
}

Expand Down Expand Up @@ -4058,24 +4065,26 @@ Message _withArgumentsFfiSizeAnnotationDimensions(String name) {
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)> templateFfiStructGeneric =
const Template<Message Function(String name)>(
messageTemplate: r"""Struct '#name' should not be generic.""",
const Template<Message Function(String string, String name)>
templateFfiStructGeneric =
const Template<Message Function(String string, String name)>(
messageTemplate: r"""#string '#name' should not be generic.""",
withArguments: _withArgumentsFfiStructGeneric);

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

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsFfiStructGeneric(String name) {
Message _withArgumentsFfiStructGeneric(String string, String name) {
if (string.isEmpty) throw 'No string provided';
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(codeFfiStructGeneric,
message: """Struct '${name}' should not be generic.""",
arguments: {'name': name});
message: """${string} '${name}' should not be generic.""",
arguments: {'string': string, 'name': name});
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Expand Down
10 changes: 5 additions & 5 deletions pkg/front_end/messages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4366,7 +4366,7 @@ FfiTypeMismatch:

FfiEmptyStruct:
# Used by dart:ffi
template: "Struct '#name' is empty. Empty structs are undefined behavior."
template: "#string '#name' is empty. Empty structs and unions are undefined behavior."
external: test/ffi_test.dart

FfiTypeInvalid:
Expand All @@ -4376,12 +4376,12 @@ FfiTypeInvalid:

FfiFieldNull:
# Used by dart:ffi
template: "Field '#name' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct`."
template: "Field '#name' cannot have type 'Null', it must be `int`, `double`, `Pointer`, or a subtype of `Struct` or `Union`."
external: test/ffi_test.dart

FfiFieldAnnotation:
# Used by dart:ffi
template: "Field '#name' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields."
template: "Field '#name' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs and Unions cannot have regular Dart fields."
external: test/ffi_test.dart

FfiFieldNoAnnotation:
Expand All @@ -4392,7 +4392,7 @@ FfiFieldNoAnnotation:
FfiFieldCyclic:
# Used by dart:ffi
template: |
Struct '#name' contains itself. Cycle elements:
#string '#name' contains itself. Cycle elements:
#names
external: test/ffi_test.dart

Expand Down Expand Up @@ -4439,7 +4439,7 @@ FfiSizeAnnotationDimensions:

FfiStructGeneric:
# Used by dart:ffi
template: "Struct '#name' should not be generic."
template: "#string '#name' should not be generic."
external: test/ffi_test.dart

FfiDartTypeMismatch:
Expand Down
1 change: 1 addition & 0 deletions pkg/front_end/test/spell_checking_list_common.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3181,6 +3181,7 @@ unimplemented
uninitialized
union
unioned
unions
unique
unit
unite
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ constants {

Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:134:9)
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:135:9)
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ constants {

Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:134:9)
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:135:9)
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ constants {

Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:134:9)
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:135:9)
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ constants {

Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array.dart:
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:134:9)
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:135:9)
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ constants {

Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:134:9)
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:135:9)
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@ Extra constant evaluation: evaluated: 110, effectively constant: 2

Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:134:9)
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:135:9)
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ constants {

Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:134:9)
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:135:9)
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@ Extra constant evaluation: evaluated: 110, effectively constant: 2

Constructor coverage from constants:
org-dartlang-testcase:///ffi_struct_inline_array_multi_dimensional.dart:
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:134:9)
- _ArraySize. (from org-dartlang-sdk:///sdk/lib/ffi/ffi.dart:135:9)
20 changes: 17 additions & 3 deletions pkg/vm/lib/transformations/ffi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ class FfiTransformer extends Transformer {
final Class pointerClass;
final Class compoundClass;
final Class structClass;
final Class unionClass;
final Class ffiStructLayoutClass;
final Field ffiStructLayoutTypesField;
final Field ffiStructLayoutPackingField;
Expand All @@ -247,7 +248,10 @@ class FfiTransformer extends Transformer {
final Procedure addressGetter;
final Procedure structPointerRef;
final Procedure structPointerElemAt;
final Procedure unionPointerRef;
final Procedure unionPointerElemAt;
final Procedure structArrayElemAt;
final Procedure unionArrayElemAt;
final Procedure arrayArrayElemAt;
final Procedure arrayArrayAssignAt;
final Procedure asFunctionMethod;
Expand All @@ -264,6 +268,7 @@ class FfiTransformer extends Transformer {
final Field arrayNestedDimensionsFirst;
final Field arrayNestedDimensionsRest;
final Constructor structFromTypedDataBase;
final Constructor unionFromTypedDataBase;
final Constructor arrayConstructor;
final Procedure fromAddressInternal;
final Procedure libraryLookupMethod;
Expand Down Expand Up @@ -333,6 +338,7 @@ class FfiTransformer extends Transformer {
pointerClass = index.getClass('dart:ffi', 'Pointer'),
compoundClass = index.getClass('dart:ffi', '_Compound'),
structClass = index.getClass('dart:ffi', 'Struct'),
unionClass = index.getClass('dart:ffi', 'Union'),
ffiStructLayoutClass = index.getClass('dart:ffi', '_FfiStructLayout'),
ffiStructLayoutTypesField =
index.getMember('dart:ffi', '_FfiStructLayout', 'fieldTypes'),
Expand Down Expand Up @@ -369,14 +375,20 @@ class FfiTransformer extends Transformer {
index.getMember('dart:ffi', 'Array', '_nestedDimensionsRest'),
structFromTypedDataBase =
index.getMember('dart:ffi', 'Struct', '_fromTypedDataBase'),
unionFromTypedDataBase =
index.getMember('dart:ffi', 'Union', '_fromTypedDataBase'),
arrayConstructor = index.getMember('dart:ffi', 'Array', '_'),
fromAddressInternal =
index.getTopLevelMember('dart:ffi', '_fromAddress'),
structPointerRef =
index.getMember('dart:ffi', 'StructPointer', 'get:ref'),
structPointerElemAt =
index.getMember('dart:ffi', 'StructPointer', '[]'),
unionPointerRef =
index.getMember('dart:ffi', 'UnionPointer', 'get:ref'),
unionPointerElemAt = index.getMember('dart:ffi', 'UnionPointer', '[]'),
structArrayElemAt = index.getMember('dart:ffi', 'StructArray', '[]'),
unionArrayElemAt = index.getMember('dart:ffi', 'UnionArray', '[]'),
arrayArrayElemAt = index.getMember('dart:ffi', 'ArrayArray', '[]'),
arrayArrayAssignAt = index.getMember('dart:ffi', 'ArrayArray', '[]='),
asFunctionMethod =
Expand Down Expand Up @@ -478,7 +490,7 @@ class FfiTransformer extends Transformer {
return nativeType;
}
if (hierarchy.isSubclassOf(nativeClass, compoundClass)) {
if (nativeClass == structClass) {
if (nativeClass == structClass || nativeClass == unionClass) {
return null;
}
return allowCompounds ? nativeType : null;
Expand Down Expand Up @@ -749,11 +761,13 @@ class FfiTransformer extends Transformer {
return false;
}
if (type is InterfaceType) {
if (type.classNode == structClass) {
if (type.classNode == structClass || type.classNode == unionClass) {
return false;
}
}
return env.isSubtypeOf(type, InterfaceType(structClass, Nullability.legacy),
return env.isSubtypeOf(
type,
InterfaceType(compoundClass, Nullability.legacy),
SubtypeCheckMode.ignoringNullabilities);
}
}
Expand Down
Loading

0 comments on commit 8a2b7bb

Please sign in to comment.