Skip to content

Commit

Permalink
Relax ordering rules for asm! operands
Browse files Browse the repository at this point in the history
The `asm!` and `global_asm!` macros require their operands to appear
strictly in the following order:
- Template strings
- Positional operands
- Named operands
- Explicit register operands
- `clobber_abi`
- `options`

This is overly strict and can be inconvienent when building complex
`asm!` statements with macros. This PR relaxes the ordering requirements
as follows:
- Template strings must still come before all other operands.
- Positional operands must still come before named and explicit register
operands.
- Named and explicit register operands can be freely mixed.
- `options` and `clobber_abi` can appear in any position.
  • Loading branch information
Amanieu committed Jan 27, 2023
1 parent db137ba commit 52f7a21
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 291 deletions.
35 changes: 4 additions & 31 deletions compiler/rustc_builtin_macros/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,17 +203,6 @@ pub fn parse_asm_args<'a>(
// Validate the order of named, positional & explicit register operands and
// clobber_abi/options. We do this at the end once we have the full span
// of the argument available.
if !args.options_spans.is_empty() {
diag.struct_span_err(span, "arguments are not allowed after options")
.span_labels(args.options_spans.clone(), "previous options")
.span_label(span, "argument")
.emit();
} else if let Some((_, abi_span)) = args.clobber_abis.last() {
diag.struct_span_err(span, "arguments are not allowed after clobber_abi")
.span_label(*abi_span, "clobber_abi")
.span_label(span, "argument")
.emit();
}
if explicit_reg {
if name.is_some() {
diag.struct_span_err(span, "explicit register arguments cannot have names").emit();
Expand All @@ -227,17 +216,6 @@ pub fn parse_asm_args<'a>(
.emit();
continue;
}
if !args.reg_args.is_empty() {
let mut err = diag.struct_span_err(
span,
"named arguments cannot follow explicit register arguments",
);
err.span_label(span, "named argument");
for pos in &args.reg_args {
err.span_label(args.operands[*pos].1, "explicit register argument");
}
err.emit();
}
args.named_args.insert(name, slot);
} else {
if !args.named_args.is_empty() || !args.reg_args.is_empty() {
Expand Down Expand Up @@ -478,15 +456,6 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,

let full_span = span_start.to(p.prev_token.span);

if !args.options_spans.is_empty() {
let mut err = p
.sess
.span_diagnostic
.struct_span_err(full_span, "clobber_abi is not allowed after options");
err.span_labels(args.options_spans.clone(), "options");
return Err(err);
}

match &new_abis[..] {
// should have errored above during parsing
[] => unreachable!(),
Expand Down Expand Up @@ -699,6 +668,10 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
args.operands[idx].1,
"explicit register arguments cannot be used in the asm template",
);
err.span_help(
args.operands[idx].1,
"use the register name directly in the assembly code",
);
}
err.emit();
None
Expand Down
23 changes: 8 additions & 15 deletions tests/ui/asm/aarch64/parse-error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,18 @@ fn main() {
asm!("", options(nomem, foo));
//~^ ERROR expected one of
asm!("{}", options(), const foo);
//~^ ERROR arguments are not allowed after options
//~^^ ERROR attempt to use a non-constant value in a constant
//~^ ERROR attempt to use a non-constant value in a constant
asm!("", clobber_abi(foo));
//~^ ERROR expected string literal
asm!("", clobber_abi("C" foo));
//~^ ERROR expected one of `)` or `,`, found `foo`
asm!("", clobber_abi("C", foo));
//~^ ERROR expected string literal
asm!("{}", clobber_abi("C"), const foo);
//~^ ERROR arguments are not allowed after clobber_abi
//~^^ ERROR attempt to use a non-constant value in a constant
//~^ ERROR attempt to use a non-constant value in a constant
asm!("", options(), clobber_abi("C"));
//~^ ERROR clobber_abi is not allowed after options
asm!("{}", options(), clobber_abi("C"), const foo);
//~^ ERROR clobber_abi is not allowed after options
//~^ ERROR attempt to use a non-constant value in a constant
asm!("{a}", a = const foo, a = const bar);
//~^ ERROR duplicate argument named `a`
//~^^ ERROR argument never used
Expand All @@ -60,11 +57,9 @@ fn main() {
asm!("", a = in("x0") foo);
//~^ ERROR explicit register arguments cannot have names
asm!("{a}", in("x0") foo, a = const bar);
//~^ ERROR named arguments cannot follow explicit register arguments
//~^^ ERROR attempt to use a non-constant value in a constant
//~^ ERROR attempt to use a non-constant value in a constant
asm!("{a}", in("x0") foo, a = const bar);
//~^ ERROR named arguments cannot follow explicit register arguments
//~^^ ERROR attempt to use a non-constant value in a constant
//~^ ERROR attempt to use a non-constant value in a constant
asm!("{1}", in("x0") foo, const bar);
//~^ ERROR positional arguments cannot follow named arguments or explicit register arguments
//~^^ ERROR attempt to use a non-constant value in a constant
Expand Down Expand Up @@ -106,20 +101,18 @@ global_asm!("", options(nomem FOO));
global_asm!("", options(nomem, FOO));
//~^ ERROR expected one of
global_asm!("{}", options(), const FOO);
//~^ ERROR arguments are not allowed after options
global_asm!("", clobber_abi(FOO));
//~^ ERROR expected string literal
global_asm!("", clobber_abi("C" FOO));
//~^ ERROR expected one of `)` or `,`, found `FOO`
global_asm!("", clobber_abi("C", FOO));
//~^ ERROR expected string literal
global_asm!("{}", clobber_abi("C"), const FOO);
//~^ ERROR arguments are not allowed after clobber_abi
//~^^ ERROR `clobber_abi` cannot be used with `global_asm!`
//~^ ERROR `clobber_abi` cannot be used with `global_asm!`
global_asm!("", options(), clobber_abi("C"));
//~^ ERROR clobber_abi is not allowed after options
//~^ ERROR `clobber_abi` cannot be used with `global_asm!`
global_asm!("{}", options(), clobber_abi("C"), const FOO);
//~^ ERROR clobber_abi is not allowed after options
//~^ ERROR `clobber_abi` cannot be used with `global_asm!`
global_asm!("{a}", a = const FOO, a = const BAR);
//~^ ERROR duplicate argument named `a`
//~^^ ERROR argument never used
Expand Down
Loading

0 comments on commit 52f7a21

Please sign in to comment.