Add tests for asm goto

This commit is contained in:
Gary Guo 2023-12-27 22:57:17 +00:00
parent 31f078ea99
commit 4677a71369
10 changed files with 270 additions and 21 deletions

51
tests/codegen/asm-goto.rs Normal file
View file

@ -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
}

View file

@ -142,3 +142,5 @@ fn main() {
//~^ 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

View file

@ -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`.

View file

@ -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 {

View file

@ -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

View file

@ -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

111
tests/ui/asm/x86_64/goto.rs Normal file
View file

@ -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();
}

View file

@ -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

View file

@ -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
}
}

View file

@ -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`.