mirror of https://github.com/rust-lang/rust.git
Add support for Arm64EC to the Standard Library
This commit is contained in:
parent
99d0186b1d
commit
32f5ca4be7
|
@ -6330,9 +6330,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-bindgen"
|
||||
version = "0.55.0"
|
||||
version = "0.56.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "073ff8a486ebad239d557809d2cd5fe5e04ee1de29e09c6cd83fb0bae19b8a4c"
|
||||
checksum = "a28e3ea6330cf17fdcdce8bf08d0549ce93769dca9bedc6c39c36c8c0e17db46"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"rayon",
|
||||
|
@ -6353,9 +6353,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-metadata"
|
||||
version = "0.55.0"
|
||||
version = "0.56.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b602635050172a1fc57a35040d4d225baefc6098fefd97094919921d95961a7d"
|
||||
checksum = "3993f7827fff10c454e3a24847075598c7c08108304b8b07943c2c73d78f3b34"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
|
|
|
@ -415,6 +415,7 @@ impl<'a> LlvmArchiveBuilder<'a> {
|
|||
members.as_ptr() as *const &_,
|
||||
true,
|
||||
kind,
|
||||
self.sess.target.arch == "arm64ec",
|
||||
);
|
||||
let ret = if r.into_result().is_err() {
|
||||
let err = llvm::LLVMRustGetLastError();
|
||||
|
|
|
@ -2303,6 +2303,7 @@ extern "C" {
|
|||
Members: *const &RustArchiveMember<'_>,
|
||||
WriteSymbtab: bool,
|
||||
Kind: ArchiveKind,
|
||||
isEC: bool,
|
||||
) -> LLVMRustResult;
|
||||
pub fn LLVMRustArchiveMemberNew<'a>(
|
||||
Filename: *const c_char,
|
||||
|
|
|
@ -175,7 +175,7 @@ extern "C" void LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
|
|||
extern "C" LLVMRustResult
|
||||
LLVMRustWriteArchive(char *Dst, size_t NumMembers,
|
||||
const LLVMRustArchiveMemberRef *NewMembers,
|
||||
bool WriteSymbtab, LLVMRustArchiveKind RustKind) {
|
||||
bool WriteSymbtab, LLVMRustArchiveKind RustKind, bool isEC) {
|
||||
|
||||
std::vector<NewArchiveMember> Members;
|
||||
auto Kind = fromRust(RustKind);
|
||||
|
@ -207,7 +207,7 @@ LLVMRustWriteArchive(char *Dst, size_t NumMembers,
|
|||
auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false);
|
||||
#else
|
||||
auto SymtabMode = WriteSymbtab ? SymtabWritingMode::NormalSymtab : SymtabWritingMode::NoSymtab;
|
||||
auto Result = writeArchive(Dst, Members, SymtabMode, Kind, true, false);
|
||||
auto Result = writeArchive(Dst, Members, SymtabMode, Kind, true, false, nullptr, isEC);
|
||||
#endif
|
||||
if (!Result)
|
||||
return LLVMRustResult::Success;
|
||||
|
|
|
@ -237,7 +237,7 @@ pub fn spin_loop() {
|
|||
crate::arch::riscv64::pause();
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
|
||||
{
|
||||
// SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
|
||||
unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) };
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
|
||||
#![panic_runtime]
|
||||
#![allow(unused_features)]
|
||||
#![feature(asm_experimental_arch)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(panic_runtime)]
|
||||
#![feature(std_internals)]
|
||||
|
@ -78,7 +79,7 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
|
|||
core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
|
||||
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
|
||||
core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
|
||||
} else if #[cfg(target_arch = "aarch64")] {
|
||||
} else if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] {
|
||||
core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
|
||||
} else {
|
||||
core::intrinsics::abort();
|
||||
|
|
|
@ -277,6 +277,7 @@
|
|||
#![feature(allocator_internals)]
|
||||
#![feature(allow_internal_unsafe)]
|
||||
#![feature(allow_internal_unstable)]
|
||||
#![feature(asm_experimental_arch)]
|
||||
#![feature(c_unwind)]
|
||||
#![feature(cfg_sanitizer_cfi)]
|
||||
#![feature(cfg_target_thread_local)]
|
||||
|
|
|
@ -23,6 +23,7 @@ pub const MIN_ALIGN: usize = 8;
|
|||
#[cfg(any(
|
||||
target_arch = "x86_64",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "arm64ec",
|
||||
target_arch = "loongarch64",
|
||||
target_arch = "mips64",
|
||||
target_arch = "mips64r6",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Bindings generated by `windows-bindgen` 0.55.0
|
||||
// Bindings generated by `windows-bindgen` 0.56.0
|
||||
|
||||
#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]
|
||||
#[link(name = "advapi32")]
|
||||
|
@ -345,7 +345,7 @@ extern "system" {
|
|||
}
|
||||
#[link(name = "kernel32")]
|
||||
extern "system" {
|
||||
pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> ();
|
||||
pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME);
|
||||
}
|
||||
#[link(name = "kernel32")]
|
||||
extern "system" {
|
||||
|
@ -1018,7 +1018,7 @@ impl Clone for CONTEXT_0_0 {
|
|||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
pub struct CONTEXT {
|
||||
pub P1Home: u64,
|
||||
pub P2Home: u64,
|
||||
|
@ -1067,30 +1067,30 @@ pub struct CONTEXT {
|
|||
pub LastExceptionToRip: u64,
|
||||
pub LastExceptionFromRip: u64,
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Copy for CONTEXT {}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Clone for CONTEXT {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
pub union CONTEXT_0 {
|
||||
pub FltSave: XSAVE_FORMAT,
|
||||
pub Anonymous: CONTEXT_0_0,
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Copy for CONTEXT_0 {}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Clone for CONTEXT_0 {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
pub struct CONTEXT_0_0 {
|
||||
pub Header: [M128A; 2],
|
||||
pub Legacy: [M128A; 8],
|
||||
|
@ -1111,9 +1111,9 @@ pub struct CONTEXT_0_0 {
|
|||
pub Xmm14: M128A,
|
||||
pub Xmm15: M128A,
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Copy for CONTEXT_0_0 {}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Clone for CONTEXT_0_0 {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
|
@ -3339,7 +3339,7 @@ pub const FILE_WRITE_EA: FILE_ACCESS_RIGHTS = 16u32;
|
|||
pub const FILE_WRITE_THROUGH: NTCREATEFILE_CREATE_OPTIONS = 2u32;
|
||||
pub const FIONBIO: i32 = -2147195266i32;
|
||||
#[repr(C)]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
pub struct FLOATING_SAVE_AREA {
|
||||
pub ControlWord: u32,
|
||||
pub StatusWord: u32,
|
||||
|
@ -3351,9 +3351,9 @@ pub struct FLOATING_SAVE_AREA {
|
|||
pub RegisterArea: [u8; 80],
|
||||
pub Cr0NpxState: u32,
|
||||
}
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Copy for FLOATING_SAVE_AREA {}
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Clone for FLOATING_SAVE_AREA {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
|
@ -4106,7 +4106,7 @@ impl Clone for WSABUF {
|
|||
}
|
||||
}
|
||||
#[repr(C)]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
pub struct WSADATA {
|
||||
pub wVersion: u16,
|
||||
pub wHighVersion: u16,
|
||||
|
@ -4116,9 +4116,9 @@ pub struct WSADATA {
|
|||
pub szDescription: [i8; 257],
|
||||
pub szSystemStatus: [i8; 129],
|
||||
}
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Copy for WSADATA {}
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Clone for WSADATA {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
|
@ -4286,7 +4286,7 @@ pub const WSA_SECURE_HOST_NOT_FOUND: WSA_ERROR = 11032i32;
|
|||
pub const WSA_WAIT_EVENT_0: WSA_ERROR = 0i32;
|
||||
pub const WSA_WAIT_IO_COMPLETION: WSA_ERROR = 192i32;
|
||||
#[repr(C)]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
pub struct XSAVE_FORMAT {
|
||||
pub ControlWord: u16,
|
||||
pub StatusWord: u16,
|
||||
|
@ -4305,9 +4305,9 @@ pub struct XSAVE_FORMAT {
|
|||
pub XmmRegisters: [M128A; 16],
|
||||
pub Reserved4: [u8; 96],
|
||||
}
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Copy for XSAVE_FORMAT {}
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
|
||||
impl Clone for XSAVE_FORMAT {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
|
|
|
@ -332,7 +332,7 @@ pub fn abort_internal() -> ! {
|
|||
core::arch::asm!("int $$0x29", in("ecx") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
|
||||
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
|
||||
core::arch::asm!(".inst 0xDEFB", in("r0") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
|
||||
} else if #[cfg(target_arch = "aarch64")] {
|
||||
} else if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] {
|
||||
core::arch::asm!("brk 0xF003", in("x0") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
|
||||
} else {
|
||||
core::intrinsics::abort();
|
||||
|
|
|
@ -11,48 +11,69 @@ applications on AArch64 Windows 11. See <https://learn.microsoft.com/en-us/windo
|
|||
|
||||
## Requirements
|
||||
|
||||
Target only supports cross-compilation, `core` and `alloc` are supported but
|
||||
`std` is not.
|
||||
|
||||
Builds Arm64EC static and dynamic libraries and executables which can be run on
|
||||
AArch64 Windows 11 devices. Arm64EC static libraries can also be linked into
|
||||
Arm64X dynamic libraries and executables.
|
||||
|
||||
Uses `arm64ec` as its `target_arch` - code built for Arm64EC must be compatible
|
||||
with x86_64 code (e.g., same structure layouts, function signatures, etc.) but
|
||||
use AArch64 intrinsics.
|
||||
Only supported backend is LLVM 18 or above:
|
||||
* 18.1.0 added initial support for Arm64EC.
|
||||
* 18.1.2 fixed import library generation (required for `raw-dylib` support).
|
||||
* 18.1.4 fixed linking issue for some intrinsics implemented in
|
||||
`compiler_builtins`.
|
||||
|
||||
Only supported backend is LLVM 18 (or above).
|
||||
### Reusing code from other architectures - x86_64 or AArch64?
|
||||
|
||||
Arm64EC uses `arm64ec` as its `target_arch`, but it is possible to reuse
|
||||
existing architecture-specific code in most cases. The best mental model for
|
||||
deciding which architecture to reuse is to is to think of Arm64EC as an x86_64
|
||||
process that happens to use the AArch64 instruction set (with some caveats) and
|
||||
has a completely custom ABI.
|
||||
|
||||
To put this in practice:
|
||||
* Arm64EC interacts with the operating system, other processes and other DLLs as
|
||||
x86_64.
|
||||
- For example, [in `backtrace`](https://github.com/rust-lang/backtrace-rs/commit/ef39a7d7da58b4cae8c8f3fc67a8300fd8d2d0d9)
|
||||
we use the x86_64 versions of `CONTEXT` and `RtlVirtualUnwind`.
|
||||
- If you are configuring a search path to find DLLs (e.g., to load plugins or
|
||||
addons into your application), you should use the same path as the x86_64
|
||||
version of your application, not the AArch64 path (since Arm64EC (i.e.,
|
||||
x86_64) processes cannot load native AArch64 DLLs).
|
||||
* Arm64EC uses AArch64 intrinsics.
|
||||
- For example, <https://github.com/rust-lang/portable-simd/commit/ca4033f49b1f6019561b8b161b4097b4a07f2e1b>
|
||||
and <https://github.com/rust-lang/stdarch/commit/166ef7ba22b6a1d908d4b29a36e68ceca324808a>.
|
||||
* Assembly for AArch64 might be reusable for Arm64EC, but there are many
|
||||
caveats. For full details see [Microsoft's documentation on the Arm64EC ABI](https://learn.microsoft.com/en-us/windows/arm/arm64ec-abi)
|
||||
but in brief:
|
||||
- Arm64EC uses a subset of AArch64 registers.
|
||||
- Arm64EC uses a different name mangling scheme than AArch64.
|
||||
- Arm64EC requires entry and exit thunks be generated for some functions.
|
||||
- Indirect calls must be done via a call checker.
|
||||
- Control Flow Guard and stack checks use different functions than AArch64.
|
||||
|
||||
## Building the target
|
||||
|
||||
You can build Rust with support for the targets by adding it to the `target`
|
||||
list in `config.toml` and disabling `std`:
|
||||
list in `config.toml`:
|
||||
|
||||
```toml
|
||||
[build]
|
||||
target = [ "arm64ec-pc-windows-msvc" ]
|
||||
|
||||
[target.arm64ec-pc-windows-msvc]
|
||||
no-std = true
|
||||
```
|
||||
|
||||
## Building Rust programs
|
||||
|
||||
Rust does not yet ship pre-compiled artifacts for this target. To compile for
|
||||
this target, you will either need to build Rust with the target enabled (see
|
||||
"Building the target" above), or build your own copy of `core` by using
|
||||
`build-std` or similar.
|
||||
"Building the target" above), or build your own copy using `build-std` or
|
||||
similar.
|
||||
|
||||
## Testing
|
||||
|
||||
Tests can be run on AArch64 Windows 11 devices.
|
||||
|
||||
Since this is a `no_std` target, the Rust test suite is not supported.
|
||||
|
||||
## Cross-compilation toolchains and C code
|
||||
|
||||
C code can be built using the Arm64-targetting MSVC toolchain.
|
||||
C code can be built using the Arm64-targetting MSVC or Clang toolchain.
|
||||
|
||||
To compile:
|
||||
|
||||
|
|
|
@ -4,4 +4,4 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies.windows-bindgen]
|
||||
version = "0.55.0"
|
||||
version = "0.56.0"
|
||||
|
|
Loading…
Reference in New Issue