about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGary Guo <gary@garyguo.net>2023-12-27 22:57:17 +0000
committerGary Guo <gary@garyguo.net>2024-02-24 19:49:16 +0000
commit4677a71369f690b5aecf9380cf12074792f09a3f (patch)
tree80f9f938951ab256dcd1ff4c3d8c5b942d125143
parent31f078ea9941ce89f1f5ab5fb1239bbbddfe4d49 (diff)
downloadrust-4677a71369f690b5aecf9380cf12074792f09a3f.tar.gz
rust-4677a71369f690b5aecf9380cf12074792f09a3f.zip
Add tests for asm goto
-rw-r--r--tests/codegen/asm-goto.rs51
-rw-r--r--tests/ui/asm/parse-error.rs2
-rw-r--r--tests/ui/asm/parse-error.stderr16
-rw-r--r--tests/ui/asm/x86_64/bad-options.rs4
-rw-r--r--tests/ui/asm/x86_64/bad-options.stderr38
-rw-r--r--tests/ui/asm/x86_64/goto.mirunsafeck.stderr23
-rw-r--r--tests/ui/asm/x86_64/goto.rs111
-rw-r--r--tests/ui/asm/x86_64/goto.thirunsafeck.stderr23
-rw-r--r--tests/ui/feature-gates/feature-gate-asm_goto.rs10
-rw-r--r--tests/ui/feature-gates/feature-gate-asm_goto.stderr13
10 files changed, 270 insertions, 21 deletions
diff --git a/tests/codegen/asm-goto.rs b/tests/codegen/asm-goto.rs
new file mode 100644
index 00000000000..e522d0da5b4
--- /dev/null
+++ b/tests/codegen/asm-goto.rs
@@ -0,0 +1,51 @@
+//@ compile-flags: -O
+//@ only-x86_64
+
+#![crate_type = "rlib"]
+#![feature(asm_goto)]
+
+use std::arch::asm;
+
+#[no_mangle]
+pub extern "C" fn panicky() {}
+
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!();
+    }
+}
+
+// CHECK-LABEL: @asm_goto
+#[no_mangle]
+pub unsafe fn asm_goto() {
+    // CHECK: callbr void asm sideeffect alignstack inteldialect "
+    // CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]]
+    asm!("jmp {}", label {});
+}
+
+// CHECK-LABEL: @asm_goto_with_outputs
+#[no_mangle]
+pub unsafe fn asm_goto_with_outputs() -> u64 {
+    let out: u64;
+    // CHECK: [[RES:%[0-9]+]] = callbr i64 asm sideeffect alignstack inteldialect "
+    // CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]]
+    asm!("{} /* {} */", out(reg) out, label { return 1; });
+    // CHECK: [[JUMPBB]]:
+    // CHECK-NEXT: [[RET:%.+]] = phi i64 [ [[RES]], %[[FALLTHROUGHBB]] ], [ 1, %start ]
+    // CHECK-NEXT: ret i64 [[RET]]
+    out
+}
+
+// CHECK-LABEL: @asm_goto_noreturn
+#[no_mangle]
+pub unsafe fn asm_goto_noreturn() -> u64 {
+    let out: u64;
+    // CHECK: callbr void asm sideeffect alignstack inteldialect "
+    // CHECK-NEXT: to label %unreachable [label %[[JUMPBB:[a-b0-9]+]]]
+    asm!("jmp {}", label { return 1; }, options(noreturn));
+    // CHECK: [[JUMPBB]]:
+    // CHECK-NEXT: ret i64 1
+    out
+}
diff --git a/tests/ui/asm/parse-error.rs b/tests/ui/asm/parse-error.rs
index 6f32293511b..a0251c6763b 100644
--- a/tests/ui/asm/parse-error.rs
+++ b/tests/ui/asm/parse-error.rs
@@ -142,3 +142,5 @@ global_asm!(format!("{{{}}}", 0), const FOO);
 //~^ ERROR asm template must be a string literal
 global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
 //~^ ERROR asm template must be a string literal
