Skip to content

Commit 8650df5

Browse files
authored
Rollup merge of rust-lang#73230 - Amanieu:asm-unused2, r=petrochenkov
Suggest including unused asm arguments in a comment to avoid error We require all arguments to an `asm!` to be used in the template string, just like format strings. However in some cases (e.g. `black_box`) it may be desirable to have `asm!` arguments that are not used in the template string. Currently this is a hard error rather than a lint since `#[allow]` does not work on macros (rust-lang#63221), so this PR suggests using the unused arguments in an asm comment as a workaround. r? @petrochenkov
2 parents 6b418b3 + ddacc67 commit 8650df5

File tree

5 files changed

+54
-21
lines changed

5 files changed

+54
-21
lines changed

src/doc/unstable-book/src/library-features/asm.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ fn mul(a: u64, b: u64) -> u128 {
201201
);
202202
}
203203
204-
(hi as u128) << 64 + lo as u128
204+
((hi as u128) << 64) + lo as u128
205205
}
206206
```
207207

@@ -382,7 +382,9 @@ The macro will initially be supported only on ARM, AArch64, x86, x86-64 and RISC
382382

383383
The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported.
384384

385-
As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after any named arguments if any. Explicit register operands cannot be used by placeholders in the template string. All other operands must appear at least once in the template string, otherwise a compiler error is generated.
385+
As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after named arguments if any.
386+
387+
Explicit register operands cannot be used by placeholders in the template string. All other named and positional operands must appear at least once in the template string, otherwise a compiler error is generated.
386388

387389
The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler.
388390

src/librustc_builtin_macros/asm.rs

+29-18
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
391391
used[*pos] = true;
392392
}
393393

394-
let named_pos: FxHashSet<usize> = args.named_args.values().cloned().collect();
394+
let named_pos: FxHashMap<usize, Symbol> =
395+
args.named_args.iter().map(|(&sym, &idx)| (idx, sym)).collect();
395396
let mut arg_spans = parser.arg_places.iter().map(|span| template_span.from_inner(*span));
396397
let mut template = vec![];
397398
for piece in unverified_pieces {
@@ -405,7 +406,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
405406
let operand_idx = match arg.position {
406407
parse::ArgumentIs(idx) | parse::ArgumentImplicitlyIs(idx) => {
407408
if idx >= args.operands.len()
408-
|| named_pos.contains(&idx)
409+
|| named_pos.contains_key(&idx)
409410
|| args.reg_args.contains(&idx)
410411
{
411412
let msg = format!("invalid reference to argument at index {}", idx);
@@ -426,7 +427,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
426427
};
427428
err.note(&msg);
428429

429-
if named_pos.contains(&idx) {
430+
if named_pos.contains_key(&idx) {
430431
err.span_label(args.operands[idx].1, "named argument");
431432
err.span_note(
432433
args.operands[idx].1,
@@ -480,27 +481,31 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
480481
}
481482
}
482483

483-
let operands = args.operands;
484-
let unused_operands: Vec<_> = used
485-
.into_iter()
486-
.enumerate()
487-
.filter(|&(_, used)| !used)
488-
.map(|(idx, _)| {
489-
if named_pos.contains(&idx) {
490-
// named argument
491-
(operands[idx].1, "named argument never used")
484+
let mut unused_operands = vec![];
485+
let mut help_str = String::new();
486+
for (idx, used) in used.into_iter().enumerate() {
487+
if !used {
488+
let msg = if let Some(sym) = named_pos.get(&idx) {
489+
help_str.push_str(&format!(" {{{}}}", sym));
490+
"named argument never used"
492491
} else {
493-
// positional argument
494-
(operands[idx].1, "argument never used")
495-
}
496-
})
497-
.collect();
492+
help_str.push_str(&format!(" {{{}}}", idx));
493+
"argument never used"
494+
};
495+
unused_operands.push((args.operands[idx].1, msg));
496+
}
497+
}
498498
match unused_operands.len() {
499499
0 => {}
500500
1 => {
501501
let (sp, msg) = unused_operands.into_iter().next().unwrap();
502502
let mut err = ecx.struct_span_err(sp, msg);
503503
err.span_label(sp, msg);
504+
err.help(&format!(
505+
"if this argument is intentionally unused, \
506+
consider using it in an asm comment: `\"/*{} */\"`",
507+
help_str
508+
));
504509
err.emit();
505510
}
506511
_ => {
@@ -511,6 +516,11 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
511516
for (sp, msg) in unused_operands {
512517
err.span_label(sp, msg);
513518
}
519+
err.help(&format!(
520+
"if these arguments are intentionally unused, \
521+
consider using them in an asm comment: `\"/*{} */\"`",
522+
help_str
523+
));
514524
err.emit();
515525
}
516526
}
@@ -521,7 +531,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
521531
parser.line_spans.iter().map(|span| template_span.from_inner(*span)).collect()
522532
};
523533

524-
let inline_asm = ast::InlineAsm { template, operands, options: args.options, line_spans };
534+
let inline_asm =
535+
ast::InlineAsm { template, operands: args.operands, options: args.options, line_spans };
525536
P(ast::Expr {
526537
id: ast::DUMMY_NODE_ID,
527538
kind: ast::ExprKind::InlineAsm(P(inline_asm)),

src/test/ui/asm/bad-template.rs

+2
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,7 @@ fn main() {
2222
//~^ ERROR invalid reference to argument at index 0
2323
asm!("{:foo}", in(reg) foo);
2424
//~^ ERROR asm template modifier must be a single character
25+
asm!("", in(reg) 0, in(reg) 1);
26+
//~^ ERROR multiple unused asm arguments
2527
}
2628
}

src/test/ui/asm/bad-template.stderr

+17-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ error: argument never used
1919
|
2020
LL | asm!("{1}", in(reg) foo);
2121
| ^^^^^^^^^^^ argument never used
22+
|
23+
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
2224

2325
error: there is no argument named `a`
2426
--> $DIR/bad-template.rs:13:15
@@ -46,6 +48,8 @@ error: named argument never used
4648
|
4749
LL | asm!("{}", a = in(reg) foo);
4850
| ^^^^^^^^^^^^^^^ named argument never used
51+
|
52+
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
4953

5054
error: invalid reference to argument at index 1
5155
--> $DIR/bad-template.rs:18:15
@@ -60,6 +64,8 @@ error: named argument never used
6064
|
6165
LL | asm!("{1}", a = in(reg) foo);
6266
| ^^^^^^^^^^^^^^^ named argument never used
67+
|
68+
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
6369

6470
error: invalid reference to argument at index 0
6571
--> $DIR/bad-template.rs:21:15
@@ -82,5 +88,15 @@ error: asm template modifier must be a single character
8288
LL | asm!("{:foo}", in(reg) foo);
8389
| ^^^
8490

85-
error: aborting due to 10 previous errors
91+
error: multiple unused asm arguments
92+
--> $DIR/bad-template.rs:25:18
93+
|
94+
LL | asm!("", in(reg) 0, in(reg) 1);
95+
| ^^^^^^^^^ ^^^^^^^^^ argument never used
96+
| |
97+
| argument never used
98+
|
99+
= help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
100+
101+
error: aborting due to 11 previous errors
86102

src/test/ui/asm/parse-error.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ error: argument never used
127127
|
128128
LL | asm!("{a}", a = const foo, a = const bar);
129129
| ^^^^^^^^^^^^^ argument never used
130+
|
131+
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
130132

131133
error: explicit register arguments cannot have names
132134
--> $DIR/parse-error.rs:47:18

0 commit comments

Comments
 (0)