Skip to content

Commit 05ccc49

Browse files
committed
Auto merge of rust-lang#123507 - dpaoliello:arm64ecasm, r=Amanieu
Add support for Arm64EC inline assembly (as unstable) Compiler support for Arm64EC assembly mostly reuses the existing AArch64 support, except that it needs to block registers that are not permitted: <https://learn.microsoft.com/en-us/windows/arm/arm64ec-abi#register-mapping-and-blocked-registers> For assembly authors there are several caveats and differences that need to be considered, I've provided documentation for this as part of the "Standard Library Support" PR: <https://github.com/rust-lang/rust/pull/123144/files#diff-6b08532480943c8b82f5dbda7ee1521afa74c9f626466aeb308dfa6956397edd> r? rust-lang/compiler
2 parents f13f37f + 2e44d29 commit 05ccc49

File tree

5 files changed

+158
-103
lines changed

5 files changed

+158
-103
lines changed

compiler/rustc_codegen_llvm/src/asm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
220220
constraints.append(&mut clobbers);
221221
if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) {
222222
match asm_arch {
223-
InlineAsmArch::AArch64 | InlineAsmArch::Arm => {
223+
InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC | InlineAsmArch::Arm => {
224224
constraints.push("~{cc}".to_string());
225225
}
226226
InlineAsmArch::X86 | InlineAsmArch::X86_64 => {

compiler/rustc_target/src/asm/aarch64.rs

+35-21
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,20 @@ fn reserved_x18(
8787
}
8888
}
8989

90+
fn restricted_for_arm64ec(
91+
arch: InlineAsmArch,
92+
_reloc_model: RelocModel,
93+
_target_features: &FxIndexSet<Symbol>,
94+
_target: &Target,
95+
_is_clobber: bool,
96+
) -> Result<(), &'static str> {
97+
if arch == InlineAsmArch::Arm64EC {
98+
Err("x13, x14, x23, x24, x28, v16-v31 cannot be used for Arm64EC")
99+
} else {
100+
Ok(())
101+
}
102+
}
103+
90104
def_regs! {
91105
AArch64 AArch64InlineAsmReg AArch64InlineAsmRegClass {
92106
x0: reg = ["x0", "w0"],
@@ -102,21 +116,21 @@ def_regs! {
102116
x10: reg = ["x10", "w10"],
103117
x11: reg = ["x11", "w11"],
104118
x12: reg = ["x12", "w12"],
105-
x13: reg = ["x13", "w13"],
106-
x14: reg = ["x14", "w14"],
119+
x13: reg = ["x13", "w13"] % restricted_for_arm64ec,
120+
x14: reg = ["x14", "w14"] % restricted_for_arm64ec,
107121
x15: reg = ["x15", "w15"],
108122
x16: reg = ["x16", "w16"],
109123
x17: reg = ["x17", "w17"],
110124
x18: reg = ["x18", "w18"] % reserved_x18,
111125
x20: reg = ["x20", "w20"],
112126
x21: reg = ["x21", "w21"],
113127
x22: reg = ["x22", "w22"],
114-
x23: reg = ["x23", "w23"],
115-
x24: reg = ["x24", "w24"],
128+
x23: reg = ["x23", "w23"] % restricted_for_arm64ec,
129+
x24: reg = ["x24", "w24"] % restricted_for_arm64ec,
116130
x25: reg = ["x25", "w25"],
117131
x26: reg = ["x26", "w26"],
118132
x27: reg = ["x27", "w27"],
119-
x28: reg = ["x28", "w28"],
133+
x28: reg = ["x28", "w28"] % restricted_for_arm64ec,
120134
x30: reg = ["x30", "w30", "lr", "wlr"],
121135
v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0", "z0"],
122136
v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1", "z1"],
@@ -134,22 +148,22 @@ def_regs! {
134148
v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13", "z13"],
135149
v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14", "z14"],
136150
v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15", "z15"],
137-
v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"],
138-
v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"],
139-
v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"],
140-
v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"],
141-
v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"],
142-
v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"],
143-
v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"],
144-
v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"],
145-
v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"],
146-
v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"],
147-
v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"],
148-
v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"],
149-
v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"],
150-
v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"],
151-
v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"],
152-
v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"],
151+
v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"] % restricted_for_arm64ec,
152+
v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"] % restricted_for_arm64ec,
153+
v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"] % restricted_for_arm64ec,
154+
v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"] % restricted_for_arm64ec,
155+
v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"] % restricted_for_arm64ec,
156+
v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"] % restricted_for_arm64ec,
157+
v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"] % restricted_for_arm64ec,
158+
v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"] % restricted_for_arm64ec,
159+
v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"] % restricted_for_arm64ec,
160+
v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"] % restricted_for_arm64ec,
161+
v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"] % restricted_for_arm64ec,
162+
v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"] % restricted_for_arm64ec,
163+
v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"] % restricted_for_arm64ec,
164+
v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"] % restricted_for_arm64ec,
165+
v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"] % restricted_for_arm64ec,
166+
v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"] % restricted_for_arm64ec,
153167
p0: preg = ["p0"],
154168
p1: preg = ["p1"],
155169
p2: preg = ["p2"],

compiler/rustc_target/src/asm/mod.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ pub enum InlineAsmArch {
217217
X86_64,
218218
Arm,
219219
AArch64,
220+
Arm64EC,
220221
RiscV32,
221222
RiscV64,
222223
Nvptx64,
@@ -246,6 +247,7 @@ impl FromStr for InlineAsmArch {
246247
"x86_64" => Ok(Self::X86_64),
247248
"arm" => Ok(Self::Arm),
248249
"aarch64" => Ok(Self::AArch64),
250+
"arm64ec" => Ok(Self::Arm64EC),
249251
"riscv32" => Ok(Self::RiscV32),
250252
"riscv64" => Ok(Self::RiscV64),
251253
"nvptx64" => Ok(Self::Nvptx64),
@@ -341,7 +343,9 @@ impl InlineAsmReg {
341343
Ok(match arch {
342344
InlineAsmArch::X86 | InlineAsmArch::X86_64 => Self::X86(X86InlineAsmReg::parse(name)?),
343345
InlineAsmArch::Arm => Self::Arm(ArmInlineAsmReg::parse(name)?),
344-
InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmReg::parse(name)?),
346+
InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC => {
347+
Self::AArch64(AArch64InlineAsmReg::parse(name)?)
348+
}
345349
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
346350
Self::RiscV(RiscVInlineAsmReg::parse(name)?)
347351
}
@@ -610,7 +614,9 @@ impl InlineAsmRegClass {
610614
Self::X86(X86InlineAsmRegClass::parse(name)?)
611615
}
612616
InlineAsmArch::Arm => Self::Arm(ArmInlineAsmRegClass::parse(name)?),
613-
InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmRegClass::parse(name)?),
617+
InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC => {
618+
Self::AArch64(AArch64InlineAsmRegClass::parse(name)?)
619+
}
614620
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
615621
Self::RiscV(RiscVInlineAsmRegClass::parse(name)?)
616622
}
@@ -783,7 +789,7 @@ pub fn allocatable_registers(
783789
arm::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
784790
map
785791
}
786-
InlineAsmArch::AArch64 => {
792+
InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC => {
787793
let mut map = aarch64::regclass_map();
788794
aarch64::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
789795
map
@@ -909,6 +915,10 @@ impl InlineAsmClobberAbi {
909915
}),
910916
_ => Err(&["C", "system", "efiapi"]),
911917
},
918+
InlineAsmArch::Arm64EC => match name {
919+
"C" | "system" => Ok(InlineAsmClobberAbi::AArch64NoX18),
920+
_ => Err(&["C", "system"]),
921+
},
912922
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {
913923
"C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV),
914924
_ => Err(&["C", "system", "efiapi"]),

src/doc/unstable-book/src/language-features/asm-experimental-arch.md

+30-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
1919
- M68k
2020
- CSKY
2121
- s390x
22+
- Arm64EC
2223

2324
## Register classes
2425

@@ -51,6 +52,9 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
5152
| CSKY | `freg` | `f[0-31]` | `f` |
5253
| s390x | `reg` | `r[0-10]`, `r[12-14]` | `r` |
5354
| s390x | `freg` | `f[0-15]` | `f` |
55+
| Arm64EC | `reg` | `x[0-12]`, `x[15-22]`, `x[25-27]`, `x30` | `r` |
56+
| Arm64EC | `vreg` | `v[0-15]` | `w` |
57+
| Arm64EC | `vreg_low16` | `v[0-15]` | `x` |
5458

5559
> **Notes**:
5660
> - NVPTX doesn't have a fixed register set, so named registers are not supported.
@@ -86,6 +90,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
8690
| CSKY | `freg` | None | `f32`, |
8791
| s390x | `reg`, `reg_addr` | None | `i8`, `i16`, `i32`, `i64` |
8892
| s390x | `freg` | None | `f32`, `f64` |
93+
| Arm64EC | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
94+
| Arm64EC | `vreg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
8995

9096
## Register aliases
9197

@@ -118,6 +124,12 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
118124
| CSKY | `r29` | `rtb` |
119125
| CSKY | `r30` | `svbr` |
120126
| CSKY | `r31` | `tls` |
127+
| Arm64EC | `x[0-30]` | `w[0-30]` |
128+
| Arm64EC | `x29` | `fp` |
129+
| Arm64EC | `x30` | `lr` |
130+
| Arm64EC | `sp` | `wsp` |
131+
| Arm64EC | `xzr` | `wzr` |
132+
| Arm64EC | `v[0-15]` | `b[0-15]`, `h[0-15]`, `s[0-15]`, `d[0-15]`, `q[0-15]` |
121133

122134
> **Notes**:
123135
> - TI does not mandate a frame pointer for MSP430, but toolchains are allowed
@@ -128,8 +140,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
128140
| Architecture | Unsupported register | Reason |
129141
| ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
130142
| All | `sp`, `r15` (s390x) | The stack pointer must be restored to its original value at the end of an asm code block. |
131-
| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x) | The frame pointer cannot be used as an input or output. |
132-
| All | `r19` (Hexagon) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. |
143+
| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output. |
144+
| All | `r19` (Hexagon), `x19` (Arm64EC) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. |
133145
| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
134146
| MIPS | `$1` or `$at` | Reserved for assembler. |
135147
| MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. |
@@ -145,6 +157,9 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
145157
| CSKY | `r15` | This is the link register. |
146158
| CSKY | `r[26-30]` | Reserved by its ABI. |
147159
| CSKY | `r31` | This is the TLS register. |
160+
| Arm64EC | `xzr` | This is a constant zero register which can't be modified. |
161+
| Arm64EC | `x18` | This is an OS-reserved register. |
162+
| Arm64EC | `x13`, `x14`, `x23`, `x24`, `x28`, `v[16-31]` | These are AArch64 registers that are not supported for Arm64EC. |
148163

149164

150165
## Template modifiers
@@ -165,6 +180,16 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
165180
| s390x | `freg` | None | `%f0` | None |
166181
| CSKY | `reg` | None | `r0` | None |
167182
| CSKY | `freg` | None | `f0` | None |
183+
| Arm64EC | `reg` | None | `x0` | `x` |
184+
| Arm64EC | `reg` | `w` | `w0` | `w` |
185+
| Arm64EC | `reg` | `x` | `x0` | `x` |
186+
| Arm64EC | `vreg` | None | `v0` | None |
187+
| Arm64EC | `vreg` | `v` | `v0` | None |
188+
| Arm64EC | `vreg` | `b` | `b0` | `b` |
189+
| Arm64EC | `vreg` | `h` | `h0` | `h` |
190+
| Arm64EC | `vreg` | `s` | `s0` | `s` |
191+
| Arm64EC | `vreg` | `d` | `d0` | `d` |
192+
| Arm64EC | `vreg` | `q` | `q0` | `q` |
168193

169194
# Flags covered by `preserves_flags`
170195

@@ -177,3 +202,6 @@ These flags registers must be restored upon exiting the asm block if the `preser
177202
- The condition code register `ccr`.
178203
- s390x
179204
- The condition code register `cc`.
205+
- Arm64EC
206+
- Condition flags (`NZCV` register).
207+
- Floating-point status (`FPSR` register).

0 commit comments

Comments
 (0)