Skip to content

add asm_cfg: #[cfg(...)] within asm! #140367

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 7 commits into
base: master
Choose a base branch
from

Conversation

folkertdev
Copy link
Contributor

tracking issue: #140364

This feature was discussed in #140279. It allows configuring templates and operands in the assembly macros, for example:

asm!( // or global_asm! or naked_asm!
    "nop",
    #[cfg(target_feature = "sse2")]
    "nop",
    // ...
    #[cfg(target_feature = "sse2")]
    a = const 123, // only used on sse2
);

r? @tgross35

cc @traviscross @Amanieu

This needs some squashing, but I suspect we'll iterate a bunch here. I'll leave some inline comments too.

@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 27, 2025
let is_configured_out =
ecx.ecfg.features.asm_cfg() && strip_unconfigured.configure(attributes).is_none();

let template = p.parse_expr()?;
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 fact that we use parse_expr here mean that this does not work, and does not produce a great error message. This complains about an unexpected , after the 6, but the real problem is that this cannot possibly be or expand to a string literal.

asm!(
    #[cfg(false)]
    a = const 6,
    "nop",
);

Maybe we should specialize the parser to specifically only parse string literals and item macros?

if p.token == token::Eof {
return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp }));
}

let first_template = p.parse_expr()?;
let first_template = loop {
let attributes = AsmAttrVec::parse(ecx, p)?;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

attributes are now parsed before the parse_expr below, and never attached to the expression. In theory that could interact with #[feature(stmt_expr_attributes)], but:

  • that feature is unstable
  • any attributes it parsed would have no effect

Comment on lines +90 to +92
_ => {
ecx.dcx().emit_err(errors::AsmAttributeNotSupported { span: attr.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.

non-cfg attributes are now accepted by the parser, but emit this error. Previously attributes were only parsed (and later rejected, unless #[feature(stmt_expr_attributes)] was enabled) on expressions. We now also always parse them on operands.

@rust-log-analyzer
Copy link
Collaborator

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
[RUSTC-TIMING] toml test:false 0.195
error[E0061]: this function takes 4 arguments but 3 arguments were supplied
   --> src/tools/rustfmt/src/parse/macros/asm.rs:10:5
    |
10  |     parse_asm_args(&mut parser, mac.span(), ast::AsmMacro::Asm).ok()
    |     ^^^^^^^^^^^^^^ ----------- argument #1 of type `&ExtCtxt<'_>` is missing
    |
note: function defined here
   --> /checkout/compiler/rustc_builtin_macros/src/asm.rs:134:8
    |
134 | pub fn parse_asm_args<'a>(
    |        ^^^^^^^^^^^^^^
help: provide the argument
    |
10  |     parse_asm_args(/* &ExtCtxt<'_> */, &mut parser, mac.span(), ast::AsmMacro::Asm).ok()
    |                    +++++++++++++++++++

For more information about this error, try `rustc --explain E0061`.
[RUSTC-TIMING] rustfmt_nightly test:false 2.371
error: could not compile `rustfmt-nightly` (lib) due to 1 previous error

@folkertdev
Copy link
Contributor Author

Hmm, rust analyzer also parses the assembly, but from what I can see it has no way of evaluating the cfgs while parsing. Maybe that can change, but if not we'll have to fundamentally change the parser to just parse, and then later have a validation pass. I tried that before and it's possible but messy, and you need to store a lot more information in AsmArgs (that rust-analyzer then would also have to process).

@rust-lang/rust-analyzer how can we make this work?

@ChayimFriedman2
Copy link
Contributor

(I haven't looked at the PR, but) parsing does not evaluated cfgs. Hir lowering does.

@folkertdev
Copy link
Contributor Author

Well in any case the parser doesn't. I'm not exactly sure where to draw the line for when HIR lowering starts, but certainly macro expansion of builtin macros is able to do it, e.g. here for cfg!:

let matches_cfg = attr::cfg_matches(
&cfg,
&cx.sess,
cx.current_expansion.lint_node_id,
Some(cx.ecfg.features),
);
MacEager::expr(cx.expr_bool(sp, matches_cfg))

Anyway, are you saying that rust-analyzer just cannot evaluate cfg's while parsing the asm! macro? We can delay it, but I think that just means that rust-analyzer would have to duplicate the logic.

@Veykril
Copy link
Member

Veykril commented Apr 28, 2025

rust-analyzer has to duplicate these changes either way. We don't use any of the touched rustc crates here.

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.

6 participants