summaryrefslogtreecommitdiffstats
path: root/tests/ui/asm/aarch64
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/asm/aarch64')
-rw-r--r--tests/ui/asm/aarch64/bad-options.rs39
-rw-r--r--tests/ui/asm/aarch64/bad-options.stderr84
-rw-r--r--tests/ui/asm/aarch64/bad-reg.rs61
-rw-r--r--tests/ui/asm/aarch64/bad-reg.stderr162
-rw-r--r--tests/ui/asm/aarch64/const.rs44
-rw-r--r--tests/ui/asm/aarch64/duplicate-options.fixed27
-rw-r--r--tests/ui/asm/aarch64/duplicate-options.rs27
-rw-r--r--tests/ui/asm/aarch64/duplicate-options.stderr56
-rw-r--r--tests/ui/asm/aarch64/interpolated-idents.rs24
-rw-r--r--tests/ui/asm/aarch64/interpolated-idents.stderr46
-rw-r--r--tests/ui/asm/aarch64/llvm-58384.rs16
-rw-r--r--tests/ui/asm/aarch64/may_unwind.rs37
-rw-r--r--tests/ui/asm/aarch64/parse-error.rs133
-rw-r--r--tests/ui/asm/aarch64/parse-error.stderr446
-rw-r--r--tests/ui/asm/aarch64/srcloc.rs129
-rw-r--r--tests/ui/asm/aarch64/srcloc.stderr290
-rw-r--r--tests/ui/asm/aarch64/sym.rs84
-rw-r--r--tests/ui/asm/aarch64/type-check-2-2.rs35
-rw-r--r--tests/ui/asm/aarch64/type-check-2-2.stderr46
-rw-r--r--tests/ui/asm/aarch64/type-check-2.rs76
-rw-r--r--tests/ui/asm/aarch64/type-check-2.stderr75
-rw-r--r--tests/ui/asm/aarch64/type-check-3.rs97
-rw-r--r--tests/ui/asm/aarch64/type-check-3.stderr147
-rw-r--r--tests/ui/asm/aarch64/type-check-4.rs32
-rw-r--r--tests/ui/asm/aarch64/type-check-4.stderr27
25 files changed, 2240 insertions, 0 deletions
diff --git a/tests/ui/asm/aarch64/bad-options.rs b/tests/ui/asm/aarch64/bad-options.rs
new file mode 100644
index 000000000..6172027a2
--- /dev/null
+++ b/tests/ui/asm/aarch64/bad-options.rs
@@ -0,0 +1,39 @@
+// only-aarch64
+
+use std::arch::{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
diff --git a/tests/ui/asm/aarch64/bad-options.stderr b/tests/ui/asm/aarch64/bad-options.stderr
new file mode 100644
index 000000000..21bcc4a9c
--- /dev/null
+++ b/tests/ui/asm/aarch64/bad-options.stderr
@@ -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
+
diff --git a/tests/ui/asm/aarch64/bad-reg.rs b/tests/ui/asm/aarch64/bad-reg.rs
new file mode 100644
index 000000000..9ccb8ed67
--- /dev/null
+++ b/tests/ui/asm/aarch64/bad-reg.rs
@@ -0,0 +1,61 @@
+// only-aarch64
+// compile-flags: -C target-feature=+neon
+
+#![feature(asm_const)]
+
+use std::arch::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("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
+ //~| ERROR type `i32` cannot be used with this register class
+ asm!("", out("p0") _);
+ asm!("{}", in(preg) foo);
+ //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
+ //~| ERROR type `i32` cannot be used with this register class
+ 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);
+ }
+}
diff --git a/tests/ui/asm/aarch64/bad-reg.stderr b/tests/ui/asm/aarch64/bad-reg.stderr
new file mode 100644
index 000000000..0ba627dac
--- /dev/null
+++ b/tests/ui/asm/aarch64/bad-reg.stderr
@@ -0,0 +1,162 @@
+error: invalid register class `foo`: unknown register class
+ --> $DIR/bad-reg.rs:14:20
+ |
+LL | asm!("{}", in(foo) foo);
+ | ^^^^^^^^^^^
+
+error: invalid register `foo`: unknown register
+ --> $DIR/bad-reg.rs:16:18
+ |
+LL | asm!("", in("foo") foo);
+ | ^^^^^^^^^^^^^
+
+error: invalid asm template modifier for this register class
+ --> $DIR/bad-reg.rs:18: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:20: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:22: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:24:15
+ |
+LL | asm!("{:a}", const 0);
+ | ^^^^ ------- argument
+ | |
+ | template modifier
+
+error: asm template modifiers are not allowed for `sym` arguments
+ --> $DIR/bad-reg.rs:26: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:28: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:30: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:32:18
+ |
+LL | asm!("", in("xzr") 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:41: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:44:20
+ |
+LL | asm!("{}", out(preg) _);
+ | ^^^^^^^^^^^
+
+error: register `x0` conflicts with register `x0`
+ --> $DIR/bad-reg.rs:50:32
+ |
+LL | asm!("", in("x0") foo, in("w0") bar);
+ | ------------ ^^^^^^^^^^^^ register `x0`
+ | |
+ | register `x0`
+
+error: register `x0` conflicts with register `x0`
+ --> $DIR/bad-reg.rs:52: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:52:18
+ |
+LL | asm!("", in("x0") foo, out("x0") bar);
+ | ^^^^^^^^^^^^
+
+error: register `v0` conflicts with register `v0`
+ --> $DIR/bad-reg.rs:55:32
+ |
+LL | asm!("", in("v0") foo, in("q0") bar);
+ | ------------ ^^^^^^^^^^^^ register `v0`
+ | |
+ | register `v0`
+
+error: register `v0` conflicts with register `v0`
+ --> $DIR/bad-reg.rs:57: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:57:18
+ |
+LL | asm!("", in("v0") foo, out("q0") bar);
+ | ^^^^^^^^^^^^
+
+error: type `i32` cannot be used with this register class
+ --> $DIR/bad-reg.rs:37:27
+ |
+LL | asm!("", in("p0") foo);
+ | ^^^
+ |
+ = note: register class `preg` supports these types:
+
+error: type `i32` cannot be used with this register class
+ --> $DIR/bad-reg.rs:41:29
+ |
+LL | asm!("{}", in(preg) foo);
+ | ^^^
+ |
+ = note: register class `preg` supports these types:
+
+error: aborting due to 20 previous errors
+
diff --git a/tests/ui/asm/aarch64/const.rs b/tests/ui/asm/aarch64/const.rs
new file mode 100644
index 000000000..de299bfdb
--- /dev/null
+++ b/tests/ui/asm/aarch64/const.rs
@@ -0,0 +1,44 @@
+// only-aarch64
+// run-pass
+// needs-asm-support
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(asm_const)]
+
+use std::arch::{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));
diff --git a/tests/ui/asm/aarch64/duplicate-options.fixed b/tests/ui/asm/aarch64/duplicate-options.fixed
new file mode 100644
index 000000000..fa1dd4aef
--- /dev/null
+++ b/tests/ui/asm/aarch64/duplicate-options.fixed
@@ -0,0 +1,27 @@
+// only-aarch64
+// needs-asm-support
+// run-rustfix
+
+use std::arch::asm;
+
+fn main() {
+ unsafe {
+ asm!("", options(nomem, ));
+ //~^ ERROR the `nomem` option was already provided
+ asm!("", options(preserves_flags, ));
+ //~^ ERROR the `preserves_flags` option was already provided
+ asm!("", options(nostack, preserves_flags), options());
+ //~^ ERROR the `nostack` option was already provided
+ asm!("", options(nostack, ), options(), options());
+ //~^ ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ asm!(
+ "",
+ options(nomem, noreturn),
+ options(preserves_flags, ), //~ ERROR the `noreturn` option was already provided
+ options( nostack), //~ ERROR the `nomem` option was already provided
+ options(), //~ ERROR the `noreturn` option was already provided
+ );
+ }
+}
diff --git a/tests/ui/asm/aarch64/duplicate-options.rs b/tests/ui/asm/aarch64/duplicate-options.rs
new file mode 100644
index 000000000..b2d3fe7d9
--- /dev/null
+++ b/tests/ui/asm/aarch64/duplicate-options.rs
@@ -0,0 +1,27 @@
+// only-aarch64
+// needs-asm-support
+// run-rustfix
+
+use std::arch::asm;
+
+fn main() {
+ unsafe {
+ asm!("", options(nomem, nomem));
+ //~^ ERROR the `nomem` option was already provided
+ asm!("", options(preserves_flags, preserves_flags));
+ //~^ ERROR the `preserves_flags` option was already provided
+ asm!("", options(nostack, preserves_flags), options(nostack));
+ //~^ ERROR the `nostack` option was already provided
+ asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ //~^ ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ asm!(
+ "",
+ options(nomem, noreturn),
+ options(preserves_flags, noreturn), //~ ERROR the `noreturn` option was already provided
+ options(nomem, nostack), //~ ERROR the `nomem` option was already provided
+ options(noreturn), //~ ERROR the `noreturn` option was already provided
+ );
+ }
+}
diff --git a/tests/ui/asm/aarch64/duplicate-options.stderr b/tests/ui/asm/aarch64/duplicate-options.stderr
new file mode 100644
index 000000000..feb3838f4
--- /dev/null
+++ b/tests/ui/asm/aarch64/duplicate-options.stderr
@@ -0,0 +1,56 @@
+error: the `nomem` option was already provided
+ --> $DIR/duplicate-options.rs:9:33
+ |
+LL | asm!("", options(nomem, nomem));
+ | ^^^^^ this option was already provided
+
+error: the `preserves_flags` option was already provided
+ --> $DIR/duplicate-options.rs:11:43
+ |
+LL | asm!("", options(preserves_flags, preserves_flags));
+ | ^^^^^^^^^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:13:61
+ |
+LL | asm!("", options(nostack, preserves_flags), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:15:35
+ |
+LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:15:53
+ |
+LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:15:71
+ |
+LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `noreturn` option was already provided
+ --> $DIR/duplicate-options.rs:22:38
+ |
+LL | options(preserves_flags, noreturn),
+ | ^^^^^^^^ this option was already provided
+
+error: the `nomem` option was already provided
+ --> $DIR/duplicate-options.rs:23:21
+ |
+LL | options(nomem, nostack),
+ | ^^^^^ this option was already provided
+
+error: the `noreturn` option was already provided
+ --> $DIR/duplicate-options.rs:24:21
+ |
+LL | options(noreturn),
+ | ^^^^^^^^ this option was already provided
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui/asm/aarch64/interpolated-idents.rs b/tests/ui/asm/aarch64/interpolated-idents.rs
new file mode 100644
index 000000000..e87a88434
--- /dev/null
+++ b/tests/ui/asm/aarch64/interpolated-idents.rs
@@ -0,0 +1,24 @@
+// only-aarch64
+// needs-asm-support
+use std::arch::asm;
+
+macro_rules! m {
+ ($in:ident $out:ident $lateout:ident $inout:ident $inlateout:ident $const:ident $sym:ident
+ $pure:ident $nomem:ident $readonly:ident $preserves_flags:ident
+ $noreturn:ident $nostack:ident $options:ident) => {
+ unsafe {
+ asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x,
+ //~^ ERROR asm outputs are not allowed with the `noreturn` option
+ const x, sym x,
+ $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack));
+ //~^ ERROR the `nomem` and `readonly` options are mutually exclusive
+ //~| ERROR the `pure` and `noreturn` options are mutually exclusive
+ }
+ };
+}
+
+fn main() {
+ m!(in out lateout inout inlateout const sym
+ pure nomem readonly preserves_flags
+ noreturn nostack options);
+}
diff --git a/tests/ui/asm/aarch64/interpolated-idents.stderr b/tests/ui/asm/aarch64/interpolated-idents.stderr
new file mode 100644
index 000000000..f6c50c2e1
--- /dev/null
+++ b/tests/ui/asm/aarch64/interpolated-idents.stderr
@@ -0,0 +1,46 @@
+error: the `nomem` and `readonly` options are mutually exclusive
+ --> $DIR/interpolated-idents.rs:13:13
+ |
+LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | / m!(in out lateout inout inlateout const sym
+LL | | pure nomem readonly preserves_flags
+LL | | noreturn nostack options);
+ | |________________________________- in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: the `pure` and `noreturn` options are mutually exclusive
+ --> $DIR/interpolated-idents.rs:13:13
+ |
+LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | / m!(in out lateout inout inlateout const sym
+LL | | pure nomem readonly preserves_flags
+LL | | noreturn nostack options);
+ | |________________________________- in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: asm outputs are not allowed with the `noreturn` option
+ --> $DIR/interpolated-idents.rs:10:32
+ |
+LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x,
+ | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^
+...
+LL | / m!(in out lateout inout inlateout const sym
+LL | | pure nomem readonly preserves_flags
+LL | | noreturn nostack options);
+ | | -
+ | |________________________________|
+ | |________________________________in this macro invocation
+ | |________________________________in this macro invocation
+ | |________________________________in this macro invocation
+ | in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/asm/aarch64/llvm-58384.rs b/tests/ui/asm/aarch64/llvm-58384.rs
new file mode 100644
index 000000000..308f78908
--- /dev/null
+++ b/tests/ui/asm/aarch64/llvm-58384.rs
@@ -0,0 +1,16 @@
+// only-aarch64
+// run-pass
+// needs-asm-support
+
+// Test that we properly work around this LLVM issue:
+// https://github.com/llvm/llvm-project/issues/58384
+
+use std::arch::asm;
+
+fn main() {
+ let a: i32;
+ unsafe {
+ asm!("", inout("x0") 435 => a);
+ }
+ assert_eq!(a, 435);
+}
diff --git a/tests/ui/asm/aarch64/may_unwind.rs b/tests/ui/asm/aarch64/may_unwind.rs
new file mode 100644
index 000000000..6af8728bb
--- /dev/null
+++ b/tests/ui/asm/aarch64/may_unwind.rs
@@ -0,0 +1,37 @@
+// only-aarch64
+// run-pass
+// needs-asm-support
+
+#![feature(asm_unwind)]
+
+use std::arch::asm;
+use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
+
+struct Foo<'a>(&'a mut bool);
+
+impl Drop for Foo<'_> {
+ fn drop(&mut self) {
+ *self.0 = false;
+ }
+}
+
+extern "C" fn panicky() {
+ resume_unwind(Box::new(()));
+}
+
+fn main() {
+ let flag = &mut true;
+ catch_unwind(AssertUnwindSafe(|| {
+ let _foo = Foo(flag);
+ unsafe {
+ asm!(
+ "bl {}",
+ sym panicky,
+ clobber_abi("C"),
+ options(may_unwind)
+ );
+ }
+ }))
+ .expect_err("expected a panic");
+ assert_eq!(*flag, false);
+}
diff --git a/tests/ui/asm/aarch64/parse-error.rs b/tests/ui/asm/aarch64/parse-error.rs
new file mode 100644
index 000000000..cbc93cd3f
--- /dev/null
+++ b/tests/ui/asm/aarch64/parse-error.rs
@@ -0,0 +1,133 @@
+// only-aarch64
+
+#![feature(asm_const)]
+
+use std::arch::{asm, global_asm};
+
+fn main() {
+ let mut foo = 0;
+ let mut bar = 0;
+ unsafe {
+ asm!();
+ //~^ ERROR requires at least a template string argument
+ asm!(foo);
+ //~^ ERROR asm template must be a string literal
+ asm!("{}" foo);
+ //~^ ERROR expected token: `,`
+ asm!("{}", foo);
+ //~^ ERROR expected operand, clobber_abi, options, or additional template string
+ asm!("{}", in foo);
+ //~^ ERROR expected `(`, found `foo`
+ asm!("{}", in(reg foo));
+ //~^ ERROR expected `)`, found `foo`
+ asm!("{}", in(reg));
+ //~^ ERROR expected expression, found end of macro arguments
+ asm!("{}", inout(=) foo => bar);
+ //~^ ERROR expected register class or explicit register
+ asm!("{}", inout(reg) foo =>);
+ //~^ ERROR expected expression, found end of macro arguments
+ asm!("{}", in(reg) foo => bar);
+ //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
+ asm!("{}", sym foo + bar);
+ //~^ ERROR expected a path for argument to `sym`
+ asm!("", options(foo));
+ //~^ ERROR expected one of
+ asm!("", options(nomem foo));
+ //~^ ERROR expected one of
+ asm!("", options(nomem, foo));
+ //~^ ERROR expected one of
+ asm!("{}", options(), const foo);
+ //~^ ERROR arguments are not allowed after options
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", clobber_abi(foo));
+ //~^ ERROR expected string literal
+ asm!("", clobber_abi("C" foo));
+ //~^ ERROR expected one of `)` or `,`, found `foo`
+ asm!("", clobber_abi("C", foo));
+ //~^ ERROR expected string literal
+ asm!("{}", clobber_abi("C"), const foo);
+ //~^ ERROR arguments are not allowed after clobber_abi
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", options(), clobber_abi("C"));
+ //~^ ERROR clobber_abi is not allowed after options
+ asm!("{}", options(), clobber_abi("C"), const foo);
+ //~^ ERROR clobber_abi is not allowed after options
+ asm!("{a}", a = const foo, a = const bar);
+ //~^ ERROR duplicate argument named `a`
+ //~^^ ERROR argument never used
+ //~^^^ ERROR attempt to use a non-constant value in a constant
+ //~^^^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", a = in("x0") foo);
+ //~^ ERROR explicit register arguments cannot have names
+ asm!("{a}", in("x0") foo, a = const bar);
+ //~^ ERROR named arguments cannot follow explicit register arguments
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("{a}", in("x0") foo, a = const bar);
+ //~^ ERROR named arguments cannot follow explicit register arguments
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("{1}", in("x0") foo, const bar);
+ //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", options(), "");
+ //~^ ERROR expected one of
+ asm!("{}", in(reg) foo, "{}", out(reg) foo);
+ //~^ ERROR expected one of
+ asm!(format!("{{{}}}", 0), in(reg) foo);
+ //~^ ERROR asm template must be a string literal
+ asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
+ //~^ ERROR asm template must be a string literal
+ asm!("{}", in(reg) _);
+ //~^ ERROR _ cannot be used for input operands
+ asm!("{}", inout(reg) _);
+ //~^ ERROR _ cannot be used for input operands
+ asm!("{}", inlateout(reg) _);
+ //~^ ERROR _ cannot be used for input operands
+ }
+}
+
+const FOO: i32 = 1;
+const BAR: i32 = 2;
+global_asm!();
+//~^ ERROR requires at least a template string argument
+global_asm!(FOO);
+//~^ ERROR asm template must be a string literal
+global_asm!("{}" FOO);
+//~^ ERROR expected token: `,`
+global_asm!("{}", FOO);
+//~^ ERROR expected operand, options, or additional template string
+global_asm!("{}", const);
+//~^ ERROR expected expression, found end of macro arguments
+global_asm!("{}", const(reg) FOO);
+//~^ ERROR expected one of
+global_asm!("", options(FOO));
+//~^ ERROR expected one of
+global_asm!("", options(nomem FOO));
+//~^ ERROR expected one of
+global_asm!("", options(nomem, FOO));
+//~^ ERROR expected one of
+global_asm!("{}", options(), const FOO);
+//~^ ERROR arguments are not allowed after options
+global_asm!("", clobber_abi(FOO));
+//~^ ERROR expected string literal
+global_asm!("", clobber_abi("C" FOO));
+//~^ ERROR expected one of `)` or `,`, found `FOO`
+global_asm!("", clobber_abi("C", FOO));
+//~^ ERROR expected string literal
+global_asm!("{}", clobber_abi("C"), const FOO);
+//~^ ERROR arguments are not allowed after clobber_abi
+//~^^ ERROR `clobber_abi` cannot be used with `global_asm!`
+global_asm!("", options(), clobber_abi("C"));
+//~^ ERROR clobber_abi is not allowed after options
+global_asm!("{}", options(), clobber_abi("C"), const FOO);
+//~^ ERROR clobber_abi is not allowed after options
+global_asm!("{a}", a = const FOO, a = const BAR);
+//~^ ERROR duplicate argument named `a`
+//~^^ ERROR argument never used
+global_asm!("", options(), "");
+//~^ ERROR expected one of
+global_asm!("{}", const FOO, "{}", const FOO);
+//~^ ERROR expected one of
+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
diff --git a/tests/ui/asm/aarch64/parse-error.stderr b/tests/ui/asm/aarch64/parse-error.stderr
new file mode 100644
index 000000000..804966b06
--- /dev/null
+++ b/tests/ui/asm/aarch64/parse-error.stderr
@@ -0,0 +1,446 @@
+error: requires at least a template string argument
+ --> $DIR/parse-error.rs:11:9
+ |
+LL | asm!();
+ | ^^^^^^
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:13:14
+ |
+LL | asm!(foo);
+ | ^^^
+
+error: expected token: `,`
+ --> $DIR/parse-error.rs:15:19
+ |
+LL | asm!("{}" foo);
+ | ^^^ expected `,`
+
+error: expected operand, clobber_abi, options, or additional template string
+ --> $DIR/parse-error.rs:17:20
+ |
+LL | asm!("{}", foo);
+ | ^^^ expected operand, clobber_abi, options, or additional template string
+
+error: expected `(`, found `foo`
+ --> $DIR/parse-error.rs:19:23
+ |
+LL | asm!("{}", in foo);
+ | ^^^ expected `(`
+
+error: expected `)`, found `foo`
+ --> $DIR/parse-error.rs:21:27
+ |
+LL | asm!("{}", in(reg foo));
+ | ^^^ expected `)`
+
+error: expected expression, found end of macro arguments
+ --> $DIR/parse-error.rs:23:27
+ |
+LL | asm!("{}", in(reg));
+ | ^ expected expression
+
+error: expected register class or explicit register
+ --> $DIR/parse-error.rs:25:26
+ |
+LL | asm!("{}", inout(=) foo => bar);
+ | ^
+
+error: expected expression, found end of macro arguments
+ --> $DIR/parse-error.rs:27:37
+ |
+LL | asm!("{}", inout(reg) foo =>);
+ | ^ expected expression
+
+error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
+ --> $DIR/parse-error.rs:29:32
+ |
+LL | asm!("{}", in(reg) foo => bar);
+ | ^^ expected one of 7 possible tokens
+
+error: expected a path for argument to `sym`
+ --> $DIR/parse-error.rs:31:24
+ |
+LL | asm!("{}", sym foo + bar);
+ | ^^^^^^^^^
+
+error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
+ --> $DIR/parse-error.rs:33:26
+ |
+LL | asm!("", options(foo));
+ | ^^^ expected one of 10 possible tokens
+
+error: expected one of `)` or `,`, found `foo`
+ --> $DIR/parse-error.rs:35:32
+ |
+LL | asm!("", options(nomem foo));
+ | ^^^ expected one of `)` or `,`
+
+error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
+ --> $DIR/parse-error.rs:37:33
+ |
+LL | asm!("", options(nomem, foo));
+ | ^^^ expected one of 10 possible tokens
+
+error: arguments are not allowed after options
+ --> $DIR/parse-error.rs:39:31
+ |
+LL | asm!("{}", options(), const foo);
+ | --------- ^^^^^^^^^ argument
+ | |
+ | previous options
+
+error: expected string literal
+ --> $DIR/parse-error.rs:42:30
+ |
+LL | asm!("", clobber_abi(foo));
+ | ^^^ not a string literal
+
+error: expected one of `)` or `,`, found `foo`
+ --> $DIR/parse-error.rs:44:34
+ |
+LL | asm!("", clobber_abi("C" foo));
+ | ^^^ expected one of `)` or `,`
+
+error: expected string literal
+ --> $DIR/parse-error.rs:46:35
+ |
+LL | asm!("", clobber_abi("C", foo));
+ | ^^^ not a string literal
+
+error: arguments are not allowed after clobber_abi
+ --> $DIR/parse-error.rs:48:38
+ |
+LL | asm!("{}", clobber_abi("C"), const foo);
+ | ---------------- ^^^^^^^^^ argument
+ | |
+ | clobber_abi
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:51:29
+ |
+LL | asm!("", options(), clobber_abi("C"));
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:53:31
+ |
+LL | asm!("{}", options(), clobber_abi("C"), const foo);
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: duplicate argument named `a`
+ --> $DIR/parse-error.rs:55:36
+ |
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ------------- ^^^^^^^^^^^^^ duplicate argument
+ | |
+ | previously here
+
+error: argument never used
+ --> $DIR/parse-error.rs:55:36
+ |
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ^^^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
+
+error: explicit register arguments cannot have names
+ --> $DIR/parse-error.rs:60:18
+ |
+LL | asm!("", a = in("x0") foo);
+ | ^^^^^^^^^^^^^^^^
+
+error: named arguments cannot follow explicit register arguments
+ --> $DIR/parse-error.rs:62:35
+ |
+LL | asm!("{a}", in("x0") foo, a = const bar);
+ | ------------ ^^^^^^^^^^^^^ named argument
+ | |
+ | explicit register argument
+
+error: named arguments cannot follow explicit register arguments
+ --> $DIR/parse-error.rs:65:35
+ |
+LL | asm!("{a}", in("x0") foo, a = const bar);
+ | ------------ ^^^^^^^^^^^^^ named argument
+ | |
+ | explicit register argument
+
+error: positional arguments cannot follow named arguments or explicit register arguments
+ --> $DIR/parse-error.rs:68:35
+ |
+LL | asm!("{1}", in("x0") foo, const bar);
+ | ------------ ^^^^^^^^^ positional argument
+ | |
+ | explicit register argument
+
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
+ --> $DIR/parse-error.rs:71:29
+ |
+LL | asm!("", options(), "");
+ | ^^ expected one of 9 possible tokens
+
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
+ --> $DIR/parse-error.rs:73:33
+ |
+LL | asm!("{}", in(reg) foo, "{}", out(reg) foo);
+ | ^^^^ expected one of 9 possible tokens
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:75:14
+ |
+LL | asm!(format!("{{{}}}", 0), in(reg) foo);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:77:21
+ |
+LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:79:28
+ |
+LL | asm!("{}", in(reg) _);
+ | ^
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:81:31
+ |
+LL | asm!("{}", inout(reg) _);
+ | ^
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:83:35
+ |
+LL | asm!("{}", inlateout(reg) _);
+ | ^
+
+error: requires at least a template string argument
+ --> $DIR/parse-error.rs:90:1
+ |
+LL | global_asm!();
+ | ^^^^^^^^^^^^^
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:92:13
+ |
+LL | global_asm!(FOO);
+ | ^^^
+
+error: expected token: `,`
+ --> $DIR/parse-error.rs:94:18
+ |
+LL | global_asm!("{}" FOO);
+ | ^^^ expected `,`
+
+error: expected operand, options, or additional template string
+ --> $DIR/parse-error.rs:96:19
+ |
+LL | global_asm!("{}", FOO);
+ | ^^^ expected operand, options, or additional template string
+
+error: expected expression, found end of macro arguments
+ --> $DIR/parse-error.rs:98:24
+ |
+LL | global_asm!("{}", const);
+ | ^ expected expression
+
+error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
+ --> $DIR/parse-error.rs:100:30
+ |
+LL | global_asm!("{}", const(reg) FOO);
+ | ^^^ expected one of `,`, `.`, `?`, or an operator
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
+ --> $DIR/parse-error.rs:102:25
+ |
+LL | global_asm!("", options(FOO));
+ | ^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+ --> $DIR/parse-error.rs:104:25
+ |
+LL | global_asm!("", options(nomem FOO));
+ | ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+ --> $DIR/parse-error.rs:106:25
+ |
+LL | global_asm!("", options(nomem, FOO));
+ | ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: arguments are not allowed after options
+ --> $DIR/parse-error.rs:108:30
+ |
+LL | global_asm!("{}", options(), const FOO);
+ | --------- ^^^^^^^^^ argument
+ | |
+ | previous options
+
+error: expected string literal
+ --> $DIR/parse-error.rs:110:29
+ |
+LL | global_asm!("", clobber_abi(FOO));
+ | ^^^ not a string literal
+
+error: expected one of `)` or `,`, found `FOO`
+ --> $DIR/parse-error.rs:112:33
+ |
+LL | global_asm!("", clobber_abi("C" FOO));
+ | ^^^ expected one of `)` or `,`
+
+error: expected string literal
+ --> $DIR/parse-error.rs:114:34
+ |
+LL | global_asm!("", clobber_abi("C", FOO));
+ | ^^^ not a string literal
+
+error: arguments are not allowed after clobber_abi
+ --> $DIR/parse-error.rs:116:37
+ |
+LL | global_asm!("{}", clobber_abi("C"), const FOO);
+ | ---------------- ^^^^^^^^^ argument
+ | |
+ | clobber_abi
+
+error: `clobber_abi` cannot be used with `global_asm!`
+ --> $DIR/parse-error.rs:116:19
+ |
+LL | global_asm!("{}", clobber_abi("C"), const FOO);
+ | ^^^^^^^^^^^^^^^^
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:119:28
+ |
+LL | global_asm!("", options(), clobber_abi("C"));
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:121:30
+ |
+LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: duplicate argument named `a`
+ --> $DIR/parse-error.rs:123:35
+ |
+LL | global_asm!("{a}", a = const FOO, a = const BAR);
+ | ------------- ^^^^^^^^^^^^^ duplicate argument
+ | |
+ | previously here
+
+error: argument never used
+ --> $DIR/parse-error.rs:123:35
+ |
+LL | global_asm!("{a}", a = const FOO, a = const BAR);
+ | ^^^^^^^^^^^^^ argument never used
+ |
+ = 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 `""`
+ --> $DIR/parse-error.rs:126:28
+ |
+LL | global_asm!("", options(), "");
+ | ^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
+
+error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"`
+ --> $DIR/parse-error.rs:128:30
+ |
+LL | global_asm!("{}", const FOO, "{}", const FOO);
+ | ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:130:13
+ |
+LL | global_asm!(format!("{{{}}}", 0), const FOO);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:132:20
+ |
+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[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:39:37
+ |
+LL | let mut foo = 0;
+ | ----------- help: consider using `const` instead of `let`: `const foo`
+...
+LL | asm!("{}", options(), const foo);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:48:44
+ |
+LL | let mut foo = 0;
+ | ----------- help: consider using `const` instead of `let`: `const foo`
+...
+LL | asm!("{}", clobber_abi("C"), const foo);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:55:31
+ |
+LL | let mut foo = 0;
+ | ----------- help: consider using `const` instead of `let`: `const foo`
+...
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:55:46
+ |
+LL | let mut bar = 0;
+ | ----------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:62:45
+ |
+LL | let mut bar = 0;
+ | ----------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{a}", in("x0") foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:65:45
+ |
+LL | let mut bar = 0;
+ | ----------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{a}", in("x0") foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:68:41
+ |
+LL | let mut bar = 0;
+ | ----------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{1}", in("x0") foo, const bar);
+ | ^^^ non-constant value
+
+error: aborting due to 64 previous errors
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/asm/aarch64/srcloc.rs b/tests/ui/asm/aarch64/srcloc.rs
new file mode 100644
index 000000000..dbb6cbb94
--- /dev/null
+++ b/tests/ui/asm/aarch64/srcloc.rs
@@ -0,0 +1,129 @@
+// only-aarch64
+// build-fail
+// needs-asm-support
+// compile-flags: -Ccodegen-units=1
+
+use std::arch::asm;
+
+// Checks that inline asm errors are mapped to the correct line in the source code.
+
+fn main() {
+ unsafe {
+ asm!("invalid_instruction");
+ //~^ ERROR: unrecognized instruction mnemonic
+
+ asm!("
+ invalid_instruction
+ ");
+ //~^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(r#"
+ invalid_instruction
+ "#);
+ //~^^ ERROR: unrecognized instruction mnemonic
+
+ asm!("
+ mov x0, x0
+ invalid_instruction
+ mov x0, x0
+ ");
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(r#"
+ mov x0, x0
+ invalid_instruction
+ mov x0, x0
+ "#);
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(concat!("invalid", "_", "instruction"));
+ //~^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ "invalid_instruction",
+ );
+ //~^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ "mov x0, x0",
+ "invalid_instruction",
+ "mov x0, x0",
+ );
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ "mov x0, x0\n",
+ "invalid_instruction",
+ "mov x0, x0",
+ );
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ "mov x0, x0",
+ concat!("invalid", "_", "instruction"),
+ "mov x0, x0",
+ );
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ concat!("mov x0", ", ", "x0"),
+ concat!("invalid", "_", "instruction"),
+ concat!("mov x0", ", ", "x0"),
+ );
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ // Make sure template strings get separated
+ asm!(
+ "invalid_instruction1",
+ "invalid_instruction2",
+ );
+ //~^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2",
+ ),
+ );
+ //~^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2",
+ ),
+ concat!(
+ "invalid", "_", "instruction3", "\n",
+ "invalid", "_", "instruction4",
+ ),
+ );
+ //~^^^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2", "\n",
+ ),
+ concat!(
+ "invalid", "_", "instruction3", "\n",
+ "invalid", "_", "instruction4", "\n",
+ ),
+ );
+ //~^^^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ "",
+ "\n",
+ "invalid_instruction"
+ );
+ //~^^ ERROR: unrecognized instruction mnemonic
+ }
+}
diff --git a/tests/ui/asm/aarch64/srcloc.stderr b/tests/ui/asm/aarch64/srcloc.stderr
new file mode 100644
index 000000000..2e17b60b9
--- /dev/null
+++ b/tests/ui/asm/aarch64/srcloc.stderr
@@ -0,0 +1,290 @@
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:12:15
+ |
+LL | asm!("invalid_instruction");
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:16:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:13
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:21:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:13
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:27:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:13
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:34:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:13
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:39:14
+ |
+LL | asm!(concat!("invalid", "_", "instruction"));
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:43:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:49:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:56:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:63:13
+ |
+LL | concat!("invalid", "_", "instruction"),
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:70:13
+ |
+LL | concat!("invalid", "_", "instruction"),
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:77:14
+ |
+LL | "invalid_instruction1",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction1
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:78:14
+ |
+LL | "invalid_instruction2",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction2
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:84:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction1
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:84:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction2
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:93:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction1
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:93:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction2
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:97:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction3
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:97:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:1
+ |
+LL | invalid_instruction4
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:108:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction1
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:108:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction2
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:112:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:1
+ |
+LL | invalid_instruction3
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:112:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:5:1
+ |
+LL | invalid_instruction4
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:125:14
+ |
+LL | "invalid_instruction"
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:1
+ |
+LL | invalid_instruction
+ | ^
+
+error: aborting due to 24 previous errors
+
diff --git a/tests/ui/asm/aarch64/sym.rs b/tests/ui/asm/aarch64/sym.rs
new file mode 100644
index 000000000..6a6cdb00d
--- /dev/null
+++ b/tests/ui/asm/aarch64/sym.rs
@@ -0,0 +1,84 @@
+// only-aarch64
+// only-linux
+// needs-asm-support
+// run-pass
+
+#![feature(thread_local)]
+
+use std::arch::asm;
+
+extern "C" fn f1() -> i32 {
+ 111
+}
+
+// The compiler will generate a shim to hide the caller location parameter.
+#[track_caller]
+fn f2() -> i32 {
+ 222
+}
+
+macro_rules! call {
+ ($func:path) => {
+ unsafe {
+ let result: i32;
+ asm!("bl {}", sym $func,
+ out("w0") result,
+ out("x20") _, out("x21") _, out("x22") _,
+ out("x23") _, out("x24") _, out("x25") _,
+ out("x26") _, out("x27") _, out("x28") _,
+ );
+ result
+ }
+ }
+}
+
+macro_rules! static_addr {
+ ($s:expr) => {
+ unsafe {
+ let result: *const u32;
+ asm!(
+ // ADRP gives the address of a 4KB page from a PC-relative address
+ "adrp {out}, {sym}",
+ // We then add the remaining lower 12 bits
+ "add {out}, {out}, #:lo12:{sym}",
+ out = out(reg) result,
+ sym = sym $s);
+ result
+ }
+ }
+}
+macro_rules! static_tls_addr {
+ ($s:expr) => {
+ unsafe {
+ let result: *const u32;
+ asm!(
+ // Load the thread pointer register
+ "mrs {out}, TPIDR_EL0",
+ // Add the top 12 bits of the symbol's offset
+ "add {out}, {out}, :tprel_hi12:{sym}",
+ // And the bottom 12 bits
+ "add {out}, {out}, :tprel_lo12_nc:{sym}",
+ out = out(reg) result,
+ sym = sym $s
+ );
+ result
+ }
+ }
+}
+
+static S1: u32 = 111;
+#[thread_local]
+static S2: u32 = 222;
+
+fn main() {
+ assert_eq!(call!(f1), 111);
+ assert_eq!(call!(f2), 222);
+ assert_eq!(static_addr!(S1), &S1 as *const u32);
+ assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
+ std::thread::spawn(|| {
+ assert_eq!(static_addr!(S1), &S1 as *const u32);
+ assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
+ })
+ .join()
+ .unwrap();
+}
diff --git a/tests/ui/asm/aarch64/type-check-2-2.rs b/tests/ui/asm/aarch64/type-check-2-2.rs
new file mode 100644
index 000000000..89f2b3bb7
--- /dev/null
+++ b/tests/ui/asm/aarch64/type-check-2-2.rs
@@ -0,0 +1,35 @@
+// only-aarch64
+
+#![feature(repr_simd, never_type)]
+
+use std::arch::{asm, global_asm};
+
+#[repr(simd)]
+#[derive(Clone, Copy)]
+struct SimdType(f32, f32, f32, f32);
+
+#[repr(simd)]
+struct SimdNonCopy(f32, f32, f32, f32);
+
+fn main() {
+ unsafe {
+ // Inputs must be initialized
+
+ let x: u64;
+ asm!("{}", in(reg) x);
+ //~^ ERROR used binding `x` isn't initialized
+ let mut y: u64;
+ asm!("{}", inout(reg) y);
+ //~^ ERROR used binding `y` isn't initialized
+ let _ = y;
+
+ // Outputs require mutable places
+
+ let v: Vec<u64> = vec![0, 1, 2]; //~ ERROR cannot borrow `v` as mutable
+ asm!("{}", in(reg) v[0]);
+ asm!("{}", out(reg) v[0]);
+ asm!("{}", inout(reg) v[0]);
+
+ // Sym operands must point to a function or static
+ }
+}
diff --git a/tests/ui/asm/aarch64/type-check-2-2.stderr b/tests/ui/asm/aarch64/type-check-2-2.stderr
new file mode 100644
index 000000000..41f7c01dc
--- /dev/null
+++ b/tests/ui/asm/aarch64/type-check-2-2.stderr
@@ -0,0 +1,46 @@
+error[E0381]: used binding `x` isn't initialized
+ --> $DIR/type-check-2-2.rs:19:28
+ |
+LL | let x: u64;
+ | - binding declared here but left uninitialized
+LL | asm!("{}", in(reg) x);
+ | ^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: u64 = 0;
+ | +++
+
+error[E0381]: used binding `y` isn't initialized
+ --> $DIR/type-check-2-2.rs:22:9
+ |
+LL | let mut y: u64;
+ | ----- binding declared here but left uninitialized
+LL | asm!("{}", inout(reg) y);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let mut y: u64 = 0;
+ | +++
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+ --> $DIR/type-check-2-2.rs:28:13
+ |
+LL | let v: Vec<u64> = vec![0, 1, 2];
+ | ^ not mutable
+LL | asm!("{}", in(reg) v[0]);
+LL | asm!("{}", out(reg) v[0]);
+ | - cannot borrow as mutable
+LL | asm!("{}", inout(reg) v[0]);
+ | - cannot borrow as mutable
+ |
+help: consider changing this to be mutable
+ |
+LL | let mut v: Vec<u64> = vec![0, 1, 2];
+ | +++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0381, E0596.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/tests/ui/asm/aarch64/type-check-2.rs b/tests/ui/asm/aarch64/type-check-2.rs
new file mode 100644
index 000000000..1c71c1185
--- /dev/null
+++ b/tests/ui/asm/aarch64/type-check-2.rs
@@ -0,0 +1,76 @@
+// only-aarch64
+
+#![feature(repr_simd, never_type)]
+
+use std::arch::{asm, global_asm};
+
+#[repr(simd)]
+#[derive(Clone, Copy)]
+struct SimdType(f32, f32, f32, f32);
+
+#[repr(simd)]
+struct SimdNonCopy(f32, f32, f32, f32);
+
+fn main() {
+ unsafe {
+ // Inputs must be initialized
+
+ // Sym operands must point to a function or static
+
+ const C: i32 = 0;
+ static S: i32 = 0;
+ asm!("{}", sym S);
+ asm!("{}", sym main);
+ asm!("{}", sym C);
+ //~^ ERROR invalid `sym` operand
+
+ // Register operands must be Copy
+
+ asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
+ //~^ ERROR arguments for inline assembly must be copyable
+
+ // Register operands must be integers, floats, SIMD vectors, pointers or
+ // function pointers.
+
+ asm!("{}", in(reg) 0i64);
+ asm!("{}", in(reg) 0f64);
+ asm!("{:v}", in(vreg) SimdType(0.0, 0.0, 0.0, 0.0));
+ asm!("{}", in(reg) 0 as *const u8);
+ asm!("{}", in(reg) 0 as *mut u8);
+ asm!("{}", in(reg) main as fn());
+ asm!("{}", in(reg) |x: i32| x);
+ //~^ ERROR cannot use value of type
+ asm!("{}", in(reg) vec![0]);
+ //~^ ERROR cannot use value of type `Vec<i32>` for inline assembly
+ asm!("{}", in(reg) (1, 2, 3));
+ //~^ ERROR cannot use value of type `(i32, i32, i32)` for inline assembly
+ asm!("{}", in(reg) [1, 2, 3]);
+ //~^ ERROR cannot use value of type `[i32; 3]` for inline assembly
+
+ // Register inputs (but not outputs) allow references and function types
+
+ let mut f = main;
+ let mut r = &mut 0;
+ asm!("{}", in(reg) f);
+ asm!("{}", inout(reg) f);
+ //~^ ERROR cannot use value of type `fn() {main}` for inline assembly
+ asm!("{}", in(reg) r);
+ asm!("{}", inout(reg) r);
+ //~^ ERROR cannot use value of type `&mut i32` for inline assembly
+ let _ = (f, r);
+
+ // Type checks ignore never type
+
+ let u: ! = unreachable!();
+ asm!("{}", in(reg) u);
+ }
+}
+
+// Sym operands must point to a function or static
+
+const C: i32 = 0;
+static S: i32 = 0;
+global_asm!("{}", sym S);
+global_asm!("{}", sym main);
+global_asm!("{}", sym C);
+//~^ ERROR invalid `sym` operand
diff --git a/tests/ui/asm/aarch64/type-check-2.stderr b/tests/ui/asm/aarch64/type-check-2.stderr
new file mode 100644
index 000000000..875df44ff
--- /dev/null
+++ b/tests/ui/asm/aarch64/type-check-2.stderr
@@ -0,0 +1,75 @@
+error: invalid `sym` operand
+ --> $DIR/type-check-2.rs:75:19
+ |
+LL | global_asm!("{}", sym C);
+ | ^^^^^ is an `i32`
+ |
+ = help: `sym` operands must refer to either a function or a static
+
+error: invalid `sym` operand
+ --> $DIR/type-check-2.rs:24:20
+ |
+LL | asm!("{}", sym C);
+ | ^^^^^ is an `i32`
+ |
+ = help: `sym` operands must refer to either a function or a static
+
+error: arguments for inline assembly must be copyable
+ --> $DIR/type-check-2.rs:29:31
+ |
+LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `SimdNonCopy` does not implement the Copy trait
+
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:41:28: 41:36]` for inline assembly
+ --> $DIR/type-check-2.rs:41:28
+ |
+LL | asm!("{}", in(reg) |x: i32| x);
+ | ^^^^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `Vec<i32>` for inline assembly
+ --> $DIR/type-check-2.rs:43:28
+ |
+LL | asm!("{}", in(reg) vec![0]);
+ | ^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+ = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot use value of type `(i32, i32, i32)` for inline assembly
+ --> $DIR/type-check-2.rs:45:28
+ |
+LL | asm!("{}", in(reg) (1, 2, 3));
+ | ^^^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `[i32; 3]` for inline assembly
+ --> $DIR/type-check-2.rs:47:28
+ |
+LL | asm!("{}", in(reg) [1, 2, 3]);
+ | ^^^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `fn() {main}` for inline assembly
+ --> $DIR/type-check-2.rs:55:31
+ |
+LL | asm!("{}", inout(reg) f);
+ | ^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `&mut i32` for inline assembly
+ --> $DIR/type-check-2.rs:58:31
+ |
+LL | asm!("{}", inout(reg) r);
+ | ^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: aborting due to 9 previous errors
+
diff --git a/tests/ui/asm/aarch64/type-check-3.rs b/tests/ui/asm/aarch64/type-check-3.rs
new file mode 100644
index 000000000..623f6593d
--- /dev/null
+++ b/tests/ui/asm/aarch64/type-check-3.rs
@@ -0,0 +1,97 @@
+// only-aarch64
+// compile-flags: -C target-feature=+neon
+
+#![feature(repr_simd, stdsimd, asm_const)]
+
+use std::arch::aarch64::float64x2_t;
+use std::arch::{asm, global_asm};
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct Simd256bit(f64, f64, f64, f64);
+
+fn main() {
+ let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) };
+ let f64x4 = Simd256bit(0.0, 0.0, 0.0, 0.0);
+
+ unsafe {
+ // Types must be listed in the register class.
+
+ // Success cases
+ asm!("{:w}", in(reg) 0u8);
+ asm!("{:w}", in(reg) 0u16);
+ asm!("{:w}", in(reg) 0u32);
+ asm!("{:w}", in(reg) 0f32);
+ asm!("{}", in(reg) 0i64);
+ asm!("{}", in(reg) 0f64);
+
+ asm!("{:b}", in(vreg) 0u8);
+ asm!("{:h}", in(vreg) 0u16);
+ asm!("{:s}", in(vreg) 0u32);
+ asm!("{:s}", in(vreg) 0f32);
+ asm!("{:d}", in(vreg) 0u64);
+ asm!("{:d}", in(vreg) 0f64);
+ asm!("{:q}", in(vreg) f64x2);
+ asm!("{:v}", in(vreg) f64x2);
+
+ // Should be the same as vreg
+ asm!("{:q}", in(vreg_low16) f64x2);
+
+ // Template modifiers of a different size to the argument are fine
+ asm!("{:w}", in(reg) 0u64);
+ asm!("{:x}", in(reg) 0u32);
+ asm!("{:b}", in(vreg) 0u64);
+ asm!("{:d}", in(vreg_low16) f64x2);
+
+ // Template modifier suggestions for sub-registers
+
+ asm!("{}", in(reg) 0u8);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(reg) 0u16);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(reg) 0i32);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(reg) 0f32);
+ //~^ WARN formatting may not be suitable for sub-register argument
+
+ asm!("{}", in(vreg) 0i16);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(vreg) 0f32);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(vreg) 0f64);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(vreg_low16) 0f64);
+ //~^ WARN formatting may not be suitable for sub-register argument
+
+ asm!("{0} {0}", in(reg) 0i16);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{0} {0:x}", in(reg) 0i16);
+ //~^ WARN formatting may not be suitable for sub-register argument
+
+ // Invalid registers
+
+ asm!("{}", in(reg) 0i128);
+ //~^ ERROR type `i128` cannot be used with this register class
+ asm!("{}", in(reg) f64x2);
+ //~^ ERROR type `float64x2_t` cannot be used with this register class
+ asm!("{}", in(vreg) f64x4);
+ //~^ ERROR type `Simd256bit` cannot be used with this register class
+
+ // Split inout operands must have compatible types
+
+ let mut val_i16: i16;
+ let mut val_f32: f32;
+ let mut val_u32: u32;
+ let mut val_u64: u64;
+ let mut val_ptr: *mut u8;
+ asm!("{:x}", inout(reg) 0u16 => val_i16);
+ asm!("{:x}", inout(reg) 0u32 => val_f32);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:x}", inout(reg) 0u32 => val_ptr);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:x}", inout(reg) main => val_u32);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:x}", inout(reg) 0u64 => val_ptr);
+ asm!("{:x}", inout(reg) main => val_u64);
+ }
+}
diff --git a/tests/ui/asm/aarch64/type-check-3.stderr b/tests/ui/asm/aarch64/type-check-3.stderr
new file mode 100644
index 000000000..f710df2dc
--- /dev/null
+++ b/tests/ui/asm/aarch64/type-check-3.stderr
@@ -0,0 +1,147 @@
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:48:15
+ |
+LL | asm!("{}", in(reg) 0u8);
+ | ^^ --- for this argument
+ |
+ = help: use `{0:w}` to have the register formatted as `w0`
+ = help: or use `{0:x}` to keep the default formatting of `x0`
+ = note: `#[warn(asm_sub_register)]` on by default
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:50:15
+ |
+LL | asm!("{}", in(reg) 0u16);
+ | ^^ ---- for this argument
+ |
+ = help: use `{0:w}` to have the register formatted as `w0`
+ = help: or use `{0:x}` to keep the default formatting of `x0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:52:15
+ |
+LL | asm!("{}", in(reg) 0i32);
+ | ^^ ---- for this argument
+ |
+ = help: use `{0:w}` to have the register formatted as `w0`
+ = help: or use `{0:x}` to keep the default formatting of `x0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:54:15
+ |
+LL | asm!("{}", in(reg) 0f32);
+ | ^^ ---- for this argument
+ |
+ = help: use `{0:w}` to have the register formatted as `w0`
+ = help: or use `{0:x}` to keep the default formatting of `x0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:57:15
+ |
+LL | asm!("{}", in(vreg) 0i16);
+ | ^^ ---- for this argument
+ |
+ = help: use `{0:h}` to have the register formatted as `h0`
+ = help: or use `{0:v}` to keep the default formatting of `v0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:59:15
+ |
+LL | asm!("{}", in(vreg) 0f32);
+ | ^^ ---- for this argument
+ |
+ = help: use `{0:s}` to have the register formatted as `s0`
+ = help: or use `{0:v}` to keep the default formatting of `v0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:61:15
+ |
+LL | asm!("{}", in(vreg) 0f64);
+ | ^^ ---- for this argument
+ |
+ = help: use `{0:d}` to have the register formatted as `d0`
+ = help: or use `{0:v}` to keep the default formatting of `v0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:63:15
+ |
+LL | asm!("{}", in(vreg_low16) 0f64);
+ | ^^ ---- for this argument
+ |
+ = help: use `{0:d}` to have the register formatted as `d0`
+ = help: or use `{0:v}` to keep the default formatting of `v0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:66:15
+ |
+LL | asm!("{0} {0}", in(reg) 0i16);
+ | ^^^ ^^^ ---- for this argument
+ |
+ = help: use `{0:w}` to have the register formatted as `w0`
+ = help: or use `{0:x}` to keep the default formatting of `x0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:68:15
+ |
+LL | asm!("{0} {0:x}", in(reg) 0i16);
+ | ^^^ ---- for this argument
+ |
+ = help: use `{0:w}` to have the register formatted as `w0`
+ = help: or use `{0:x}` to keep the default formatting of `x0`
+
+error: type `i128` cannot be used with this register class
+ --> $DIR/type-check-3.rs:73:28
+ |
+LL | asm!("{}", in(reg) 0i128);
+ | ^^^^^
+ |
+ = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
+
+error: type `float64x2_t` cannot be used with this register class
+ --> $DIR/type-check-3.rs:75:28
+ |
+LL | asm!("{}", in(reg) f64x2);
+ | ^^^^^
+ |
+ = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
+
+error: type `Simd256bit` cannot be used with this register class
+ --> $DIR/type-check-3.rs:77:29
+ |
+LL | asm!("{}", in(vreg) f64x4);
+ | ^^^^^
+ |
+ = note: register class `vreg` supports these types: i8, i16, i32, i64, f32, f64, i8x8, i16x4, i32x2, i64x1, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
+
+error: incompatible types for asm inout argument
+ --> $DIR/type-check-3.rs:88:33
+ |
+LL | asm!("{:x}", inout(reg) 0u32 => val_f32);
+ | ^^^^ ^^^^^^^ type `f32`
+ | |
+ | type `u32`
+ |
+ = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
+
+error: incompatible types for asm inout argument
+ --> $DIR/type-check-3.rs:90:33
+ |
+LL | asm!("{:x}", inout(reg) 0u32 => val_ptr);
+ | ^^^^ ^^^^^^^ type `*mut u8`
+ | |
+ | type `u32`
+ |
+ = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
+
+error: incompatible types for asm inout argument
+ --> $DIR/type-check-3.rs:92:33
+ |
+LL | asm!("{:x}", inout(reg) main => val_u32);
+ | ^^^^ ^^^^^^^ type `u32`
+ | |
+ | type `fn()`
+ |
+ = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
+
+error: aborting due to 6 previous errors; 10 warnings emitted
+
diff --git a/tests/ui/asm/aarch64/type-check-4.rs b/tests/ui/asm/aarch64/type-check-4.rs
new file mode 100644
index 000000000..bd23755c0
--- /dev/null
+++ b/tests/ui/asm/aarch64/type-check-4.rs
@@ -0,0 +1,32 @@
+// only-aarch64
+// compile-flags: -C target-feature=+neon
+
+#![feature(repr_simd, stdsimd, asm_const)]
+
+use std::arch::aarch64::float64x2_t;
+use std::arch::{asm, global_asm};
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct Simd256bit(f64, f64, f64, f64);
+
+fn main() {
+}
+
+// Constants must be... constant
+
+static S: i32 = 1;
+const fn const_foo(x: i32) -> i32 {
+ x
+}
+const fn const_bar<T>(x: T) -> T {
+ x
+}
+global_asm!("{}", const S);
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_foo(0));
+global_asm!("{}", const const_foo(S));
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_bar(0));
+global_asm!("{}", const const_bar(S));
+//~^ ERROR constants cannot refer to statics
diff --git a/tests/ui/asm/aarch64/type-check-4.stderr b/tests/ui/asm/aarch64/type-check-4.stderr
new file mode 100644
index 000000000..4837e647b
--- /dev/null
+++ b/tests/ui/asm/aarch64/type-check-4.stderr
@@ -0,0 +1,27 @@
+error[E0013]: constants cannot refer to statics
+ --> $DIR/type-check-4.rs:25:25
+ |
+LL | global_asm!("{}", const S);
+ | ^
+ |
+ = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+ --> $DIR/type-check-4.rs:28:35
+ |
+LL | global_asm!("{}", const const_foo(S));
+ | ^
+ |
+ = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+ --> $DIR/type-check-4.rs:31:35
+ |
+LL | global_asm!("{}", const const_bar(S));
+ | ^
+ |
+ = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0013`.