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 27, 2023
1 parent 6836330 commit 7cfb8a3
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 24 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
}
16 changes: 8 additions & 8 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 @@ -334,17 +334,17 @@ LL | global_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`, `options`, or `sym`, found `""`
error: expected one of `clobber_abi`, `const`, `label`, `options`, or `sym`, found `""`
--> $DIR/parse-error.rs:137:28
|
LL | global_asm!("", options(), "");
| ^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
| ^^ expected one of `clobber_abi`, `const`, `label`, `options`, or `sym`

error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"`
error: expected one of `clobber_abi`, `const`, `label`, `options`, or `sym`, found `"{}"`
--> $DIR/parse-error.rs:139:30
|
LL | global_asm!("{}", const FOO, "{}", const FOO);
| ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
| ^^^^ expected one of `clobber_abi`, `const`, `label`, `options`, or `sym`

error: asm template must be a string literal
--> $DIR/parse-error.rs:141:13
Expand Down
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

95 changes: 95 additions & 0 deletions tests/ui/asm/x86_64/goto.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// 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 {
'a: {
asm!(
"jmp {}",
label {
break 'a;
},
options(noreturn)
);
}
}
}

fn main() {
goto_fallthough();
goto_jump();
// goto_out_fallthrough();
// goto_out_jump();
goto_noreturn();
}
10 changes: 10 additions & 0 deletions tests/ui/feature-gates/feature-gate-asm_goto.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
11 changes: 11 additions & 0 deletions tests/ui/feature-gates/feature-gate-asm_goto.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0658]: label operands for inline assembly are unstable
--> $DIR/feature-gate-asm_goto.rs:7:24
|
LL | asm!("jmp {}", label {});
| ^^^^^^^^
|
= help: add `#![feature(asm_goto)]` to the crate attributes to enable

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0658`.

0 comments on commit 7cfb8a3

Please sign in to comment.