diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index a1e14b5245137..d779089eeaa4c 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -10,7 +10,7 @@ use rustc_parse_format as parse; use rustc_session::lint; use rustc_span::{ErrorGuaranteed, InnerSpan, Span, Symbol, sym}; use rustc_target::asm::InlineAsmArch; -use smallvec::smallvec; +use smallvec::{SmallVec, smallvec}; use crate::errors; use crate::util::{ExprToSpannedString, expr_to_spanned_string}; @@ -26,6 +26,24 @@ struct ValidatedAsmArgs { pub options_spans: Vec, } +struct MacGlobalAsm { + item: ast::Item, +} + +impl MacResult for MacGlobalAsm { + fn make_items(self: Box) -> Option; 1]>> { + Some(smallvec![Box::new(self.item)]) + } + + fn make_stmts(self: Box) -> Option> { + Some(smallvec![ast::Stmt { + id: ast::DUMMY_NODE_ID, + span: self.item.span, + kind: ast::StmtKind::Item(Box::new(self.item)), + }]) + } +} + fn parse_args<'a>( ecx: &ExtCtxt<'a>, sp: Span, @@ -650,18 +668,20 @@ pub(super) fn expand_global_asm<'cx>( return ExpandResult::Retry(()); }; match mac { - Ok(inline_asm) => MacEager::items(smallvec![Box::new(ast::Item { - attrs: ast::AttrVec::new(), - id: ast::DUMMY_NODE_ID, - kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)), - vis: ast::Visibility { - span: sp.shrink_to_lo(), - kind: ast::VisibilityKind::Inherited, + Ok(inline_asm) => Box::new(MacGlobalAsm { + item: ast::Item { + attrs: ast::AttrVec::new(), + id: ast::DUMMY_NODE_ID, + kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)), + vis: ast::Visibility { + span: sp.shrink_to_lo(), + kind: ast::VisibilityKind::Inherited, + tokens: None, + }, + span: sp, tokens: None, }, - span: sp, - tokens: None, - })]), + }), Err(guar) => DummyResult::any(sp, guar), } } diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 55f2f552ad31c..abe26ca91e5d8 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -6,7 +6,7 @@ #![feature(asm_unwind, linkage, rustc_attrs, cfg_target_object_format)] #![crate_type = "lib"] -use std::arch::{asm, naked_asm}; +use std::arch::{asm, global_asm, naked_asm}; #[unsafe(naked)] pub extern "C" fn inline_asm_macro() { @@ -14,6 +14,12 @@ pub extern "C" fn inline_asm_macro() { //~^ERROR the `asm!` macro is not allowed in naked functions } +#[unsafe(naked)] +pub extern "C" fn global_asm_macro() { + //~^ERROR naked functions must contain a single `naked_asm!` invocation + global_asm!(""); +} + #[repr(C)] pub struct P { x: u8, diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr index 2b67c3aecd73c..e8963f7e1d52c 100644 --- a/tests/ui/asm/naked-functions.stderr +++ b/tests/ui/asm/naked-functions.stderr @@ -1,71 +1,71 @@ error: the `in` operand cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:47:29 + --> $DIR/naked-functions.rs:53:29 | LL | naked_asm!("/* {0} */", in(reg) a) | ^^ the `in` operand is not meaningful for global-scoped inline assembly, remove it error: the `in` operand cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:68:10 + --> $DIR/naked-functions.rs:74:10 | LL | in(reg) a, | ^^ the `in` operand is not meaningful for global-scoped inline assembly, remove it error: the `noreturn` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:88:28 + --> $DIR/naked-functions.rs:94:28 | LL | naked_asm!("", options(noreturn)); | ^^^^^^^^ the `noreturn` option is not meaningful for global-scoped inline assembly error: the `nomem` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:105:28 + --> $DIR/naked-functions.rs:111:28 | LL | naked_asm!("", options(nomem, preserves_flags)); | ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly error: the `preserves_flags` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:105:35 + --> $DIR/naked-functions.rs:111:35 | LL | naked_asm!("", options(nomem, preserves_flags)); | ^^^^^^^^^^^^^^^ the `preserves_flags` option is not meaningful for global-scoped inline assembly error: the `readonly` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:112:28 + --> $DIR/naked-functions.rs:118:28 | LL | naked_asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^ the `readonly` option is not meaningful for global-scoped inline assembly error: the `nostack` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:112:38 + --> $DIR/naked-functions.rs:118:38 | LL | naked_asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^ the `nostack` option is not meaningful for global-scoped inline assembly error: the `pure` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:112:56 + --> $DIR/naked-functions.rs:118:56 | LL | naked_asm!("", options(readonly, nostack), options(pure)); | ^^^^ the `pure` option is not meaningful for global-scoped inline assembly error: the `may_unwind` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:120:28 + --> $DIR/naked-functions.rs:126:28 | LL | naked_asm!("", options(may_unwind)); | ^^^^^^^^^^ the `may_unwind` option is not meaningful for global-scoped inline assembly error: this is a user specified error - --> $DIR/naked-functions.rs:151:5 + --> $DIR/naked-functions.rs:157:5 | LL | compile_error!("this is a user specified error") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:157:5 + --> $DIR/naked-functions.rs:163:5 | LL | compile_error!("this is a user specified error"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/naked-functions.rs:164:16 + --> $DIR/naked-functions.rs:170:16 | LL | naked_asm!(invalid_syntax) | ^^^^^^^^^^^^^^ @@ -76,32 +76,38 @@ error[E0787]: the `asm!` macro is not allowed in naked functions LL | unsafe { asm!("", options(raw)) }; | ^^^^^^^^^^^^^^^^^^^^^^ consider using the `naked_asm!` macro instead +error[E0787]: naked functions must contain a single `naked_asm!` invocation + --> $DIR/naked-functions.rs:18:1 + | +LL | pub extern "C" fn global_asm_macro() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:25:5 + --> $DIR/naked-functions.rs:31:5 | LL | mut a: u32, | ^^^^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:27:5 + --> $DIR/naked-functions.rs:33:5 | LL | &b: &i32, | ^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:29:6 + --> $DIR/naked-functions.rs:35:6 | LL | (None | Some(_)): Option>, | ^^^^^^^^^^^^^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:31:5 + --> $DIR/naked-functions.rs:37:5 | LL | P { x, y }: P, | ^^^^^^^^^^ error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:40:5 + --> $DIR/naked-functions.rs:46:5 | LL | a + 1 | ^ @@ -109,7 +115,7 @@ LL | a + 1 = help: follow the calling convention in asm block to use parameters error[E0787]: naked functions must contain a single `naked_asm!` invocation - --> $DIR/naked-functions.rs:38:1 + --> $DIR/naked-functions.rs:44:1 | LL | pub extern "C" fn inc(a: u32) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +124,7 @@ LL | a + 1 | ----- not allowed in naked functions error[E0787]: naked functions must contain a single `naked_asm!` invocation - --> $DIR/naked-functions.rs:52:1 + --> $DIR/naked-functions.rs:58:1 | LL | pub extern "C" fn inc_closure(a: u32) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,7 +133,7 @@ LL | (|| a + 1)() | ------------ not allowed in naked functions error[E0787]: naked functions must contain a single `naked_asm!` invocation - --> $DIR/naked-functions.rs:58:1 + --> $DIR/naked-functions.rs:64:1 | LL | pub extern "C" fn unsupported_operands() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -144,13 +150,13 @@ LL | let mut e = 0usize; | ------------------- not allowed in naked functions error[E0787]: naked functions must contain a single `naked_asm!` invocation - --> $DIR/naked-functions.rs:80:1 + --> $DIR/naked-functions.rs:86:1 | LL | pub extern "C" fn missing_assembly() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0787]: naked functions must contain a single `naked_asm!` invocation - --> $DIR/naked-functions.rs:85:1 + --> $DIR/naked-functions.rs:91:1 | LL | pub extern "C" fn too_many_asm_blocks() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -159,7 +165,7 @@ LL | naked_asm!(""); | -------------- multiple `naked_asm!` invocations are not allowed in naked functions error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:97:11 + --> $DIR/naked-functions.rs:103:11 | LL | *&y | ^ @@ -167,7 +173,7 @@ LL | *&y = help: follow the calling convention in asm block to use parameters error[E0787]: naked functions must contain a single `naked_asm!` invocation - --> $DIR/naked-functions.rs:95:5 + --> $DIR/naked-functions.rs:101:5 | LL | pub extern "C" fn inner(y: usize) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -175,6 +181,6 @@ LL | LL | *&y | --- not allowed in naked functions -error: aborting due to 25 previous errors +error: aborting due to 26 previous errors For more information about this error, try `rustc --explain E0787`. diff --git a/tests/ui/asm/statement-global-asm-error.rs b/tests/ui/asm/statement-global-asm-error.rs new file mode 100644 index 0000000000000..f32ba73357a19 --- /dev/null +++ b/tests/ui/asm/statement-global-asm-error.rs @@ -0,0 +1,13 @@ +//@ needs-asm-support + +use std::arch::global_asm; + +fn main() { + let x = 42; + global_asm!("{}", in(x)); + //~^ ERROR the `in` operand cannot be used with `global_asm!` + //~^^ NOTE the `in` operand is not meaningful for global-scoped inline assembly, remove it + + let y = global_asm!(""); + //~^ ERROR non-expression macro in expression position: global_asm +} diff --git a/tests/ui/asm/statement-global-asm-error.stderr b/tests/ui/asm/statement-global-asm-error.stderr new file mode 100644 index 0000000000000..35dde6ac1a781 --- /dev/null +++ b/tests/ui/asm/statement-global-asm-error.stderr @@ -0,0 +1,14 @@ +error: the `in` operand cannot be used with `global_asm!` + --> $DIR/statement-global-asm-error.rs:7:23 + | +LL | global_asm!("{}", in(x)); + | ^^ the `in` operand is not meaningful for global-scoped inline assembly, remove it + +error: non-expression macro in expression position: global_asm + --> $DIR/statement-global-asm-error.rs:11:13 + | +LL | let y = global_asm!(""); + | ^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/asm/statement-global-asm.rs b/tests/ui/asm/statement-global-asm.rs new file mode 100644 index 0000000000000..597495546d955 --- /dev/null +++ b/tests/ui/asm/statement-global-asm.rs @@ -0,0 +1,8 @@ +//@ needs-asm-support +//@ run-pass + +use std::arch::global_asm; + +fn main() { + global_asm!(""); +}