Skip to content

Commit 32f5ca4

Browse files
committed
Add support for Arm64EC to the Standard Library
1 parent 99d0186 commit 32f5ca4

File tree

12 files changed

+73
-47
lines changed

12 files changed

+73
-47
lines changed

Cargo.lock

+4-4
Original file line numberDiff line numberDiff line change
@@ -6330,9 +6330,9 @@ dependencies = [
63306330

63316331
[[package]]
63326332
name = "windows-bindgen"
6333-
version = "0.55.0"
6333+
version = "0.56.0"
63346334
source = "registry+https://github.com/rust-lang/crates.io-index"
6335-
checksum = "073ff8a486ebad239d557809d2cd5fe5e04ee1de29e09c6cd83fb0bae19b8a4c"
6335+
checksum = "a28e3ea6330cf17fdcdce8bf08d0549ce93769dca9bedc6c39c36c8c0e17db46"
63366336
dependencies = [
63376337
"proc-macro2",
63386338
"rayon",
@@ -6353,9 +6353,9 @@ dependencies = [
63536353

63546354
[[package]]
63556355
name = "windows-metadata"
6356-
version = "0.55.0"
6356+
version = "0.56.0"
63576357
source = "registry+https://github.com/rust-lang/crates.io-index"
6358-
checksum = "b602635050172a1fc57a35040d4d225baefc6098fefd97094919921d95961a7d"
6358+
checksum = "3993f7827fff10c454e3a24847075598c7c08108304b8b07943c2c73d78f3b34"
63596359

63606360
[[package]]
63616361
name = "windows-sys"

compiler/rustc_codegen_llvm/src/back/archive.rs

+1
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ impl<'a> LlvmArchiveBuilder<'a> {
415415
members.as_ptr() as *const &_,
416416
true,
417417
kind,
418+
self.sess.target.arch == "arm64ec",
418419
);
419420
let ret = if r.into_result().is_err() {
420421
let err = llvm::LLVMRustGetLastError();

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2303,6 +2303,7 @@ extern "C" {
23032303
Members: *const &RustArchiveMember<'_>,
23042304
WriteSymbtab: bool,
23052305
Kind: ArchiveKind,
2306+
isEC: bool,
23062307
) -> LLVMRustResult;
23072308
pub fn LLVMRustArchiveMemberNew<'a>(
23082309
Filename: *const c_char,

compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ extern "C" void LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
175175
extern "C" LLVMRustResult
176176
LLVMRustWriteArchive(char *Dst, size_t NumMembers,
177177
const LLVMRustArchiveMemberRef *NewMembers,
178-
bool WriteSymbtab, LLVMRustArchiveKind RustKind) {
178+
bool WriteSymbtab, LLVMRustArchiveKind RustKind, bool isEC) {
179179

180180
std::vector<NewArchiveMember> Members;
181181
auto Kind = fromRust(RustKind);
@@ -207,7 +207,7 @@ LLVMRustWriteArchive(char *Dst, size_t NumMembers,
207207
auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false);
208208
#else
209209
auto SymtabMode = WriteSymbtab ? SymtabWritingMode::NormalSymtab : SymtabWritingMode::NoSymtab;
210-
auto Result = writeArchive(Dst, Members, SymtabMode, Kind, true, false);
210+
auto Result = writeArchive(Dst, Members, SymtabMode, Kind, true, false, nullptr, isEC);
211211
#endif
212212
if (!Result)
213213
return LLVMRustResult::Success;

library/core/src/hint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ pub fn spin_loop() {
237237
crate::arch::riscv64::pause();
238238
}
239239

240-
#[cfg(target_arch = "aarch64")]
240+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
241241
{
242242
// SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
243243
unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) };

library/panic_abort/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
99
#![panic_runtime]
1010
#![allow(unused_features)]
11+
#![feature(asm_experimental_arch)]
1112
#![feature(core_intrinsics)]
1213
#![feature(panic_runtime)]
1314
#![feature(std_internals)]
@@ -78,7 +79,7 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 {
7879
core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
7980
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
8081
core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
81-
} else if #[cfg(target_arch = "aarch64")] {
82+
} else if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] {
8283
core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
8384
} else {
8485
core::intrinsics::abort();

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@
277277
#![feature(allocator_internals)]
278278
#![feature(allow_internal_unsafe)]
279279
#![feature(allow_internal_unstable)]
280+
#![feature(asm_experimental_arch)]
280281
#![feature(c_unwind)]
281282
#![feature(cfg_sanitizer_cfi)]
282283
#![feature(cfg_target_thread_local)]

library/std/src/sys/pal/common/alloc.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub const MIN_ALIGN: usize = 8;
2323
#[cfg(any(
2424
target_arch = "x86_64",
2525
target_arch = "aarch64",
26+
target_arch = "arm64ec",
2627
target_arch = "loongarch64",
2728
target_arch = "mips64",
2829
target_arch = "mips64r6",

library/std/src/sys/pal/windows/c/windows_sys.rs

+20-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Bindings generated by `windows-bindgen` 0.55.0
1+
// Bindings generated by `windows-bindgen` 0.56.0
22

33
#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]
44
#[link(name = "advapi32")]
@@ -345,7 +345,7 @@ extern "system" {
345345
}
346346
#[link(name = "kernel32")]
347347
extern "system" {
348-
pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> ();
348+
pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME);
349349
}
350350
#[link(name = "kernel32")]
351351
extern "system" {
@@ -1018,7 +1018,7 @@ impl Clone for CONTEXT_0_0 {
10181018
}
10191019
}
10201020
#[repr(C)]
1021-
#[cfg(target_arch = "x86_64")]
1021+
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
10221022
pub struct CONTEXT {
10231023
pub P1Home: u64,
10241024
pub P2Home: u64,
@@ -1067,30 +1067,30 @@ pub struct CONTEXT {
10671067
pub LastExceptionToRip: u64,
10681068
pub LastExceptionFromRip: u64,
10691069
}
1070-
#[cfg(target_arch = "x86_64")]
1070+
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
10711071
impl Copy for CONTEXT {}
1072-
#[cfg(target_arch = "x86_64")]
1072+
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
10731073
impl Clone for CONTEXT {
10741074
fn clone(&self) -> Self {
10751075
*self
10761076
}
10771077
}
10781078
#[repr(C)]
1079-
#[cfg(target_arch = "x86_64")]
1079+
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
10801080
pub union CONTEXT_0 {
10811081
pub FltSave: XSAVE_FORMAT,
10821082
pub Anonymous: CONTEXT_0_0,
10831083
}
1084-
#[cfg(target_arch = "x86_64")]
1084+
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
10851085
impl Copy for CONTEXT_0 {}
1086-
#[cfg(target_arch = "x86_64")]
1086+
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
10871087
impl Clone for CONTEXT_0 {
10881088
fn clone(&self) -> Self {
10891089
*self
10901090
}
10911091
}
10921092
#[repr(C)]
1093-
#[cfg(target_arch = "x86_64")]
1093+
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
10941094
pub struct CONTEXT_0_0 {
10951095
pub Header: [M128A; 2],
10961096
pub Legacy: [M128A; 8],
@@ -1111,9 +1111,9 @@ pub struct CONTEXT_0_0 {
11111111
pub Xmm14: M128A,
11121112
pub Xmm15: M128A,
11131113
}
1114-
#[cfg(target_arch = "x86_64")]
1114+
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
11151115
impl Copy for CONTEXT_0_0 {}
1116-
#[cfg(target_arch = "x86_64")]
1116+
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
11171117
impl Clone for CONTEXT_0_0 {
11181118
fn clone(&self) -> Self {
11191119
*self
@@ -3339,7 +3339,7 @@ pub const FILE_WRITE_EA: FILE_ACCESS_RIGHTS = 16u32;
33393339
pub const FILE_WRITE_THROUGH: NTCREATEFILE_CREATE_OPTIONS = 2u32;
33403340
pub const FIONBIO: i32 = -2147195266i32;
33413341
#[repr(C)]
3342-
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
3342+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
33433343
pub struct FLOATING_SAVE_AREA {
33443344
pub ControlWord: u32,
33453345
pub StatusWord: u32,
@@ -3351,9 +3351,9 @@ pub struct FLOATING_SAVE_AREA {
33513351
pub RegisterArea: [u8; 80],
33523352
pub Cr0NpxState: u32,
33533353
}
3354-
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
3354+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
33553355
impl Copy for FLOATING_SAVE_AREA {}
3356-
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
3356+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
33573357
impl Clone for FLOATING_SAVE_AREA {
33583358
fn clone(&self) -> Self {
33593359
*self
@@ -4106,7 +4106,7 @@ impl Clone for WSABUF {
41064106
}
41074107
}
41084108
#[repr(C)]
4109-
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
4109+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
41104110
pub struct WSADATA {
41114111
pub wVersion: u16,
41124112
pub wHighVersion: u16,
@@ -4116,9 +4116,9 @@ pub struct WSADATA {
41164116
pub szDescription: [i8; 257],
41174117
pub szSystemStatus: [i8; 129],
41184118
}
4119-
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
4119+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
41204120
impl Copy for WSADATA {}
4121-
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
4121+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
41224122
impl Clone for WSADATA {
41234123
fn clone(&self) -> Self {
41244124
*self
@@ -4286,7 +4286,7 @@ pub const WSA_SECURE_HOST_NOT_FOUND: WSA_ERROR = 11032i32;
42864286
pub const WSA_WAIT_EVENT_0: WSA_ERROR = 0i32;
42874287
pub const WSA_WAIT_IO_COMPLETION: WSA_ERROR = 192i32;
42884288
#[repr(C)]
4289-
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
4289+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
42904290
pub struct XSAVE_FORMAT {
42914291
pub ControlWord: u16,
42924292
pub StatusWord: u16,
@@ -4305,9 +4305,9 @@ pub struct XSAVE_FORMAT {
43054305
pub XmmRegisters: [M128A; 16],
43064306
pub Reserved4: [u8; 96],
43074307
}
4308-
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
4308+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
43094309
impl Copy for XSAVE_FORMAT {}
4310-
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
4310+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
43114311
impl Clone for XSAVE_FORMAT {
43124312
fn clone(&self) -> Self {
43134313
*self

library/std/src/sys/pal/windows/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ pub fn abort_internal() -> ! {
332332
core::arch::asm!("int $$0x29", in("ecx") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
333333
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
334334
core::arch::asm!(".inst 0xDEFB", in("r0") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
335-
} else if #[cfg(target_arch = "aarch64")] {
335+
} else if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] {
336336
core::arch::asm!("brk 0xF003", in("x0") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
337337
} else {
338338
core::intrinsics::abort();

src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md

+38-17
Original file line numberDiff line numberDiff line change
@@ -11,48 +11,69 @@ applications on AArch64 Windows 11. See <https://learn.microsoft.com/en-us/windo
1111

1212
## Requirements
1313

14-
Target only supports cross-compilation, `core` and `alloc` are supported but
15-
`std` is not.
16-
1714
Builds Arm64EC static and dynamic libraries and executables which can be run on
1815
AArch64 Windows 11 devices. Arm64EC static libraries can also be linked into
1916
Arm64X dynamic libraries and executables.
2017

21-
Uses `arm64ec` as its `target_arch` - code built for Arm64EC must be compatible
22-
with x86_64 code (e.g., same structure layouts, function signatures, etc.) but
23-
use AArch64 intrinsics.
24-
25-
Only supported backend is LLVM 18 (or above).
18+
Only supported backend is LLVM 18 or above:
19+
* 18.1.0 added initial support for Arm64EC.
20+
* 18.1.2 fixed import library generation (required for `raw-dylib` support).
21+
* 18.1.4 fixed linking issue for some intrinsics implemented in
22+
`compiler_builtins`.
23+
24+
### Reusing code from other architectures - x86_64 or AArch64?
25+
26+
Arm64EC uses `arm64ec` as its `target_arch`, but it is possible to reuse
27+
existing architecture-specific code in most cases. The best mental model for
28+
deciding which architecture to reuse is to is to think of Arm64EC as an x86_64
29+
process that happens to use the AArch64 instruction set (with some caveats) and
30+
has a completely custom ABI.
31+
32+
To put this in practice:
33+
* Arm64EC interacts with the operating system, other processes and other DLLs as
34+
x86_64.
35+
- For example, [in `backtrace`](https://github.com/rust-lang/backtrace-rs/commit/ef39a7d7da58b4cae8c8f3fc67a8300fd8d2d0d9)
36+
we use the x86_64 versions of `CONTEXT` and `RtlVirtualUnwind`.
37+
- If you are configuring a search path to find DLLs (e.g., to load plugins or
38+
addons into your application), you should use the same path as the x86_64
39+
version of your application, not the AArch64 path (since Arm64EC (i.e.,
40+
x86_64) processes cannot load native AArch64 DLLs).
41+
* Arm64EC uses AArch64 intrinsics.
42+
- For example, <https://github.com/rust-lang/portable-simd/commit/ca4033f49b1f6019561b8b161b4097b4a07f2e1b>
43+
and <https://github.com/rust-lang/stdarch/commit/166ef7ba22b6a1d908d4b29a36e68ceca324808a>.
44+
* Assembly for AArch64 might be reusable for Arm64EC, but there are many
45+
caveats. For full details see [Microsoft's documentation on the Arm64EC ABI](https://learn.microsoft.com/en-us/windows/arm/arm64ec-abi)
46+
but in brief:
47+
- Arm64EC uses a subset of AArch64 registers.
48+
- Arm64EC uses a different name mangling scheme than AArch64.
49+
- Arm64EC requires entry and exit thunks be generated for some functions.
50+
- Indirect calls must be done via a call checker.
51+
- Control Flow Guard and stack checks use different functions than AArch64.
2652

2753
## Building the target
2854

2955
You can build Rust with support for the targets by adding it to the `target`
30-
list in `config.toml` and disabling `std`:
56+
list in `config.toml`:
3157

3258
```toml
3359
[build]
3460
target = [ "arm64ec-pc-windows-msvc" ]
35-
36-
[target.arm64ec-pc-windows-msvc]
37-
no-std = true
3861
```
3962

4063
## Building Rust programs
4164

4265
Rust does not yet ship pre-compiled artifacts for this target. To compile for
4366
this target, you will either need to build Rust with the target enabled (see
44-
"Building the target" above), or build your own copy of `core` by using
45-
`build-std` or similar.
67+
"Building the target" above), or build your own copy using `build-std` or
68+
similar.
4669

4770
## Testing
4871

4972
Tests can be run on AArch64 Windows 11 devices.
5073

51-
Since this is a `no_std` target, the Rust test suite is not supported.
52-
5374
## Cross-compilation toolchains and C code
5475

55-
C code can be built using the Arm64-targetting MSVC toolchain.
76+
C code can be built using the Arm64-targetting MSVC or Clang toolchain.
5677

5778
To compile:
5879

src/tools/generate-windows-sys/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ version = "0.1.0"
44
edition = "2021"
55

66
[dependencies.windows-bindgen]
7-
version = "0.55.0"
7+
version = "0.56.0"

0 commit comments

Comments
 (0)