Skip to content

Commit 52cace8

Browse files
dcharkescommit-bot@chromium.org
authored andcommitted
Reland "[vm/ffi] Support structs on 32bit architectures"
Fixed Flutter iOS build. Fixes: #36334 Change-Id: Idee38671cf0f33797824b37f08a92f32f931d8e0 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,vm-ffi-android-product-arm-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108818 Reviewed-by: Samir Jindel <[email protected]> Commit-Queue: Daco Harkes <[email protected]>
1 parent d76238d commit 52cace8

File tree

16 files changed

+315
-171
lines changed

16 files changed

+315
-171
lines changed

pkg/vm/lib/transformations/ffi.dart

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,74 @@ 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) and in iOS Arm 32 bit.
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+
//
134+
// iOS 32 bit alignment:
135+
// https://developer.apple.com/documentation/uikit/app_and_environment/updating_your_app_from_32-bit_to_64-bit_architecture/updating_data_structures
136+
Abi.wordSize32Align32: {NativeType.kDouble: 4, NativeType.kInt64: 4},
137+
138+
// The default for MSVC x86:
139+
// > The alignment-requirement for all data except structures, unions, and
140+
// > arrays is either the size of the object or the current packing size
141+
// > (specified with either /Zp or the pack pragma, whichever is less).
142+
// https://docs.microsoft.com/en-us/cpp/c-language/padding-and-alignment-of-structure-members?view=vs-2019
143+
//
144+
// GCC _can_ compile on Linux to this alignment with -malign-double, but does
145+
// not do so by default:
146+
// > Warning: if you use the -malign-double switch, structures containing the
147+
// > above types are aligned differently than the published application
148+
// > binary interface specifications for the x86-32 and are not binary
149+
// > compatible with structures in code compiled without that switch.
150+
// https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
151+
//
152+
// Arm always requires 8 byte alignment for 8 byte values:
153+
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf 4.1 Fundamental Data Types
154+
Abi.wordSize32Align64: {},
155+
};
156+
89157
/// [FfiTransformer] contains logic which is shared between
90158
/// _FfiUseSiteTransformer and _FfiDefinitionTransformer.
91159
class FfiTransformer extends Transformer {
@@ -98,6 +166,7 @@ class FfiTransformer extends Transformer {
98166
final Class intClass;
99167
final Class doubleClass;
100168
final Constructor pragmaConstructor;
169+
final Procedure listElementAt;
101170

102171
final Library ffiLibrary;
103172
final Class nativeFunctionClass;
@@ -114,6 +183,7 @@ class FfiTransformer extends Transformer {
114183
final Field addressOfField;
115184
final Constructor structFromPointer;
116185
final Procedure libraryLookupMethod;
186+
final Procedure abiMethod;
117187

118188
/// Classes corresponding to [NativeType], indexed by [NativeType].
119189
final List<Class> nativeTypesClasses;
@@ -124,6 +194,7 @@ class FfiTransformer extends Transformer {
124194
intClass = coreTypes.intClass,
125195
doubleClass = coreTypes.doubleClass,
126196
pragmaConstructor = coreTypes.pragmaConstructor,
197+
listElementAt = coreTypes.index.getMember('dart:core', 'List', '[]'),
127198
ffiLibrary = index.getLibrary('dart:ffi'),
128199
nativeFunctionClass = index.getClass('dart:ffi', 'NativeFunction'),
129200
pointerClass = index.getClass('dart:ffi', 'Pointer'),
@@ -144,6 +215,7 @@ class FfiTransformer extends Transformer {
144215
index.getMember('dart:ffi', 'Pointer', 'fromFunction'),
145216
libraryLookupMethod =
146217
index.getMember('dart:ffi', 'DynamicLibrary', 'lookup'),
218+
abiMethod = index.getTopLevelMember('dart:ffi', '_abi'),
147219
nativeTypesClasses = nativeTypeClassNames
148220
.map((name) => index.getClass('dart:ffi', name))
149221
.toList();

0 commit comments

Comments
 (0)