about summary refs log tree commit diff
path: root/tests/ui/asm
diff options
context:
space:
mode:
authorFolkert de Vries <folkert@folkertdev.nl>2025-04-30 11:23:09 +0200
committerFolkert de Vries <folkert@folkertdev.nl>2025-05-27 09:44:04 +0200
commite3bbbeeafd159b9cb7b000950420a20d8910fd5e (patch)
tree89532d311a99463ff3f7c0ff20d14a088f22b134 /tests/ui/asm
parent6eef33bb399cabfab16aa4e0825895f5f32f4e26 (diff)
downloadrust-e3bbbeeafd159b9cb7b000950420a20d8910fd5e.tar.gz
rust-e3bbbeeafd159b9cb7b000950420a20d8910fd5e.zip
support `#[cfg(...)]` on arguments to the `asm!` macros
Diffstat (limited to 'tests/ui/asm')
-rw-r--r--tests/ui/asm/cfg-parse-error.rs56
-rw-r--r--tests/ui/asm/cfg-parse-error.stderr36
-rw-r--r--tests/ui/asm/cfg.rs125
3 files changed, 217 insertions, 0 deletions
diff --git a/tests/ui/asm/cfg-parse-error.rs b/tests/ui/asm/cfg-parse-error.rs
new file mode 100644
index 00000000000..c66a627ca94
--- /dev/null
+++ b/tests/ui/asm/cfg-parse-error.rs
@@ -0,0 +1,56 @@
+//@ needs-asm-support
+#![feature(asm_cfg)]
+
+use std::arch::asm;
+
+fn main() {
+    unsafe {
+        asm!(
+            "",
+            #[cfg(false)]
+            clobber_abi("C"),
+            #[cfg(false)]
+            options(att_syntax),
+            #[cfg(false)]
+            a = out(reg) x,
+            "",
+            //~^ ERROR expected one of `clobber_abi`, `const`
+        );
+        asm!(
+            #[cfg(false)]
+            "",
+            #[cfg(false)]
+            const {
+                5
+            },
+            "", //~ ERROR expected one of `clobber_abi`, `const`
+        );
+
+        asm!(
+            #[cfg_attr(true, cfg(false))]
+            const {
+                5
+            },
+            "",
+        );
+
+        // This is not accepted because `a = out(reg) x` is not a valid expression.
+        asm!(
+            #[cfg(false)]
+            a = out(reg) x, //~ ERROR expected token: `,`
+            "",
+        );
+
+        // For now, any non-cfg attributes are rejected
+        asm!(
+            #[rustfmt::skip] //~ ERROR this attribute is not supported on assembly
+            "",
+        );
+
+        // For now, any non-cfg attributes are rejected
+        asm!(
+            #![rustfmt::skip] //~ ERROR an inner attribute is not permitted in this context
+            "",
+        );
+    }
+}
diff --git a/tests/ui/asm/cfg-parse-error.stderr b/tests/ui/asm/cfg-parse-error.stderr
new file mode 100644
index 00000000000..19c76adee63
--- /dev/null
+++ b/tests/ui/asm/cfg-parse-error.stderr
@@ -0,0 +1,36 @@
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
+  --> $DIR/cfg-parse-error.rs:16:13
+   |
+LL |             a = out(reg) x,
+   |                            - expected one of 10 possible tokens
+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
+   |
+LL |             },
+   |               - expected one of 10 possible tokens
+LL |             "",
+   |             ^^ unexpected token
+
+error: expected token: `,`
+  --> $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:46:13
+   |
+LL |             #[rustfmt::skip]
+   |             ^^^^^^^^^^^^^^^^
+
+error: this attribute is not supported on assembly
+  --> $DIR/cfg-parse-error.rs:52:13
+   |
+LL |             #![rustfmt::skip]
+   |             ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/asm/cfg.rs b/tests/ui/asm/cfg.rs
new file mode 100644
index 00000000000..bcf86340b9d
--- /dev/null
+++ b/tests/ui/asm/cfg.rs
@@ -0,0 +1,125 @@
+// Check that `cfg` and `cfg_attr` work as expected.
+//
+//@ revisions: reva revb
+//@ only-x86_64
+//@ run-pass
+#![feature(asm_cfg, cfg_select)]
+
+use std::arch::{asm, naked_asm};
+
+#[unsafe(naked)]
+extern "C" fn ignore_const_operand() -> u64 {
+    naked_asm!(
+        "mov rax, 5",
+        #[cfg(revb)]
+        "mov rax, {a}",
+        "ret",
+        #[cfg(revb)]
+        a = const 10,
+    )
+}
+
+#[unsafe(naked)]
+extern "C" fn ignore_const_operand_cfg_attr() -> u64 {
+    naked_asm!(
+        "mov rax, 5",
+        #[cfg_attr(true, cfg(revb))]
+        "mov rax, {a}",
+        "ret",
+        #[cfg_attr(true, cfg(revb))]
+        a = const 10,
+    )
+}
+
+#[unsafe(naked)]
+extern "C" fn const_operand() -> u64 {
+    naked_asm!(
+        "mov rax, {a}",
+        "ret",
+        #[cfg(reva)]
+        a = const 5,
+        #[cfg(revb)]
+        a = const 10,
+    )
+}
+
+fn options() {
+    // Without the cfg, this throws an error that the `att_syntax` option is provided twice.
+    unsafe {
+        asm!(
+            "nop",
+            #[cfg(false)]
+            options(att_syntax),
+            options(att_syntax)
+        )
+    }
+}
+
+fn clobber_abi() {
+    // Without the cfg, this throws an error that the "C" abi is provided twice.
+    unsafe {
+        asm!(
+            "nop",
+            #[cfg(false)]
+            clobber_abi("C"),
+            clobber_abi("C"),
+        );
+    }
+}
+
+#[unsafe(naked)]
+extern "C" fn first_template() -> u64 {
+    naked_asm!(
+        #[cfg(reva)]
+        "mov rax, 5",
+        #[cfg(revb)]
+        "mov rax, 10",
+        "ret",
+    )
+}
+
+#[unsafe(naked)]
+extern "C" fn true_and_false() -> u64 {
+    naked_asm!(
+        "mov rax, 5",
+        #[cfg(true)]
+        #[cfg(false)]
+        "mov rax, 10",
+        "ret",
+    )
+}
+
+#[unsafe(naked)]
+extern "C" fn false_and_true() -> u64 {
+    naked_asm!(
+        "mov rax, 5",
+        #[cfg(false)]
+        #[cfg(true)]
+        "mov rax, 10",
+        "ret",
+    )
+}
+
+pub fn main() {
+    std::cfg_select! {
+        reva => {
+            assert_eq!(const_operand(), 5);
+            assert_eq!(ignore_const_operand_cfg_attr(), 5);
+            assert_eq!(ignore_const_operand(), 5);
+            assert_eq!(first_template(), 5);
+
+        }
+        revb => {
+            assert_eq!(const_operand(), 10);
+            assert_eq!(ignore_const_operand_cfg_attr(), 10);
+            assert_eq!(ignore_const_operand(), 10);
+            assert_eq!(first_template(), 10);
+
+        }
+    }
+    options();
+    clobber_abi();
+
+    assert_eq!(true_and_false(), 5);
+    assert_eq!(false_and_true(), 5);
+}