1
Fork 0

Rollup merge of #131332 - taiki-e:arm64ec-clobber-abi, r=Amanieu

Fix clobber_abi and disallow SVE-related registers in Arm64EC inline assembly

Currently `clobber_abi` in Arm64EC inline assembly is implemented using `InlineAsmClobberAbi::AArch64NoX18`, but broken since it attempts to clobber registers that cannot be used in Arm64EC: https://godbolt.org/z/r3PTrGz5r

```
error: cannot use register `x13`: x13, x14, x23, x24, x28, v16-v31 cannot be used for Arm64EC
 --> <source>:6:14
  |
6 |     asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags));
  |              ^^^^^^^^^^^^^^^^

error: cannot use register `x14`: x13, x14, x23, x24, x28, v16-v31 cannot be used for Arm64EC
 --> <source>:6:14
  |
6 |     asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags));
  |              ^^^^^^^^^^^^^^^^

<omitted the same errors for v16-v31>
```

Additionally, this disallows SVE-related registers per https://github.com/rust-lang/rust/pull/131332#issuecomment-2401189142.

cc ``@dpaoliello``

r? ``@Amanieu``

``@rustbot`` label O-windows O-AArch64 +A-inline-assembly
This commit is contained in:
Matthias Krüger 2024-10-14 17:06:35 +02:00 committed by GitHub
commit 43bf4f1fd3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 143 additions and 20 deletions

View file

@ -64,6 +64,7 @@ impl AArch64InlineAsmRegClass {
neon: I8, I16, I32, I64, F16, F32, F64, F128, neon: I8, I16, I32, I64, F16, F32, F64, F128,
VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2), VecF64(1), VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF16(4), VecF32(2), VecF64(1),
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2); VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2);
// Note: When adding support for SVE vector types, they must be rejected for Arm64EC.
}, },
Self::preg => &[], Self::preg => &[],
} }
@ -96,7 +97,7 @@ fn restricted_for_arm64ec(
_is_clobber: bool, _is_clobber: bool,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
if arch == InlineAsmArch::Arm64EC { if arch == InlineAsmArch::Arm64EC {
Err("x13, x14, x23, x24, x28, v16-v31 cannot be used for Arm64EC") Err("x13, x14, x23, x24, x28, v16-v31, p*, ffr cannot be used for Arm64EC")
} else { } else {
Ok(()) Ok(())
} }
@ -165,23 +166,23 @@ def_regs! {
v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"] % restricted_for_arm64ec, v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"] % restricted_for_arm64ec,
v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"] % restricted_for_arm64ec, v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"] % restricted_for_arm64ec,
v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"] % restricted_for_arm64ec, v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"] % restricted_for_arm64ec,
p0: preg = ["p0"], p0: preg = ["p0"] % restricted_for_arm64ec,
p1: preg = ["p1"], p1: preg = ["p1"] % restricted_for_arm64ec,
p2: preg = ["p2"], p2: preg = ["p2"] % restricted_for_arm64ec,
p3: preg = ["p3"], p3: preg = ["p3"] % restricted_for_arm64ec,
p4: preg = ["p4"], p4: preg = ["p4"] % restricted_for_arm64ec,
p5: preg = ["p5"], p5: preg = ["p5"] % restricted_for_arm64ec,
p6: preg = ["p6"], p6: preg = ["p6"] % restricted_for_arm64ec,
p7: preg = ["p7"], p7: preg = ["p7"] % restricted_for_arm64ec,
p8: preg = ["p8"], p8: preg = ["p8"] % restricted_for_arm64ec,
p9: preg = ["p9"], p9: preg = ["p9"] % restricted_for_arm64ec,
p10: preg = ["p10"], p10: preg = ["p10"] % restricted_for_arm64ec,
p11: preg = ["p11"], p11: preg = ["p11"] % restricted_for_arm64ec,
p12: preg = ["p12"], p12: preg = ["p12"] % restricted_for_arm64ec,
p13: preg = ["p13"], p13: preg = ["p13"] % restricted_for_arm64ec,
p14: preg = ["p14"], p14: preg = ["p14"] % restricted_for_arm64ec,
p15: preg = ["p15"], p15: preg = ["p15"] % restricted_for_arm64ec,
ffr: preg = ["ffr"], ffr: preg = ["ffr"] % restricted_for_arm64ec,
#error = ["x19", "w19"] => #error = ["x19", "w19"] =>
"x19 is used internally by LLVM and cannot be used as an operand for inline asm", "x19 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["x29", "w29", "fp", "wfp"] => #error = ["x29", "w29", "fp", "wfp"] =>

View file

@ -890,6 +890,7 @@ pub enum InlineAsmClobberAbi {
Arm, Arm,
AArch64, AArch64,
AArch64NoX18, AArch64NoX18,
Arm64EC,
RiscV, RiscV,
LoongArch, LoongArch,
S390x, S390x,
@ -932,7 +933,7 @@ impl InlineAsmClobberAbi {
_ => Err(&["C", "system", "efiapi"]), _ => Err(&["C", "system", "efiapi"]),
}, },
InlineAsmArch::Arm64EC => match name { InlineAsmArch::Arm64EC => match name {
"C" | "system" => Ok(InlineAsmClobberAbi::AArch64NoX18), "C" | "system" => Ok(InlineAsmClobberAbi::Arm64EC),
_ => Err(&["C", "system"]), _ => Err(&["C", "system"]),
}, },
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name { InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {
@ -1033,7 +1034,6 @@ impl InlineAsmClobberAbi {
p0, p1, p2, p3, p4, p5, p6, p7, p0, p1, p2, p3, p4, p5, p6, p7,
p8, p9, p10, p11, p12, p13, p14, p15, p8, p9, p10, p11, p12, p13, p14, p15,
ffr, ffr,
} }
}, },
InlineAsmClobberAbi::AArch64NoX18 => clobbered_regs! { InlineAsmClobberAbi::AArch64NoX18 => clobbered_regs! {
@ -1052,7 +1052,20 @@ impl InlineAsmClobberAbi {
p0, p1, p2, p3, p4, p5, p6, p7, p0, p1, p2, p3, p4, p5, p6, p7,
p8, p9, p10, p11, p12, p13, p14, p15, p8, p9, p10, p11, p12, p13, p14, p15,
ffr, ffr,
}
},
InlineAsmClobberAbi::Arm64EC => clobbered_regs! {
AArch64 AArch64InlineAsmReg {
// x13 and x14 cannot be used in Arm64EC.
x0, x1, x2, x3, x4, x5, x6, x7,
x8, x9, x10, x11, x12, x15,
x16, x17, x30,
// Technically the low 64 bits of v8-v15 are preserved, but
// we have no way of expressing this using clobbers.
v0, v1, v2, v3, v4, v5, v6, v7,
v8, v9, v10, v11, v12, v13, v14, v15,
// v16-v31, p*, and ffr cannot be used in Arm64EC.
} }
}, },
InlineAsmClobberAbi::Arm => clobbered_regs! { InlineAsmClobberAbi::Arm => clobbered_regs! {

View file

@ -0,0 +1,36 @@
//@ assembly-output: emit-asm
//@ compile-flags: --target arm64ec-pc-windows-msvc
//@ needs-llvm-components: aarch64
#![crate_type = "rlib"]
#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
#![no_core]
#[lang = "sized"]
trait Sized {}
#[rustc_builtin_macro]
macro_rules! asm {
() => {};
}
// CHECK-LABEL: @cc_clobber
// CHECK: call void asm sideeffect "", "~{cc}"()
#[no_mangle]
pub unsafe fn cc_clobber() {
asm!("", options(nostack, nomem));
}
// CHECK-LABEL: @no_clobber
// CHECK: call void asm sideeffect "", ""()
#[no_mangle]
pub unsafe fn no_clobber() {
asm!("", options(nostack, nomem, preserves_flags));
}
// CHECK-LABEL: @clobber_abi
// CHECK: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15}"()
#[no_mangle]
pub unsafe fn clobber_abi() {
asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags));
}

View file

@ -0,0 +1,28 @@
//@ only-aarch64
//@ build-pass
//@ needs-asm-support
#![crate_type = "rlib"]
#![feature(no_core, rustc_attrs, lang_items)]
#![no_core]
// AArch64 test corresponding to arm64ec-sve.rs.
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
impl Copy for f64 {}
#[rustc_builtin_macro]
macro_rules! asm {
() => {};
}
fn f(x: f64) {
unsafe {
asm!("", out("p0") _);
asm!("", out("ffr") _);
}
}

View file

@ -0,0 +1,31 @@
//@ compile-flags: --target arm64ec-pc-windows-msvc
//@ needs-asm-support
//@ needs-llvm-components: aarch64
#![crate_type = "rlib"]
#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
#![no_core]
// SVE cannot be used for Arm64EC
// https://github.com/rust-lang/rust/pull/131332#issuecomment-2401189142
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
impl Copy for f64 {}
#[rustc_builtin_macro]
macro_rules! asm {
() => {};
}
fn f(x: f64) {
unsafe {
asm!("", out("p0") _);
//~^ ERROR cannot use register `p0`
asm!("", out("ffr") _);
//~^ ERROR cannot use register `ffr`
}
}

View file

@ -0,0 +1,14 @@
error: cannot use register `p0`: x13, x14, x23, x24, x28, v16-v31, p*, ffr cannot be used for Arm64EC
--> $DIR/arm64ec-sve.rs:26:18
|
LL | asm!("", out("p0") _);
| ^^^^^^^^^^^
error: cannot use register `ffr`: x13, x14, x23, x24, x28, v16-v31, p*, ffr cannot be used for Arm64EC
--> $DIR/arm64ec-sve.rs:28:18
|
LL | asm!("", out("ffr") _);
| ^^^^^^^^^^^^
error: aborting due to 2 previous errors