Skip to content

Commit

Permalink
Name explicit registers in conflict register errors for inline assembly
Browse files Browse the repository at this point in the history
  • Loading branch information
GeorgeWort committed Nov 28, 2023
1 parent a6b8ae5 commit e0bfb61
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 22 deletions.
12 changes: 12 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");`.
Expand Down
21 changes: 15 additions & 6 deletions compiler/rustc_ast_lowering/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,10 +353,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {

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) {
(
Expand All @@ -374,11 +370,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
_ => 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,
});
}
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/asm/aarch64/bad-reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
12 changes: 6 additions & 6 deletions tests/ui/asm/aarch64/bad-reg.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand All @@ -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`
|
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/asm/x86_64/bad-reg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions tests/ui/asm/x86_64/bad-reg.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit e0bfb61

Please sign in to comment.