+global_asm!("{}", label {});
+//~^ ERROR expected operand, options, or additional template string
diff --git a/tests/ui/asm/parse-error.stderr b/tests/ui/asm/parse-error.stderr
index 075d28e176a..80ee5191dbb 100644
--- a/tests/ui/asm/parse-error.stderr
+++ b/tests/ui/asm/parse-error.stderr
@@ -176,17 +176,17 @@ LL |         asm!("{a}", a = const foo, a = const bar);
    |
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
 
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
   --> $DIR/parse-error.rs:82:29
    |
 LL |         asm!("", options(), "");
-   |                             ^^ expected one of 9 possible tokens
+   |                             ^^ expected one of 10 possible tokens
 
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
   --> $DIR/parse-error.rs:84:33
    |
 LL |         asm!("{}", in(reg) foo, "{}", out(reg) foo);
-   |                                 ^^^^ expected one of 9 possible tokens
+   |                                 ^^^^ expected one of 10 possible tokens
 
 error: asm template must be a string literal
   --> $DIR/parse-error.rs:86:14
@@ -362,6 +362,12 @@ LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
    |
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
+error: expected operand, options, or additional template string
+  --> $DIR/parse-error.rs:145:19
+   |
+LL | global_asm!("{}", label {});
+   |                   ^^^^^^^^ expected operand, options, or additional template string
+
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:39:37
    |
@@ -407,6 +413,6 @@ LL |     let mut bar = 0;
 LL |         asm!("{a}", a = const foo, a = const bar);
    |                                              ^^^ non-constant value
 
-error: aborting due to 63 previous errors
+error: aborting due to 64 previous errors
 
 For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/asm/x86_64/bad-options.rs b/tests/ui/asm/x86_64/bad-options.rs
index a6d5022ecf1..f9cc13cfc5a 100644
--- a/tests/ui/asm/x86_64/bad-options.rs
+++ b/tests/ui/asm/x86_64/bad-options.rs
@@ -1,5 +1,7 @@
 //@ only-x86_64
 
