Skip to content

split asm! parsing and validation #140490

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

folkertdev
Copy link
Contributor

This PR splits asm! parsing and validation into two separate steps.

The parser constructs a Vec<RawAsmArg>, with each element corresponding to an argument to one of the asm! macros.
The validation then checks things like ordering of arguments or that options are not provided twice.

The motivation is #140279, which wants to add #[cfg(...)] support to these arguments. This support can now be added in a straightforward way by adding an attributes: ast::AttrVec field to RawAsmArg.

An extra reason for this split is that rustfmt probably wants to format the assembly at some point (currently that appears to be stubbed out, and the formatting is unstable rust-lang/style-team#152).

r? @ghost (just want to look at CI for now)

cc @ytmimi we discussed asm formatting a little while ago in rust-lang/rustfmt#6526. Am I correct in assuming that AsmArgs does not give enough information for formatting, but that RawAsmArgs would (it e.g. does not join information from multiple lines). This must have been an issue before?

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 29, 2025
@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the asm-parser-changes branch 2 times, most recently from c53bbd4 to d30124a Compare April 30, 2025 09:33
Copy link
Contributor Author

@folkertdev folkertdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r? @Amanieu (I suspect you're most familiar with this code).

I've left some inline comments to hopefully make reviewing this easier.

Comment on lines 21 to 33
/// An argument to one of the `asm!` macros. The argument is syntactically valid, but is otherwise
/// not validated at all.
pub struct RawAsmArg {
pub kind: RawAsmArgKind,
pub span: Span,
}

pub enum RawAsmArgKind {
Template(P<ast::Expr>),
Operand(Option<Symbol>, ast::InlineAsmOperand),
Options(Vec<(Symbol, ast::InlineAsmOptions, Span, Span)>),
ClobberAbi(Vec<(Symbol, Span)>),
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main idea of this PR is to parse into these data structures first, and then validate them in to the pre-existing AsmArgs.

Comment on lines +83 to +97
Ok(Some(if eat_operand_keyword(p, exp!(In), asm_macro)? {
let reg = parse_reg(p)?;
if p.eat_keyword(exp!(Underscore)) {
let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
return Err(err);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a messy diff, but this is just the old operand parsing code extracted into its own function. No changes were made here.

Comment on lines 493 to 502
// NOTE: should this be handled during validation instead?
if !asm_macro.is_supported_option(option) {
// Tool-only output
p.dcx().emit_err(errors::AsmUnsupportedOption {
span,
symbol: exp.kw,
full_span,
macro_name: asm_macro.macro_name(),
});
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to emit this error later, but that changes some of the error messages. For example currently global_asm emits a (non-fatal) warning here when it encounters an unsupported option (e.g. noreturn) even if the remainder of its argument list causes a parse error. By emitting the unsupported option error later, no error is emitted if the argument causes a parse error.

I can add that, but not changing the error output at all in this PR seemed like a good idea to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd at least be worth adding a FIXME(..) then about this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just made the change in a separate commit. I think this is the right call, and the error message change is acceptable: the user is now no longer hitting a "this option is not supported for this flavor of asm" error when there is a parse error in the list of options. When the parse error is resolved, of course the unsupported error is emitted.

Comment on lines 6 to 11
#[allow(dead_code)]
pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option<AsmArgs> {
pub(crate) fn parse_asm(
context: &RewriteContext<'_>,
mac: &ast::MacCall,
) -> Option<Vec<RawAsmArg>> {
let ts = mac.args.tokens.clone();
let mut parser = super::build_parser(context, ts);
parse_asm_args(&mut parser, mac.span(), ast::AsmMacro::Asm).ok()
parse_raw_asm_args(&mut parser, mac.span(), ast::AsmMacro::Asm).ok()
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is defined, but currently not used by rustfmt. I'm assuming that it will be if/when we start formatting the asm! operands, and that RawAsmArg can actually be used for that, while AsmArgs does not have enough information to faithfully reproduce the user's syntax.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rust-lang/rustfmt#5191, an old PR for asm! formatting, does a bunch of its own parsing that I think would not be needed with RawAsmArg.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Speaking with my t-style hat, we do not yet have any established formatting rules for asm!, just a general desire to do so with some fairly concrete thoughts on what those rules would look like.

Speaking with my t-rustfmt hat, this split does look like it'll make our lives much easier to handle asm! formatting whenever t-style does finalize the style rules for it, as it does seem to me this would allow us to avoid needing the custom parsing within rustfmt (though Yacin please correct me if I'm missing something)

@folkertdev folkertdev marked this pull request as ready for review April 30, 2025 10:43
@rustbot
Copy link
Collaborator

rustbot commented Apr 30, 2025

Some changes occurred in src/tools/rustfmt

cc @rust-lang/rustfmt

@folkertdev
Copy link
Contributor Author

#140367, specifically the last commit (currently feddf14) shows how #[cfg(...)] can be built on top of this change.

Copy link
Contributor

@traviscross traviscross left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some nits; seems OK overall to me. Along with the nits addressed and @Amanieu's review, r=me.

Comment on lines 493 to 502
// NOTE: should this be handled during validation instead?
if !asm_macro.is_supported_option(option) {
// Tool-only output
p.dcx().emit_err(errors::AsmUnsupportedOption {
span,
symbol: exp.kw,
full_span,
macro_name: asm_macro.macro_name(),
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd at least be worth adding a FIXME(..) then about this.

@folkertdev folkertdev force-pushed the asm-parser-changes branch 3 times, most recently from 6c50ded to 16880b2 Compare May 3, 2025 10:22
pub struct AsmArgs {
/// An argument to one of the `asm!` macros. The argument is syntactically valid, but is otherwise
/// not validated at all.
pub struct RawAsmArg {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be renamed to AsmArgs (and in other places too).

pub enum RawAsmArgKind {
Template(P<ast::Expr>),
Operand(Option<Symbol>, ast::InlineAsmOperand),
Options(Vec<(Symbol, ast::InlineAsmOptions, Span, Span)>),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this 4-tuple be replaced with a struct.

@folkertdev folkertdev force-pushed the asm-parser-changes branch from 16880b2 to 2e788d1 Compare May 17, 2025 21:53
@rust-log-analyzer

This comment has been minimized.

@folkertdev folkertdev force-pushed the asm-parser-changes branch from 2e788d1 to d91e3d3 Compare May 17, 2025 22:09
@Amanieu
Copy link
Member

Amanieu commented May 17, 2025

r=me once CI passes

@traviscross
Copy link
Contributor

@bors r=Amanieu,traviscross rollup

@bors
Copy link
Collaborator

bors commented May 18, 2025

📌 Commit d91e3d3 has been approved by Amanieu,traviscross

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 18, 2025
fmease added a commit to fmease/rust that referenced this pull request May 18, 2025
…manieu,traviscross

split `asm!` parsing and validation

This PR splits `asm!` parsing and validation into two separate steps.

The parser constructs a `Vec<RawAsmArg>`, with each element corresponding to an argument to one of the `asm!` macros.
The validation then checks things like ordering of arguments or that options are not provided twice.

The motivation is rust-lang#140279, which wants to add `#[cfg(...)]` support to these arguments. This support can now be added in a straightforward way by adding an `attributes: ast::AttrVec` field to `RawAsmArg`.

An extra reason for this split is that `rustfmt` probably wants to format the assembly at some point (currently that appears to be stubbed out, and the formatting is unstable rust-lang/style-team#152).

r? `@ghost` (just want to look at CI for now)

cc `@ytmimi` we discussed asm formatting a little while ago in rust-lang/rustfmt#6526. Am I correct in assuming that `AsmArgs` does not give enough information for formatting, but that `RawAsmArgs` would (it e.g. does not join information from multiple lines). This must have been an issue before?
fmease added a commit to fmease/rust that referenced this pull request May 18, 2025
…manieu,traviscross

split `asm!` parsing and validation

This PR splits `asm!` parsing and validation into two separate steps.

The parser constructs a `Vec<RawAsmArg>`, with each element corresponding to an argument to one of the `asm!` macros.
The validation then checks things like ordering of arguments or that options are not provided twice.

The motivation is rust-lang#140279, which wants to add `#[cfg(...)]` support to these arguments. This support can now be added in a straightforward way by adding an `attributes: ast::AttrVec` field to `RawAsmArg`.

An extra reason for this split is that `rustfmt` probably wants to format the assembly at some point (currently that appears to be stubbed out, and the formatting is unstable rust-lang/style-team#152).

r? ``@ghost`` (just want to look at CI for now)

cc ``@ytmimi`` we discussed asm formatting a little while ago in rust-lang/rustfmt#6526. Am I correct in assuming that `AsmArgs` does not give enough information for formatting, but that `RawAsmArgs` would (it e.g. does not join information from multiple lines). This must have been an issue before?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants