Rollup merge of #91643 - Amanieu:r9x18, r=joshtriplett

asm: Allow using r9 (ARM) and x18 (AArch64) if they are not reserved by the current target

This supersedes https://github.com/rust-lang/rust/pull/88879.

cc `@Skirmisher`

r? `@joshtriplett`
This commit is contained in:
Matthias Krüger 2021-12-11 23:31:49 +01:00 committed by GitHub
commit 443ed7c620
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 83 additions and 28 deletions

View File

@ -64,7 +64,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let mut clobber_abis = FxHashMap::default();
if let Some(asm_arch) = asm_arch {
for (abi_name, abi_span) in &asm.clobber_abis {
match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, *abi_name) {
match asm::InlineAsmClobberAbi::parse(
asm_arch,
|feature| self.sess.target_features.contains(&Symbol::intern(feature)),
&self.sess.target,
*abi_name,
) {
Ok(abi) => {
// If the abi was already in the list, emit an error
match clobber_abis.get(&abi) {

View File

@ -36,6 +36,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
// #[target_feature].
("thumb-mode", Some(sym::arm_target_feature)),
("thumb2", Some(sym::arm_target_feature)),
("reserve-r9", Some(sym::arm_target_feature)),
];
const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[

View File

@ -1,4 +1,5 @@
use super::{InlineAsmArch, InlineAsmType};
use crate::spec::Target;
use rustc_macros::HashStable_Generic;
use std::fmt;
@ -70,6 +71,22 @@ impl AArch64InlineAsmRegClass {
}
}
pub fn reserved_x18(
_arch: InlineAsmArch,
_has_feature: impl FnMut(&str) -> bool,
target: &Target,
) -> Result<(), &'static str> {
if target.os == "android"
|| target.is_like_fuchsia
|| target.is_like_osx
|| target.is_like_windows
{
Err("x18 is a reserved register on this target")
} else {
Ok(())
}
}
def_regs! {
AArch64 AArch64InlineAsmReg AArch64InlineAsmRegClass {
x0: reg = ["x0", "w0"],
@ -90,6 +107,7 @@ def_regs! {
x15: reg = ["x15", "w15"],
x16: reg = ["x16", "w16"],
x17: reg = ["x17", "w17"],
x18: reg = ["x18", "w18"] % reserved_x18,
x20: reg = ["x20", "w20"],
x21: reg = ["x21", "w21"],
x22: reg = ["x22", "w22"],
@ -149,8 +167,6 @@ def_regs! {
p14: preg = ["p14"],
p15: preg = ["p15"],
ffr: preg = ["ffr"],
#error = ["x18", "w18"] =>
"x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm",
#error = ["x19", "w19"] =>
"x19 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["x29", "w29", "fp", "wfp"] =>

View File

@ -99,6 +99,22 @@ fn not_thumb1(
}
}
fn reserved_r9(
arch: InlineAsmArch,
mut has_feature: impl FnMut(&str) -> bool,
target: &Target,
) -> Result<(), &'static str> {
not_thumb1(arch, &mut has_feature, target)?;
// We detect this using the reserved-r9 feature instead of using the target
// because the relocation model can be changed with compiler options.
if has_feature("reserved-r9") {
Err("the RWPI static base register (r9) cannot be used as an operand for inline asm")
} else {
Ok(())
}
}
def_regs! {
Arm ArmInlineAsmReg ArmInlineAsmRegClass {
r0: reg = ["r0", "a1"],
@ -109,6 +125,7 @@ def_regs! {
r5: reg = ["r5", "v2"],
r7: reg = ["r7", "v4"] % frame_pointer_r7,
r8: reg = ["r8", "v5"] % not_thumb1,
r9: reg = ["r9", "v6", "rfp"] % reserved_r9,
r10: reg = ["r10", "sl"] % not_thumb1,
r11: reg = ["r11", "fp"] % frame_pointer_r11,
r12: reg = ["r12", "ip"] % not_thumb1,
@ -195,8 +212,6 @@ def_regs! {
q15: qreg = ["q15"],
#error = ["r6", "v3"] =>
"r6 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["r9", "v6", "rfp"] =>
"r9 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["r13", "sp"] =>
"the stack pointer cannot be used as an operand for inline asm",
#error = ["r15", "pc"] =>

View File

@ -785,6 +785,7 @@ pub enum InlineAsmClobberAbi {
X86_64SysV,
Arm,
AArch64,
AArch64NoX18,
RiscV,
}
@ -793,6 +794,7 @@ impl InlineAsmClobberAbi {
/// clobber ABIs for the target.
pub fn parse(
arch: InlineAsmArch,
has_feature: impl FnMut(&str) -> bool,
target: &Target,
name: Symbol,
) -> Result<Self, &'static [&'static str]> {
@ -816,7 +818,13 @@ impl InlineAsmClobberAbi {
_ => Err(&["C", "system", "efiapi", "aapcs"]),
},
InlineAsmArch::AArch64 => match name {
"C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::AArch64),
"C" | "system" | "efiapi" => {
Ok(if aarch64::reserved_x18(arch, has_feature, target).is_err() {
InlineAsmClobberAbi::AArch64NoX18
} else {
InlineAsmClobberAbi::AArch64
})
}
_ => Err(&["C", "system", "efiapi"]),
},
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {
@ -891,8 +899,25 @@ impl InlineAsmClobberAbi {
AArch64 AArch64InlineAsmReg {
x0, x1, x2, x3, x4, x5, x6, x7,
x8, x9, x10, x11, x12, x13, x14, x15,
// x18 is platform-reserved or temporary, but we exclude it
// here since it is a reserved register.
x16, x17, x18, 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, v17, v18, v19, v20, v21, v22, v23,
v24, v25, v26, v27, v28, v29, v30, v31,
p0, p1, p2, p3, p4, p5, p6, p7,
p8, p9, p10, p11, p12, p13, p14, p15,
ffr,
}
},
InlineAsmClobberAbi::AArch64NoX18 => clobbered_regs! {
AArch64 AArch64InlineAsmReg {
x0, x1, x2, x3, x4, x5, x6, x7,
x8, x9, x10, x11, x12, x13, x14, x15,
x16, x17, x30,
// Technically the low 64 bits of v8-v15 are preserved, but
@ -910,7 +935,8 @@ impl InlineAsmClobberAbi {
},
InlineAsmClobberAbi::Arm => clobbered_regs! {
Arm ArmInlineAsmReg {
// r9 is platform-reserved and is treated as callee-saved.
// r9 is either platform-reserved or callee-saved. Either
// way we don't need to clobber it.
r0, r1, r2, r3, r12, r14,
// The finest-grained register variant is used here so that

View File

@ -29,8 +29,6 @@ fn main() {
//~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand
asm!("", in("xzr") foo);
//~^ ERROR invalid register `xzr`: the zero register cannot be used as an operand
asm!("", in("x18") foo);
//~^ ERROR invalid register `x18`: x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm
asm!("", in("x19") foo);
//~^ ERROR invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm

View File

@ -74,38 +74,32 @@ error: invalid register `xzr`: the zero register cannot be used as an operand fo
LL | asm!("", in("xzr") foo);
| ^^^^^^^^^^^^^
error: invalid register `x18`: x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:32:18
|
LL | asm!("", in("x18") foo);
| ^^^^^^^^^^^^^
error: invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:34:18
--> $DIR/bad-reg.rs:32:18
|
LL | asm!("", in("x19") foo);
| ^^^^^^^^^^^^^
error: register class `preg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:37:18
--> $DIR/bad-reg.rs:35:18
|
LL | asm!("", in("p0") foo);
| ^^^^^^^^^^^^
error: register class `preg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:40:20
--> $DIR/bad-reg.rs:38:20
|
LL | asm!("{}", in(preg) foo);
| ^^^^^^^^^^^^
error: register class `preg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:42:20
--> $DIR/bad-reg.rs:40:20
|
LL | asm!("{}", out(preg) _);
| ^^^^^^^^^^^
error: register `x0` conflicts with register `x0`
--> $DIR/bad-reg.rs:48:32
--> $DIR/bad-reg.rs:46:32
|
LL | asm!("", in("x0") foo, in("w0") bar);
| ------------ ^^^^^^^^^^^^ register `x0`
@ -113,7 +107,7 @@ LL | asm!("", in("x0") foo, in("w0") bar);
| register `x0`
error: register `x0` conflicts with register `x0`
--> $DIR/bad-reg.rs:50:32
--> $DIR/bad-reg.rs:48:32
|
LL | asm!("", in("x0") foo, out("x0") bar);
| ------------ ^^^^^^^^^^^^^ register `x0`
@ -121,13 +115,13 @@ LL | asm!("", in("x0") foo, out("x0") bar);
| register `x0`
|
help: use `lateout` instead of `out` to avoid conflict
--> $DIR/bad-reg.rs:50:18
--> $DIR/bad-reg.rs:48:18
|
LL | asm!("", in("x0") foo, out("x0") bar);
| ^^^^^^^^^^^^
error: register `v0` conflicts with register `v0`
--> $DIR/bad-reg.rs:53:32
--> $DIR/bad-reg.rs:51:32
|
LL | asm!("", in("v0") foo, in("q0") bar);
| ------------ ^^^^^^^^^^^^ register `v0`
@ -135,7 +129,7 @@ LL | asm!("", in("v0") foo, in("q0") bar);
| register `v0`
error: register `v0` conflicts with register `v0`
--> $DIR/bad-reg.rs:55:32
--> $DIR/bad-reg.rs:53:32
|
LL | asm!("", in("v0") foo, out("q0") bar);
| ------------ ^^^^^^^^^^^^^ register `v0`
@ -143,10 +137,10 @@ LL | asm!("", in("v0") foo, out("q0") bar);
| register `v0`
|
help: use `lateout` instead of `out` to avoid conflict
--> $DIR/bad-reg.rs:55:18
--> $DIR/bad-reg.rs:53:18
|
LL | asm!("", in("v0") foo, out("q0") bar);
| ^^^^^^^^^^^^
error: aborting due to 19 previous errors
error: aborting due to 18 previous errors