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 9 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.

apparently it doesn't really use the asm parsing at present, so this may work?
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 +88
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.

Comment on lines 6 to 14
#[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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants