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

This commit is contained in:
Taiki Endo 2024-10-14 05:30:45 +09:00
parent 8f8bee4f60
commit d858dfedbb
6 changed files with 143 additions and 20 deletions

View File

@ -64,6 +64,7 @@ pub fn supported_types(
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 @@ fn restricted_for_arm64ec(
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 @@ pub fn parse(
_ => 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 @@ macro_rules! clobbered_regs {
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 @@ macro_rules! clobbered_regs {
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