Skip to content

Commit

Permalink
Auto merge of #87584 - adamgemmell:dev/asm-tests, r=Amanieu
Browse files Browse the repository at this point in the history
Add inline asm! tests for aarch64

Port many of the x86-only UI tests for inline asm! over to aarch64.
  • Loading branch information
bors committed Sep 25, 2021
2 parents 63cc2bb + 27213b0 commit 9620f3a
Show file tree
Hide file tree
Showing 64 changed files with 2,839 additions and 237 deletions.
39 changes: 39 additions & 0 deletions src/test/ui/asm/aarch64/bad-options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// only-aarch64

#![feature(asm, global_asm)]

fn main() {
let mut foo = 0;
unsafe {
asm!("", options(nomem, readonly));
//~^ ERROR the `nomem` and `readonly` options are mutually exclusive
asm!("", options(pure, nomem, noreturn));
//~^ ERROR the `pure` and `noreturn` options are mutually exclusive
//~^^ ERROR asm with the `pure` option must have at least one output
asm!("{}", in(reg) foo, options(pure, nomem));
//~^ 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
}

unsafe {
asm!("", clobber_abi("foo"));
//~^ ERROR invalid ABI for `clobber_abi`
asm!("{}", out(reg) foo, clobber_abi("C"));
//~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs
asm!("", out("x0") foo, clobber_abi("C"));
}
}

global_asm!("", options(nomem));
//~^ ERROR expected one of
global_asm!("", options(readonly));
//~^ ERROR expected one of
global_asm!("", options(noreturn));
//~^ ERROR expected one of
global_asm!("", options(pure));
//~^ ERROR expected one of
global_asm!("", options(nostack));
//~^ ERROR expected one of
global_asm!("", options(preserves_flags));
//~^ ERROR expected one of
84 changes: 84 additions & 0 deletions src/test/ui/asm/aarch64/bad-options.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
error: the `nomem` and `readonly` options are mutually exclusive
--> $DIR/bad-options.rs:8:18
|
LL | asm!("", options(nomem, readonly));
| ^^^^^^^^^^^^^^^^^^^^^^^^

error: the `pure` and `noreturn` options are mutually exclusive
--> $DIR/bad-options.rs:10: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
|
LL | asm!("", options(pure, nomem, noreturn));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: asm with the `pure` option must have at least one output
--> $DIR/bad-options.rs:13: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
|
LL | asm!("{}", out(reg) foo, options(noreturn));
| ^^^^^^^^^^^^

error: asm with `clobber_abi` must specify explicit registers for outputs
--> $DIR/bad-options.rs:22:20
|
LL | asm!("{}", out(reg) foo, clobber_abi("C"));
| ^^^^^^^^^^^^ ---------------- clobber_abi
| |
| generic outputs

error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
--> $DIR/bad-options.rs:28: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:30: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:32: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:34: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:36: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:38: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
|
LL | asm!("", clobber_abi("foo"));
| ^^^^^^^^^^^^^^^^^^
|
= note: the following ABIs are supported on this target: `C`, `system`, `efiapi`

error: aborting due to 13 previous errors

59 changes: 59 additions & 0 deletions src/test/ui/asm/aarch64/bad-reg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// only-aarch64
// compile-flags: -C target-feature=+fp

#![feature(asm)]

fn main() {
let mut foo = 0;
let mut bar = 0;
unsafe {
// Bad register/register class

asm!("{}", in(foo) foo);
//~^ ERROR invalid register class `foo`: unknown register class
asm!("", in("foo") foo);
//~^ ERROR invalid register `foo`: unknown register
asm!("{:z}", in(reg) foo);
//~^ ERROR invalid asm template modifier for this register class
asm!("{:r}", in(vreg) foo);
//~^ ERROR invalid asm template modifier for this register class
asm!("{:r}", in(vreg_low16) foo);
//~^ ERROR invalid asm template modifier for this register class
asm!("{:a}", const 0);
//~^ ERROR asm template modifiers are not allowed for `const` arguments
asm!("{:a}", sym main);
//~^ ERROR asm template modifiers are not allowed for `sym` arguments
asm!("", in("x29") foo);
//~^ ERROR invalid register `x29`: the frame pointer cannot be used as an operand
asm!("", in("sp") foo);
//~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand
asm!("", in("xzr") foo);
//~^ ERROR invalid register `xzr`: the zero register cannot be used as an operand
asm!("", in("x18") foo);
//~^ ERROR invalid register `x18`: x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm
asm!("", in("x19") foo);
//~^ ERROR invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm

asm!("", in("p0") foo);
//~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
asm!("", out("p0") _);
asm!("{}", in(preg) foo);
//~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
asm!("{}", out(preg) _);
//~^ ERROR register class `preg` can only be used as a clobber, not as an input or output

// Explicit register conflicts
// (except in/lateout which don't conflict)

asm!("", in("x0") foo, in("w0") bar);
//~^ ERROR register `x0` conflicts with register `x0`
asm!("", in("x0") foo, out("x0") bar);
//~^ ERROR register `x0` conflicts with register `x0`
asm!("", in("w0") foo, lateout("w0") bar);
asm!("", in("v0") foo, in("q0") bar);
//~^ ERROR register `v0` conflicts with register `v0`
asm!("", in("v0") foo, out("q0") bar);
//~^ ERROR register `v0` conflicts with register `v0`
asm!("", in("v0") foo, lateout("q0") bar);
}
}
152 changes: 152 additions & 0 deletions src/test/ui/asm/aarch64/bad-reg.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
error: invalid register class `foo`: unknown register class
--> $DIR/bad-reg.rs:12:20
|
LL | asm!("{}", in(foo) foo);
| ^^^^^^^^^^^

