Skip to content

Add arm64ec-pc-windows-msvc target #119199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 7, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -469,9 +469,9 @@ version = "0.1.0"

[[package]]
name = "cc"
version = "1.0.79"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"

[[package]]
name = "cfg-if"
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/back/archive.rs
Original file line number Diff line number Diff line change
@@ -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}"),
}
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
@@ -56,6 +56,7 @@ pub enum LLVMMachineType {
AMD64 = 0x8664,
I386 = 0x14c,
ARM64 = 0xaa64,
ARM64EC = 0xa641,
ARM = 0x01c0,
}

8 changes: 7 additions & 1 deletion compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
@@ -201,7 +201,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"))
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/va_arg.rs
Original file line number Diff line number Diff line change
@@ -288,7 +288,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
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/Cargo.toml
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ edition = "2021"
# tidy-alphabetical-start
ar_archive_writer = "0.1.5"
bitflags = "2.4.1"
cc = "1.0.69"
cc = "1.0.90"
itertools = "0.11"
jobserver = "0.1.28"
pathdiff = "0.2.0"
52 changes: 28 additions & 24 deletions compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
@@ -8,7 +8,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;
@@ -182,37 +182,40 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
Endian::Little => 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,
};
@@ -227,6 +230,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
};

let mut file = write::Object::new(binary_format, architecture, endianness);
file.set_sub_architecture(sub_architecture);
if sess.target.is_like_osx {
if macho_is_arm64e(&sess.target) {
file.set_macho_cpu_subtype(object::macho::CPU_SUBTYPE_ARM64E);
11 changes: 6 additions & 5 deletions compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
@@ -567,9 +567,10 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>(
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,
};
@@ -606,8 +607,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;
}
6 changes: 5 additions & 1 deletion compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
@@ -907,7 +907,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") => "#",
_ => "",
};

// This loop only adds new items to values of the hash map, so the order in which we
// iterate over the values is not important.
7 changes: 1 addition & 6 deletions compiler/rustc_llvm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -8,12 +8,7 @@ edition = "2021"
libc = "0.2.73"
# tidy-alphabetical-end

# FIXME: updating cc past 1.0.79 breaks libstd bootstrapping, pin
# to the last working version here so `cargo update` doesn't cause the
# a higher version to be selected
# https://github.com/rust-lang/cc-rs/issues/913
# 1.0.{84, 85} fix this but have been yanked
[build-dependencies]
# tidy-alphabetical-start
cc = "=1.0.79"
cc = "1.0.90"
# tidy-alphabetical-end
2 changes: 1 addition & 1 deletion compiler/rustc_target/src/abi/call/mod.rs
Original file line number Diff line number Diff line change
@@ -814,7 +814,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 {
1 change: 1 addition & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
@@ -1564,6 +1564,7 @@ supported_targets! {

("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc),
("arm64ec-pc-windows-msvc", arm64ec_pc_windows_msvc),
("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc),
("x86_64-win7-windows-msvc", x86_64_win7_windows_msvc),
21 changes: 21 additions & 0 deletions compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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(),
description: None,
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,
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/target_features.rs
Original file line number Diff line number Diff line change
@@ -409,7 +409,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,
@@ -425,7 +425,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,
_ => &[],
}
}
2 changes: 1 addition & 1 deletion src/bootstrap/src/lib.rs
Original file line number Diff line number Diff line change
@@ -91,7 +91,7 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
/* Extra values not defined in the built-in targets yet, but used in std */
(Some(Mode::Std), "target_env", Some(&["libnx", "p2"])),
// (Some(Mode::Std), "target_os", Some(&[])),
(Some(Mode::Std), "target_arch", Some(&["spirv", "nvptx", "xtensa"])),
(Some(Mode::Std), "target_arch", Some(&["arm64ec", "spirv", "nvptx", "xtensa"])),
/* Extra names used by dependencies */
// FIXME: Used by serde_json, but we should not be triggering on external dependencies.
(Some(Mode::Rustc), "no_btreemap_remove_entry", None),
1 change: 1 addition & 0 deletions src/doc/rustc/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -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)
1 change: 1 addition & 0 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
@@ -241,6 +241,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
69 changes: 69 additions & 0 deletions src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# `arm64ec-pc-windows-msvc`

**Tier: 3**

Arm64EC ("Emulation Compatible") for mixed architecture (AArch64 and x86_64)
applications on AArch64 Windows 11. See <https://learn.microsoft.com/en-us/windows/arm/arm64ec>.

## 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.

Only supported backend is LLVM 18 (or above).

## 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: <https://learn.microsoft.com/en-us/windows/arm/arm64ec-build>
3 changes: 3 additions & 0 deletions tests/assembly/targets/targets-pe.rs
Original file line number Diff line number Diff line change
@@ -12,6 +12,9 @@
//@ revisions: aarch64_uwp_windows_msvc
//@ [aarch64_uwp_windows_msvc] compile-flags: --target aarch64-uwp-windows-msvc
//@ [aarch64_uwp_windows_msvc] needs-llvm-components: aarch64
//@ revisions: arm64ec_pc_windows_msvc
//@ [arm64ec_pc_windows_msvc] compile-flags: --target arm64ec-pc-windows-msvc
//@ [arm64ec_pc_windows_msvc] needs-llvm-components: aarch64
//@ revisions: avr_unknown_gnu_atmega328
//@ [avr_unknown_gnu_atmega328] compile-flags: --target avr-unknown-gnu-atmega328
//@ [avr_unknown_gnu_atmega328] needs-llvm-components: avr
2 changes: 1 addition & 1 deletion tests/ui/check-cfg/well-known-values.stderr
Original file line number Diff line number Diff line change
@@ -118,7 +118,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
LL | target_arch = "_UNEXPECTED_VALUE",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`
= note: expected values for `target_arch` are: `aarch64`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`
= note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration

warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`