Rollup merge of #154228 - folkertdev:mention-invalid-template-modifier, r=nnethercote

Improve inline assembly error messages

by

- using `DiagSymbolList` to get nicely formatted lists
- mentioning the `modifier` when an invalid modifier is used. This is useful in case the span cannot be resolved (which I ran into).
This commit is contained in:
Jonathan Brouwer
2026-03-23 12:01:03 +01:00
committed by GitHub
11 changed files with 76 additions and 81 deletions
+11 -22
View File
@@ -1,5 +1,4 @@
use std::collections::hash_map::Entry;
use std::fmt::Write;
use rustc_ast::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
@@ -124,13 +123,9 @@ pub(crate) fn lower_inline_asm(
self.dcx().emit_err(ClobberAbiNotSupported { abi_span: *abi_span });
}
Err(supported_abis) => {
let mut abis = format!("`{}`", supported_abis[0]);
for m in &supported_abis[1..] {
let _ = write!(abis, ", `{m}`");
}
self.dcx().emit_err(InvalidAbiClobberAbi {
abi_span: *abi_span,
supported_abis: abis,
supported_abis: supported_abis.to_vec().into(),
});
}
}
@@ -164,15 +159,12 @@ pub(crate) fn lower_inline_asm(
asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch {
asm::InlineAsmRegClass::parse(asm_arch, reg_class).unwrap_or_else(
|supported_register_classes| {
let mut register_classes =
format!("`{}`", supported_register_classes[0]);
for m in &supported_register_classes[1..] {
let _ = write!(register_classes, ", `{m}`");
}
self.dcx().emit_err(InvalidRegisterClass {
op_span: *op_sp,
reg_class,
supported_register_classes: register_classes,
supported_register_classes: supported_register_classes
.to_vec()
.into(),
});
asm::InlineAsmRegClass::Err
},
@@ -272,23 +264,20 @@ pub(crate) fn lower_inline_asm(
}
let valid_modifiers = class.valid_modifiers(asm_arch.unwrap());
if !valid_modifiers.contains(&modifier) {
let sub = if !valid_modifiers.is_empty() {
let mut mods = format!("`{}`", valid_modifiers[0]);
for m in &valid_modifiers[1..] {
let _ = write!(mods, ", `{m}`");
}
InvalidAsmTemplateModifierRegClassSub::SupportModifier {
class_name: class.name(),
modifiers: mods,
}
} else {
let sub = if valid_modifiers.is_empty() {
InvalidAsmTemplateModifierRegClassSub::DoesNotSupportModifier {
class_name: class.name(),
}
} else {
InvalidAsmTemplateModifierRegClassSub::SupportModifier {
class_name: class.name(),
modifiers: valid_modifiers.to_vec().into(),
}
};
self.dcx().emit_err(InvalidAsmTemplateModifierRegClass {
placeholder_span,
op_span: op_sp,
modifier: modifier.to_string(),
sub,
});
}
+7 -6
View File
@@ -1,5 +1,5 @@
use rustc_errors::DiagArgFromDisplay;
use rustc_errors::codes::*;
use rustc_errors::{DiagArgFromDisplay, DiagSymbolList};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Ident, Span, Symbol};
@@ -191,10 +191,10 @@ pub(crate) struct ClobberAbiNotSupported {
#[derive(Diagnostic)]
#[note("the following ABIs are supported on this target: {$supported_abis}")]
#[diag("invalid ABI for `clobber_abi`")]
pub(crate) struct InvalidAbiClobberAbi {
pub(crate) struct InvalidAbiClobberAbi<'a> {
#[primary_span]
pub abi_span: Span,
pub supported_abis: String,
pub supported_abis: DiagSymbolList<&'a str>,
}
#[derive(Diagnostic)]
@@ -215,17 +215,18 @@ pub(crate) struct InvalidRegisterClass {
#[primary_span]
pub op_span: Span,
pub reg_class: Symbol,
pub supported_register_classes: String,
pub supported_register_classes: DiagSymbolList<Symbol>,
}
#[derive(Diagnostic)]
#[diag("invalid asm template modifier for this register class")]
#[diag("invalid asm template modifier `{$modifier}` for this register class")]
pub(crate) struct InvalidAsmTemplateModifierRegClass {
#[primary_span]
#[label("template modifier")]
pub placeholder_span: Span,
#[label("argument")]
pub op_span: Span,
pub modifier: String,
#[subdiagnostic]
pub sub: InvalidAsmTemplateModifierRegClassSub,
}
@@ -235,7 +236,7 @@ pub(crate) enum InvalidAsmTemplateModifierRegClassSub {
#[note(
"the `{$class_name}` register class supports the following template modifiers: {$modifiers}"
)]
SupportModifier { class_name: Symbol, modifiers: String },
SupportModifier { class_name: Symbol, modifiers: DiagSymbolList<char> },
#[note("the `{$class_name}` register class does not support template modifiers")]
DoesNotSupportModifier { class_name: Symbol },
}
+1 -1
View File
@@ -78,7 +78,7 @@ error: invalid ABI for `clobber_abi`
LL | asm!("", clobber_abi("foo"));
| ^^^^^^^^^^^^^^^^^^
|
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`
= note: the following ABIs are supported on this target: `C`, `system`, and `efiapi`
error: aborting due to 13 previous errors
+9 -4
View File
@@ -1,7 +1,12 @@
//@ add-minicore
//@ only-aarch64
//@ compile-flags: -C target-feature=+neon
#![crate_type = "lib"]
#![feature(no_core)]
#![no_core]
use std::arch::asm;
extern crate minicore;
use minicore::*;
fn main() {
let mut foo = 0;
@@ -14,11 +19,11 @@ fn main() {
asm!("", in("foo") foo);
//~^ ERROR invalid register `foo`: unknown register
asm!("{:z}", in(reg) foo);
//~^ ERROR invalid asm template modifier for this register class
//~^ ERROR invalid asm template modifier `z` for this register class
asm!("{:r}", in(vreg) foo);
//~^ ERROR invalid asm template modifier for this register class
//~^ ERROR invalid asm template modifier `r` for this register class
asm!("{:r}", in(vreg_low16) foo);
//~^ ERROR invalid asm template modifier for this register class
//~^ ERROR invalid asm template modifier `r` for this register class
asm!("{:a}", const 0);
//~^ ERROR asm template modifiers are not allowed for `const` arguments
asm!("{:a}", sym main);
+29 -29
View File
@@ -1,49 +1,49 @@
error: invalid register class `foo`: unknown register class
--> $DIR/bad-reg.rs:12:20
--> $DIR/bad-reg.rs:17:20
|
LL | asm!("{}", in(foo) foo);
| ^^^^^^^^^^^
|
= note: the following register classes are supported on this target: `reg`, `vreg`, `vreg_low16`, `preg`
= note: the following register classes are supported on this target: `reg`, `vreg`, `vreg_low16`, and `preg`
error: invalid register `foo`: unknown register
--> $DIR/bad-reg.rs:14:18
--> $DIR/bad-reg.rs:19:18
|
LL | asm!("", in("foo") foo);
| ^^^^^^^^^^^^^
error: invalid asm template modifier for this register class
--> $DIR/bad-reg.rs:16:15
error: invalid asm template modifier `z` for this register class
--> $DIR/bad-reg.rs:21:15
|
LL | asm!("{:z}", in(reg) foo);
| ^^^^ ----------- argument
| |
| template modifier
|
= note: the `reg` register class supports the following template modifiers: `w`, `x`
= note: the `reg` register class supports the following template modifiers: `w` and `x`
error: invalid asm template modifier for this register class
--> $DIR/bad-reg.rs:18:15
error: invalid asm template modifier `r` for this register class
--> $DIR/bad-reg.rs:23:15
|
LL | asm!("{:r}", in(vreg) foo);
| ^^^^ ------------ argument
| |
| template modifier
|
= note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`
= note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v`
error: invalid asm template modifier for this register class
--> $DIR/bad-reg.rs:20:15
error: invalid asm template modifier `r` for this register class
--> $DIR/bad-reg.rs:25:15
|
LL | asm!("{:r}", in(vreg_low16) foo);
| ^^^^ ------------------ argument
| |
| template modifier
|
= note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`
= note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, and `v`
error: asm template modifiers are not allowed for `const` arguments
--> $DIR/bad-reg.rs:22:15
--> $DIR/bad-reg.rs:27:15
|
LL | asm!("{:a}", const 0);
| ^^^^ ------- argument
@@ -51,7 +51,7 @@ LL | asm!("{:a}", const 0);
| template modifier
error: asm template modifiers are not allowed for `sym` arguments
--> $DIR/bad-reg.rs:24:15
--> $DIR/bad-reg.rs:29:15
|
LL | asm!("{:a}", sym main);
| ^^^^ -------- argument
@@ -59,49 +59,49 @@ LL | asm!("{:a}", sym main);
| template modifier
error: invalid register `x29`: the frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:26:18
--> $DIR/bad-reg.rs:31:18
|
LL | asm!("", in("x29") foo);
| ^^^^^^^^^^^^^
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:28:18
--> $DIR/bad-reg.rs:33:18
|
LL | asm!("", in("sp") foo);
| ^^^^^^^^^^^^
error: invalid register `xzr`: the zero register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:30:18
--> $DIR/bad-reg.rs:35:18
|
LL | asm!("", in("xzr") 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:32:18
--> $DIR/bad-reg.rs:37: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:35:18
--> $DIR/bad-reg.rs:40: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:39:20
--> $DIR/bad-reg.rs:44: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:47:20
|
LL | asm!("{}", out(preg) _);
| ^^^^^^^^^^^
error: register `w0` conflicts with register `x0`
--> $DIR/bad-reg.rs:48:32
--> $DIR/bad-reg.rs:53:32
|
LL | asm!("", in("x0") foo, in("w0") bar);
| ------------ ^^^^^^^^^^^^ register `w0`
@@ -109,7 +109,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:55:32
|
LL | asm!("", in("x0") foo, out("x0") bar);
| ------------ ^^^^^^^^^^^^^ register `x0`
@@ -117,13 +117,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:55:18
|
LL | asm!("", in("x0") foo, out("x0") bar);
| ^^^^^^^^^^^^
error: register `q0` conflicts with register `v0`
--> $DIR/bad-reg.rs:53:32
--> $DIR/bad-reg.rs:58:32
|
LL | asm!("", in("v0") foo, in("q0") bar);
| ------------ ^^^^^^^^^^^^ register `q0`
@@ -131,7 +131,7 @@ LL | asm!("", in("v0") foo, in("q0") bar);
| register `v0`
error: register `q0` conflicts with register `v0`
--> $DIR/bad-reg.rs:55:32
--> $DIR/bad-reg.rs:60:32
|
LL | asm!("", in("v0") foo, out("q0") bar);
| ------------ ^^^^^^^^^^^^^ register `q0`
@@ -139,13 +139,13 @@ 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:60:18
|
LL | asm!("", in("v0") foo, out("q0") bar);
| ^^^^^^^^^^^^
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:35:27
--> $DIR/bad-reg.rs:40:27
|
LL | asm!("", in("p0") foo);
| ^^^
@@ -153,7 +153,7 @@ LL | asm!("", in("p0") foo);
= note: register class `preg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:39:29
--> $DIR/bad-reg.rs:44:29
|
LL | asm!("{}", in(preg) foo);
| ^^^
+4 -4
View File
@@ -4,7 +4,7 @@ error: invalid ABI for `clobber_abi`
LL | asm!("", clobber_abi("foo"));
| ^^^^^^^^^^^^^^^^^^
|
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, and `sysv64`
error: invalid ABI for `clobber_abi`
--> $DIR/bad-clobber-abi.rs:13:35
@@ -12,7 +12,7 @@ error: invalid ABI for `clobber_abi`
LL | asm!("", clobber_abi("C", "foo"));
| ^^^^^
|
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, and `sysv64`
error: `C` ABI specified multiple times
--> $DIR/bad-clobber-abi.rs:15:35
@@ -38,7 +38,7 @@ error: invalid ABI for `clobber_abi`
LL | asm!("", clobber_abi("C", "foo", "C"));
| ^^^^^
|
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, and `sysv64`
error: `C` ABI specified multiple times
--> $DIR/bad-clobber-abi.rs:20:42
@@ -54,7 +54,7 @@ error: invalid ABI for `clobber_abi`
LL | asm!("", clobber_abi("win64", "foo", "efiapi"));
| ^^^^^
|
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, and `sysv64`
error: `win64` ABI specified multiple times
--> $DIR/bad-clobber-abi.rs:23:46
+1 -1
View File
@@ -93,7 +93,7 @@ error: invalid ABI for `clobber_abi`
LL | asm!("", clobber_abi("foo"));
| ^^^^^^^^^^^^^^^^^^
|
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, and `sysv64`
error: `C` ABI specified multiple times
--> $DIR/bad-options.rs:28:52
@@ -4,7 +4,7 @@ error: invalid register class `foo`: unknown register class
LL | asm!("{}", in(foo) foo);
| ^^^^^^^^^^^
|
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, and `tmm_reg`
error: invalid register `foo`: unknown register
--> $DIR/bad-reg.rs:22:18
@@ -12,7 +12,7 @@ error: invalid register `foo`: unknown register
LL | asm!("", in("foo") foo);
| ^^^^^^^^^^^^^
error: invalid asm template modifier for this register class
error: invalid asm template modifier `z` for this register class
--> $DIR/bad-reg.rs:24:15
|
LL | asm!("{:z}", in(reg) foo);
@@ -20,9 +20,9 @@ LL | asm!("{:z}", in(reg) foo);
| |
| template modifier
|
= note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, `r`
= note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, and `r`
error: invalid asm template modifier for this register class
error: invalid asm template modifier `r` for this register class
--> $DIR/bad-reg.rs:26:15
|
LL | asm!("{:r}", in(xmm_reg) foo);
@@ -30,7 +30,7 @@ LL | asm!("{:r}", in(xmm_reg) foo);
| |
| template modifier
|
= note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z`
= note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, and `z`
error: asm template modifiers are not allowed for `const` arguments
--> $DIR/bad-reg.rs:28:15
+2 -2
View File
@@ -22,9 +22,9 @@ fn main() {
asm!("", in("foo") foo);
//~^ ERROR invalid register `foo`: unknown register
asm!("{:z}", in(reg) foo);
//~^ ERROR invalid asm template modifier for this register class
//~^ ERROR invalid asm template modifier `z` for this register class
asm!("{:r}", in(xmm_reg) foo);
//~^ ERROR invalid asm template modifier for this register class
//~^ ERROR invalid asm template modifier `r` for this register class
asm!("{:a}", const 0);
//~^ ERROR asm template modifiers are not allowed for `const` arguments
asm!("{:a}", sym main);
+5 -5
View File
@@ -4,7 +4,7 @@ error: invalid register class `foo`: unknown register class
LL | asm!("{}", in(foo) foo);
| ^^^^^^^^^^^
|
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, and `tmm_reg`
error: invalid register `foo`: unknown register
--> $DIR/bad-reg.rs:22:18
@@ -12,7 +12,7 @@ error: invalid register `foo`: unknown register
LL | asm!("", in("foo") foo);
| ^^^^^^^^^^^^^
error: invalid asm template modifier for this register class
error: invalid asm template modifier `z` for this register class
--> $DIR/bad-reg.rs:24:15
|
LL | asm!("{:z}", in(reg) foo);
@@ -20,9 +20,9 @@ LL | asm!("{:z}", in(reg) foo);
| |
| template modifier
|
= note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, `r`
= note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, and `r`
error: invalid asm template modifier for this register class
error: invalid asm template modifier `r` for this register class
--> $DIR/bad-reg.rs:26:15
|
LL | asm!("{:r}", in(xmm_reg) foo);
@@ -30,7 +30,7 @@ LL | asm!("{:r}", in(xmm_reg) foo);
| |
| template modifier
|
= note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z`
= note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, and `z`
error: asm template modifiers are not allowed for `const` arguments
--> $DIR/bad-reg.rs:28:15
+2 -2
View File
@@ -4,7 +4,7 @@ error: invalid register class `vreg`: unknown register class
LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
| ^^^^^^^^^^^
|
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, and `tmm_reg`
error: invalid register class `vreg`: unknown register class
--> $DIR/issue-82869.rs:11:45
@@ -12,7 +12,7 @@ error: invalid register class `vreg`: unknown register class
LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
| ^^^^^^^^^^
|
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, and `tmm_reg`
error: invalid register `d0`: unknown register
--> $DIR/issue-82869.rs:11:57