Skip to content
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

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

Merged
merged 1 commit into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
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
37 changes: 19 additions & 18 deletions compiler/rustc_target/src/asm/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ impl AArch64InlineAsmRegClass {
neon: I8, I16, I32, I64, F16, F32, F64, F128,
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);
// Note: When adding support for SVE vector types, they must be rejected for Arm64EC.
},
Self::preg => &[],
}
Expand Down Expand Up @@ -96,7 +97,7 @@ fn restricted_for_arm64ec(
_is_clobber: bool,
) -> Result<(), &'static str> {
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 {
Ok(())
}
Expand Down Expand Up @@ -165,23 +166,23 @@ def_regs! {
v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"] % 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,
p0: preg = ["p0"],
p1: preg = ["p1"],
p2: preg = ["p2"],
p3: preg = ["p3"],
p4: preg = ["p4"],
p5: preg = ["p5"],
p6: preg = ["p6"],
p7: preg = ["p7"],
p8: preg = ["p8"],
p9: preg = ["p9"],
p10: preg = ["p10"],
p11: preg = ["p11"],
p12: preg = ["p12"],
p13: preg = ["p13"],
p14: preg = ["p14"],
p15: preg = ["p15"],
ffr: preg = ["ffr"],
p0: preg = ["p0"] % restricted_for_arm64ec,
p1: preg = ["p1"] % restricted_for_arm64ec,
p2: preg = ["p2"] % restricted_for_arm64ec,
p3: preg = ["p3"] % restricted_for_arm64ec,
p4: preg = ["p4"] % restricted_for_arm64ec,
p5: preg = ["p5"] % restricted_for_arm64ec,
p6: preg = ["p6"] % restricted_for_arm64ec,
p7: preg = ["p7"] % restricted_for_arm64ec,
p8: preg = ["p8"] % restricted_for_arm64ec,
p9: preg = ["p9"] % restricted_for_arm64ec,
p10: preg = ["p10"] % restricted_for_arm64ec,
p11: preg = ["p11"] % restricted_for_arm64ec,
p12: preg = ["p12"] % restricted_for_arm64ec,
p13: preg = ["p13"] % restricted_for_arm64ec,
p14: preg = ["p14"] % restricted_for_arm64ec,
p15: preg = ["p15"] % restricted_for_arm64ec,
ffr: preg = ["ffr"] % restricted_for_arm64ec,
#error = ["x19", "w19"] =>
"x19 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["x29", "w29", "fp", "wfp"] =>
Expand Down
17 changes: 15 additions & 2 deletions compiler/rustc_target/src/asm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,7 @@ pub enum InlineAsmClobberAbi {
Arm,
AArch64,
AArch64NoX18,
Arm64EC,
RiscV,
LoongArch,
S390x,
Expand Down Expand Up @@ -932,7 +933,7 @@ impl InlineAsmClobberAbi {
_ => Err(&["C", "system", "efiapi"]),
},
InlineAsmArch::Arm64EC => match name {
"C" | "system" => Ok(InlineAsmClobberAbi::AArch64NoX18),
"C" | "system" => Ok(InlineAsmClobberAbi::Arm64EC),
_ => Err(&["C", "system"]),
},
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {
Expand Down Expand Up @@ -1033,7 +1034,6 @@ impl InlineAsmClobberAbi {
p0, p1, p2, p3, p4, p5, p6, p7,
p8, p9, p10, p11, p12, p13, p14, p15,
ffr,

}
},
InlineAsmClobberAbi::AArch64NoX18 => clobbered_regs! {
Expand All @@ -1052,7 +1052,20 @@ impl InlineAsmClobberAbi {
p0, p1, p2, p3, p4, p5, p6, p7,
p8, p9, p10, p11, p12, p13, p14, p15,
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! {
Expand Down
36 changes: 36 additions & 0 deletions tests/codegen/asm-arm64ec-clobbers.rs
Original file line number Diff line number Diff line change
@@ -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));
}
28 changes: 28 additions & 0 deletions tests/ui/asm/aarch64/aarch64-sve.rs
Original file line number Diff line number Diff line change
@@ -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") _);
}
}
31 changes: 31 additions & 0 deletions tests/ui/asm/aarch64/arm64ec-sve.rs
Original file line number Diff line number Diff line change
@@ -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`
}
}
14 changes: 14 additions & 0 deletions tests/ui/asm/aarch64/arm64ec-sve.stderr
Original file line number Diff line number Diff line change
@@ -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

Loading