From 32f5ca4be7fc71274879800cb51c90ccdb7f35a5 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Wed, 27 Mar 2024 10:49:21 -0700 Subject: [PATCH] Add support for Arm64EC to the Standard Library --- Cargo.lock | 8 +-- .../rustc_codegen_llvm/src/back/archive.rs | 1 + compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 + .../llvm-wrapper/ArchiveWrapper.cpp | 4 +- library/core/src/hint.rs | 2 +- library/panic_abort/src/lib.rs | 3 +- library/std/src/lib.rs | 1 + library/std/src/sys/pal/common/alloc.rs | 1 + .../std/src/sys/pal/windows/c/windows_sys.rs | 40 +++++++------- library/std/src/sys/pal/windows/mod.rs | 2 +- .../arm64ec-pc-windows-msvc.md | 53 +++++++++++++------ src/tools/generate-windows-sys/Cargo.toml | 2 +- 12 files changed, 72 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f26dd7c43c..7a500078dbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 0619000364b..d4a3e39cef7 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -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(); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 5509baaa3e9..83158f6f1d5 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2303,6 +2303,7 @@ extern "C" { Members: *const &RustArchiveMember<'_>, WriteSymbtab: bool, Kind: ArchiveKind, + isEC: bool, ) -> LLVMRustResult; pub fn LLVMRustArchiveMemberNew<'a>( Filename: *const c_char, diff --git a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp index 64e6c18092f..8871f410e36 100644 --- a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp @@ -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 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; diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index b27d0db4619..6e2d88c6b83 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -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) }; diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index a6d07fd1984..353de8c5c57 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -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(); diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 72ae38cfa20..9a741bed348 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -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)] diff --git a/library/std/src/sys/pal/common/alloc.rs b/library/std/src/sys/pal/common/alloc.rs index 8cf9ef68047..598b6db71f5 100644 --- a/library/std/src/sys/pal/common/alloc.rs +++ b/library/std/src/sys/pal/common/alloc.rs @@ -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", diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index d180122d735..1da8871ae44 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -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 diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index a734c2bd4c7..b49585599cb 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -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(); diff --git a/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md index 1bb2c677b08..9fd0ac49881 100644 --- a/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md +++ b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md @@ -11,48 +11,69 @@ applications on AArch64 Windows 11. See + and . +* 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: diff --git a/src/tools/generate-windows-sys/Cargo.toml b/src/tools/generate-windows-sys/Cargo.toml index 9ea26defdc4..8b971d6efe7 100644 --- a/src/tools/generate-windows-sys/Cargo.toml +++ b/src/tools/generate-windows-sys/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies.windows-bindgen] -version = "0.55.0" +version = "0.56.0"