Rollup merge of #147736 - folkertdev:stabilize-asm-cfg, r=jdonszelmann
Stabilize `asm_cfg` tracking issue: https://github.com/rust-lang/rust/issues/140364 closes https://github.com/rust-lang/rust/issues/140364 Reference PR: - https://github.com/rust-lang/reference/pull/2063 # Request for Stabilization ## Summary The `cfg_asm` feature allows `#[cfg(...)]` and `#[cfg_attr(...)]` on the arguments of the assembly macros, for instance: ```rust asm!( // or global_asm! or naked_asm! "nop", #[cfg(target_feature = "sse2")] "nop", // ... #[cfg(target_feature = "sse2")] a = const 123, // only used on sse2 ); ``` ## Semantics Templates, operands, `options` and `clobber_abi` in the assembly macros (`asm!`, `naked_asm!` and `global_asm!`) can be annotated with `#[cfg(...)]` and `#[cfg_attr(...)]`. When the condition evaluates to true, the annotated argument has no effect, and is completely ignored when expanding the assembly macro. ## Documentation reference PR: https://github.com/rust-lang/reference/pull/2063 ## Tests - [tests/ui/asm/cfg.rs](https://github.com/rust-lang/rust/blob/master/tests/ui/asm/cfg.rs) checks that `cfg`'d arguments where the condition evaluates to false have no effect - [tests/ui/asm/cfg-parse-error.rs](https://github.com/rust-lang/rust/blob/master/tests/ui/asm/cfg.rs) checks the parsing rules (parsing effectively assumes that the cfg conditions are all true) ## History - https://github.com/rust-lang/rust/issues/140279 - https://github.com/rust-lang/rust/pull/140367 # Resolved questions **how are other attributes handled** Other attributes are parsed, but explicitly rejected. # unresolved questions **operand before template** The current implementation expects at least one template string before any operands. In the example below, if the `cfg` condition evaluates to true, the assembly block is ill-formed. But even when it evaluates to `false` this block is rejected, because the parser still expects just a template (a template is parsed as an expression and then validated to ensure that it is or expands to a string literal). Changing how this works is difficult. ```rust // This is rejected because `a = out(reg) x` does not parse as an expresion. asm!( #[cfg(false)] a = out(reg) x, //~ ERROR expected token: `,` "", ); ``` **lint on positional arguments?** Adding a lint to warn on the definition or use of positional arguments being `cfg`'d out was discussed in https://github.com/rust-lang/rust/issues/140279#issuecomment-2832237372 and subsequent comments. Such a lint is not currently implemented, but that may not be a blocker based on the comments there. r? `@traviscross` (I'm assuming you'll reassign as needed)
This commit is contained in:
commit
04e4f95e7e
10 changed files with 12 additions and 131 deletions
|
|
@ -3,8 +3,6 @@ builtin_macros_alloc_must_statics = allocators must be statics
|
|||
|
||||
builtin_macros_asm_attribute_not_supported =
|
||||
this attribute is not supported on assembly
|
||||
builtin_macros_asm_cfg =
|
||||
the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
|
||||
|
||||
builtin_macros_asm_clobber_abi = clobber_abi
|
||||
builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs
|
||||
|
|
|
|||
|
|
@ -6,14 +6,13 @@ use rustc_expand::base::*;
|
|||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_parse::parser::asm::*;
|
||||
use rustc_session::lint;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, sym};
|
||||
use rustc_target::asm::InlineAsmArch;
|
||||
use smallvec::smallvec;
|
||||
use {rustc_ast as ast, rustc_parse_format as parse};
|
||||
|
||||
use crate::errors;
|
||||
use crate::util::{ExprToSpannedString, expr_to_spanned_string};
|
||||
use crate::{errors, fluent_generated as fluent};
|
||||
|
||||
/// Validated assembly arguments, ready for macro expansion.
|
||||
struct ValidatedAsmArgs {
|
||||
|
|
@ -64,22 +63,13 @@ fn validate_asm_args<'a>(
|
|||
|
||||
for arg in args {
|
||||
for attr in arg.attributes.0.iter() {
|
||||
match attr.name() {
|
||||
Some(sym::cfg | sym::cfg_attr) => {
|
||||
if !ecx.ecfg.features.asm_cfg() {
|
||||
let span = attr.span();
|
||||
feature_err(ecx.sess, sym::asm_cfg, span, fluent::builtin_macros_asm_cfg)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
ecx.dcx().emit_err(errors::AsmAttributeNotSupported { span: attr.span() });
|
||||
}
|
||||
if !matches!(attr.name(), Some(sym::cfg | sym::cfg_attr)) {
|
||||
ecx.dcx().emit_err(errors::AsmAttributeNotSupported { span: attr.span() });
|
||||
}
|
||||
}
|
||||
|
||||
// Skip arguments that are configured out.
|
||||
if ecx.ecfg.features.asm_cfg() && strip_unconfigured.configure(arg.attributes).is_none() {
|
||||
if strip_unconfigured.configure(arg.attributes).is_none() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ declare_features! (
|
|||
(accepted, adx_target_feature, "1.61.0", Some(44839)),
|
||||
/// Allows explicit discriminants on non-unit enum variants.
|
||||
(accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553)),
|
||||
/// Allows #[cfg(...)] on inline assembly templates and operands.
|
||||
(accepted, asm_cfg, "CURRENT_RUSTC_VERSION", Some(140364)),
|
||||
/// Allows using `const` operands in inline assembly.
|
||||
(accepted, asm_const, "1.82.0", Some(93332)),
|
||||
/// Allows using `label` operands in inline assembly.
|
||||
|
|
|
|||
|
|
@ -382,8 +382,6 @@ declare_features! (
|
|||
(unstable, arbitrary_self_types, "1.23.0", Some(44874)),
|
||||
/// Allows inherent and trait methods with arbitrary self types that are raw pointers.
|
||||
(unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)),
|
||||
/// Allows #[cfg(...)] on inline assembly templates and operands.
|
||||
(unstable, asm_cfg, "1.89.0", Some(140364)),
|
||||
/// Enables experimental inline assembly support for additional architectures.
|
||||
(unstable, asm_experimental_arch, "1.58.0", Some(93335)),
|
||||
/// Enables experimental register support in inline assembly.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#![feature(compiler_builtins)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(linkage)]
|
||||
#![feature(asm_cfg)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(repr_simd)]
|
||||
#![feature(macro_metavar_expr_concat)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//@ needs-asm-support
|
||||
#![feature(asm_cfg)]
|
||||
|
||||
use std::arch::asm;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: expected one of `#`, `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
|
||||
--> $DIR/cfg-parse-error.rs:16:13
|
||||
--> $DIR/cfg-parse-error.rs:15:13
|
||||
|
|
||||
LL | a = out(reg) x,
|
||||
| - expected one of 11 possible tokens
|
||||
|
|
@ -7,7 +7,7 @@ LL | "",
|
|||
| ^^ unexpected token
|
||||
|
||||
error: expected one of `#`, `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
|
||||
--> $DIR/cfg-parse-error.rs:26:13
|
||||
--> $DIR/cfg-parse-error.rs:25:13
|
||||
|
|
||||
LL | },
|
||||
| - expected one of 11 possible tokens
|
||||
|
|
@ -15,19 +15,19 @@ LL | "",
|
|||
| ^^ unexpected token
|
||||
|
||||
error: expected token: `,`
|
||||
--> $DIR/cfg-parse-error.rs:41:26
|
||||
--> $DIR/cfg-parse-error.rs:40:26
|
||||
|
|
||||
LL | a = out(reg) x,
|
||||
| ^ expected `,`
|
||||
|
||||
error: this attribute is not supported on assembly
|
||||
--> $DIR/cfg-parse-error.rs:47:13
|
||||
--> $DIR/cfg-parse-error.rs:46:13
|
||||
|
|
||||
LL | #[rustfmt::skip]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: an inner attribute is not permitted in this context
|
||||
--> $DIR/cfg-parse-error.rs:53:13
|
||||
--> $DIR/cfg-parse-error.rs:52:13
|
||||
|
|
||||
LL | #![rustfmt::skip]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
//@ revisions: reva revb
|
||||
//@ only-x86_64
|
||||
//@ run-pass
|
||||
#![feature(asm_cfg, cfg_select)]
|
||||
#![feature(cfg_select)]
|
||||
|
||||
use std::arch::{asm, naked_asm};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
//@ only-x86_64
|
||||
#![crate_type = "lib"]
|
||||
|
||||
use std::arch::{asm, global_asm, naked_asm};
|
||||
|
||||
global_asm!(
|
||||
"nop",
|
||||
#[cfg(false)]
|
||||
//~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
|
||||
"nop"
|
||||
);
|
||||
|
||||
#[unsafe(naked)]
|
||||
#[no_mangle]
|
||||
extern "C" fn naked() {
|
||||
naked_asm!(
|
||||
"mov rax, 5",
|
||||
#[cfg(false)]
|
||||
//~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
|
||||
"mov rax, {a}",
|
||||
"ret",
|
||||
#[cfg(false)]
|
||||
//~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
|
||||
a = const 10,
|
||||
)
|
||||
}
|
||||
|
||||
fn asm() {
|
||||
unsafe {
|
||||
asm!(
|
||||
"nop",
|
||||
#[cfg(false)]
|
||||
//~^ ERROR the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
|
||||
clobber_abi("C"),
|
||||
clobber_abi("C"), //~ ERROR `C` ABI specified multiple times
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn bad_attribute() {
|
||||
unsafe {
|
||||
asm!(
|
||||
#[inline]
|
||||
//~^ ERROR this attribute is not supported on assembly
|
||||
"nop"
|
||||
)
|
||||
};
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
|
||||
--> $DIR/feature-gate-asm_cfg.rs:8:5
|
||||
|
|
||||
LL | #[cfg(false)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
|
||||
= help: add `#![feature(asm_cfg)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
|
||||
--> $DIR/feature-gate-asm_cfg.rs:18:9
|
||||
|
|
||||
LL | #[cfg(false)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
|
||||
= help: add `#![feature(asm_cfg)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
|
||||
--> $DIR/feature-gate-asm_cfg.rs:22:9
|
||||
|
|
||||
LL | #[cfg(false)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
|
||||
= help: add `#![feature(asm_cfg)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the `#[cfg(/* ... */)]` and `#[cfg_attr(/* ... */)]` attributes on assembly are unstable
|
||||
--> $DIR/feature-gate-asm_cfg.rs:32:13
|
||||
|
|
||||
LL | #[cfg(false)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #140364 <https://github.com/rust-lang/rust/issues/140364> for more information
|
||||
= help: add `#![feature(asm_cfg)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: this attribute is not supported on assembly
|
||||
--> $DIR/feature-gate-asm_cfg.rs:43:13
|
||||
|
|
||||
LL | #[inline]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: `C` ABI specified multiple times
|
||||
--> $DIR/feature-gate-asm_cfg.rs:35:13
|
||||
|
|
||||
LL | clobber_abi("C"),
|
||||
| ---------------- previously specified here
|
||||
LL | clobber_abi("C"),
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue