Skip to content

Commit 2e44d29

Browse files
committed
Add support for Arm64EC inline assembly
1 parent 5974fe8 commit 2e44d29

File tree

5 files changed

+158
-103
lines changed

5 files changed

+158
-103
lines changed

Diff for: 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 => {

Diff for: 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"],

Diff for: 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"]),

Diff for: 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)