+#![feature(asm_unwind, asm_goto)]
+
 use std::arch::{asm, global_asm};
 
 fn main() {
@@ -14,6 +16,8 @@ fn main() {
         //~^ ERROR asm with the `pure` option must have at least one output
         asm!("{}", out(reg) foo, options(noreturn));
         //~^ ERROR asm outputs are not allowed with the `noreturn` option
+        asm!("{}", label {}, options(may_unwind));
+        //~^ ERROR asm labels are not allowed with the `may_unwind` option
     }
 
     unsafe {
diff --git a/tests/ui/asm/x86_64/bad-options.stderr b/tests/ui/asm/x86_64/bad-options.stderr
index e2351840eef..aa167e7913c 100644
--- a/tests/ui/asm/x86_64/bad-options.stderr
+++ b/tests/ui/asm/x86_64/bad-options.stderr
@@ -1,35 +1,41 @@
 error: the `nomem` and `readonly` options are mutually exclusive
-  --> $DIR/bad-options.rs:8:18
+  --> $DIR/bad-options.rs:10:18
    |
 LL |         asm!("", options(nomem, readonly));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `pure` and `noreturn` options are mutually exclusive
-  --> $DIR/bad-options.rs:10:18
+  --> $DIR/bad-options.rs:12:18
    |
 LL |         asm!("", options(pure, nomem, noreturn));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: asm with the `pure` option must have at least one output
-  --> $DIR/bad-options.rs:10:18
+  --> $DIR/bad-options.rs:12:18
    |
 LL |         asm!("", options(pure, nomem, noreturn));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: asm with the `pure` option must have at least one output
-  --> $DIR/bad-options.rs:13:33
+  --> $DIR/bad-options.rs:15:33
    |
 LL |         asm!("{}", in(reg) foo, options(pure, nomem));
    |                                 ^^^^^^^^^^^^^^^^^^^^
 
 error: asm outputs are not allowed with the `noreturn` option
-  --> $DIR/bad-options.rs:15:20
+  --> $DIR/bad-options.rs:17:20
    |
 LL |         asm!("{}", out(reg) foo, options(noreturn));
    |                    ^^^^^^^^^^^^
 
+error: asm labels are not allowed with the `may_unwind` option
+  --> $DIR/bad-options.rs:19:20
+   |
+LL |         asm!("{}", label {}, options(may_unwind));
+   |                    ^^^^^^^^
+
 error: asm with `clobber_abi` must specify explicit registers for outputs
-  --> $DIR/bad-options.rs:22:20
+  --> $DIR/bad-options.rs:26:20
    |
 LL |         asm!("{}", out(reg) foo, clobber_abi("C"));
    |                    ^^^^^^^^^^^^  ---------------- clobber_abi
@@ -37,7 +43,7 @@ LL |         asm!("{}", out(reg) foo, clobber_abi("C"));
    |                    generic outputs
 
 error: asm with `clobber_abi` must specify explicit registers for outputs
-  --> $DIR/bad-options.rs:24:20
+  --> $DIR/bad-options.rs:28:20
    |
 LL |         asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
    |                    ^^^^^^^^^^^^  ----------------  ---------------- clobber_abi
@@ -46,43 +52,43 @@ LL |         asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
    |                    generic outputs
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
-  --> $DIR/bad-options.rs:31:25
+  --> $DIR/bad-options.rs:35:25
    |
 LL | global_asm!("", options(nomem));
    |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `readonly`
-  --> $DIR/bad-options.rs:33:25
+  --> $DIR/bad-options.rs:37:25
    |
 LL | global_asm!("", options(readonly));
    |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn`
-  --> $DIR/bad-options.rs:35:25
+  --> $DIR/bad-options.rs:39:25
    |
 LL | global_asm!("", options(noreturn));
    |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `pure`
-  --> $DIR/bad-options.rs:37:25
+  --> $DIR/bad-options.rs:41:25
    |
 LL | global_asm!("", options(pure));
    |                         ^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `nostack`
-  --> $DIR/bad-options.rs:39:25
+  --> $DIR/bad-options.rs:43:25
    |
 LL | global_asm!("", options(nostack));
    |                         ^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags`
-  --> $DIR/bad-options.rs:41:25
+  --> $DIR/bad-options.rs:45:25
    |
 LL | global_asm!("", options(preserves_flags));
    |                         ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: invalid ABI for `clobber_abi`
-  --> $DIR/bad-options.rs:20:18
+  --> $DIR/bad-options.rs:24:18
    |
 LL |         asm!("", clobber_abi("foo"));
    |                  ^^^^^^^^^^^^^^^^^^
@@ -90,12 +96,12 @@ LL |         asm!("", clobber_abi("foo"));
    = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
 
 error: `C` ABI specified multiple times
-  --> $DIR/bad-options.rs:24:52
+  --> $DIR/bad-options.rs:28:52
    |
 LL |         asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
    |                                  ----------------  ^^^^^^^^^^^^^^^^
    |                                  |
    |                                  previously specified here
 
-error: aborting due to 15 previous errors
+error: aborting due to 16 previous errors
 
diff --git a/tests/ui/asm/x86_64/goto.mirunsafeck.stderr b/tests/ui/asm/x86_64/goto.mirunsafeck.stderr
new file mode 100644
index 00000000000..fe189c14f0a
--- /dev/null
+++ b/tests/ui/asm/x86_64/goto.mirunsafeck.stderr
@@ -0,0 +1,23 @@
+warning: unreachable statement
+  --> $DIR/goto.rs:99:9
+   |
+LL | /         asm!(
+LL | |             "jmp {}",
+LL | |             label {
+LL | |                 return;
+LL | |             },
+LL | |             options(noreturn)
+LL | |         );
+   | |_________- any code following this expression is unreachable
+LL |           unreachable!();
+   |           ^^^^^^^^^^^^^^ unreachable statement
+   |
+note: the lint level is defined here
+  --> $DIR/goto.rs:89:8
+   |
+LL | #[warn(unreachable_code)]
+   |        ^^^^^^^^^^^^^^^^
+   = note: this warning originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/asm/x86_64/goto.rs b/tests/ui/asm/x86_64/goto.rs
new file mode 100644
index 00000000000..6a567efbb2c
--- /dev/null
+++ b/tests/ui/asm/x86_64/goto.rs
@@ -0,0 +1,111 @@
+//@ only-x86_64
+//@ run-pass
+//@ needs-asm-support
+//@ revisions: mirunsafeck thirunsafeck
+//@ [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![deny(unreachable_code)]
+#![feature(asm_goto)]
+
+use std::arch::asm;
+
+fn goto_fallthough() {
+    unsafe {
+        asm!(
+            "/* {} */",
+            label {
+                unreachable!();
+            }
+        )
+    }
+}
+
+fn goto_jump() {
+    unsafe {
+        let mut value = false;
+        asm!(
+            "jmp {}",
+            label {
+                value = true;
+            }
+        );
+        assert!(value);
+    }
+}
+
+// asm goto with outputs cause miscompilation in LLVM. UB can be triggered
+// when outputs are used inside the label block when optimisation is enabled.
+// See: https://github.com/llvm/llvm-project/issues/74483
+/*
+fn goto_out_fallthrough() {
+    unsafe {
+        let mut out: usize;
+        asm!(
+            "lea {}, [{} + 1]",
+            "/* {} */",
+            out(reg) out,
+            in(reg) 0x12345678usize,
+            label {
+                unreachable!();
+            }
+        );
+        assert_eq!(out, 0x12345679);
+    }
+}
+
+fn goto_out_jump() {
+    unsafe {
+        let mut value = false;
+        let mut out: usize;
+        asm!(
+            "lea {}, [{} + 1]",
+            "jmp {}",
+            out(reg) out,
+            in(reg) 0x12345678usize,
+            label {
+                value = true;
+                assert_eq!(out, 0x12345679);
+            }
+        );
+        assert!(value);
+    }
+}
+*/
+
+fn goto_noreturn() {
+    unsafe {
+        let a;
+        asm!(
+            "jmp {}",
+            label {
+                a = 1;
+            },
+            options(noreturn)
+        );
+        assert_eq!(a, 1);
+    }
+}
+
+#[warn(unreachable_code)]
+fn goto_noreturn_diverge() {
+    unsafe {
+        asm!(
+            "jmp {}",
+            label {
+                return;
+            },
+            options(noreturn)
+        );
+        unreachable!();
+        //~^ WARN unreachable statement
+    }
+}
+
+fn main() {
+    goto_fallthough();
+    goto_jump();
+    // goto_out_fallthrough();
+    // goto_out_jump();
+    goto_noreturn();
+    goto_noreturn_diverge();
+}
diff --git a/tests/ui/asm/x86_64/goto.thirunsafeck.stderr b/tests/ui/asm/x86_64/goto.thirunsafeck.stderr
new file mode 100644
index 00000000000..fe189c14f0a
--- /dev/null
+++ b/tests/ui/asm/x86_64/goto.thirunsafeck.stderr
@@ -0,0 +1,23 @@
+warning: unreachable statement
+  --> $DIR/goto.rs:99:9
+   |
+LL | /         asm!(
+LL | |             "jmp {}",
+LL | |             label {
+LL | |                 return;
+LL | |             },
+LL | |             options(noreturn)
+LL | |         );
+   | |_________- any code following this expression is unreachable
+LL |           unreachable!();
+   |           ^^^^^^^^^^^^^^ unreachable statement
+   |
+note: the lint level is defined here
+  --> $DIR/goto.rs:89:8
+   |
+LL | #[warn(unreachable_code)]
+   |        ^^^^^^^^^^^^^^^^
+   = note: this warning originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.rs b/tests/ui/feature-gates/feature-gate-asm_goto.rs
new file mode 100644
index 00000000000..beac4590349
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-asm_goto.rs
@@ -0,0 +1,10 @@
+//@ only-x86_64
+
+use std::arch::asm;
+
+fn main() {
+    unsafe {
+        asm!("jmp {}", label {});
+        //~^ ERROR label operands for inline assembly are unstable
+    }
+}
diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.stderr b/tests/ui/feature-gates/feature-gate-asm_goto.stderr
new file mode 100644
index 00000000000..62fd1a320d3
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-asm_goto.stderr
@@ -0,0 +1,13 @@
+error[E0658]: label operands for inline assembly are unstable
+  --> $DIR/feature-gate-asm_goto.rs:7:24
+   |
+LL |         asm!("jmp {}", label {});
+   |                        ^^^^^^^^
+   |
+   = note: see issue #119364 <https://github.com/rust-lang/rust/issues/119364> for more information
+   = help: add `#![feature(asm_goto)]` 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: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.