Skip to content

Commit

Permalink
Add tests for asm goto
Browse files Browse the repository at this point in the history
  • Loading branch information
nbdd0121 committed Dec 28, 2023
1 parent db591d5 commit 5bb0191
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 21 deletions.
51 changes: 51 additions & 0 deletions tests/codegen/asm-goto.rs
Original file line number Diff line number Diff line change
@@ -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
}
2 changes: 2 additions & 0 deletions tests/ui/asm/parse-error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 11 additions & 5 deletions tests/ui/asm/parse-error.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
|
Expand Down Expand Up @@ -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`.
4 changes: 4 additions & 0 deletions tests/ui/asm/x86_64/bad-options.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// only-x86_64

#![feature(asm_unwind, asm_goto)]

use std::arch::{asm, global_asm};

fn main() {
Expand All @@ -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 {
Expand Down
38 changes: 22 additions & 16 deletions tests/ui/asm/x86_64/bad-options.stderr
Original file line number Diff line number Diff line change
@@ -1,43 +1,49 @@
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
| |
| 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
Expand All @@ -46,56 +52,56 @@ 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"));
| ^^^^^^^^^^^^^^^^^^
|
= 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

23 changes: 23 additions & 0 deletions tests/ui/asm/x86_64/goto.mirunsafeck.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 111 additions & 0 deletions tests/ui/asm/x86_64/goto.rs
Original file line number Diff line number Diff line change
@@ -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();
}
Loading

0 comments on commit 5bb0191

Please sign in to comment.