error: invalid register `foo`: unknown register
--> $DIR/bad-reg.rs:14:18
|
LL | asm!("", in("foo") foo);
| ^^^^^^^^^^^^^

error: invalid asm template modifier for this register class
--> $DIR/bad-reg.rs:16:15
|
LL | asm!("{:z}", in(reg) foo);
| ^^^^ ----------- argument
| |
| template modifier
|
= note: the `reg` register class supports the following template modifiers: `w`, `x`

error: invalid asm template modifier for this register class
--> $DIR/bad-reg.rs:18:15
|
LL | asm!("{:r}", in(vreg) foo);
| ^^^^ ------------ argument
| |
| template modifier
|
= note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`

error: invalid asm template modifier for this register class
--> $DIR/bad-reg.rs:20:15
|
LL | asm!("{:r}", in(vreg_low16) foo);
| ^^^^ ------------------ argument
| |
| template modifier
|
= note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`

error: asm template modifiers are not allowed for `const` arguments
--> $DIR/bad-reg.rs:22:15
|
LL | asm!("{:a}", const 0);
| ^^^^ ------- argument
| |
| template modifier

error: asm template modifiers are not allowed for `sym` arguments
--> $DIR/bad-reg.rs:24:15
|
LL | asm!("{:a}", sym main);
| ^^^^ -------- argument
| |
| template modifier

error: invalid register `x29`: the frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:26:18
|
LL | asm!("", in("x29") foo);
| ^^^^^^^^^^^^^

error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:28:18
|
LL | asm!("", in("sp") foo);
| ^^^^^^^^^^^^

error: invalid register `xzr`: the zero register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:30:18
|
LL | asm!("", in("xzr") foo);
| ^^^^^^^^^^^^^

error: invalid register `x18`: x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:32:18
|
LL | asm!("", in("x18") foo);
| ^^^^^^^^^^^^^

error: invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:34:18
|
LL | asm!("", in("x19") foo);
| ^^^^^^^^^^^^^

error: register class `preg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:37:18
|
LL | asm!("", in("p0") foo);
| ^^^^^^^^^^^^

error: register class `preg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:40:20
|
LL | asm!("{}", in(preg) foo);
| ^^^^^^^^^^^^

error: register class `preg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:42:20
|
LL | asm!("{}", out(preg) _);
| ^^^^^^^^^^^

error: register `x0` conflicts with register `x0`
--> $DIR/bad-reg.rs:48:32
|
LL | asm!("", in("x0") foo, in("w0") bar);
| ------------ ^^^^^^^^^^^^ register `x0`
| |
| register `x0`

error: register `x0` conflicts with register `x0`
--> $DIR/bad-reg.rs:50:32
|
LL | asm!("", in("x0") foo, out("x0") bar);
| ------------ ^^^^^^^^^^^^^ register `x0`
| |
| register `x0`
|
help: use `lateout` instead of `out` to avoid conflict
--> $DIR/bad-reg.rs:50:18
|
LL | asm!("", in("x0") foo, out("x0") bar);
| ^^^^^^^^^^^^

error: register `v0` conflicts with register `v0`
--> $DIR/bad-reg.rs:53:32
|
LL | asm!("", in("v0") foo, in("q0") bar);
| ------------ ^^^^^^^^^^^^ register `v0`
| |
| register `v0`

error: register `v0` conflicts with register `v0`
--> $DIR/bad-reg.rs:55:32
|
LL | asm!("", in("v0") foo, out("q0") bar);
| ------------ ^^^^^^^^^^^^^ register `v0`
| |
| register `v0`
|
help: use `lateout` instead of `out` to avoid conflict
--> $DIR/bad-reg.rs:55:18
|
LL | asm!("", in("v0") foo, out("q0") bar);
| ^^^^^^^^^^^^

error: aborting due to 19 previous errors

42 changes: 42 additions & 0 deletions src/test/ui/asm/aarch64/const.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// min-llvm-version: 10.0.1
// only-aarch64
// run-pass
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck

#![feature(asm, global_asm)]

fn const_generic<const X: usize>() -> usize {
unsafe {
let a: usize;
asm!("mov {}, {}", out(reg) a, const X);
a
}
}

const fn constfn(x: usize) -> usize {
x
}

fn main() {
unsafe {
let a: usize;
asm!("mov {}, {}", out(reg) a, const 5);
assert_eq!(a, 5);

let b: usize;
asm!("mov {}, {}", out(reg) b, const constfn(5));
assert_eq!(b, 5);

let c: usize;
asm!("mov {}, {}", out(reg) c, const constfn(5) + constfn(5));
assert_eq!(c, 10);
}

let d = const_generic::<5>();
assert_eq!(d, 5);
}

global_asm!("mov x0, {}", const 5);
global_asm!("mov x0, {}", const constfn(5));
global_asm!("mov x0, {}", const constfn(5) + constfn(5));
Loading

0 comments on commit 9620f3a

Please sign in to comment.