Skip to content

Commit 0c9abb8

Browse files
dcharkescommit-bot@chromium.org
authored andcommitted
[vm/ffi] Support structs on 32bit architectures
Fixes: #36334 Change-Id: Ie22e7fe87724f8d2497934cd681908c9015bd2f2 Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try, app-kernel-linux-debug-x64-try, vm-kernel-linux-debug-simdbc64-try,vm-kernel-linux-debug-ia32-try,vm-dartkb-linux-debug-simarm64-try,vm-kernel-win-debug-x64-try,vm-kernel-win-debug-ia32-try,vm-dartkb-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108103 Commit-Queue: Daco Harkes <[email protected]> Reviewed-by: Samir Jindel <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent 25bac04 commit 0c9abb8

File tree

16 files changed

+309
-171
lines changed

16 files changed

+309
-171
lines changed

pkg/vm/lib/transformations/ffi.dart

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,71 @@ const List<int> nativeTypeSizes = [
8686
UNKNOWN, // Struct
8787
];
8888

89+
/// The struct layout in various ABIs.
90+
///
91+
/// ABIs differ per architectures and with different compilers.
92+
/// We pick the default struct layout based on the architecture and OS.
93+
///
94+
/// Compilers _can_ deviate from the default layout, but this prevents
95+
/// executables from making system calls. So this seems rather uncommon.
96+
///
97+
/// In the future, we might support custom struct layouts. For more info see
98+
/// https://github.com/dart-lang/sdk/issues/35768.
99+
enum Abi {
100+
/// Layout in all 64bit ABIs (x64 and arm64).
101+
wordSize64,
102+
103+
/// Layout in System V ABI for x386 (ia32 on Linux).
104+
wordSize32Align32,
105+
106+
/// Layout in both the Arm 32 bit ABI and the Windows ia32 ABI.
107+
wordSize32Align64,
108+
}
109+
110+
/// WORD_SIZE in bytes.
111+
const wordSize = <Abi, int>{
112+
Abi.wordSize64: 8,
113+
Abi.wordSize32Align32: 4,
114+
Abi.wordSize32Align64: 4,
115+
};
116+
117+
/// Elements that are not aligned to their size.
118+
///
119+
/// Has an entry for all Abis. Empty entries document that every native
120+
/// type is aligned to it's own size in this ABI.
121+
///
122+
/// See runtime/vm/compiler/ffi.cc for asserts in the VM that verify these
123+
/// alignments.
124+
///
125+
/// TODO(37470): Add uncommon primitive data types when we want to support them.
126+
const nonSizeAlignment = <Abi, Map<NativeType, int>>{
127+
Abi.wordSize64: {},
128+
129+
// x86 System V ABI:
130+
// > uint64_t | size 8 | alignment 4
131+
// > double | size 8 | alignment 4
132+
// https://github.com/hjl-tools/x86-psABI/wiki/intel386-psABI-1.1.pdf page 8.
133+
Abi.wordSize32Align32: {NativeType.kDouble: 4, NativeType.kInt64: 4},
134+
135+
// The default for MSVC x86:
136+
// > The alignment-requirement for all data except structures, unions, and
137+
// > arrays is either the size of the object or the current packing size
138+
// > (specified with either /Zp or the pack pragma, whichever is less).
139+
// https://docs.microsoft.com/en-us/cpp/c-language/padding-and-alignment-of-structure-members?view=vs-2019
140+
//
141+
// GCC _can_ compile on Linux to this alignment with -malign-double, but does
142+
// not do so by default:
143+
// > Warning: if you use the -malign-double switch, structures containing the
144+
// > above types are aligned differently than the published application
145+
// > binary interface specifications for the x86-32 and are not binary
146+
// > compatible with structures in code compiled without that switch.
147+
// https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
148+
//
149+
// Arm always requires 8 byte alignment for 8 byte values:
150+
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf 4.1 Fundamental Data Types
151+
Abi.wordSize32Align64: {},
152+
};
153+
89154
/// [FfiTransformer] contains logic which is shared between
90155
/// _FfiUseSiteTransformer and _FfiDefinitionTransformer.
91156
class FfiTransformer extends Transformer {
@@ -98,6 +163,7 @@ class FfiTransformer extends Transformer {
98163
final Class intClass;
99164
final Class doubleClass;
100165
final Constructor pragmaConstructor;
166+
final Procedure listElementAt;
101167

102168
final Library ffiLibrary;
103169
final Class nativeFunctionClass;
@@ -114,6 +180,7 @@ class FfiTransformer extends Transformer {
114180
final Field addressOfField;
115181
final Constructor structFromPointer;
116182
final Procedure libraryLookupMethod;
183+
final Procedure abiMethod;
117184

118185
/// Classes corresponding to [NativeType], indexed by [NativeType].
119186
final List<Class> nativeTypesClasses;
@@ -124,6 +191,7 @@ class FfiTransformer extends Transformer {
124191
intClass = coreTypes.intClass,
125192
doubleClass = coreTypes.doubleClass,
126193
pragmaConstructor = coreTypes.pragmaConstructor,
194+
listElementAt = coreTypes.index.getMember('dart:core', 'List', '[]'),
127195
ffiLibrary = index.getLibrary('dart:ffi'),
128196
nativeFunctionClass = index.getClass('dart:ffi', 'NativeFunction'),
129197
pointerClass = index.getClass('dart:ffi', 'Pointer'),
@@ -144,6 +212,7 @@ class FfiTransformer extends Transformer {
144212
index.getMember('dart:ffi', 'Pointer', 'fromFunction'),
145213
libraryLookupMethod =
146214
index.getMember('dart:ffi', 'DynamicLibrary', 'lookup'),
215+
abiMethod = index.getTopLevelMember('dart:ffi', '_abi'),
147216
nativeTypesClasses = nativeTypeClassNames
148217
.map((name) => index.getClass('dart:ffi', name))
149218
.toList();

0 commit comments

Comments
 (0)