From e0bfb615da4f48e08f0c86e1ce0e9af765d603fb Mon Sep 17 00:00:00 2001 From: George Wort Date: Tue, 28 Nov 2023 10:25:22 +0000 Subject: [PATCH] Name explicit registers in conflict register errors for inline assembly --- compiler/rustc_ast/src/ast.rs | 12 ++++++++++++ compiler/rustc_ast_lowering/src/asm.rs | 21 +++++++++++++++------ tests/ui/asm/aarch64/bad-reg.rs | 6 +++--- tests/ui/asm/aarch64/bad-reg.stderr | 12 ++++++------ tests/ui/asm/x86_64/bad-reg.rs | 4 ++-- tests/ui/asm/x86_64/bad-reg.stderr | 10 +++++----- 6 files changed, 43 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 83fe95f16f9..b9d959ab605 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2237,6 +2237,18 @@ pub enum InlineAsmOperand { }, } +impl InlineAsmOperand { + pub fn reg(&self) -> Option<&InlineAsmRegOrRegClass> { + match self { + Self::In { reg, .. } + | Self::Out { reg, .. } + | Self::InOut { reg, .. } + | Self::SplitInOut { reg, .. } => Some(reg), + Self::Const { .. } | Self::Sym { .. } => None, + } + } +} + /// Inline assembly. /// /// E.g., `asm!("NOP");`. diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index a1e62699680..d0198615388 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -353,10 +353,6 @@ pub(crate) fn lower_inline_asm( let idx2 = *o.get(); let (ref op2, op_sp2) = operands[idx2]; - let Some(asm::InlineAsmRegOrRegClass::Reg(reg2)) = op2.reg() - else { - unreachable!(); - }; let in_out = match (op, op2) { ( @@ -374,11 +370,24 @@ pub(crate) fn lower_inline_asm( _ => None, }; + let reg_str = |idx| -> &str { + // HIR asm doesn't preserve the original alias string of the explicit register, + // so we have to retrieve it from AST + let (op, _): &(InlineAsmOperand, Span) = &asm.operands[idx]; + if let Some(ast::InlineAsmRegOrRegClass::Reg(reg_sym)) = + op.reg() + { + reg_sym.as_str() + } else { + unreachable!(); + } + }; + sess.emit_err(RegisterConflict { op_span1: op_sp, op_span2: op_sp2, - reg1_name: reg.name(), - reg2_name: reg2.name(), + reg1_name: reg_str(idx), + reg2_name: reg_str(idx2), in_out, }); } diff --git a/tests/ui/asm/aarch64/bad-reg.rs b/tests/ui/asm/aarch64/bad-reg.rs index 9ccb8ed6762..f71418161f2 100644 --- a/tests/ui/asm/aarch64/bad-reg.rs +++ b/tests/ui/asm/aarch64/bad-reg.rs @@ -48,14 +48,14 @@ fn main() { // (except in/lateout which don't conflict) asm!("", in("x0") foo, in("w0") bar); - //~^ ERROR register `x0` conflicts with register `x0` + //~^ ERROR register `w0` conflicts with register `x0` asm!("", in("x0") foo, out("x0") bar); //~^ ERROR register `x0` conflicts with register `x0` asm!("", in("w0") foo, lateout("w0") bar); asm!("", in("v0") foo, in("q0") bar); - //~^ ERROR register `v0` conflicts with register `v0` + //~^ ERROR register `q0` conflicts with register `v0` asm!("", in("v0") foo, out("q0") bar); - //~^ ERROR register `v0` conflicts with register `v0` + //~^ ERROR register `q0` conflicts with register `v0` asm!("", in("v0") foo, lateout("q0") bar); } } diff --git a/tests/ui/asm/aarch64/bad-reg.stderr b/tests/ui/asm/aarch64/bad-reg.stderr index 0ba627dac30..717a788caf6 100644 --- a/tests/ui/asm/aarch64/bad-reg.stderr +++ b/tests/ui/asm/aarch64/bad-reg.stderr @@ -98,11 +98,11 @@ error: register class `preg` can only be used as a clobber, not as an input or o LL | asm!("{}", out(preg) _); | ^^^^^^^^^^^ -error: register `x0` conflicts with register `x0` +error: register `w0` conflicts with register `x0` --> $DIR/bad-reg.rs:50:32 | LL | asm!("", in("x0") foo, in("w0") bar); - | ------------ ^^^^^^^^^^^^ register `x0` + | ------------ ^^^^^^^^^^^^ register `w0` | | | register `x0` @@ -120,19 +120,19 @@ help: use `lateout` instead of `out` to avoid conflict LL | asm!("", in("x0") foo, out("x0") bar); | ^^^^^^^^^^^^ -error: register `v0` conflicts with register `v0` +error: register `q0` conflicts with register `v0` --> $DIR/bad-reg.rs:55:32 | LL | asm!("", in("v0") foo, in("q0") bar); - | ------------ ^^^^^^^^^^^^ register `v0` + | ------------ ^^^^^^^^^^^^ register `q0` | | | register `v0` -error: register `v0` conflicts with register `v0` +error: register `q0` conflicts with register `v0` --> $DIR/bad-reg.rs:57:32 | LL | asm!("", in("v0") foo, out("q0") bar); - | ------------ ^^^^^^^^^^^^^ register `v0` + | ------------ ^^^^^^^^^^^^^ register `q0` | | | register `v0` | diff --git a/tests/ui/asm/x86_64/bad-reg.rs b/tests/ui/asm/x86_64/bad-reg.rs index f5728079a6a..e19221bc04e 100644 --- a/tests/ui/asm/x86_64/bad-reg.rs +++ b/tests/ui/asm/x86_64/bad-reg.rs @@ -56,10 +56,10 @@ fn main() { // (except in/lateout which don't conflict) asm!("", in("eax") foo, in("al") bar); - //~^ ERROR register `al` conflicts with register `ax` + //~^ ERROR register `al` conflicts with register `eax` //~| ERROR `i32` cannot be used with this register class asm!("", in("rax") foo, out("rax") bar); - //~^ ERROR register `ax` conflicts with register `ax` + //~^ ERROR register `rax` conflicts with register `rax` asm!("", in("al") foo, lateout("al") bar); //~^ ERROR `i32` cannot be used with this register class //~| ERROR `i32` cannot be used with this register class diff --git a/tests/ui/asm/x86_64/bad-reg.stderr b/tests/ui/asm/x86_64/bad-reg.stderr index 82b7ebd0fb0..8017008e97d 100644 --- a/tests/ui/asm/x86_64/bad-reg.stderr +++ b/tests/ui/asm/x86_64/bad-reg.stderr @@ -106,21 +106,21 @@ error: register class `mmx_reg` can only be used as a clobber, not as an input o LL | asm!("{}", out(mmx_reg) _); | ^^^^^^^^^^^^^^ -error: register `al` conflicts with register `ax` +error: register `al` conflicts with register `eax` --> $DIR/bad-reg.rs:58:33 | LL | asm!("", in("eax") foo, in("al") bar); | ------------- ^^^^^^^^^^^^ register `al` | | - | register `ax` + | register `eax` -error: register `ax` conflicts with register `ax` +error: register `rax` conflicts with register `rax` --> $DIR/bad-reg.rs:61:33 | LL | asm!("", in("rax") foo, out("rax") bar); - | ------------- ^^^^^^^^^^^^^^ register `ax` + | ------------- ^^^^^^^^^^^^^^ register `rax` | | - | register `ax` + | register `rax` | help: use `lateout` instead of `out` to avoid conflict --> $DIR/bad-reg.rs:61:18