@@ -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.
91156class 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