diff --git a/Cargo.lock b/Cargo.lock index 117d8c2610e2d..635a50e4e253d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -438,9 +438,11 @@ version = "0.1.0" [[package]] name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +version = "1.0.84" +source = "git+https://github.com/dpaoliello/cc-rs.git?branch=arm64ec#bef78556512ca76e0a6b937ca1236f775edb614d" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -2589,8 +2591,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +source = "git+https://github.com/gimli-rs/object.git#f242fe77355325b2f6fb2040e3fbbf35021dd985" dependencies = [ "compiler_builtins", "crc32fast", diff --git a/Cargo.toml b/Cargo.toml index 9b11ae8744b4f..3815046c1dd65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -110,6 +110,8 @@ object.debug = 0 rustc-std-workspace-core = { path = 'library/rustc-std-workspace-core' } rustc-std-workspace-alloc = { path = 'library/rustc-std-workspace-alloc' } rustc-std-workspace-std = { path = 'library/rustc-std-workspace-std' } +object = { git = 'https://github.com/gimli-rs/object.git' } +cc = { git = 'https://github.com/dpaoliello/cc-rs.git', branch = 'arm64ec' } [patch."https://github.com/rust-lang/rust-clippy"] clippy_lints = { path = "src/tools/clippy/clippy_lints" } diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index cf47c94a81ff8..3c039cab9fd27 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -55,6 +55,7 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType { "x86_64" => LLVMMachineType::AMD64, "x86" => LLVMMachineType::I386, "aarch64" => LLVMMachineType::ARM64, + "arm64ec" => LLVMMachineType::ARM64EC, "arm" => LLVMMachineType::ARM, _ => panic!("unsupported cpu type {cpu}"), } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 81702baa8c053..8a83dadc16693 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -56,6 +56,7 @@ pub enum LLVMMachineType { AMD64 = 0x8664, I386 = 0x14c, ARM64 = 0xaa64, + ARM64EC = 0xa641, ARM = 0x01c0, } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 08519723eba4f..4e04fb7404324 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -204,7 +204,13 @@ impl<'a> IntoIterator for LLVMFeature<'a> { // which might lead to failures if the oldest tested / supported LLVM version // doesn't yet support the relevant intrinsics pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { - let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; + let arch = if sess.target.arch == "x86_64" { + "x86" + } else if sess.target.arch == "arm64ec" { + "aarch64" + } else { + &*sess.target.arch + }; match (arch, s) { ("x86", "sse4.2") => { LLVMFeature::with_dependency("sse4.2", TargetFeatureFoldStrength::EnableOnly("crc32")) diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 172c66a7af13c..d51aceddefa08 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -266,7 +266,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( // Generic x86 "x86" => emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true), // Windows AArch64 - "aarch64" if target.is_like_windows => { + "aarch64" | "arm64ec" if target.is_like_windows => { emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false) } // macOS / iOS AArch64 diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index b683e1b45a8d1..a762c51bbad9d 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -7,7 +7,7 @@ use std::path::Path; use object::write::{self, StandardSegment, Symbol, SymbolSection}; use object::{ elf, pe, xcoff, Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, - ObjectSymbol, SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope, + ObjectSymbol, SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope, }; use rustc_data_structures::memmap::Mmap; @@ -181,37 +181,40 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Endianness::Little, Endian::Big => Endianness::Big, }; - let architecture = match &sess.target.arch[..] { - "arm" => Architecture::Arm, - "aarch64" => { + let (architecture, sub_architecture) = match &sess.target.arch[..] { + "arm" => (Architecture::Arm, None), + "aarch64" => ( if sess.target.pointer_width == 32 { Architecture::Aarch64_Ilp32 } else { Architecture::Aarch64 - } - } - "x86" => Architecture::I386, - "s390x" => Architecture::S390x, - "mips" | "mips32r6" => Architecture::Mips, - "mips64" | "mips64r6" => Architecture::Mips64, - "x86_64" => { + }, + None, + ), + "x86" => (Architecture::I386, None), + "s390x" => (Architecture::S390x, None), + "mips" | "mips32r6" => (Architecture::Mips, None), + "mips64" | "mips64r6" => (Architecture::Mips64, None), + "x86_64" => ( if sess.target.pointer_width == 32 { Architecture::X86_64_X32 } else { Architecture::X86_64 - } - } - "powerpc" => Architecture::PowerPc, - "powerpc64" => Architecture::PowerPc64, - "riscv32" => Architecture::Riscv32, - "riscv64" => Architecture::Riscv64, - "sparc64" => Architecture::Sparc64, - "avr" => Architecture::Avr, - "msp430" => Architecture::Msp430, - "hexagon" => Architecture::Hexagon, - "bpf" => Architecture::Bpf, - "loongarch64" => Architecture::LoongArch64, - "csky" => Architecture::Csky, + }, + None, + ), + "powerpc" => (Architecture::PowerPc, None), + "powerpc64" => (Architecture::PowerPc64, None), + "riscv32" => (Architecture::Riscv32, None), + "riscv64" => (Architecture::Riscv64, None), + "sparc64" => (Architecture::Sparc64, None), + "avr" => (Architecture::Avr, None), + "msp430" => (Architecture::Msp430, None), + "hexagon" => (Architecture::Hexagon, None), + "bpf" => (Architecture::Bpf, None), + "loongarch64" => (Architecture::LoongArch64, None), + "csky" => (Architecture::Csky, None), + "arm64ec" => (Architecture::Aarch64, Some(SubArchitecture::Arm64EC)), // Unsupported architecture. _ => return None, }; @@ -226,6 +229,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option( return undecorated; } - let x86 = match &target.arch[..] { - "x86" => true, - "x86_64" => false, + let prefix = match &target.arch[..] { + "x86" => Some('_'), + "x86_64" => None, + "arm64ec" => Some('#'), // Only x86/64 use symbol decorations. _ => return undecorated, }; @@ -616,8 +617,8 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>( Conv::X86Stdcall => ("_", "@"), Conv::X86VectorCall => ("", "@@"), _ => { - if x86 { - undecorated.insert(0, '_'); + if let Some(prefix) = prefix { + undecorated.insert(0, prefix); } return undecorated; } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index b87f4b6bf8907..bbacf88dc86b4 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -904,7 +904,11 @@ impl CrateInfo { lang_items::required(tcx, l).then_some(name) }) .collect(); - let prefix = if target.is_like_windows && target.arch == "x86" { "_" } else { "" }; + let prefix = match (target.is_like_windows, target.arch.as_ref()) { + (true, "x86") => "_", + (true, "arm64ec") => "#", + _ => "", + }; info.linked_symbols .iter_mut() .filter(|(crate_type, _)| { diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index e9730947389fe..92533bf78d507 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -813,7 +813,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { } } }, - "aarch64" => { + "aarch64" | "arm64ec" => { let kind = if cx.target_spec().is_like_osx { aarch64::AbiKind::DarwinPCS } else if cx.target_spec().is_like_windows { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index b688c97311a09..8836c56691cef 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1601,6 +1601,7 @@ supported_targets! { ("x86_64-pc-windows-gnullvm", x86_64_pc_windows_gnullvm), ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc), + ("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc), ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc), ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc), ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc), diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs new file mode 100644 index 0000000000000..ac50b08c2fda4 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs @@ -0,0 +1,16 @@ +use crate::spec::{add_link_args, base, LinkerFlavor, Lld, Target}; + +pub fn target() -> Target { + let mut base = base::windows_msvc::opts(); + base.max_atomic_width = Some(128); + base.features = "+v8a,+neon,+fp-armv8".into(); + add_link_args(&mut base.late_link_args, LinkerFlavor::Msvc(Lld::No), &["/machine:arm64ec", "softintrin.lib"]); + + Target { + llvm_target: "arm64ec-pc-windows-msvc".into(), + pointer_width: 64, + data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(), + arch: "arm64ec".into(), + options: base, + } +} diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 5f5de57dd1d87..f26eec899795c 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -406,7 +406,7 @@ impl super::spec::Target { pub fn supported_target_features(&self) -> &'static [(&'static str, Stability)] { match &*self.arch { "arm" => ARM_ALLOWED_FEATURES, - "aarch64" => AARCH64_ALLOWED_FEATURES, + "aarch64" | "arm64ec" => AARCH64_ALLOWED_FEATURES, "x86" | "x86_64" => X86_ALLOWED_FEATURES, "hexagon" => HEXAGON_ALLOWED_FEATURES, "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_ALLOWED_FEATURES, @@ -422,7 +422,7 @@ impl super::spec::Target { pub fn tied_target_features(&self) -> &'static [&'static [&'static str]] { match &*self.arch { - "aarch64" => AARCH64_TIED_FEATURES, + "aarch64" | "arm64ec" => AARCH64_TIED_FEATURES, _ => &[], } } diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index fadd64a0353cb..12fe54cde90c1 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -18,6 +18,7 @@ - [arm64e-apple-ios.md](platform-support/arm64e-apple-ios.md) - [arm64e-apple-darwin.md](platform-support/arm64e-apple-darwin.md) - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) + - [arm64ec-pc-windows-msvc](platform-support/arm64ec-pc-windows-msvc.md) - [\*-apple-tvos](platform-support/apple-tvos.md) - [\*-apple-watchos\*](platform-support/apple-watchos.md) - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 59ef744102415..4d3f6f6d3f88f 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -217,6 +217,7 @@ target | std | host | notes -------|:---:|:----:|------- [`arm64e-apple-ios`](platform-support/arm64e-apple-ios.md) | ✓ | | ARM64e Apple iOS [`arm64e-apple-darwin`](platform-support/arm64e-apple-darwin.md) | ✓ | ✓ | ARM64e Apple Darwin +[`arm64ec-pc-windows-msvc`](platform-support/arm64ec-pc-windows-msvc.md) | ? | | Arm64EC Windows MSVC `aarch64-apple-ios-macabi` | ? | | Apple Catalyst on ARM64 [`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS [`aarch64-apple-tvos-sim`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS Simulator 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 new file mode 100644 index 0000000000000..f30fdb7c2aa23 --- /dev/null +++ b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md @@ -0,0 +1,67 @@ +# `arm64ec-pc-windows-msvc` + +**Tier: 3** + +Arm64EC ("Emulation Compatible") for mixed architecture (AArch64 and x86_64) +applications on AArch64 Windows 11. See . + +## Target maintainers + +- [@dpaoliello](https://github.com/dpaoliello) + +## 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. + +## 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`: + +```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. + +## 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. + +To compile: + +```bash +cl /arm64EC /c ... +``` + +To link: + +```bash +link /MACHINE:ARM64EC ... +``` + +Further reading: