blob: 795574adc55b310bfebdd483e13e358be40e90a8 [file] [log] [blame]
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'common.dart';
/// The hardware architectures the Dart VM runs on.
enum _Architecture {
arm,
arm64,
ia32,
x64,
}
extension on _Architecture {
/// The size of integer registers and memory addresses in bytes.
int get wordSize {
switch (this) {
case _Architecture.arm:
case _Architecture.ia32:
return 4;
case _Architecture.arm64:
case _Architecture.x64:
return 8;
}
}
}
/// The operating systems the Dart VM runs on.
enum _OS {
android,
fuchsia,
ios,
linux,
macos,
windows,
}
/// Application binary interface.
///
/// The Dart VM can run on a variety of [Abi]s, see [supportedAbis].
class Abi {
/// The operating system of this [Abi].
// ignore: unused_field
final _OS _os;
/// The architecture of this [Abi].
final _Architecture _architecture;
/// The size of integer registers and memory addresses in bytes.
int get wordSize => _architecture.wordSize;
const Abi._(this._architecture, this._os);
}
const androidArm = Abi._(_Architecture.arm, _OS.android);
const androidArm64 = Abi._(_Architecture.arm64, _OS.android);
const androidIA32 = Abi._(_Architecture.ia32, _OS.android);
const androidX64 = Abi._(_Architecture.x64, _OS.android);
const fuchsiaArm64 = Abi._(_Architecture.arm64, _OS.fuchsia);
const fuchsiaX64 = Abi._(_Architecture.x64, _OS.fuchsia);
const iosArm = Abi._(_Architecture.arm, _OS.ios);
const iosArm64 = Abi._(_Architecture.arm64, _OS.ios);
const iosX64 = Abi._(_Architecture.x64, _OS.ios);
const linuxArm = Abi._(_Architecture.arm, _OS.linux);
const linuxArm64 = Abi._(_Architecture.arm64, _OS.linux);
const linuxIA32 = Abi._(_Architecture.ia32, _OS.linux);
const linuxX64 = Abi._(_Architecture.x64, _OS.linux);
const macosArm64 = Abi._(_Architecture.arm64, _OS.macos);
// No macosIA32, not intending to support.
// https://github.com/dart-lang/sdk/issues/39810
const macosX64 = Abi._(_Architecture.x64, _OS.macos);
/// Currently not supported, but feature requested for Flutter.
/// https://github.com/flutter/flutter/issues/53120
const windowsArm64 = Abi._(_Architecture.arm64, _OS.windows);
const windowsIA32 = Abi._(_Architecture.ia32, _OS.windows);
const windowsX64 = Abi._(_Architecture.x64, _OS.windows);
/// All ABIs that the DartVM can run on sorted alphabetically.
///
/// Keep consistent with runtime/vm/compiler/ffi/abi.cc.
const supportedAbisOrdered = [
androidArm,
androidArm64,
androidIA32,
androidX64,
fuchsiaArm64,
fuchsiaX64,
iosArm,
iosArm64,
iosX64,
linuxArm,
linuxArm64,
linuxIA32,
linuxX64,
macosArm64,
macosX64,
windowsArm64,
windowsIA32,
windowsX64,
];
/// The size of integer registers and memory addresses in bytes per [Abi].
// Keep consistent with sdk/lib/_internal/vm/lib/ffi_patch.dart
final Map<Abi, int> wordSize = {
for (final abi in supportedAbisOrdered) abi: abi.wordSize
};
/// Struct and union fields that are not aligned to their size.
///
/// Has an entry for all Abis. Empty entries document that every native
/// type is aligned to it's own size in this ABI.
///
/// See runtime/vm/compiler/ffi/abi.cc for asserts in the VM that verify these
/// alignments.
const nonSizeAlignment = <Abi, Map<NativeType, int>>{
// _wordSize64
androidArm64: _wordSize64,
androidX64: _wordSize64,
fuchsiaArm64: _wordSize64,
fuchsiaX64: _wordSize64,
iosArm64: _wordSize64,
iosX64: _wordSize64,
linuxArm64: _wordSize64,
linuxX64: _wordSize64,
macosArm64: _wordSize64,
macosX64: _wordSize64,
windowsArm64: _wordSize64,
windowsX64: _wordSize64,
// _wordSize32Align32
androidIA32: _wordSize32Align32,
iosArm: _wordSize32Align32,
linuxIA32: _wordSize32Align32,
// _wordSize32Align64
androidArm: _wordSize32Align64,
linuxArm: _wordSize32Align64,
windowsIA32: _wordSize32Align64,
};
// All 64 bit ABIs align struct fields to their size.
const Map<NativeType, int> _wordSize64 = {};
// x86 System V ABI:
// > uint64_t | size 8 | alignment 4
// > double | size 8 | alignment 4
// https://github.com/hjl-tools/x86-psABI/wiki/intel386-psABI-1.1.pdf page 8.
//
// ios 32 bit alignment:
// https://developer.apple.com/documentation/uikit/app_and_environment/updating_your_app_from_32-bit_to_64-bit_architecture/updating_data_structures
const Map<NativeType, int> _wordSize32Align32 = {
NativeType.kDouble: 4,
NativeType.kInt64: 4,
NativeType.kUint64: 4
};
// The default for MSVC x86:
// > The alignment-requirement for all data except structures, unions, and
// > arrays is either the size of the object or the current packing size
// > (specified with either /Zp or the pack pragma, whichever is less).
// https://docs.microsoft.com/en-us/cpp/c-language/padding-and-alignment-of-structure-members?view=vs-2019
//
// GCC _can_ compile on Linux to this alignment with -malign-double, but does
// not do so by default:
// > Warning: if you use the -malign-double switch, structures containing the
// > above types are aligned differently than the published application
// > binary interface specifications for the x86-32 and are not binary
// > compatible with structures in code compiled without that switch.
// https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
//
// ARM always requires 8 byte alignment for 8 byte values:
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf 4.1 Fundamental Data Types
const Map<NativeType, int> _wordSize32Align64 = {};