about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-11-25 07:01:37 +0100
committerGitHub <noreply@github.com>2024-11-25 07:01:37 +0100
commitc5230d1148995a30ad5fd56aacffe3576fc0e95f (patch)
treefbc57ea3cfab87835428157a3a2fb331315f7e6e /tests
parent28fc2ba7142654fa6e654926f96ff913027b200e (diff)
parent0178ba2c2547c3677b5624d684a392dccae12abc (diff)
downloadrust-c5230d1148995a30ad5fd56aacffe3576fc0e95f.tar.gz
rust-c5230d1148995a30ad5fd56aacffe3576fc0e95f.zip
Rollup merge of #131523 - nbdd0121:asm, r=compiler-errors
Fix asm goto with outputs and move it to a separate feature gate

Tracking issue: #119364

This PR addresses 3 aspects of asm goto with outputs:
* Codegen is fixed. My initial implementation has an oversight which cause the output to be only stored in fallthrough path, but not in label blocks.
* Outputs can now be used with `options(noreturn)` if a label block is given.
* All of this is moved to a new feature gate, because we likely want to stabilise `asm_goto` before asm goto with outputs.

`@rustbot` labels: +A-inline-assembly +F-asm
Diffstat (limited to 'tests')
-rw-r--r--tests/codegen/asm/goto.rs38
-rw-r--r--tests/ui/asm/x86_64/goto.rs64
-rw-r--r--tests/ui/asm/x86_64/goto.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs13
-rw-r--r--tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr13
5 files changed, 109 insertions, 23 deletions
diff --git a/tests/codegen/asm/goto.rs b/tests/codegen/asm/goto.rs
index e522d0da5b4..c40a43fbe1b 100644
--- a/tests/codegen/asm/goto.rs
+++ b/tests/codegen/asm/goto.rs
@@ -2,21 +2,10 @@
 //@ only-x86_64
 
 #![crate_type = "rlib"]
-#![feature(asm_goto)]
+#![feature(asm_goto, asm_goto_with_outputs)]
 
 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() {
@@ -38,14 +27,37 @@ pub unsafe fn asm_goto_with_outputs() -> u64 {
     out
 }
 
+// CHECK-LABEL: @asm_goto_with_outputs_use_in_label
+#[no_mangle]
+pub unsafe fn asm_goto_with_outputs_use_in_label() -> 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 out; });
+    // CHECK: [[JUMPBB]]:
+    // CHECK-NEXT: [[RET:%.+]] = phi i64 [ 1, %[[FALLTHROUGHBB]] ], [ [[RES]], %start ]
+    // CHECK-NEXT: ret i64 [[RET]]
+    1
+}
+
 // 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
+}
+
+// CHECK-LABEL: @asm_goto_noreturn_with_outputs
+#[no_mangle]
+pub unsafe fn asm_goto_noreturn_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!("mov {}, 1", "jmp {}", out(reg) out, label { return out; });
+    // CHECK: [[JUMPBB]]:
+    // CHECK-NEXT: ret i64 [[RES]]
     out
 }
diff --git a/tests/ui/asm/x86_64/goto.rs b/tests/ui/asm/x86_64/goto.rs
index 6c14bb57ac6..50e7441509a 100644
--- a/tests/ui/asm/x86_64/goto.rs
+++ b/tests/ui/asm/x86_64/goto.rs
@@ -3,7 +3,7 @@
 //@ needs-asm-support
 
 #![deny(unreachable_code)]
-#![feature(asm_goto)]
+#![feature(asm_goto, asm_goto_with_outputs)]
 
 use std::arch::asm;
 
@@ -31,10 +31,6 @@ fn goto_jump() {
     }
 }
 
-// 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;
@@ -68,7 +64,57 @@ fn goto_out_jump() {
         assert!(value);
     }
 }
-*/
+
+fn goto_out_jump_noreturn() {
+    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);
+            },
+            options(noreturn)
+        );
+        assert!(value);
+    }
+}
+
+// asm goto with outputs cause miscompilation in LLVM when multiple outputs are present.
+// The code sample below is adapted from https://github.com/llvm/llvm-project/issues/74483
+// and does not work with `-C opt-level=0`
+#[expect(unused)]
+fn goto_multi_out() {
+    #[inline(never)]
+    #[allow(unused)]
+    fn goto_multi_out(a: usize, b: usize) -> usize {
+        let mut x: usize;
+        let mut y: usize;
+        let mut z: usize;
+        unsafe {
+            core::arch::asm!(
+                "mov {x}, {a}",
+                "test {a}, {a}",
+                "jnz {label1}",
+                "/* {y} {z} {b} {label2} */",
+                x = out(reg) x,
+                y = out(reg) y,
+                z = out(reg) z,
+                a = in(reg) a,
+                b = in(reg) b,
+                label1 = label { return x },
+                label2 = label { return 1 },
+            );
+            0
+        }
+    }
+
+    assert_eq!(goto_multi_out(11, 22), 11);
+}
 
 fn goto_noreturn() {
     unsafe {
@@ -102,8 +148,10 @@ fn goto_noreturn_diverge() {
 fn main() {
     goto_fallthough();
     goto_jump();
-    // goto_out_fallthrough();
-    // goto_out_jump();
+    goto_out_fallthrough();
+    goto_out_jump();
+    goto_out_jump_noreturn();
+    // goto_multi_out();
     goto_noreturn();
     goto_noreturn_diverge();
 }
diff --git a/tests/ui/asm/x86_64/goto.stderr b/tests/ui/asm/x86_64/goto.stderr
index 27e227d71a5..8f89e2b1290 100644
--- a/tests/ui/asm/x86_64/goto.stderr
+++ b/tests/ui/asm/x86_64/goto.stderr
@@ -1,5 +1,5 @@
 warning: unreachable statement
-  --> $DIR/goto.rs:97:9
+  --> $DIR/goto.rs:143:9
    |
 LL | /         asm!(
 LL | |             "jmp {}",
@@ -13,7 +13,7 @@ LL |           unreachable!();
    |           ^^^^^^^^^^^^^^ unreachable statement
    |
 note: the lint level is defined here
-  --> $DIR/goto.rs:87:8
+  --> $DIR/goto.rs:133:8
    |
 LL | #[warn(unreachable_code)]
    |        ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs
new file mode 100644
index 00000000000..294827f78d2
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs
@@ -0,0 +1,13 @@
+//@ only-x86_64
+
+#![feature(asm_goto)]
+
+use std::arch::asm;
+
+fn main() {
+    let mut _out: u64;
+    unsafe {
+        asm!("mov {}, 1", "jmp {}", out(reg) _out, label {});
+        //~^ ERROR using both label and output operands for inline assembly is unstable
+    }
+}
diff --git a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr
new file mode 100644
index 00000000000..ff7a7d5760a
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr
@@ -0,0 +1,13 @@
+error[E0658]: using both label and output operands for inline assembly is unstable
+  --> $DIR/feature-gate-asm_goto_with_outputs.rs:10:52
+   |
+LL |         asm!("mov {}, 1", "jmp {}", out(reg) _out, label {});
+   |                                                    ^^^^^^^^
+   |
+   = note: see issue #119364 <https://github.com/rust-lang/rust/issues/119364> for more information
+   = help: add `#![feature(asm_goto_with_outputs)]` 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`.