summaryrefslogtreecommitdiffstats
path: root/src/test/ui/asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/asm')
-rw-r--r--src/test/ui/asm/aarch64/bad-options.rs39
-rw-r--r--src/test/ui/asm/aarch64/bad-options.stderr84
-rw-r--r--src/test/ui/asm/aarch64/bad-reg.rs61
-rw-r--r--src/test/ui/asm/aarch64/bad-reg.stderr162
-rw-r--r--src/test/ui/asm/aarch64/const.rs44
-rw-r--r--src/test/ui/asm/aarch64/duplicate-options.fixed27
-rw-r--r--src/test/ui/asm/aarch64/duplicate-options.rs27
-rw-r--r--src/test/ui/asm/aarch64/duplicate-options.stderr56
-rw-r--r--src/test/ui/asm/aarch64/interpolated-idents.rs24
-rw-r--r--src/test/ui/asm/aarch64/interpolated-idents.stderr51
-rw-r--r--src/test/ui/asm/aarch64/may_unwind.rs38
-rw-r--r--src/test/ui/asm/aarch64/parse-error.rs133
-rw-r--r--src/test/ui/asm/aarch64/parse-error.stderr446
-rw-r--r--src/test/ui/asm/aarch64/srcloc.rs129
-rw-r--r--src/test/ui/asm/aarch64/srcloc.stderr290
-rw-r--r--src/test/ui/asm/aarch64/sym.rs84
-rw-r--r--src/test/ui/asm/aarch64/type-check-2-2.rs37
-rw-r--r--src/test/ui/asm/aarch64/type-check-2-2.stderr38
-rw-r--r--src/test/ui/asm/aarch64/type-check-2.rs76
-rw-r--r--src/test/ui/asm/aarch64/type-check-2.stderr75
-rw-r--r--src/test/ui/asm/aarch64/type-check-3.rs97
-rw-r--r--src/test/ui/asm/aarch64/type-check-3.stderr147
-rw-r--r--src/test/ui/asm/aarch64/type-check-4.rs32
-rw-r--r--src/test/ui/asm/aarch64/type-check-4.stderr27
-rw-r--r--src/test/ui/asm/bad-arch.mirunsafeck.stderr16
-rw-r--r--src/test/ui/asm/bad-arch.rs28
-rw-r--r--src/test/ui/asm/bad-arch.thirunsafeck.stderr16
-rw-r--r--src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr197
-rw-r--r--src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr197
-rw-r--r--src/test/ui/asm/bad-template.rs75
-rw-r--r--src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr197
-rw-r--r--src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr197
-rw-r--r--src/test/ui/asm/generic-const.rs30
-rw-r--r--src/test/ui/asm/inline-syntax.arm.stderr88
-rw-r--r--src/test/ui/asm/inline-syntax.rs60
-rw-r--r--src/test/ui/asm/inline-syntax.x86_64.stderr46
-rw-r--r--src/test/ui/asm/issue-72570.rs12
-rw-r--r--src/test/ui/asm/issue-72570.stderr8
-rw-r--r--src/test/ui/asm/issue-85247.rs26
-rw-r--r--src/test/ui/asm/issue-85247.rwpi.stderr8
-rw-r--r--src/test/ui/asm/issue-87802.rs20
-rw-r--r--src/test/ui/asm/issue-87802.stderr10
-rw-r--r--src/test/ui/asm/issue-89305.rs16
-rw-r--r--src/test/ui/asm/issue-89305.stderr15
-rw-r--r--src/test/ui/asm/issue-92378.rs31
-rw-r--r--src/test/ui/asm/issue-97490.rs12
-rw-r--r--src/test/ui/asm/issue-99071.rs21
-rw-r--r--src/test/ui/asm/issue-99071.stderr8
-rw-r--r--src/test/ui/asm/issue-99122-2.rs21
-rw-r--r--src/test/ui/asm/issue-99122.rs13
-rw-r--r--src/test/ui/asm/issue-99122.stderr11
-rw-r--r--src/test/ui/asm/may_unwind.rs11
-rw-r--r--src/test/ui/asm/naked-functions-ffi.rs15
-rw-r--r--src/test/ui/asm/naked-functions-ffi.stderr20
-rw-r--r--src/test/ui/asm/naked-functions-unused.aarch64.stderr69
-rw-r--r--src/test/ui/asm/naked-functions-unused.rs87
-rw-r--r--src/test/ui/asm/naked-functions-unused.x86_64.stderr69
-rw-r--r--src/test/ui/asm/naked-functions.rs218
-rw-r--r--src/test/ui/asm/naked-functions.stderr303
-rw-r--r--src/test/ui/asm/naked-invalid-attr.rs52
-rw-r--r--src/test/ui/asm/naked-invalid-attr.stderr42
-rw-r--r--src/test/ui/asm/named-asm-labels.rs196
-rw-r--r--src/test/ui/asm/named-asm-labels.s5
-rw-r--r--src/test/ui/asm/named-asm-labels.stderr334
-rw-r--r--src/test/ui/asm/noreturn.rs19
-rw-r--r--src/test/ui/asm/reg-conflict.rs20
-rw-r--r--src/test/ui/asm/reg-conflict.stderr10
-rw-r--r--src/test/ui/asm/type-check-1.rs79
-rw-r--r--src/test/ui/asm/type-check-1.stderr144
-rw-r--r--src/test/ui/asm/type-check-4.rs26
-rw-r--r--src/test/ui/asm/type-check-4.stderr26
-rw-r--r--src/test/ui/asm/x86_64/bad-clobber-abi.rs32
-rw-r--r--src/test/ui/asm/x86_64/bad-clobber-abi.stderr88
-rw-r--r--src/test/ui/asm/x86_64/bad-options.rs42
-rw-r--r--src/test/ui/asm/x86_64/bad-options.stderr101
-rw-r--r--src/test/ui/asm/x86_64/bad-reg.rs72
-rw-r--r--src/test/ui/asm/x86_64/bad-reg.stderr218
-rw-r--r--src/test/ui/asm/x86_64/const.rs44
-rw-r--r--src/test/ui/asm/x86_64/duplicate-options.fixed29
-rw-r--r--src/test/ui/asm/x86_64/duplicate-options.rs29
-rw-r--r--src/test/ui/asm/x86_64/duplicate-options.stderr62
-rw-r--r--src/test/ui/asm/x86_64/interpolated-idents.rs24
-rw-r--r--src/test/ui/asm/x86_64/interpolated-idents.stderr51
-rw-r--r--src/test/ui/asm/x86_64/issue-82869.rs25
-rw-r--r--src/test/ui/asm/x86_64/issue-82869.stderr24
-rw-r--r--src/test/ui/asm/x86_64/issue-89875.rs17
-rw-r--r--src/test/ui/asm/x86_64/issue-96797.rs26
-rw-r--r--src/test/ui/asm/x86_64/may_unwind.rs38
-rw-r--r--src/test/ui/asm/x86_64/multiple-clobber-abi.rs35
-rw-r--r--src/test/ui/asm/x86_64/parse-error.rs137
-rw-r--r--src/test/ui/asm/x86_64/parse-error.stderr458
-rw-r--r--src/test/ui/asm/x86_64/srcloc.rs131
-rw-r--r--src/test/ui/asm/x86_64/srcloc.stderr302
-rw-r--r--src/test/ui/asm/x86_64/sym.rs85
-rw-r--r--src/test/ui/asm/x86_64/target-feature-attr.rs42
-rw-r--r--src/test/ui/asm/x86_64/target-feature-attr.stderr26
-rw-r--r--src/test/ui/asm/x86_64/type-check-2.rs87
-rw-r--r--src/test/ui/asm/x86_64/type-check-2.stderr83
-rw-r--r--src/test/ui/asm/x86_64/type-check-3.rs73
-rw-r--r--src/test/ui/asm/x86_64/type-check-3.stderr118
-rw-r--r--src/test/ui/asm/x86_64/type-check-4.rs29
-rw-r--r--src/test/ui/asm/x86_64/type-check-4.stderr27
-rw-r--r--src/test/ui/asm/x86_64/type-check-5.rs63
-rw-r--r--src/test/ui/asm/x86_64/type-check-5.stderr38
104 files changed, 8004 insertions, 0 deletions
diff --git a/src/test/ui/asm/aarch64/bad-options.rs b/src/test/ui/asm/aarch64/bad-options.rs
new file mode 100644
index 000000000..6172027a2
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/bad-options.stderr b/src/test/ui/asm/aarch64/bad-options.stderr
new file mode 100644
index 000000000..21bcc4a9c
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/bad-reg.rs b/src/test/ui/asm/aarch64/bad-reg.rs
new file mode 100644
index 000000000..2b6a9b71c
--- /dev/null
+++ b/src/test/ui/asm/aarch64/bad-reg.rs
@@ -0,0 +1,61 @@
+// only-aarch64
+// compile-flags: -C target-feature=+neon
+
+#![feature(asm_const, asm_sym)]
+
+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/src/test/ui/asm/aarch64/bad-reg.stderr b/src/test/ui/asm/aarch64/bad-reg.stderr
new file mode 100644
index 000000000..0ba627dac
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/const.rs b/src/test/ui/asm/aarch64/const.rs
new file mode 100644
index 000000000..de299bfdb
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/duplicate-options.fixed b/src/test/ui/asm/aarch64/duplicate-options.fixed
new file mode 100644
index 000000000..fa1dd4aef
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/duplicate-options.rs b/src/test/ui/asm/aarch64/duplicate-options.rs
new file mode 100644
index 000000000..b2d3fe7d9
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/duplicate-options.stderr b/src/test/ui/asm/aarch64/duplicate-options.stderr
new file mode 100644
index 000000000..feb3838f4
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/interpolated-idents.rs b/src/test/ui/asm/aarch64/interpolated-idents.rs
new file mode 100644
index 000000000..e87a88434
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/interpolated-idents.stderr b/src/test/ui/asm/aarch64/interpolated-idents.stderr
new file mode 100644
index 000000000..2df17f2e0
--- /dev/null
+++ b/src/test/ui/asm/aarch64/interpolated-idents.stderr
@@ -0,0 +1,51 @@
+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/src/test/ui/asm/aarch64/may_unwind.rs b/src/test/ui/asm/aarch64/may_unwind.rs
new file mode 100644
index 000000000..ac8cc6202
--- /dev/null
+++ b/src/test/ui/asm/aarch64/may_unwind.rs
@@ -0,0 +1,38 @@
+// min-llvm-version: 13.0.0
+// only-aarch64
+// run-pass
+// needs-asm-support
+
+#![feature(asm_sym, 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/src/test/ui/asm/aarch64/parse-error.rs b/src/test/ui/asm/aarch64/parse-error.rs
new file mode 100644
index 000000000..cbc93cd3f
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/parse-error.stderr b/src/test/ui/asm/aarch64/parse-error.stderr
new file mode 100644
index 000000000..804966b06
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/srcloc.rs b/src/test/ui/asm/aarch64/srcloc.rs
new file mode 100644
index 000000000..dbb6cbb94
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/srcloc.stderr b/src/test/ui/asm/aarch64/srcloc.stderr
new file mode 100644
index 000000000..2e17b60b9
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/sym.rs b/src/test/ui/asm/aarch64/sym.rs
new file mode 100644
index 000000000..3f659363c
--- /dev/null
+++ b/src/test/ui/asm/aarch64/sym.rs
@@ -0,0 +1,84 @@
+// only-aarch64
+// only-linux
+// needs-asm-support
+// run-pass
+
+#![feature(thread_local, asm_sym)]
+
+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/src/test/ui/asm/aarch64/type-check-2-2.rs b/src/test/ui/asm/aarch64/type-check-2-2.rs
new file mode 100644
index 000000000..aa12d4aa4
--- /dev/null
+++ b/src/test/ui/asm/aarch64/type-check-2-2.rs
@@ -0,0 +1,37 @@
+// only-aarch64
+
+#![feature(repr_simd, never_type, asm_sym)]
+
+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];
+ asm!("{}", in(reg) v[0]);
+ asm!("{}", out(reg) v[0]);
+ //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+ asm!("{}", inout(reg) v[0]);
+ //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+
+ // Sym operands must point to a function or static
+ }
+}
diff --git a/src/test/ui/asm/aarch64/type-check-2-2.stderr b/src/test/ui/asm/aarch64/type-check-2-2.stderr
new file mode 100644
index 000000000..b2a695529
--- /dev/null
+++ b/src/test/ui/asm/aarch64/type-check-2-2.stderr
@@ -0,0 +1,38 @@
+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
+
+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
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+ --> $DIR/type-check-2-2.rs:30:29
+ |
+LL | let v: Vec<u64> = vec![0, 1, 2];
+ | - help: consider changing this to be mutable: `mut v`
+LL | asm!("{}", in(reg) v[0]);
+LL | asm!("{}", out(reg) v[0]);
+ | ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+ --> $DIR/type-check-2-2.rs:32:31
+ |
+LL | let v: Vec<u64> = vec![0, 1, 2];
+ | - help: consider changing this to be mutable: `mut v`
+...
+LL | asm!("{}", inout(reg) v[0]);
+ | ^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0381, E0596.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/asm/aarch64/type-check-2.rs b/src/test/ui/asm/aarch64/type-check-2.rs
new file mode 100644
index 000000000..fdafe63c7
--- /dev/null
+++ b/src/test/ui/asm/aarch64/type-check-2.rs
@@ -0,0 +1,76 @@
+// only-aarch64
+
+#![feature(repr_simd, never_type, asm_sym)]
+
+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/src/test/ui/asm/aarch64/type-check-2.stderr b/src/test/ui/asm/aarch64/type-check-2.stderr
new file mode 100644
index 000000000..875df44ff
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/type-check-3.rs b/src/test/ui/asm/aarch64/type-check-3.rs
new file mode 100644
index 000000000..623f6593d
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/type-check-3.stderr b/src/test/ui/asm/aarch64/type-check-3.stderr
new file mode 100644
index 000000000..b320abdc0
--- /dev/null
+++ b/src/test/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
+ |
+ = note: `#[warn(asm_sub_register)]` on by default
+ = help: use the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier to keep the default formatting of `x0`
+
+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 the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier 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 the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier 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 the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier 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 the `h` modifier to have the register formatted as `h0`
+ = help: or use the `v` modifier 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 the `s` modifier to have the register formatted as `s0`
+ = help: or use the `v` modifier 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 the `d` modifier to have the register formatted as `d0`
+ = help: or use the `v` modifier 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 the `d` modifier to have the register formatted as `d0`
+ = help: or use the `v` modifier 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 the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier 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 the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier 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/src/test/ui/asm/aarch64/type-check-4.rs b/src/test/ui/asm/aarch64/type-check-4.rs
new file mode 100644
index 000000000..bd23755c0
--- /dev/null
+++ b/src/test/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/src/test/ui/asm/aarch64/type-check-4.stderr b/src/test/ui/asm/aarch64/type-check-4.stderr
new file mode 100644
index 000000000..4837e647b
--- /dev/null
+++ b/src/test/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`.
diff --git a/src/test/ui/asm/bad-arch.mirunsafeck.stderr b/src/test/ui/asm/bad-arch.mirunsafeck.stderr
new file mode 100644
index 000000000..4aa271807
--- /dev/null
+++ b/src/test/ui/asm/bad-arch.mirunsafeck.stderr
@@ -0,0 +1,16 @@
+error[E0472]: inline assembly is unsupported on this target
+ --> $DIR/bad-arch.rs:22:9
+ |
+LL | asm!("");
+ | ^^^^^^^^
+
+error[E0472]: inline assembly is unsupported on this target
+ --> $DIR/bad-arch.rs:27:1
+ |
+LL | global_asm!("");
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/asm/bad-arch.rs b/src/test/ui/asm/bad-arch.rs
new file mode 100644
index 000000000..93309899b
--- /dev/null
+++ b/src/test/ui/asm/bad-arch.rs
@@ -0,0 +1,28 @@
+// compile-flags: --target sparc-unknown-linux-gnu
+// needs-llvm-components: sparc
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! global_asm {
+ () => {};
+}
+#[lang = "sized"]
+trait Sized {}
+
+fn main() {
+ unsafe {
+ asm!("");
+ //~^ ERROR inline assembly is unsupported on this target
+ }
+}
+
+global_asm!("");
+//~^ ERROR inline assembly is unsupported on this target
diff --git a/src/test/ui/asm/bad-arch.thirunsafeck.stderr b/src/test/ui/asm/bad-arch.thirunsafeck.stderr
new file mode 100644
index 000000000..4aa271807
--- /dev/null
+++ b/src/test/ui/asm/bad-arch.thirunsafeck.stderr
@@ -0,0 +1,16 @@
+error[E0472]: inline assembly is unsupported on this target
+ --> $DIR/bad-arch.rs:22:9
+ |
+LL | asm!("");
+ | ^^^^^^^^
+
+error[E0472]: inline assembly is unsupported on this target
+ --> $DIR/bad-arch.rs:27:1
+ |
+LL | global_asm!("");
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `global_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
new file mode 100644
index 000000000..7ef93e15f
--- /dev/null
+++ b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
@@ -0,0 +1,197 @@
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:31:15
+ |
+LL | asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:33:15
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:33:21
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:36:16
+ |
+LL | asm!("{a}");
+ | ^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:38:15
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^ --------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:41:15
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:41:21
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:48:15
+ |
+LL | asm!("{}", in("x0") foo);
+ | ^^ ------------ explicit register argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: explicit register arguments cannot be used in the asm template
+ --> $DIR/bad-template.rs:48:20
+ |
+LL | asm!("{}", in("x0") foo);
+ | ^^^^^^^^^^^^
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:50:17
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:53:18
+ |
+LL | asm!("", in(reg) 0, in(reg) 1);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:59:14
+ |
+LL | global_asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:61:14
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:61:20
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:64:15
+ |
+LL | global_asm!("{a}");
+ | ^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:66:14
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^ ------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:66:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:66:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:69:14
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:69:20
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:72:16
+ |
+LL | global_asm!("{:foo}", const FOO);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:74:17
+ |
+LL | global_asm!("", const FOO, const FOO);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/bad-template.rs:50:15
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^^^^ --- for this argument
+ |
+ = note: `#[warn(asm_sub_register)]` on by default
+ = help: use the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier to keep the default formatting of `x0`
+
+error: aborting due to 21 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
new file mode 100644
index 000000000..7ef93e15f
--- /dev/null
+++ b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
@@ -0,0 +1,197 @@
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:31:15
+ |
+LL | asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:33:15
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:33:21
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:36:16
+ |
+LL | asm!("{a}");
+ | ^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:38:15
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^ --------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:41:15
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:41:21
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:48:15
+ |
+LL | asm!("{}", in("x0") foo);
+ | ^^ ------------ explicit register argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: explicit register arguments cannot be used in the asm template
+ --> $DIR/bad-template.rs:48:20
+ |
+LL | asm!("{}", in("x0") foo);
+ | ^^^^^^^^^^^^
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:50:17
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:53:18
+ |
+LL | asm!("", in(reg) 0, in(reg) 1);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:59:14
+ |
+LL | global_asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:61:14
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:61:20
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:64:15
+ |
+LL | global_asm!("{a}");
+ | ^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:66:14
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^ ------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:66:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:66:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:69:14
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:69:20
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:72:16
+ |
+LL | global_asm!("{:foo}", const FOO);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:74:17
+ |
+LL | global_asm!("", const FOO, const FOO);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/bad-template.rs:50:15
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^^^^ --- for this argument
+ |
+ = note: `#[warn(asm_sub_register)]` on by default
+ = help: use the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier to keep the default formatting of `x0`
+
+error: aborting due to 21 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/asm/bad-template.rs b/src/test/ui/asm/bad-template.rs
new file mode 100644
index 000000000..556371747
--- /dev/null
+++ b/src/test/ui/asm/bad-template.rs
@@ -0,0 +1,75 @@
+// revisions: x86_64_mirunsafeck aarch64_mirunsafeck x86_64_thirunsafeck aarch64_thirunsafeck
+
+// [x86_64_thirunsafeck] compile-flags: -Z thir-unsafeck --target x86_64-unknown-linux-gnu
+// [aarch64_thirunsafeck] compile-flags: -Z thir-unsafeck --target aarch64-unknown-linux-gnu
+// [x86_64_mirunsafeck] compile-flags: --target x86_64-unknown-linux-gnu
+// [aarch64_mirunsafeck] compile-flags: --target aarch64-unknown-linux-gnu
+
+// [x86_64_thirunsafeck] needs-llvm-components: x86
+// [x86_64_mirunsafeck] needs-llvm-components: x86
+// [aarch64_thirunsafeck] needs-llvm-components: aarch64
+// [aarch64_mirunsafeck] needs-llvm-components: aarch64
+
+#![feature(no_core, lang_items, rustc_attrs, asm_const)]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! global_asm {
+ () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+fn main() {
+ let mut foo = 0;
+ unsafe {
+ asm!("{}");
+ //~^ ERROR invalid reference to argument at index 0
+ asm!("{1}", in(reg) foo);
+ //~^ ERROR invalid reference to argument at index 1
+ //~^^ ERROR argument never used
+ asm!("{a}");
+ //~^ ERROR there is no argument named `a`
+ asm!("{}", a = in(reg) foo);
+ //~^ ERROR invalid reference to argument at index 0
+ //~^^ ERROR argument never used
+ asm!("{1}", a = in(reg) foo);
+ //~^ ERROR invalid reference to argument at index 1
+ //~^^ ERROR named argument never used
+ #[cfg(any(x86_64_thirunsafeck, x86_64_mirunsafeck))]
+ asm!("{}", in("eax") foo);
+ //[x86_64_thirunsafeck,x86_64_mirunsafeck]~^ ERROR invalid reference to argument at index 0
+ #[cfg(any(aarch64_thirunsafeck, aarch64_mirunsafeck))]
+ asm!("{}", in("x0") foo);
+ //[aarch64_thirunsafeck,aarch64_mirunsafeck]~^ ERROR invalid reference to argument at index 0
+ asm!("{:foo}", in(reg) foo);
+ //~^ ERROR asm template modifier must be a single character
+ //~| WARN formatting may not be suitable for sub-register argument [asm_sub_register]
+ asm!("", in(reg) 0, in(reg) 1);
+ //~^ ERROR multiple unused asm arguments
+ }
+}
+
+const FOO: i32 = 1;
+global_asm!("{}");
+//~^ ERROR invalid reference to argument at index 0
+global_asm!("{1}", const FOO);
+//~^ ERROR invalid reference to argument at index 1
+//~^^ ERROR argument never used
+global_asm!("{a}");
+//~^ ERROR there is no argument named `a`
+global_asm!("{}", a = const FOO);
+//~^ ERROR invalid reference to argument at index 0
+//~^^ ERROR argument never used
+global_asm!("{1}", a = const FOO);
+//~^ ERROR invalid reference to argument at index 1
+//~^^ ERROR named argument never used
+global_asm!("{:foo}", const FOO);
+//~^ ERROR asm template modifier must be a single character
+global_asm!("", const FOO, const FOO);
+//~^ ERROR multiple unused asm arguments
diff --git a/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
new file mode 100644
index 000000000..250bc3be4
--- /dev/null
+++ b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
@@ -0,0 +1,197 @@
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:31:15
+ |
+LL | asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:33:15
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:33:21
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:36:16
+ |
+LL | asm!("{a}");
+ | ^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:38:15
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^ --------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:41:15
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:41:21
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:45:15
+ |
+LL | asm!("{}", in("eax") foo);
+ | ^^ ------------- explicit register argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: explicit register arguments cannot be used in the asm template
+ --> $DIR/bad-template.rs:45:20
+ |
+LL | asm!("{}", in("eax") foo);
+ | ^^^^^^^^^^^^^
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:50:17
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:53:18
+ |
+LL | asm!("", in(reg) 0, in(reg) 1);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:59:14
+ |
+LL | global_asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:61:14
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:61:20
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:64:15
+ |
+LL | global_asm!("{a}");
+ | ^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:66:14
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^ ------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:66:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:66:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:69:14
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:69:20
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:72:16
+ |
+LL | global_asm!("{:foo}", const FOO);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:74:17
+ |
+LL | global_asm!("", const FOO, const FOO);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/bad-template.rs:50:15
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^^^^ --- for this argument
+ |
+ = note: `#[warn(asm_sub_register)]` on by default
+ = help: use the `e` modifier to have the register formatted as `eax`
+ = help: or use the `r` modifier to keep the default formatting of `rax`
+
+error: aborting due to 21 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
new file mode 100644
index 000000000..250bc3be4
--- /dev/null
+++ b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
@@ -0,0 +1,197 @@
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:31:15
+ |
+LL | asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:33:15
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:33:21
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:36:16
+ |
+LL | asm!("{a}");
+ | ^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:38:15
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^ --------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:41:15
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:41:21
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:45:15
+ |
+LL | asm!("{}", in("eax") foo);
+ | ^^ ------------- explicit register argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: explicit register arguments cannot be used in the asm template
+ --> $DIR/bad-template.rs:45:20
+ |
+LL | asm!("{}", in("eax") foo);
+ | ^^^^^^^^^^^^^
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:50:17
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:53:18
+ |
+LL | asm!("", in(reg) 0, in(reg) 1);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:59:14
+ |
+LL | global_asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:61:14
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:61:20
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:64:15
+ |
+LL | global_asm!("{a}");
+ | ^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:66:14
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^ ------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:66:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:66:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:69:14
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:69:20
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:72:16
+ |
+LL | global_asm!("{:foo}", const FOO);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:74:17
+ |
+LL | global_asm!("", const FOO, const FOO);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/bad-template.rs:50:15
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^^^^ --- for this argument
+ |
+ = note: `#[warn(asm_sub_register)]` on by default
+ = help: use the `e` modifier to have the register formatted as `eax`
+ = help: or use the `r` modifier to keep the default formatting of `rax`
+
+error: aborting due to 21 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/asm/generic-const.rs b/src/test/ui/asm/generic-const.rs
new file mode 100644
index 000000000..55c558780
--- /dev/null
+++ b/src/test/ui/asm/generic-const.rs
@@ -0,0 +1,30 @@
+// needs-asm-support
+// build-pass
+
+#![feature(asm_const, asm_sym)]
+
+use std::arch::asm;
+
+fn foofoo<const N: usize>() {}
+
+unsafe fn foo<const N: usize>() {
+ asm!("/* {0} */", const N);
+ asm!("/* {0} */", const N + 1);
+ asm!("/* {0} */", sym foofoo::<N>);
+}
+
+fn barbar<T>() {}
+
+unsafe fn bar<T>() {
+ asm!("/* {0} */", const std::mem::size_of::<T>());
+ asm!("/* {0} */", const std::mem::size_of::<(T, T)>());
+ asm!("/* {0} */", sym barbar::<T>);
+ asm!("/* {0} */", sym barbar::<(T, T)>);
+}
+
+fn main() {
+ unsafe {
+ foo::<0>();
+ bar::<usize>();
+ }
+}
diff --git a/src/test/ui/asm/inline-syntax.arm.stderr b/src/test/ui/asm/inline-syntax.arm.stderr
new file mode 100644
index 000000000..1352fb377
--- /dev/null
+++ b/src/test/ui/asm/inline-syntax.arm.stderr
@@ -0,0 +1,88 @@
+error: unknown directive
+.intel_syntax noprefix
+^
+error: unknown directive
+.intel_syntax noprefix
+^
+error: unknown directive
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:1
+ |
+LL | .intel_syntax noprefix
+ | ^
+
+error: unknown directive
+ --> $DIR/inline-syntax.rs:32:15
+ |
+LL | asm!(".intel_syntax noprefix", "nop");
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | .intel_syntax noprefix
+ | ^
+
+error: unknown directive
+ --> $DIR/inline-syntax.rs:35:15
+ |
+LL | asm!(".intel_syntax aaa noprefix", "nop");
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | .intel_syntax aaa noprefix
+ | ^
+
+error: unknown directive
+ --> $DIR/inline-syntax.rs:38:15
+ |
+LL | asm!(".att_syntax noprefix", "nop");
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | .att_syntax noprefix
+ | ^
+
+error: unknown directive
+ --> $DIR/inline-syntax.rs:41:15
+ |
+LL | asm!(".att_syntax bbb noprefix", "nop");
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | .att_syntax bbb noprefix
+ | ^
+
+error: unknown directive
+ --> $DIR/inline-syntax.rs:44:15
+ |
+LL | asm!(".intel_syntax noprefix; nop");
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | .intel_syntax noprefix; nop
+ | ^
+
+error: unknown directive
+ --> $DIR/inline-syntax.rs:50:13
+ |
+LL | .intel_syntax noprefix
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:13
+ |
+LL | .intel_syntax noprefix
+ | ^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/asm/inline-syntax.rs b/src/test/ui/asm/inline-syntax.rs
new file mode 100644
index 000000000..d06796e33
--- /dev/null
+++ b/src/test/ui/asm/inline-syntax.rs
@@ -0,0 +1,60 @@
+// revisions: x86_64 arm
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64] check-pass
+//[x86_64] needs-llvm-components: x86
+//[x86_64_allowed] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64_allowed] check-pass
+//[x86_64_allowed] needs-llvm-components: x86
+//[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
+//[arm] build-fail
+//[arm] needs-llvm-components: arm
+// needs-asm-support
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
+#![no_core]
+#![cfg_attr(x86_64_allowed, allow(bad_asm_style))]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! global_asm {
+ () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+pub fn main() {
+ unsafe {
+ asm!(".intel_syntax noprefix", "nop");
+ //[x86_64]~^ WARN avoid using `.intel_syntax`
+ //[arm]~^^ ERROR unknown directive
+ asm!(".intel_syntax aaa noprefix", "nop");
+ //[x86_64]~^ WARN avoid using `.intel_syntax`
+ //[arm]~^^ ERROR unknown directive
+ asm!(".att_syntax noprefix", "nop");
+ //[x86_64]~^ WARN avoid using `.att_syntax`
+ //[arm]~^^ ERROR unknown directive
+ asm!(".att_syntax bbb noprefix", "nop");
+ //[x86_64]~^ WARN avoid using `.att_syntax`
+ //[arm]~^^ ERROR unknown directive
+ asm!(".intel_syntax noprefix; nop");
+ //[x86_64]~^ WARN avoid using `.intel_syntax`
+ //[arm]~^^ ERROR unknown directive
+
+ asm!(
+ r"
+ .intel_syntax noprefix
+ nop"
+ );
+ //[x86_64]~^^^ WARN avoid using `.intel_syntax`
+ //[arm]~^^^^ ERROR unknown directive
+ }
+}
+
+global_asm!(".intel_syntax noprefix", "nop");
+//[x86_64]~^ WARN avoid using `.intel_syntax`
+// Assembler errors don't have line numbers, so no error on ARM
diff --git a/src/test/ui/asm/inline-syntax.x86_64.stderr b/src/test/ui/asm/inline-syntax.x86_64.stderr
new file mode 100644
index 000000000..840b250f8
--- /dev/null
+++ b/src/test/ui/asm/inline-syntax.x86_64.stderr
@@ -0,0 +1,46 @@
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+ --> $DIR/inline-syntax.rs:58:14
+ |
+LL | global_asm!(".intel_syntax noprefix", "nop");
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(bad_asm_style)]` on by default
+
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+ --> $DIR/inline-syntax.rs:32:15
+ |
+LL | asm!(".intel_syntax noprefix", "nop");
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+ --> $DIR/inline-syntax.rs:35:15
+ |
+LL | asm!(".intel_syntax aaa noprefix", "nop");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
+ --> $DIR/inline-syntax.rs:38:15
+ |
+LL | asm!(".att_syntax noprefix", "nop");
+ | ^^^^^^^^^^^^^^^^^^^^
+
+warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
+ --> $DIR/inline-syntax.rs:41:15
+ |
+LL | asm!(".att_syntax bbb noprefix", "nop");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+ --> $DIR/inline-syntax.rs:44:15
+ |
+LL | asm!(".intel_syntax noprefix; nop");
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+ --> $DIR/inline-syntax.rs:50:13
+ |
+LL | .intel_syntax noprefix
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 7 warnings emitted
+
diff --git a/src/test/ui/asm/issue-72570.rs b/src/test/ui/asm/issue-72570.rs
new file mode 100644
index 000000000..bb1381634
--- /dev/null
+++ b/src/test/ui/asm/issue-72570.rs
@@ -0,0 +1,12 @@
+// compile-flags: -Zsave-analysis
+// needs-asm-support
+// Also test for #72960
+
+use std::arch::asm;
+
+fn main() {
+ unsafe {
+ asm!("", in("invalid") "".len());
+ //~^ ERROR: invalid register `invalid`: unknown register
+ }
+}
diff --git a/src/test/ui/asm/issue-72570.stderr b/src/test/ui/asm/issue-72570.stderr
new file mode 100644
index 000000000..fa5792688
--- /dev/null
+++ b/src/test/ui/asm/issue-72570.stderr
@@ -0,0 +1,8 @@
+error: invalid register `invalid`: unknown register
+ --> $DIR/issue-72570.rs:9:18
+ |
+LL | asm!("", in("invalid") "".len());
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/asm/issue-85247.rs b/src/test/ui/asm/issue-85247.rs
new file mode 100644
index 000000000..e64f5e8af
--- /dev/null
+++ b/src/test/ui/asm/issue-85247.rs
@@ -0,0 +1,26 @@
+// revisions: ropi rwpi
+
+// [ropi] compile-flags: --target armv7-unknown-linux-gnueabihf -C relocation-model=ropi
+// [rwpi] compile-flags: --target armv7-unknown-linux-gnueabihf -C relocation-model=rwpi
+// [ropi] needs-llvm-components: arm
+// [rwpi] needs-llvm-components: arm
+// [ropi] build-pass
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+#![crate_type = "rlib"]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+#[lang = "sized"]
+trait Sized {}
+
+// R9 is reserved as the RWPI base register
+fn main() {
+ unsafe {
+ asm!("", out("r9") _);
+ //[rwpi]~^ cannot use register `r9`
+ }
+}
diff --git a/src/test/ui/asm/issue-85247.rwpi.stderr b/src/test/ui/asm/issue-85247.rwpi.stderr
new file mode 100644
index 000000000..996b0933a
--- /dev/null
+++ b/src/test/ui/asm/issue-85247.rwpi.stderr
@@ -0,0 +1,8 @@
+error: cannot use register `r9`: the RWPI static base register (r9) cannot be used as an operand for inline asm
+ --> $DIR/issue-85247.rs:23:18
+ |
+LL | asm!("", out("r9") _);
+ | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/asm/issue-87802.rs b/src/test/ui/asm/issue-87802.rs
new file mode 100644
index 000000000..5b2e636c2
--- /dev/null
+++ b/src/test/ui/asm/issue-87802.rs
@@ -0,0 +1,20 @@
+// needs-asm-support
+// ignore-nvptx64
+// ignore-spirv
+// ignore-wasm32
+// Make sure rustc doesn't ICE on asm! when output type is !.
+
+use std::arch::asm;
+
+fn hmm() -> ! {
+ let x;
+ unsafe {
+ asm!("/* {0} */", out(reg) x);
+ //~^ ERROR cannot use value of type `!` for inline assembly
+ }
+ x
+}
+
+fn main() {
+ hmm();
+}
diff --git a/src/test/ui/asm/issue-87802.stderr b/src/test/ui/asm/issue-87802.stderr
new file mode 100644
index 000000000..de3e28fdd
--- /dev/null
+++ b/src/test/ui/asm/issue-87802.stderr
@@ -0,0 +1,10 @@
+error: cannot use value of type `!` for inline assembly
+ --> $DIR/issue-87802.rs:12:36
+ |
+LL | asm!("/* {0} */", out(reg) x);
+ | ^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/asm/issue-89305.rs b/src/test/ui/asm/issue-89305.rs
new file mode 100644
index 000000000..05677912d
--- /dev/null
+++ b/src/test/ui/asm/issue-89305.rs
@@ -0,0 +1,16 @@
+// Regression test for #89305, where a variable was erroneously reported
+// as both unused and possibly-uninitialized.
+
+// check-pass
+// needs-asm-support
+
+#![warn(unused)]
+
+use std::arch::asm;
+
+fn main() {
+ unsafe {
+ let x: () = asm!("nop");
+ //~^ WARNING: unused variable: `x`
+ }
+}
diff --git a/src/test/ui/asm/issue-89305.stderr b/src/test/ui/asm/issue-89305.stderr
new file mode 100644
index 000000000..7efc51020
--- /dev/null
+++ b/src/test/ui/asm/issue-89305.stderr
@@ -0,0 +1,15 @@
+warning: unused variable: `x`
+ --> $DIR/issue-89305.rs:13:13
+ |
+LL | let x: () = asm!("nop");
+ | ^ help: if this is intentional, prefix it with an underscore: `_x`
+ |
+note: the lint level is defined here
+ --> $DIR/issue-89305.rs:7:9
+ |
+LL | #![warn(unused)]
+ | ^^^^^^
+ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/asm/issue-92378.rs b/src/test/ui/asm/issue-92378.rs
new file mode 100644
index 000000000..6e3c26e98
--- /dev/null
+++ b/src/test/ui/asm/issue-92378.rs
@@ -0,0 +1,31 @@
+// compile-flags: --target armv5te-unknown-linux-gnueabi
+// needs-llvm-components: arm
+// needs-asm-support
+// build-pass
+
+#![feature(no_core, lang_items, rustc_attrs, isa_attribute)]
+#![no_core]
+#![crate_type = "rlib"]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+#[lang = "sized"]
+trait Sized {}
+
+// ARM uses R11 for the frame pointer, make sure R7 is usable.
+#[instruction_set(arm::a32)]
+pub fn arm() {
+ unsafe {
+ asm!("", out("r7") _);
+ }
+}
+
+// Thumb uses R7 for the frame pointer, make sure R11 is usable.
+#[instruction_set(arm::t32)]
+pub fn thumb() {
+ unsafe {
+ asm!("", out("r11") _);
+ }
+}
diff --git a/src/test/ui/asm/issue-97490.rs b/src/test/ui/asm/issue-97490.rs
new file mode 100644
index 000000000..37862cf34
--- /dev/null
+++ b/src/test/ui/asm/issue-97490.rs
@@ -0,0 +1,12 @@
+// check-pass
+// only-x86_64
+// needs-asm-support
+
+pub type Yes = extern "sysv64" fn(&'static u8) -> !;
+
+fn main() {
+ unsafe {
+ let yes = &6 as *const _ as *const Yes;
+ core::arch::asm!("call {}", in(reg) yes, options(noreturn));
+ }
+}
diff --git a/src/test/ui/asm/issue-99071.rs b/src/test/ui/asm/issue-99071.rs
new file mode 100644
index 000000000..bb6201861
--- /dev/null
+++ b/src/test/ui/asm/issue-99071.rs
@@ -0,0 +1,21 @@
+// compile-flags: --target thumbv6m-none-eabi
+// needs-llvm-components: arm
+// needs-asm-support
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+#![crate_type = "rlib"]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+#[lang = "sized"]
+trait Sized {}
+
+pub fn foo() {
+ unsafe {
+ asm!("", in("r8") 0);
+ //~^ cannot use register `r8`: high registers (r8+) can only be used as clobbers in Thumb-1 code
+ }
+}
diff --git a/src/test/ui/asm/issue-99071.stderr b/src/test/ui/asm/issue-99071.stderr
new file mode 100644
index 000000000..47386ffa4
--- /dev/null
+++ b/src/test/ui/asm/issue-99071.stderr
@@ -0,0 +1,8 @@
+error: cannot use register `r8`: high registers (r8+) can only be used as clobbers in Thumb-1 code
+ --> $DIR/issue-99071.rs:18:18
+ |
+LL | asm!("", in("r8") 0);
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/asm/issue-99122-2.rs b/src/test/ui/asm/issue-99122-2.rs
new file mode 100644
index 000000000..cfb9fd90a
--- /dev/null
+++ b/src/test/ui/asm/issue-99122-2.rs
@@ -0,0 +1,21 @@
+// check-pass
+// needs-asm-support
+// only-x86_64
+
+// This demonstrates why we need to erase regions before sized check in intrinsicck
+
+struct NoCopy;
+
+struct Wrap<'a, T, Tail: ?Sized>(&'a T, Tail);
+
+pub unsafe fn test() {
+ let i = NoCopy;
+ let j = Wrap(&i, ());
+ let pointer = &j as *const _;
+ core::arch::asm!(
+ "nop",
+ in("eax") pointer,
+ );
+}
+
+fn main() {}
diff --git a/src/test/ui/asm/issue-99122.rs b/src/test/ui/asm/issue-99122.rs
new file mode 100644
index 000000000..744a563d3
--- /dev/null
+++ b/src/test/ui/asm/issue-99122.rs
@@ -0,0 +1,13 @@
+// needs-asm-support
+// only-x86_64
+
+pub unsafe fn test() {
+ let pointer = 1u32 as *const _;
+ //~^ ERROR cannot cast to a pointer of an unknown kind
+ core::arch::asm!(
+ "nop",
+ in("eax") pointer,
+ );
+}
+
+fn main() {}
diff --git a/src/test/ui/asm/issue-99122.stderr b/src/test/ui/asm/issue-99122.stderr
new file mode 100644
index 000000000..2758a4ac4
--- /dev/null
+++ b/src/test/ui/asm/issue-99122.stderr
@@ -0,0 +1,11 @@
+error[E0641]: cannot cast to a pointer of an unknown kind
+ --> $DIR/issue-99122.rs:5:27
+ |
+LL | let pointer = 1u32 as *const _;
+ | ^^^^^^^^ needs more type information
+ |
+ = note: the type information given here is insufficient to check whether the pointer cast is valid
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0641`.
diff --git a/src/test/ui/asm/may_unwind.rs b/src/test/ui/asm/may_unwind.rs
new file mode 100644
index 000000000..117c0a63a
--- /dev/null
+++ b/src/test/ui/asm/may_unwind.rs
@@ -0,0 +1,11 @@
+// min-llvm-version: 13.0.0
+// run-pass
+// needs-asm-support
+
+#![feature(asm_unwind)]
+
+use std::arch::asm;
+
+fn main() {
+ unsafe { asm!("", options(may_unwind)) };
+}
diff --git a/src/test/ui/asm/naked-functions-ffi.rs b/src/test/ui/asm/naked-functions-ffi.rs
new file mode 100644
index 000000000..c8bee504d
--- /dev/null
+++ b/src/test/ui/asm/naked-functions-ffi.rs
@@ -0,0 +1,15 @@
+// check-pass
+// needs-asm-support
+#![feature(naked_functions)]
+#![crate_type = "lib"]
+
+use std::arch::asm;
+
+#[naked]
+pub extern "C" fn naked(p: char) -> u128 {
+ //~^ WARN uses type `char`
+ //~| WARN uses type `u128`
+ unsafe {
+ asm!("", options(noreturn));
+ }
+}
diff --git a/src/test/ui/asm/naked-functions-ffi.stderr b/src/test/ui/asm/naked-functions-ffi.stderr
new file mode 100644
index 000000000..ac7435513
--- /dev/null
+++ b/src/test/ui/asm/naked-functions-ffi.stderr
@@ -0,0 +1,20 @@
+warning: `extern` fn uses type `char`, which is not FFI-safe
+ --> $DIR/naked-functions-ffi.rs:9:28
+ |
+LL | pub extern "C" fn naked(p: char) -> u128 {
+ | ^^^^ not FFI-safe
+ |
+ = note: `#[warn(improper_ctypes_definitions)]` on by default
+ = help: consider using `u32` or `libc::wchar_t` instead
+ = note: the `char` type has no C equivalent
+
+warning: `extern` fn uses type `u128`, which is not FFI-safe
+ --> $DIR/naked-functions-ffi.rs:9:37
+ |
+LL | pub extern "C" fn naked(p: char) -> u128 {
+ | ^^^^ not FFI-safe
+ |
+ = note: 128-bit integers don't currently have a known stable ABI
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/asm/naked-functions-unused.aarch64.stderr b/src/test/ui/asm/naked-functions-unused.aarch64.stderr
new file mode 100644
index 000000000..8d3c300e0
--- /dev/null
+++ b/src/test/ui/asm/naked-functions-unused.aarch64.stderr
@@ -0,0 +1,69 @@
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:17:32
+ |
+LL | pub extern "C" fn function(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+ |
+note: the lint level is defined here
+ --> $DIR/naked-functions-unused.rs:5:9
+ |
+LL | #![deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:17:42
+ |
+LL | pub extern "C" fn function(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:26:38
+ |
+LL | pub extern "C" fn associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:26:48
+ |
+LL | pub extern "C" fn associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:32:41
+ |
+LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:32:51
+ |
+LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:40:40
+ |
+LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:40:50
+ |
+LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:46:43
+ |
+LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:46:53
+ |
+LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/asm/naked-functions-unused.rs b/src/test/ui/asm/naked-functions-unused.rs
new file mode 100644
index 000000000..044a0e5b9
--- /dev/null
+++ b/src/test/ui/asm/naked-functions-unused.rs
@@ -0,0 +1,87 @@
+// revisions: x86_64 aarch64
+// needs-asm-support
+//[x86_64] only-x86_64
+//[aarch64] only-aarch64
+#![deny(unused)]
+#![feature(naked_functions)]
+#![crate_type = "lib"]
+
+pub trait Trait {
+ extern "C" fn trait_associated(a: usize, b: usize) -> usize;
+ extern "C" fn trait_method(&self, a: usize, b: usize) -> usize;
+}
+
+pub mod normal {
+ use std::arch::asm;
+
+ pub extern "C" fn function(a: usize, b: usize) -> usize {
+ //~^ ERROR unused variable: `a`
+ //~| ERROR unused variable: `b`
+ unsafe { asm!("", options(noreturn)); }
+ }
+
+ pub struct Normal;
+
+ impl Normal {
+ pub extern "C" fn associated(a: usize, b: usize) -> usize {
+ //~^ ERROR unused variable: `a`
+ //~| ERROR unused variable: `b`
+ unsafe { asm!("", options(noreturn)); }
+ }
+
+ pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
+ //~^ ERROR unused variable: `a`
+ //~| ERROR unused variable: `b`
+ unsafe { asm!("", options(noreturn)); }
+ }
+ }
+
+ impl super::Trait for Normal {
+ extern "C" fn trait_associated(a: usize, b: usize) -> usize {
+ //~^ ERROR unused variable: `a`
+ //~| ERROR unused variable: `b`
+ unsafe { asm!("", options(noreturn)); }
+ }
+
+ extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
+ //~^ ERROR unused variable: `a`
+ //~| ERROR unused variable: `b`
+ unsafe { asm!("", options(noreturn)); }
+ }
+ }
+}
+
+pub mod naked {
+ use std::arch::asm;
+
+ #[naked]
+ pub extern "C" fn function(a: usize, b: usize) -> usize {
+ unsafe { asm!("", options(noreturn)); }
+ }
+
+ pub struct Naked;
+
+ impl Naked {
+ #[naked]
+ pub extern "C" fn associated(a: usize, b: usize) -> usize {
+ unsafe { asm!("", options(noreturn)); }
+ }
+
+ #[naked]
+ pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
+ unsafe { asm!("", options(noreturn)); }
+ }
+ }
+
+ impl super::Trait for Naked {
+ #[naked]
+ extern "C" fn trait_associated(a: usize, b: usize) -> usize {
+ unsafe { asm!("", options(noreturn)); }
+ }
+
+ #[naked]
+ extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
+ unsafe { asm!("", options(noreturn)); }
+ }
+ }
+}
diff --git a/src/test/ui/asm/naked-functions-unused.x86_64.stderr b/src/test/ui/asm/naked-functions-unused.x86_64.stderr
new file mode 100644
index 000000000..8d3c300e0
--- /dev/null
+++ b/src/test/ui/asm/naked-functions-unused.x86_64.stderr
@@ -0,0 +1,69 @@
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:17:32
+ |
+LL | pub extern "C" fn function(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+ |
+note: the lint level is defined here
+ --> $DIR/naked-functions-unused.rs:5:9
+ |
+LL | #![deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:17:42
+ |
+LL | pub extern "C" fn function(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:26:38
+ |
+LL | pub extern "C" fn associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:26:48
+ |
+LL | pub extern "C" fn associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:32:41
+ |
+LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:32:51
+ |
+LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:40:40
+ |
+LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:40:50
+ |
+LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:46:43
+ |
+LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:46:53
+ |
+LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs
new file mode 100644
index 000000000..9e626f571
--- /dev/null
+++ b/src/test/ui/asm/naked-functions.rs
@@ -0,0 +1,218 @@
+// needs-asm-support
+// ignore-nvptx64
+// ignore-spirv
+// ignore-wasm32
+
+#![feature(naked_functions)]
+#![feature(asm_const, asm_sym, asm_unwind)]
+#![crate_type = "lib"]
+
+use std::arch::asm;
+
+#[repr(C)]
+pub struct P {
+ x: u8,
+ y: u16,
+}
+
+#[naked]
+pub unsafe extern "C" fn patterns(
+ mut a: u32,
+ //~^ ERROR patterns not allowed in naked function parameters
+ &b: &i32,
+ //~^ ERROR patterns not allowed in naked function parameters
+ (None | Some(_)): Option<std::ptr::NonNull<u8>>,
+ //~^ ERROR patterns not allowed in naked function parameters
+ P { x, y }: P,
+ //~^ ERROR patterns not allowed in naked function parameters
+) {
+ asm!("", options(noreturn))
+}
+
+#[naked]
+pub unsafe extern "C" fn inc(a: u32) -> u32 {
+ //~^ ERROR naked functions must contain a single asm block
+ a + 1
+ //~^ ERROR referencing function parameters is not allowed in naked functions
+}
+
+#[naked]
+#[allow(asm_sub_register)]
+pub unsafe extern "C" fn inc_asm(a: u32) -> u32 {
+ asm!("/* {0} */", in(reg) a, options(noreturn));
+ //~^ ERROR referencing function parameters is not allowed in naked functions
+ //~| ERROR only `const` and `sym` operands are supported in naked functions
+}
+
+#[naked]
+pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
+ //~^ ERROR naked functions must contain a single asm block
+ (|| a + 1)()
+}
+
+#[naked]
+pub unsafe extern "C" fn unsupported_operands() {
+ //~^ ERROR naked functions must contain a single asm block
+ let mut a = 0usize;
+ let mut b = 0usize;
+ let mut c = 0usize;
+ let mut d = 0usize;
+ let mut e = 0usize;
+ const F: usize = 0usize;
+ static G: usize = 0usize;
+ asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
+ //~^ ERROR asm in naked functions must use `noreturn` option
+ in(reg) a,
+ //~^ ERROR only `const` and `sym` operands are supported in naked functions
+ inlateout(reg) b,
+ inout(reg) c,
+ lateout(reg) d,
+ out(reg) e,
+ const F,
+ sym G,
+ );
+}
+
+#[naked]
+pub extern "C" fn missing_assembly() {
+ //~^ ERROR naked functions must contain a single asm block
+}
+
+#[naked]
+pub extern "C" fn too_many_asm_blocks() {
+ //~^ ERROR naked functions must contain a single asm block
+ asm!("");
+ //~^ ERROR asm in naked functions must use `noreturn` option
+ asm!("");
+ //~^ ERROR asm in naked functions must use `noreturn` option
+ asm!("");
+ //~^ ERROR asm in naked functions must use `noreturn` option
+ asm!("", options(noreturn));
+}
+
+pub fn outer(x: u32) -> extern "C" fn(usize) -> usize {
+ #[naked]
+ pub extern "C" fn inner(y: usize) -> usize {
+ //~^ ERROR naked functions must contain a single asm block
+ *&y
+ //~^ ERROR referencing function parameters is not allowed in naked functions
+ }
+ inner
+}
+
+#[naked]
+unsafe extern "C" fn invalid_options() {
+ asm!("", options(nomem, preserves_flags, noreturn));
+ //~^ ERROR asm options unsupported in naked functions: `nomem`, `preserves_flags`
+}
+
+#[naked]
+unsafe extern "C" fn invalid_options_continued() {
+ asm!("", options(readonly, nostack), options(pure));
+ //~^ ERROR asm with the `pure` option must have at least one output
+ //~| ERROR asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
+ //~| ERROR asm in naked functions must use `noreturn` option
+}
+
+#[naked]
+unsafe extern "C" fn invalid_may_unwind() {
+ asm!("", options(noreturn, may_unwind));
+ //~^ ERROR asm options unsupported in naked functions: `may_unwind`
+}
+
+#[naked]
+pub unsafe fn default_abi() {
+ //~^ WARN Rust ABI is unsupported in naked functions
+ asm!("", options(noreturn));
+}
+
+#[naked]
+pub unsafe fn rust_abi() {
+ //~^ WARN Rust ABI is unsupported in naked functions
+ asm!("", options(noreturn));
+}
+
+#[naked]
+pub extern "C" fn valid_a<T>() -> T {
+ unsafe {
+ asm!("", options(noreturn));
+ }
+}
+
+#[naked]
+pub extern "C" fn valid_b() {
+ unsafe {
+ {
+ {
+ asm!("", options(noreturn));
+ };
+ };
+ }
+}
+
+#[naked]
+pub unsafe extern "C" fn valid_c() {
+ asm!("", options(noreturn));
+}
+
+#[cfg(target_arch = "x86_64")]
+#[naked]
+pub unsafe extern "C" fn valid_att_syntax() {
+ asm!("", options(noreturn, att_syntax));
+}
+
+#[naked]
+pub unsafe extern "C" fn inline_none() {
+ asm!("", options(noreturn));
+}
+
+#[naked]
+#[inline]
+//~^ ERROR naked functions cannot be inlined
+pub unsafe extern "C" fn inline_hint() {
+ asm!("", options(noreturn));
+}
+
+#[naked]
+#[inline(always)]
+//~^ ERROR naked functions cannot be inlined
+pub unsafe extern "C" fn inline_always() {
+ asm!("", options(noreturn));
+}
+
+#[naked]
+#[inline(never)]
+//~^ ERROR naked functions cannot be inlined
+pub unsafe extern "C" fn inline_never() {
+ asm!("", options(noreturn));
+}
+
+#[naked]
+#[inline]
+//~^ ERROR naked functions cannot be inlined
+#[inline(always)]
+//~^ ERROR naked functions cannot be inlined
+#[inline(never)]
+//~^ ERROR naked functions cannot be inlined
+pub unsafe extern "C" fn inline_all() {
+ asm!("", options(noreturn));
+}
+
+#[naked]
+pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 {
+ compile_error!("this is a user specified error")
+ //~^ ERROR this is a user specified error
+}
+
+#[naked]
+pub unsafe extern "C" fn allow_compile_error_and_asm(a: u32) -> u32 {
+ compile_error!("this is a user specified error");
+ //~^ ERROR this is a user specified error
+ asm!("", options(noreturn))
+}
+
+#[naked]
+pub unsafe extern "C" fn invalid_asm_syntax(a: u32) -> u32 {
+ asm!(invalid_syntax)
+ //~^ ERROR asm template must be a string literal
+}
diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr
new file mode 100644
index 000000000..1828066b6
--- /dev/null
+++ b/src/test/ui/asm/naked-functions.stderr
@@ -0,0 +1,303 @@
+error: asm with the `pure` option must have at least one output
+ --> $DIR/naked-functions.rs:111:14
+ |
+LL | asm!("", options(readonly, nostack), options(pure));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
+
+error: this is a user specified error
+ --> $DIR/naked-functions.rs:203:5
+ |
+LL | compile_error!("this is a user specified error")
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: this is a user specified error
+ --> $DIR/naked-functions.rs:209:5
+ |
+LL | compile_error!("this is a user specified error");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: asm template must be a string literal
+ --> $DIR/naked-functions.rs:216:10
+ |
+LL | asm!(invalid_syntax)
+ | ^^^^^^^^^^^^^^
+
+error: patterns not allowed in naked function parameters
+ --> $DIR/naked-functions.rs:20:5
+ |
+LL | mut a: u32,
+ | ^^^^^
+
+error: patterns not allowed in naked function parameters
+ --> $DIR/naked-functions.rs:22:5
+ |
+LL | &b: &i32,
+ | ^^
+
+error: patterns not allowed in naked function parameters
+ --> $DIR/naked-functions.rs:24:6
+ |
+LL | (None | Some(_)): Option<std::ptr::NonNull<u8>>,
+ | ^^^^^^^^^^^^^^
+
+error: patterns not allowed in naked function parameters
+ --> $DIR/naked-functions.rs:26:5
+ |
+LL | P { x, y }: P,
+ | ^^^^^^^^^^
+
+error: referencing function parameters is not allowed in naked functions
+ --> $DIR/naked-functions.rs:35:5
+ |
+LL | a + 1
+ | ^
+ |
+ = help: follow the calling convention in asm block to use parameters
+
+error[E0787]: naked functions must contain a single asm block
+ --> $DIR/naked-functions.rs:33:1
+ |
+LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
+LL | |
+LL | | a + 1
+ | | ----- non-asm is unsupported in naked functions
+LL | |
+LL | | }
+ | |_^
+
+error: referencing function parameters is not allowed in naked functions
+ --> $DIR/naked-functions.rs:42:31
+ |
+LL | asm!("/* {0} */", in(reg) a, options(noreturn));
+ | ^
+ |
+ = help: follow the calling convention in asm block to use parameters
+
+error[E0787]: only `const` and `sym` operands are supported in naked functions
+ --> $DIR/naked-functions.rs:42:23
+ |
+LL | asm!("/* {0} */", in(reg) a, options(noreturn));
+ | ^^^^^^^^^
+
+error[E0787]: naked functions must contain a single asm block
+ --> $DIR/naked-functions.rs:48:1
+ |
+LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
+LL | |
+LL | | (|| a + 1)()
+ | | ------------ non-asm is unsupported in naked functions
+LL | | }
+ | |_^
+
+error[E0787]: only `const` and `sym` operands are supported in naked functions
+ --> $DIR/naked-functions.rs:65:10
+ |
+LL | in(reg) a,
+ | ^^^^^^^^^
+LL |
+LL | inlateout(reg) b,
+ | ^^^^^^^^^^^^^^^^
+LL | inout(reg) c,
+ | ^^^^^^^^^^^^
+LL | lateout(reg) d,
+ | ^^^^^^^^^^^^^^
+LL | out(reg) e,
+ | ^^^^^^^^^^
+
+error[E0787]: asm in naked functions must use `noreturn` option
+ --> $DIR/naked-functions.rs:63:5
+ |
+LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
+LL | |
+LL | | in(reg) a,
+LL | |
+... |
+LL | | sym G,
+LL | | );
+ | |_____^
+ |
+help: consider specifying that the asm block is responsible for returning from the function
+ |
+LL | sym G, options(noreturn),
+ | +++++++++++++++++++
+
+error[E0787]: naked functions must contain a single asm block
+ --> $DIR/naked-functions.rs:54:1
+ |
+LL | / pub unsafe extern "C" fn unsupported_operands() {
+LL | |
+LL | | let mut a = 0usize;
+ | | ------------------- non-asm is unsupported in naked functions
+LL | | let mut b = 0usize;
+ | | ------------------- non-asm is unsupported in naked functions
+LL | | let mut c = 0usize;
+ | | ------------------- non-asm is unsupported in naked functions
+LL | | let mut d = 0usize;
+ | | ------------------- non-asm is unsupported in naked functions
+LL | | let mut e = 0usize;
+ | | ------------------- non-asm is unsupported in naked functions
+... |
+LL | | );
+LL | | }
+ | |_^
+
+error[E0787]: naked functions must contain a single asm block
+ --> $DIR/naked-functions.rs:77:1
+ |
+LL | / pub extern "C" fn missing_assembly() {
+LL | |
+LL | | }
+ | |_^
+
+error[E0787]: asm in naked functions must use `noreturn` option
+ --> $DIR/naked-functions.rs:84:5
+ |
+LL | asm!("");
+ | ^^^^^^^^
+ |
+help: consider specifying that the asm block is responsible for returning from the function
+ |
+LL | asm!("", options(noreturn));
+ | +++++++++++++++++++
+
+error[E0787]: asm in naked functions must use `noreturn` option
+ --> $DIR/naked-functions.rs:86:5
+ |
+LL | asm!("");
+ | ^^^^^^^^
+ |
+help: consider specifying that the asm block is responsible for returning from the function
+ |
+LL | asm!("", options(noreturn));
+ | +++++++++++++++++++
+
+error[E0787]: asm in naked functions must use `noreturn` option
+ --> $DIR/naked-functions.rs:88:5
+ |
+LL | asm!("");
+ | ^^^^^^^^
+ |
+help: consider specifying that the asm block is responsible for returning from the function
+ |
+LL | asm!("", options(noreturn));
+ | +++++++++++++++++++
+
+error[E0787]: naked functions must contain a single asm block
+ --> $DIR/naked-functions.rs:82:1
+ |
+LL | / pub extern "C" fn too_many_asm_blocks() {
+LL | |
+LL | | asm!("");
+LL | |
+LL | | asm!("");
+ | | -------- multiple asm blocks are unsupported in naked functions
+LL | |
+LL | | asm!("");
+ | | -------- multiple asm blocks are unsupported in naked functions
+LL | |
+LL | | asm!("", options(noreturn));
+ | | --------------------------- multiple asm blocks are unsupported in naked functions
+LL | | }
+ | |_^
+
+error: referencing function parameters is not allowed in naked functions
+ --> $DIR/naked-functions.rs:97:11
+ |
+LL | *&y
+ | ^
+ |
+ = help: follow the calling convention in asm block to use parameters
+
+error[E0787]: naked functions must contain a single asm block
+ --> $DIR/naked-functions.rs:95:5
+ |
+LL | / pub extern "C" fn inner(y: usize) -> usize {
+LL | |
+LL | | *&y
+ | | --- non-asm is unsupported in naked functions
+LL | |
+LL | | }
+ | |_____^
+
+error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags`
+ --> $DIR/naked-functions.rs:105:5
+ |
+LL | asm!("", options(nomem, preserves_flags, noreturn));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
+ --> $DIR/naked-functions.rs:111:5
+ |
+LL | asm!("", options(readonly, nostack), options(pure));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0787]: asm in naked functions must use `noreturn` option
+ --> $DIR/naked-functions.rs:111:5
+ |
+LL | asm!("", options(readonly, nostack), options(pure));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider specifying that the asm block is responsible for returning from the function
+ |
+LL | asm!("", options(noreturn), options(readonly, nostack), options(pure));
+ | +++++++++++++++++++
+
+error[E0787]: asm options unsupported in naked functions: `may_unwind`
+ --> $DIR/naked-functions.rs:119:5
+ |
+LL | asm!("", options(noreturn, may_unwind));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: Rust ABI is unsupported in naked functions
+ --> $DIR/naked-functions.rs:124:15
+ |
+LL | pub unsafe fn default_abi() {
+ | ^^^^^^^^^^^
+ |
+ = note: `#[warn(undefined_naked_function_abi)]` on by default
+
+warning: Rust ABI is unsupported in naked functions
+ --> $DIR/naked-functions.rs:130:15
+ |
+LL | pub unsafe fn rust_abi() {
+ | ^^^^^^^^
+
+error: naked functions cannot be inlined
+ --> $DIR/naked-functions.rs:170:1
+ |
+LL | #[inline]
+ | ^^^^^^^^^
+
+error: naked functions cannot be inlined
+ --> $DIR/naked-functions.rs:177:1
+ |
+LL | #[inline(always)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: naked functions cannot be inlined
+ --> $DIR/naked-functions.rs:184:1
+ |
+LL | #[inline(never)]
+ | ^^^^^^^^^^^^^^^^
+
+error: naked functions cannot be inlined
+ --> $DIR/naked-functions.rs:191:1
+ |
+LL | #[inline]
+ | ^^^^^^^^^
+
+error: naked functions cannot be inlined
+ --> $DIR/naked-functions.rs:193:1
+ |
+LL | #[inline(always)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: naked functions cannot be inlined
+ --> $DIR/naked-functions.rs:195:1
+ |
+LL | #[inline(never)]
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to 33 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0787`.
diff --git a/src/test/ui/asm/naked-invalid-attr.rs b/src/test/ui/asm/naked-invalid-attr.rs
new file mode 100644
index 000000000..ea8f560ff
--- /dev/null
+++ b/src/test/ui/asm/naked-invalid-attr.rs
@@ -0,0 +1,52 @@
+// Checks that #[naked] attribute can be placed on function definitions only.
+//
+// needs-asm-support
+#![feature(naked_functions)]
+#![naked] //~ ERROR should be applied to a function definition
+
+use std::arch::asm;
+
+extern "C" {
+ #[naked] //~ ERROR should be applied to a function definition
+ fn f();
+}
+
+#[naked] //~ ERROR should be applied to a function definition
+#[repr(C)]
+struct S {
+ a: u32,
+ b: u32,
+}
+
+trait Invoke {
+ #[naked] //~ ERROR should be applied to a function definition
+ extern "C" fn invoke(&self);
+}
+
+impl Invoke for S {
+ #[naked]
+ extern "C" fn invoke(&self) {
+ unsafe { asm!("", options(noreturn)) }
+ }
+}
+
+#[naked]
+extern "C" fn ok() {
+ unsafe { asm!("", options(noreturn)) }
+}
+
+impl S {
+ #[naked]
+ extern "C" fn g() {
+ unsafe { asm!("", options(noreturn)) }
+ }
+
+ #[naked]
+ extern "C" fn h(&self) {
+ unsafe { asm!("", options(noreturn)) }
+ }
+}
+
+fn main() {
+ #[naked] || {}; //~ ERROR should be applied to a function definition
+}
diff --git a/src/test/ui/asm/naked-invalid-attr.stderr b/src/test/ui/asm/naked-invalid-attr.stderr
new file mode 100644
index 000000000..58344be93
--- /dev/null
+++ b/src/test/ui/asm/naked-invalid-attr.stderr
@@ -0,0 +1,42 @@
+error: attribute should be applied to a function definition
+ --> $DIR/naked-invalid-attr.rs:14:1
+ |
+LL | #[naked]
+ | ^^^^^^^^
+LL | #[repr(C)]
+LL | / struct S {
+LL | | a: u32,
+LL | | b: u32,
+LL | | }
+ | |_- not a function definition
+
+error: attribute should be applied to a function definition
+ --> $DIR/naked-invalid-attr.rs:51:5
+ |
+LL | #[naked] || {};
+ | ^^^^^^^^ ----- not a function definition
+
+error: attribute should be applied to a function definition
+ --> $DIR/naked-invalid-attr.rs:22:5
+ |
+LL | #[naked]
+ | ^^^^^^^^
+LL | extern "C" fn invoke(&self);
+ | ---------------------------- not a function definition
+
+error: attribute should be applied to a function definition
+ --> $DIR/naked-invalid-attr.rs:10:5
+ |
+LL | #[naked]
+ | ^^^^^^^^
+LL | fn f();
+ | ------- not a function definition
+
+error: attribute should be applied to a function definition
+ --> $DIR/naked-invalid-attr.rs:5:1
+ |
+LL | #![naked]
+ | ^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/asm/named-asm-labels.rs b/src/test/ui/asm/named-asm-labels.rs
new file mode 100644
index 000000000..160dbf617
--- /dev/null
+++ b/src/test/ui/asm/named-asm-labels.rs
@@ -0,0 +1,196 @@
+// needs-asm-support
+// ignore-nvptx64
+// ignore-spirv
+// ignore-wasm32
+
+// Tests that the use of named labels in the `asm!` macro are linted against
+// except for in `#[naked]` fns.
+// Using a named label is incorrect as per the RFC because for most cases
+// the compiler cannot ensure that inline asm is emitted exactly once per
+// codegen unit (except for naked fns) and so the label could be duplicated
+// which causes less readable LLVM errors and in the worst cases causes ICEs
+// or segfaults based on system dependent behavior and codegen flags.
+
+#![feature(naked_functions, asm_const)]
+
+use std::arch::{asm, global_asm};
+
+#[no_mangle]
+pub static FOO: usize = 42;
+
+fn main() {
+ unsafe {
+ // Basic usage
+ asm!("bar: nop"); //~ ERROR avoid using named labels
+
+ // No following asm
+ asm!("abcd:"); //~ ERROR avoid using named labels
+
+ // Multiple labels on one line
+ asm!("foo: bar1: nop");
+ //~^ ERROR avoid using named labels
+
+ // Multiple lines
+ asm!("foo1: nop", "nop"); //~ ERROR avoid using named labels
+ asm!("foo2: foo3: nop", "nop");
+ //~^ ERROR avoid using named labels
+ asm!("nop", "foo4: nop"); //~ ERROR avoid using named labels
+ asm!("foo5: nop", "foo6: nop");
+ //~^ ERROR avoid using named labels
+ //~| ERROR avoid using named labels
+
+ // Statement separator
+ asm!("foo7: nop; foo8: nop");
+ //~^ ERROR avoid using named labels
+ asm!("foo9: nop; nop"); //~ ERROR avoid using named labels
+ asm!("nop; foo10: nop"); //~ ERROR avoid using named labels
+
+ // Escaped newline
+ asm!("bar2: nop\n bar3: nop");
+ //~^ ERROR avoid using named labels
+ asm!("bar4: nop\n nop"); //~ ERROR avoid using named labels
+ asm!("nop\n bar5: nop"); //~ ERROR avoid using named labels
+ asm!("nop\n bar6: bar7: nop");
+ //~^ ERROR avoid using named labels
+
+ // Raw strings
+ asm!(
+ r"
+ blah2: nop
+ blah3: nop
+ "
+ );
+ //~^^^^ ERROR avoid using named labels
+
+ asm!(
+ r###"
+ nop
+ nop ; blah4: nop
+ "###
+ );
+ //~^^^ ERROR avoid using named labels
+
+ // Non-labels
+ // should not trigger lint, but may be invalid asm
+ asm!("ab cd: nop");
+
+ // `blah:` does not trigger because labels need to be at the start
+ // of the statement, and there was already a non-label
+ asm!("1bar: blah: nop");
+
+ // Only `blah1:` should trigger
+ asm!("blah1: 2bar: nop"); //~ ERROR avoid using named labels
+
+ // Duplicate labels
+ asm!("def: def: nop"); //~ ERROR avoid using named labels
+ asm!("def: nop\ndef: nop"); //~ ERROR avoid using named labels
+ asm!("def: nop; def: nop"); //~ ERROR avoid using named labels
+
+ // Trying to break parsing
+ asm!(":");
+ asm!("\n:\n");
+ asm!("::::");
+
+ // 0x3A is a ':'
+ asm!("fooo\u{003A} nop"); //~ ERROR avoid using named labels
+ asm!("foooo\x3A nop"); //~ ERROR avoid using named labels
+
+ // 0x0A is a newline
+ asm!("fooooo:\u{000A} nop"); //~ ERROR avoid using named labels
+ asm!("foooooo:\x0A nop"); //~ ERROR avoid using named labels
+
+ // Intentionally breaking span finding
+ // equivalent to "ABC: nop"
+ asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70"); //~ ERROR avoid using named labels
+
+ // Non-label colons - should pass
+ asm!("mov rax, qword ptr fs:[0]");
+
+ // Comments
+ asm!(
+ r"
+ ab: nop // ab: does foo
+ // cd: nop
+ "
+ );
+ //~^^^^ ERROR avoid using named labels
+
+ // Tests usage of colons in non-label positions
+ asm!(":lo12:FOO"); // this is apparently valid aarch64
+ // is there an example that is valid x86 for this test?
+ asm!(":bbb nop");
+
+ // Test include_str in asm
+ asm!(include_str!("named-asm-labels.s")); //~ ERROR avoid using named labels
+
+ // Test allowing or warning on the lint instead
+ #[allow(named_asm_labels)]
+ {
+ asm!("allowed: nop"); // Should not emit anything
+ }
+
+ #[warn(named_asm_labels)]
+ {
+ asm!("warned: nop"); //~ WARNING avoid using named labels
+ }
+ }
+}
+
+// Trigger on naked fns too, even though they can't be inlined, reusing a
+// label or LTO can cause labels to break
+#[naked]
+pub extern "C" fn foo() -> i32 {
+ unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } //~ ERROR avoid using named labels
+}
+
+// Make sure that non-naked attributes *do* still let the lint happen
+#[no_mangle]
+pub extern "C" fn bar() {
+ unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
+ //~^ ERROR avoid using named labels
+}
+
+#[naked]
+pub extern "C" fn aaa() {
+ fn _local() {}
+
+ unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels
+}
+
+pub fn normal() {
+ fn _local1() {}
+
+ #[naked]
+ pub extern "C" fn bbb() {
+ fn _very_local() {}
+
+ unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels
+ }
+
+ fn _local2() {}
+}
+
+// Make sure that the lint happens within closures
+fn closures() {
+ || unsafe {
+ asm!("closure1: nop"); //~ ERROR avoid using named labels
+ };
+
+ move || unsafe {
+ asm!("closure2: nop"); //~ ERROR avoid using named labels
+ };
+
+ || {
+ #[naked]
+ unsafe extern "C" fn _nested() {
+ asm!("ret;", options(noreturn));
+ }
+
+ unsafe {
+ asm!("closure3: nop"); //~ ERROR avoid using named labels
+ }
+ };
+}
+
+// Don't trigger on global asm
+global_asm!("aaaaaaaa: nop");
diff --git a/src/test/ui/asm/named-asm-labels.s b/src/test/ui/asm/named-asm-labels.s
new file mode 100644
index 000000000..071356d75
--- /dev/null
+++ b/src/test/ui/asm/named-asm-labels.s
@@ -0,0 +1,5 @@
+lab1: nop
+// do more things
+lab2: nop // does bar
+// a: b
+lab3: nop; lab4: nop
diff --git a/src/test/ui/asm/named-asm-labels.stderr b/src/test/ui/asm/named-asm-labels.stderr
new file mode 100644
index 000000000..001601497
--- /dev/null
+++ b/src/test/ui/asm/named-asm-labels.stderr
@@ -0,0 +1,334 @@
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:24:15
+ |
+LL | asm!("bar: nop");
+ | ^^^
+ |
+ = note: `#[deny(named_asm_labels)]` on by default
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:27:15
+ |
+LL | asm!("abcd:");
+ | ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:30:15
+ |
+LL | asm!("foo: bar1: nop");
+ | ^^^ ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:34:15
+ |
+LL | asm!("foo1: nop", "nop");
+ | ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:35:15
+ |
+LL | asm!("foo2: foo3: nop", "nop");
+ | ^^^^ ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:37:22
+ |
+LL | asm!("nop", "foo4: nop");
+ | ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:38:15
+ |
+LL | asm!("foo5: nop", "foo6: nop");
+ | ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:38:28
+ |
+LL | asm!("foo5: nop", "foo6: nop");
+ | ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:43:15
+ |
+LL | asm!("foo7: nop; foo8: nop");
+ | ^^^^ ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:45:15
+ |
+LL | asm!("foo9: nop; nop");
+ | ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:46:20
+ |
+LL | asm!("nop; foo10: nop");
+ | ^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:49:15
+ |
+LL | asm!("bar2: nop\n bar3: nop");
+ | ^^^^ ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:51:15
+ |
+LL | asm!("bar4: nop\n nop");
+ | ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:52:21
+ |
+LL | asm!("nop\n bar5: nop");
+ | ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:53:21
+ |
+LL | asm!("nop\n bar6: bar7: nop");
+ | ^^^^ ^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:59:13
+ |
+LL | blah2: nop
+ | ^^^^^
+LL | blah3: nop
+ | ^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:68:19
+ |
+LL | nop ; blah4: nop
+ | ^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:82:15
+ |
+LL | asm!("blah1: 2bar: nop");
+ | ^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:85:15
+ |
+LL | asm!("def: def: nop");
+ | ^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:86:15
+ |
+LL | asm!("def: nop\ndef: nop");
+ | ^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:87:15
+ |
+LL | asm!("def: nop; def: nop");
+ | ^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:95:15
+ |
+LL | asm!("fooo\u{003A} nop");
+ | ^^^^^^^^^^^^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:96:15
+ |
+LL | asm!("foooo\x3A nop");
+ | ^^^^^^^^^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:99:15
+ |
+LL | asm!("fooooo:\u{000A} nop");
+ | ^^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:100:15
+ |
+LL | asm!("foooooo:\x0A nop");
+ | ^^^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:104:14
+ |
+LL | asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:112:13
+ |
+LL | ab: nop // ab: does foo
+ | ^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:124:14
+ |
+LL | asm!(include_str!("named-asm-labels.s"));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+warning: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:134:19
+ |
+LL | asm!("warned: nop");
+ | ^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/named-asm-labels.rs:132:16
+ |
+LL | #[warn(named_asm_labels)]
+ | ^^^^^^^^^^^^^^^^
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:143:20
+ |
+LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
+ | ^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:149:20
+ |
+LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
+ | ^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:157:20
+ |
+LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) }
+ | ^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:167:24
+ |
+LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) }
+ | ^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:176:15
+ |
+LL | asm!("closure1: nop");
+ | ^^^^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:180:15
+ |
+LL | asm!("closure2: nop");
+ | ^^^^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+ --> $DIR/named-asm-labels.rs:190:19
+ |
+LL | asm!("closure3: nop");
+ | ^^^^^^^^
+ |
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+
+error: aborting due to 35 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/asm/noreturn.rs b/src/test/ui/asm/noreturn.rs
new file mode 100644
index 000000000..03fa087ae
--- /dev/null
+++ b/src/test/ui/asm/noreturn.rs
@@ -0,0 +1,19 @@
+// needs-asm-support
+// check-pass
+
+#![feature(never_type)]
+#![crate_type = "rlib"]
+
+use std::arch::asm;
+
+pub unsafe fn asm1() {
+ let _: () = asm!("");
+}
+
+pub unsafe fn asm2() {
+ let _: ! = asm!("", options(noreturn));
+}
+
+pub unsafe fn asm3() -> ! {
+ asm!("", options(noreturn));
+}
diff --git a/src/test/ui/asm/reg-conflict.rs b/src/test/ui/asm/reg-conflict.rs
new file mode 100644
index 000000000..983788a93
--- /dev/null
+++ b/src/test/ui/asm/reg-conflict.rs
@@ -0,0 +1,20 @@
+// compile-flags: --target armv7-unknown-linux-gnueabihf
+// needs-llvm-components: arm
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+#[lang = "sized"]
+trait Sized {}
+
+fn main() {
+ unsafe {
+ asm!("", out("d0") _, out("d1") _);
+ asm!("", out("d0") _, out("s1") _);
+ //~^ ERROR register `s1` conflicts with register `d0`
+ }
+}
diff --git a/src/test/ui/asm/reg-conflict.stderr b/src/test/ui/asm/reg-conflict.stderr
new file mode 100644
index 000000000..2395566de
--- /dev/null
+++ b/src/test/ui/asm/reg-conflict.stderr
@@ -0,0 +1,10 @@
+error: register `s1` conflicts with register `d0`
+ --> $DIR/reg-conflict.rs:17:31
+ |
+LL | asm!("", out("d0") _, out("s1") _);
+ | ----------- ^^^^^^^^^^^ register `s1`
+ | |
+ | register `d0`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/asm/type-check-1.rs b/src/test/ui/asm/type-check-1.rs
new file mode 100644
index 000000000..50b369ae0
--- /dev/null
+++ b/src/test/ui/asm/type-check-1.rs
@@ -0,0 +1,79 @@
+// needs-asm-support
+// ignore-nvptx64
+// ignore-spirv
+// ignore-wasm32
+
+#![feature(asm_const, asm_sym)]
+
+use std::arch::{asm, global_asm};
+
+fn main() {
+ unsafe {
+ // Outputs must be place expressions
+
+ asm!("{}", in(reg) 1 + 2);
+ asm!("{}", out(reg) 1 + 2);
+ //~^ ERROR invalid asm output
+ asm!("{}", inout(reg) 1 + 2);
+ //~^ ERROR invalid asm output
+
+ // Operands must be sized
+
+ let v: [u64; 3] = [0, 1, 2];
+ asm!("{}", in(reg) v[..]);
+ //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+ //~| ERROR cannot use value of type `[u64]` for inline assembly
+ asm!("{}", out(reg) v[..]);
+ //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+ //~| ERROR cannot use value of type `[u64]` for inline assembly
+ asm!("{}", inout(reg) v[..]);
+ //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
+ //~| ERROR cannot use value of type `[u64]` for inline assembly
+
+ // Constants must be... constant
+
+ let x = 0;
+ const fn const_foo(x: i32) -> i32 {
+ x
+ }
+ const fn const_bar<T>(x: T) -> T {
+ x
+ }
+ asm!("{}", const x);
+ //~^ ERROR attempt to use a non-constant value in a constant
+ asm!("{}", const const_foo(0));
+ asm!("{}", const const_foo(x));
+ //~^ ERROR attempt to use a non-constant value in a constant
+ asm!("{}", const const_bar(0));
+ asm!("{}", const const_bar(x));
+ //~^ ERROR attempt to use a non-constant value in a constant
+ asm!("{}", sym x);
+ //~^ ERROR invalid `sym` operand
+
+ // Const operands must be integers and must be constants.
+
+ asm!("{}", const 0);
+ asm!("{}", const 0i32);
+ asm!("{}", const 0i128);
+ asm!("{}", const 0f32);
+ //~^ ERROR mismatched types
+ asm!("{}", const 0 as *mut u8);
+ //~^ ERROR mismatched types
+ asm!("{}", const &0);
+ //~^ ERROR mismatched types
+ }
+}
+
+unsafe fn generic<T>() {
+ asm!("{}", sym generic::<T>);
+}
+
+// Const operands must be integers and must be constants.
+
+global_asm!("{}", const 0);
+global_asm!("{}", const 0i32);
+global_asm!("{}", const 0i128);
+global_asm!("{}", const 0f32);
+//~^ ERROR mismatched types
+global_asm!("{}", const 0 as *mut u8);
+//~^ ERROR mismatched types
diff --git a/src/test/ui/asm/type-check-1.stderr b/src/test/ui/asm/type-check-1.stderr
new file mode 100644
index 000000000..162ff1d32
--- /dev/null
+++ b/src/test/ui/asm/type-check-1.stderr
@@ -0,0 +1,144 @@
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/type-check-1.rs:42:26
+ |
+LL | let x = 0;
+ | ----- help: consider using `const` instead of `let`: `const x`
+...
+LL | asm!("{}", const x);
+ | ^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/type-check-1.rs:45:36
+ |
+LL | let x = 0;
+ | ----- help: consider using `const` instead of `let`: `const x`
+...
+LL | asm!("{}", const const_foo(x));
+ | ^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/type-check-1.rs:48:36
+ |
+LL | let x = 0;
+ | ----- help: consider using `const` instead of `let`: `const x`
+...
+LL | asm!("{}", const const_bar(x));
+ | ^ non-constant value
+
+error: invalid `sym` operand
+ --> $DIR/type-check-1.rs:50:24
+ |
+LL | asm!("{}", sym x);
+ | ^ is a local variable
+ |
+ = help: `sym` operands must refer to either a function or a static
+
+error: invalid asm output
+ --> $DIR/type-check-1.rs:15:29
+ |
+LL | asm!("{}", out(reg) 1 + 2);
+ | ^^^^^ cannot assign to this expression
+
+error: invalid asm output
+ --> $DIR/type-check-1.rs:17:31
+ |
+LL | asm!("{}", inout(reg) 1 + 2);
+ | ^^^^^ cannot assign to this expression
+
+error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
+ --> $DIR/type-check-1.rs:23:28
+ |
+LL | asm!("{}", in(reg) v[..]);
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u64]`
+ = note: all inline asm arguments must have a statically known size
+
+error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
+ --> $DIR/type-check-1.rs:26:29
+ |
+LL | asm!("{}", out(reg) v[..]);
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u64]`
+ = note: all inline asm arguments must have a statically known size
+
+error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
+ --> $DIR/type-check-1.rs:29:31
+ |
+LL | asm!("{}", inout(reg) v[..]);
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u64]`
+ = note: all inline asm arguments must have a statically known size
+
+error: cannot use value of type `[u64]` for inline assembly
+ --> $DIR/type-check-1.rs:23:28
+ |
+LL | asm!("{}", in(reg) v[..]);
+ | ^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `[u64]` for inline assembly
+ --> $DIR/type-check-1.rs:26:29
+ |
+LL | asm!("{}", out(reg) v[..]);
+ | ^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `[u64]` for inline assembly
+ --> $DIR/type-check-1.rs:29:31
+ |
+LL | asm!("{}", inout(reg) v[..]);
+ | ^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error[E0308]: mismatched types
+ --> $DIR/type-check-1.rs:58:26
+ |
+LL | asm!("{}", const 0f32);
+ | ^^^^ expected integer, found `f32`
+
+error[E0308]: mismatched types
+ --> $DIR/type-check-1.rs:60:26
+ |
+LL | asm!("{}", const 0 as *mut u8);
+ | ^^^^^^^^^^^^ expected integer, found *-ptr
+ |
+ = note: expected type `{integer}`
+ found raw pointer `*mut u8`
+
+error[E0308]: mismatched types
+ --> $DIR/type-check-1.rs:62:26
+ |
+LL | asm!("{}", const &0);
+ | ^^ expected integer, found `&{integer}`
+ |
+help: consider removing the borrow
+ |
+LL - asm!("{}", const &0);
+LL + asm!("{}", const 0);
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/type-check-1.rs:76:25
+ |
+LL | global_asm!("{}", const 0f32);
+ | ^^^^ expected integer, found `f32`
+
+error[E0308]: mismatched types
+ --> $DIR/type-check-1.rs:78:25
+ |
+LL | global_asm!("{}", const 0 as *mut u8);
+ | ^^^^^^^^^^^^ expected integer, found *-ptr
+ |
+ = note: expected type `{integer}`
+ found raw pointer `*mut u8`
+
+error: aborting due to 17 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0435.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/asm/type-check-4.rs b/src/test/ui/asm/type-check-4.rs
new file mode 100644
index 000000000..666d2c677
--- /dev/null
+++ b/src/test/ui/asm/type-check-4.rs
@@ -0,0 +1,26 @@
+// needs-asm-support
+// ignore-nvptx64
+// ignore-spirv
+// ignore-wasm32
+
+use std::arch::asm;
+
+fn main() {
+ unsafe {
+ // Can't output to borrowed values.
+
+ let mut a = 0isize;
+ let p = &a;
+ asm!("{}", out(reg) a);
+ //~^ cannot assign to `a` because it is borrowed
+ println!("{}", p);
+
+ // Can't read from mutable borrowed values.
+
+ let mut a = 0isize;
+ let p = &mut a;
+ asm!("{}", in(reg) a);
+ //~^ cannot use `a` because it was mutably borrowed
+ println!("{}", p);
+ }
+}
diff --git a/src/test/ui/asm/type-check-4.stderr b/src/test/ui/asm/type-check-4.stderr
new file mode 100644
index 000000000..c97cd171b
--- /dev/null
+++ b/src/test/ui/asm/type-check-4.stderr
@@ -0,0 +1,26 @@
+error[E0506]: cannot assign to `a` because it is borrowed
+ --> $DIR/type-check-4.rs:14:9
+ |
+LL | let p = &a;
+ | -- borrow of `a` occurs here
+LL | asm!("{}", out(reg) a);
+ | ^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `a` occurs here
+LL |
+LL | println!("{}", p);
+ | - borrow later used here
+
+error[E0503]: cannot use `a` because it was mutably borrowed
+ --> $DIR/type-check-4.rs:22:28
+ |
+LL | let p = &mut a;
+ | ------ borrow of `a` occurs here
+LL | asm!("{}", in(reg) a);
+ | ^ use of borrowed `a`
+LL |
+LL | println!("{}", p);
+ | - borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0503, E0506.
+For more information about an error, try `rustc --explain E0503`.
diff --git a/src/test/ui/asm/x86_64/bad-clobber-abi.rs b/src/test/ui/asm/x86_64/bad-clobber-abi.rs
new file mode 100644
index 000000000..ddcd2065b
--- /dev/null
+++ b/src/test/ui/asm/x86_64/bad-clobber-abi.rs
@@ -0,0 +1,32 @@
+// needs-asm-support
+// only-x86_64
+
+use std::arch::asm;
+
+// checks various modes of failure for the `clobber_abi` argument (after parsing)
+
+fn main() {
+ unsafe {
+ asm!("", clobber_abi("C"));
+ asm!("", clobber_abi("foo"));
+ //~^ ERROR invalid ABI for `clobber_abi`
+ asm!("", clobber_abi("C", "foo"));
+ //~^ ERROR invalid ABI for `clobber_abi`
+ asm!("", clobber_abi("C", "C"));
+ //~^ ERROR `C` ABI specified multiple times
+ asm!("", clobber_abi("win64", "sysv64"));
+ asm!("", clobber_abi("win64", "efiapi"));
+ //~^ ERROR `win64` ABI specified multiple times
+ asm!("", clobber_abi("C", "foo", "C"));
+ //~^ ERROR invalid ABI for `clobber_abi`
+ //~| ERROR `C` ABI specified multiple times
+ asm!("", clobber_abi("win64", "foo", "efiapi"));
+ //~^ ERROR invalid ABI for `clobber_abi`
+ //~| ERROR `win64` ABI specified multiple times
+ asm!("", clobber_abi("C"), clobber_abi("C"));
+ //~^ ERROR `C` ABI specified multiple times
+ asm!("", clobber_abi("win64"), clobber_abi("sysv64"));
+ asm!("", clobber_abi("win64"), clobber_abi("efiapi"));
+ //~^ ERROR `win64` ABI specified multiple times
+ }
+}
diff --git a/src/test/ui/asm/x86_64/bad-clobber-abi.stderr b/src/test/ui/asm/x86_64/bad-clobber-abi.stderr
new file mode 100644
index 000000000..46e91a395
--- /dev/null
+++ b/src/test/ui/asm/x86_64/bad-clobber-abi.stderr
@@ -0,0 +1,88 @@
+error: invalid ABI for `clobber_abi`
+ --> $DIR/bad-clobber-abi.rs:11:18
+ |
+LL | asm!("", clobber_abi("foo"));
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+
+error: invalid ABI for `clobber_abi`
+ --> $DIR/bad-clobber-abi.rs:13:35
+ |
+LL | asm!("", clobber_abi("C", "foo"));
+ | ^^^^^
+ |
+ = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+
+error: `C` ABI specified multiple times
+ --> $DIR/bad-clobber-abi.rs:15:35
+ |
+LL | asm!("", clobber_abi("C", "C"));
+ | --- ^^^
+ | |
+ | previously specified here
+
+error: `win64` ABI specified multiple times
+ --> $DIR/bad-clobber-abi.rs:18:39
+ |
+LL | asm!("", clobber_abi("win64", "efiapi"));
+ | ------- ^^^^^^^^
+ | |
+ | previously specified here
+ |
+ = note: these ABIs are equivalent on the current target
+
+error: invalid ABI for `clobber_abi`
+ --> $DIR/bad-clobber-abi.rs:20:35
+ |
+LL | asm!("", clobber_abi("C", "foo", "C"));
+ | ^^^^^
+ |
+ = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+
+error: `C` ABI specified multiple times
+ --> $DIR/bad-clobber-abi.rs:20:42
+ |
+LL | asm!("", clobber_abi("C", "foo", "C"));
+ | --- ^^^
+ | |
+ | previously specified here
+
+error: invalid ABI for `clobber_abi`
+ --> $DIR/bad-clobber-abi.rs:23:39
+ |
+LL | asm!("", clobber_abi("win64", "foo", "efiapi"));
+ | ^^^^^
+ |
+ = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+
+error: `win64` ABI specified multiple times
+ --> $DIR/bad-clobber-abi.rs:23:46
+ |
+LL | asm!("", clobber_abi("win64", "foo", "efiapi"));
+ | ------- ^^^^^^^^
+ | |
+ | previously specified here
+ |
+ = note: these ABIs are equivalent on the current target
+
+error: `C` ABI specified multiple times
+ --> $DIR/bad-clobber-abi.rs:26:36
+ |
+LL | asm!("", clobber_abi("C"), clobber_abi("C"));
+ | ---------------- ^^^^^^^^^^^^^^^^
+ | |
+ | previously specified here
+
+error: `win64` ABI specified multiple times
+ --> $DIR/bad-clobber-abi.rs:29:40
+ |
+LL | asm!("", clobber_abi("win64"), clobber_abi("efiapi"));
+ | -------------------- ^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | previously specified here
+ |
+ = note: these ABIs are equivalent on the current target
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/asm/x86_64/bad-options.rs b/src/test/ui/asm/x86_64/bad-options.rs
new file mode 100644
index 000000000..f7c2cd6c5
--- /dev/null
+++ b/src/test/ui/asm/x86_64/bad-options.rs
@@ -0,0 +1,42 @@
+// only-x86_64
+
+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(reg) foo, clobber_abi("C"), clobber_abi("C"));
+ //~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs
+ //~| ERROR `C` ABI specified multiple times
+ asm!("", out("eax") 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/src/test/ui/asm/x86_64/bad-options.stderr b/src/test/ui/asm/x86_64/bad-options.stderr
new file mode 100644
index 000000000..e2351840e
--- /dev/null
+++ b/src/test/ui/asm/x86_64/bad-options.stderr
@@ -0,0 +1,101 @@
+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: asm with `clobber_abi` must specify explicit registers for outputs
+ --> $DIR/bad-options.rs:24:20
+ |
+LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
+ | ^^^^^^^^^^^^ ---------------- ---------------- clobber_abi
+ | | |
+ | | clobber_abi
+ | generic outputs
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+ --> $DIR/bad-options.rs:31: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
+ |
+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
+ |
+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
+ |
+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
+ |
+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
+ |
+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`, `win64`, `sysv64`
+
+error: `C` ABI specified multiple times
+ --> $DIR/bad-options.rs:24:52
+ |
+LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C"));
+ | ---------------- ^^^^^^^^^^^^^^^^
+ | |
+ | previously specified here
+
+error: aborting due to 15 previous errors
+
diff --git a/src/test/ui/asm/x86_64/bad-reg.rs b/src/test/ui/asm/x86_64/bad-reg.rs
new file mode 100644
index 000000000..a4f50a534
--- /dev/null
+++ b/src/test/ui/asm/x86_64/bad-reg.rs
@@ -0,0 +1,72 @@
+// only-x86_64
+// compile-flags: -C target-feature=+avx2
+
+#![feature(asm_const, asm_sym)]
+
+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(xmm_reg) 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("ebp") foo);
+ //~^ ERROR invalid register `ebp`: the frame pointer cannot be used as an operand
+ asm!("", in("rsp") foo);
+ //~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand
+ asm!("", in("ip") foo);
+ //~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand
+
+ asm!("", in("st(2)") foo);
+ //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+ //~| ERROR `i32` cannot be used with this register class
+ asm!("", in("mm0") foo);
+ //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+ //~| ERROR `i32` cannot be used with this register class
+ asm!("", in("k0") foo);
+ //~^ ERROR register class `kreg0` can only be used as a clobber, not as an input or output
+ //~| ERROR `i32` cannot be used with this register class
+ asm!("", out("st(2)") _);
+ asm!("", out("mm0") _);
+ asm!("{}", in(x87_reg) foo);
+ //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+ //~| ERROR `i32` cannot be used with this register class
+ asm!("{}", in(mmx_reg) foo);
+ //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+ //~| ERROR `i32` cannot be used with this register class
+ asm!("{}", out(x87_reg) _);
+ //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+ asm!("{}", out(mmx_reg) _);
+ //~^ ERROR register class `mmx_reg` 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("eax") foo, in("al") bar);
+ //~^ ERROR register `al` conflicts with register `ax`
+ //~| ERROR `i32` cannot be used with this register class
+ asm!("", in("rax") foo, out("rax") bar);
+ //~^ ERROR register `ax` conflicts with register `ax`
+ asm!("", in("al") foo, lateout("al") bar);
+ //~^ ERROR `i32` cannot be used with this register class
+ //~| ERROR `i32` cannot be used with this register class
+ asm!("", in("xmm0") foo, in("ymm0") bar);
+ //~^ ERROR register `ymm0` conflicts with register `xmm0`
+ asm!("", in("xmm0") foo, out("ymm0") bar);
+ //~^ ERROR register `ymm0` conflicts with register `xmm0`
+ asm!("", in("xmm0") foo, lateout("ymm0") bar);
+ }
+}
diff --git a/src/test/ui/asm/x86_64/bad-reg.stderr b/src/test/ui/asm/x86_64/bad-reg.stderr
new file mode 100644
index 000000000..82b7ebd0f
--- /dev/null
+++ b/src/test/ui/asm/x86_64/bad-reg.stderr
@@ -0,0 +1,218 @@
+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: `l`, `x`, `e`, `r`
+
+error: invalid asm template modifier for this register class
+ --> $DIR/bad-reg.rs:20:15
+ |
+LL | asm!("{:r}", in(xmm_reg) foo);
+ | ^^^^ --------------- argument
+ | |
+ | template modifier
+ |
+ = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z`
+
+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 `ebp`: the frame pointer cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:26:18
+ |
+LL | asm!("", in("ebp") foo);
+ | ^^^^^^^^^^^^^
+
+error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:28:18
+ |
+LL | asm!("", in("rsp") foo);
+ | ^^^^^^^^^^^^^
+
+error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:30:18
+ |
+LL | asm!("", in("ip") foo);
+ | ^^^^^^^^^^^^
+
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:33:18
+ |
+LL | asm!("", in("st(2)") foo);
+ | ^^^^^^^^^^^^^^^
+
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:36:18
+ |
+LL | asm!("", in("mm0") foo);
+ | ^^^^^^^^^^^^^
+
+error: register class `kreg0` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:39:18
+ |
+LL | asm!("", in("k0") foo);
+ | ^^^^^^^^^^^^
+
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:44:20
+ |
+LL | asm!("{}", in(x87_reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:47:20
+ |
+LL | asm!("{}", in(mmx_reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:50:20
+ |
+LL | asm!("{}", out(x87_reg) _);
+ | ^^^^^^^^^^^^^^
+
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:52:20
+ |
+LL | asm!("{}", out(mmx_reg) _);
+ | ^^^^^^^^^^^^^^
+
+error: register `al` conflicts with register `ax`
+ --> $DIR/bad-reg.rs:58:33
+ |
+LL | asm!("", in("eax") foo, in("al") bar);
+ | ------------- ^^^^^^^^^^^^ register `al`
+ | |
+ | register `ax`
+
+error: register `ax` conflicts with register `ax`
+ --> $DIR/bad-reg.rs:61:33
+ |
+LL | asm!("", in("rax") foo, out("rax") bar);
+ | ------------- ^^^^^^^^^^^^^^ register `ax`
+ | |
+ | register `ax`
+ |
+help: use `lateout` instead of `out` to avoid conflict
+ --> $DIR/bad-reg.rs:61:18
+ |
+LL | asm!("", in("rax") foo, out("rax") bar);
+ | ^^^^^^^^^^^^^
+
+error: register `ymm0` conflicts with register `xmm0`
+ --> $DIR/bad-reg.rs:66:34
+ |
+LL | asm!("", in("xmm0") foo, in("ymm0") bar);
+ | -------------- ^^^^^^^^^^^^^^ register `ymm0`
+ | |
+ | register `xmm0`
+
+error: register `ymm0` conflicts with register `xmm0`
+ --> $DIR/bad-reg.rs:68:34
+ |
+LL | asm!("", in("xmm0") foo, out("ymm0") bar);
+ | -------------- ^^^^^^^^^^^^^^^ register `ymm0`
+ | |
+ | register `xmm0`
+ |
+help: use `lateout` instead of `out` to avoid conflict
+ --> $DIR/bad-reg.rs:68:18
+ |
+LL | asm!("", in("xmm0") foo, out("ymm0") bar);
+ | ^^^^^^^^^^^^^^
+
+error: type `i32` cannot be used with this register class
+ --> $DIR/bad-reg.rs:33:30
+ |
+LL | asm!("", in("st(2)") foo);
+ | ^^^
+ |
+ = note: register class `x87_reg` supports these types:
+
+error: type `i32` cannot be used with this register class
+ --> $DIR/bad-reg.rs:36:28
+ |
+LL | asm!("", in("mm0") foo);
+ | ^^^
+ |
+ = note: register class `mmx_reg` supports these types:
+
+error: type `i32` cannot be used with this register class
+ --> $DIR/bad-reg.rs:39:27
+ |
+LL | asm!("", in("k0") foo);
+ | ^^^
+ |
+ = note: register class `kreg0` supports these types:
+
+error: type `i32` cannot be used with this register class
+ --> $DIR/bad-reg.rs:44:32
+ |
+LL | asm!("{}", in(x87_reg) foo);
+ | ^^^
+ |
+ = note: register class `x87_reg` supports these types:
+
+error: type `i32` cannot be used with this register class
+ --> $DIR/bad-reg.rs:47:32
+ |
+LL | asm!("{}", in(mmx_reg) foo);
+ | ^^^
+ |
+ = note: register class `mmx_reg` supports these types:
+
+error: type `i32` cannot be used with this register class
+ --> $DIR/bad-reg.rs:58:42
+ |
+LL | asm!("", in("eax") foo, in("al") bar);
+ | ^^^
+ |
+ = note: register class `reg_byte` supports these types: i8
+
+error: type `i32` cannot be used with this register class
+ --> $DIR/bad-reg.rs:63:27
+ |
+LL | asm!("", in("al") foo, lateout("al") bar);
+ | ^^^
+ |
+ = note: register class `reg_byte` supports these types: i8
+
+error: type `i32` cannot be used with this register class
+ --> $DIR/bad-reg.rs:63:46
+ |
+LL | asm!("", in("al") foo, lateout("al") bar);
+ | ^^^
+ |
+ = note: register class `reg_byte` supports these types: i8
+
+error: aborting due to 28 previous errors
+
diff --git a/src/test/ui/asm/x86_64/const.rs b/src/test/ui/asm/x86_64/const.rs
new file mode 100644
index 000000000..d523ae021
--- /dev/null
+++ b/src/test/ui/asm/x86_64/const.rs
@@ -0,0 +1,44 @@
+// only-x86_64
+// 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 eax, {}", const 5);
+global_asm!("mov eax, {}", const constfn(5));
+global_asm!("mov eax, {}", const constfn(5) + constfn(5));
diff --git a/src/test/ui/asm/x86_64/duplicate-options.fixed b/src/test/ui/asm/x86_64/duplicate-options.fixed
new file mode 100644
index 000000000..c5f14f5f7
--- /dev/null
+++ b/src/test/ui/asm/x86_64/duplicate-options.fixed
@@ -0,0 +1,29 @@
+// only-x86_64
+// run-rustfix
+
+use std::arch::{asm, global_asm};
+
+fn main() {
+ unsafe {
+ asm!("", options(nomem, ));
+ //~^ ERROR the `nomem` option was already provided
+ asm!("", options(att_syntax, ));
+ //~^ ERROR the `att_syntax` option was already provided
+ asm!("", options(nostack, att_syntax), 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(att_syntax, ), //~ ERROR the `noreturn` option was already provided
+ options( nostack), //~ ERROR the `nomem` option was already provided
+ options(), //~ ERROR the `noreturn` option was already provided
+ );
+ }
+}
+
+global_asm!("", options(att_syntax, ));
+//~^ ERROR the `att_syntax` option was already provided
diff --git a/src/test/ui/asm/x86_64/duplicate-options.rs b/src/test/ui/asm/x86_64/duplicate-options.rs
new file mode 100644
index 000000000..a8dce1f8d
--- /dev/null
+++ b/src/test/ui/asm/x86_64/duplicate-options.rs
@@ -0,0 +1,29 @@
+// only-x86_64
+// run-rustfix
+
+use std::arch::{asm, global_asm};
+
+fn main() {
+ unsafe {
+ asm!("", options(nomem, nomem));
+ //~^ ERROR the `nomem` option was already provided
+ asm!("", options(att_syntax, att_syntax));
+ //~^ ERROR the `att_syntax` option was already provided
+ asm!("", options(nostack, att_syntax), 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(att_syntax, 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
+ );
+ }
+}
+
+global_asm!("", options(att_syntax, att_syntax));
+//~^ ERROR the `att_syntax` option was already provided
diff --git a/src/test/ui/asm/x86_64/duplicate-options.stderr b/src/test/ui/asm/x86_64/duplicate-options.stderr
new file mode 100644
index 000000000..53edf8fb9
--- /dev/null
+++ b/src/test/ui/asm/x86_64/duplicate-options.stderr
@@ -0,0 +1,62 @@
+error: the `nomem` option was already provided
+ --> $DIR/duplicate-options.rs:8:33
+ |
+LL | asm!("", options(nomem, nomem));
+ | ^^^^^ this option was already provided
+
+error: the `att_syntax` option was already provided
+ --> $DIR/duplicate-options.rs:10:38
+ |
+LL | asm!("", options(att_syntax, att_syntax));
+ | ^^^^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:12:56
+ |
+LL | asm!("", options(nostack, att_syntax), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:14: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:14: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:14: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:21:33
+ |
+LL | options(att_syntax, noreturn),
+ | ^^^^^^^^ this option was already provided
+
+error: the `nomem` option was already provided
+ --> $DIR/duplicate-options.rs:22:21
+ |
+LL | options(nomem, nostack),
+ | ^^^^^ this option was already provided
+
+error: the `noreturn` option was already provided
+ --> $DIR/duplicate-options.rs:23:21
+ |
+LL | options(noreturn),
+ | ^^^^^^^^ this option was already provided
+
+error: the `att_syntax` option was already provided
+ --> $DIR/duplicate-options.rs:28:37
+ |
+LL | global_asm!("", options(att_syntax, att_syntax));
+ | ^^^^^^^^^^ this option was already provided
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/asm/x86_64/interpolated-idents.rs b/src/test/ui/asm/x86_64/interpolated-idents.rs
new file mode 100644
index 000000000..c05633ae8
--- /dev/null
+++ b/src/test/ui/asm/x86_64/interpolated-idents.rs
@@ -0,0 +1,24 @@
+// only-x86_64
+
+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 $att_syntax: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, $att_syntax));
+ //~^ 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 att_syntax options);
+}
diff --git a/src/test/ui/asm/x86_64/interpolated-idents.stderr b/src/test/ui/asm/x86_64/interpolated-idents.stderr
new file mode 100644
index 000000000..6ac2ac5a7
--- /dev/null
+++ b/src/test/ui/asm/x86_64/interpolated-idents.stderr
@@ -0,0 +1,51 @@
+error: the `nomem` and `readonly` options are mutually exclusive
+ --> $DIR/interpolated-idents.rs:13:13
+ |
+LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | / m!(in out lateout inout inlateout const sym
+LL | | pure nomem readonly preserves_flags
+LL | | noreturn nostack att_syntax 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, $att_syntax));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | / m!(in out lateout inout inlateout const sym
+LL | | pure nomem readonly preserves_flags
+LL | | noreturn nostack att_syntax 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 att_syntax 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/src/test/ui/asm/x86_64/issue-82869.rs b/src/test/ui/asm/x86_64/issue-82869.rs
new file mode 100644
index 000000000..67933666e
--- /dev/null
+++ b/src/test/ui/asm/x86_64/issue-82869.rs
@@ -0,0 +1,25 @@
+// needs-asm-support
+// only-x86_64
+// Make sure rustc doesn't ICE on asm! for a foreign architecture.
+
+#![crate_type = "rlib"]
+
+use std::arch::asm;
+
+pub unsafe fn aarch64(a: f64, b: f64) -> f64 {
+ let c;
+ asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+ || {};
+ b
+ });
+ //~^^^^ invalid register class
+ //~^^^^^ invalid register class
+ //~^^^^^^ invalid register
+ c
+}
+
+pub unsafe fn x86(a: f64, b: f64) -> f64 {
+ let c;
+ asm!("addsd {}, {}, xmm0", out(xmm_reg) c, in(xmm_reg) a, in("xmm0") b);
+ c
+}
diff --git a/src/test/ui/asm/x86_64/issue-82869.stderr b/src/test/ui/asm/x86_64/issue-82869.stderr
new file mode 100644
index 000000000..3cf9d6d1c
--- /dev/null
+++ b/src/test/ui/asm/x86_64/issue-82869.stderr
@@ -0,0 +1,24 @@
+error: invalid register class `vreg`: unknown register class
+ --> $DIR/issue-82869.rs:11:32
+ |
+LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+ | ^^^^^^^^^^^
+
+error: invalid register class `vreg`: unknown register class
+ --> $DIR/issue-82869.rs:11:45
+ |
+LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+ | ^^^^^^^^^^
+
+error: invalid register `d0`: unknown register
+ --> $DIR/issue-82869.rs:11:57
+ |
+LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+ | _________________________________________________________^
+LL | | || {};
+LL | | b
+LL | | });
+ | |_____^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/asm/x86_64/issue-89875.rs b/src/test/ui/asm/x86_64/issue-89875.rs
new file mode 100644
index 000000000..669fd7e7e
--- /dev/null
+++ b/src/test/ui/asm/x86_64/issue-89875.rs
@@ -0,0 +1,17 @@
+// build-pass
+// needs-asm-support
+// only-x86_64
+
+#![feature(target_feature_11)]
+
+use std::arch::asm;
+
+#[target_feature(enable = "avx")]
+fn main() {
+ unsafe {
+ asm!(
+ "/* {} */",
+ out(ymm_reg) _,
+ );
+ }
+}
diff --git a/src/test/ui/asm/x86_64/issue-96797.rs b/src/test/ui/asm/x86_64/issue-96797.rs
new file mode 100644
index 000000000..d3e0906f3
--- /dev/null
+++ b/src/test/ui/asm/x86_64/issue-96797.rs
@@ -0,0 +1,26 @@
+// build-pass
+// compile-flags: -O
+// min-llvm-version: 14.0.5
+// needs-asm-support
+// only-x86_64
+// only-linux
+
+// regression test for #96797
+
+#![feature(asm_sym)]
+
+use std::arch::global_asm;
+
+#[no_mangle]
+fn my_func() {}
+
+global_asm!("call_foobar: jmp {}", sym foobar);
+
+fn foobar() {}
+
+fn main() {
+ extern "Rust" {
+ fn call_foobar();
+ }
+ unsafe { call_foobar() };
+}
diff --git a/src/test/ui/asm/x86_64/may_unwind.rs b/src/test/ui/asm/x86_64/may_unwind.rs
new file mode 100644
index 000000000..9844d63f0
--- /dev/null
+++ b/src/test/ui/asm/x86_64/may_unwind.rs
@@ -0,0 +1,38 @@
+// min-llvm-version: 13.0.0
+// only-x86_64
+// run-pass
+// needs-asm-support
+
+#![feature(asm_sym, 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!(
+ "call {}",
+ sym panicky,
+ clobber_abi("C"),
+ options(may_unwind)
+ );
+ }
+ }))
+ .expect_err("expected a panic");
+ assert_eq!(*flag, false);
+}
diff --git a/src/test/ui/asm/x86_64/multiple-clobber-abi.rs b/src/test/ui/asm/x86_64/multiple-clobber-abi.rs
new file mode 100644
index 000000000..513eb270e
--- /dev/null
+++ b/src/test/ui/asm/x86_64/multiple-clobber-abi.rs
@@ -0,0 +1,35 @@
+// run-pass
+// needs-asm-support
+// only-x86_64
+
+// Checks that multiple clobber_abi options can be used
+
+#![feature(asm_sym)]
+
+use std::arch::asm;
+
+extern "sysv64" fn foo(x: i32) -> i32 {
+ x + 16
+}
+
+extern "win64" fn bar(x: i32) -> i32 {
+ x / 2
+}
+
+fn main() {
+ let x = 8;
+ let y: i32;
+ // call `foo` with `x` as the input, and then `bar` with the output of `foo`
+ // and output that to `y`
+ unsafe {
+ asm!(
+ "call {}; mov rcx, rax; call {}",
+ sym foo,
+ sym bar,
+ in("rdi") x,
+ out("rax") y,
+ clobber_abi("sysv64", "win64"),
+ );
+ }
+ assert_eq!((x, y), (8, 12));
+}
diff --git a/src/test/ui/asm/x86_64/parse-error.rs b/src/test/ui/asm/x86_64/parse-error.rs
new file mode 100644
index 000000000..9aeb6b285
--- /dev/null
+++ b/src/test/ui/asm/x86_64/parse-error.rs
@@ -0,0 +1,137 @@
+// only-x86_64
+
+#![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());
+ //~^ ERROR at least one abi must be provided
+ 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("eax") foo);
+ //~^ ERROR explicit register arguments cannot have names
+ asm!("{a}", in("eax") 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("eax") 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("eax") 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!("", clobber_abi("C"), clobber_abi("C"));
+//~^ ERROR `clobber_abi` cannot be used with `global_asm!`
+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/src/test/ui/asm/x86_64/parse-error.stderr b/src/test/ui/asm/x86_64/parse-error.stderr
new file mode 100644
index 000000000..57702c37b
--- /dev/null
+++ b/src/test/ui/asm/x86_64/parse-error.stderr
@@ -0,0 +1,458 @@
+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: at least one abi must be provided as an argument to `clobber_abi`
+ --> $DIR/parse-error.rs:42:30
+ |
+LL | asm!("", clobber_abi());
+ | ^
+
+error: expected string literal
+ --> $DIR/parse-error.rs:44:30
+ |
+LL | asm!("", clobber_abi(foo));
+ | ^^^ not a string literal
+
+error: expected one of `)` or `,`, found `foo`
+ --> $DIR/parse-error.rs:46:34
+ |
+LL | asm!("", clobber_abi("C" foo));
+ | ^^^ expected one of `)` or `,`
+
+error: expected string literal
+ --> $DIR/parse-error.rs:48:35
+ |
+LL | asm!("", clobber_abi("C", foo));
+ | ^^^ not a string literal
+
+error: arguments are not allowed after clobber_abi
+ --> $DIR/parse-error.rs:50:38
+ |
+LL | asm!("{}", clobber_abi("C"), const foo);
+ | ---------------- ^^^^^^^^^ argument
+ | |
+ | clobber_abi
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:53:29
+ |
+LL | asm!("", options(), clobber_abi("C"));
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:55:31
+ |
+LL | asm!("{}", options(), clobber_abi("C"), const foo);
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: duplicate argument named `a`
+ --> $DIR/parse-error.rs:57:36
+ |
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ------------- ^^^^^^^^^^^^^ duplicate argument
+ | |
+ | previously here
+
+error: argument never used
+ --> $DIR/parse-error.rs:57: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:62:18
+ |
+LL | asm!("", a = in("eax") foo);
+ | ^^^^^^^^^^^^^^^^^
+
+error: named arguments cannot follow explicit register arguments
+ --> $DIR/parse-error.rs:64:36
+ |
+LL | asm!("{a}", in("eax") foo, a = const bar);
+ | ------------- ^^^^^^^^^^^^^ named argument
+ | |
+ | explicit register argument
+
+error: named arguments cannot follow explicit register arguments
+ --> $DIR/parse-error.rs:67:36
+ |
+LL | asm!("{a}", in("eax") foo, a = const bar);
+ | ------------- ^^^^^^^^^^^^^ named argument
+ | |
+ | explicit register argument
+
+error: positional arguments cannot follow named arguments or explicit register arguments
+ --> $DIR/parse-error.rs:70:36
+ |
+LL | asm!("{1}", in("eax") 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:73: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:75: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:77: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:79: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:81:28
+ |
+LL | asm!("{}", in(reg) _);
+ | ^
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:83:31
+ |
+LL | asm!("{}", inout(reg) _);
+ | ^
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:85:35
+ |
+LL | asm!("{}", inlateout(reg) _);
+ | ^
+
+error: requires at least a template string argument
+ --> $DIR/parse-error.rs:92:1
+ |
+LL | global_asm!();
+ | ^^^^^^^^^^^^^
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:94:13
+ |
+LL | global_asm!(FOO);
+ | ^^^
+
+error: expected token: `,`
+ --> $DIR/parse-error.rs:96:18
+ |
+LL | global_asm!("{}" FOO);
+ | ^^^ expected `,`
+
+error: expected operand, options, or additional template string
+ --> $DIR/parse-error.rs:98:19
+ |
+LL | global_asm!("{}", FOO);
+ | ^^^ expected operand, options, or additional template string
+
+error: expected expression, found end of macro arguments
+ --> $DIR/parse-error.rs:100:24
+ |
+LL | global_asm!("{}", const);
+ | ^ expected expression
+
+error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
+ --> $DIR/parse-error.rs:102: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:104: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:106: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:108: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:110:30
+ |
+LL | global_asm!("{}", options(), const FOO);
+ | --------- ^^^^^^^^^ argument
+ | |
+ | previous options
+
+error: expected string literal
+ --> $DIR/parse-error.rs:112:29
+ |
+LL | global_asm!("", clobber_abi(FOO));
+ | ^^^ not a string literal
+
+error: expected one of `)` or `,`, found `FOO`
+ --> $DIR/parse-error.rs:114:33
+ |
+LL | global_asm!("", clobber_abi("C" FOO));
+ | ^^^ expected one of `)` or `,`
+
+error: expected string literal
+ --> $DIR/parse-error.rs:116:34
+ |
+LL | global_asm!("", clobber_abi("C", FOO));
+ | ^^^ not a string literal
+
+error: arguments are not allowed after clobber_abi
+ --> $DIR/parse-error.rs:118: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:118:19
+ |
+LL | global_asm!("{}", clobber_abi("C"), const FOO);
+ | ^^^^^^^^^^^^^^^^
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:121:28
+ |
+LL | global_asm!("", options(), clobber_abi("C"));
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:123:30
+ |
+LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: `clobber_abi` cannot be used with `global_asm!`
+ --> $DIR/parse-error.rs:125:17
+ |
+LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
+ | ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
+
+error: duplicate argument named `a`
+ --> $DIR/parse-error.rs:127:35
+ |
+LL | global_asm!("{a}", a = const FOO, a = const BAR);
+ | ------------- ^^^^^^^^^^^^^ duplicate argument
+ | |
+ | previously here
+
+error: argument never used
+ --> $DIR/parse-error.rs:127: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:130: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:132: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:134: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:136: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:50: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:57: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:57: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:64:46
+ |
+LL | let mut bar = 0;
+ | ----------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{a}", in("eax") foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:67:46
+ |
+LL | let mut bar = 0;
+ | ----------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{a}", in("eax") foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:70:42
+ |
+LL | let mut bar = 0;
+ | ----------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{1}", in("eax") foo, const bar);
+ | ^^^ non-constant value
+
+error: aborting due to 66 previous errors
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/asm/x86_64/srcloc.rs b/src/test/ui/asm/x86_64/srcloc.rs
new file mode 100644
index 000000000..1135ad2e1
--- /dev/null
+++ b/src/test/ui/asm/x86_64/srcloc.rs
@@ -0,0 +1,131 @@
+// only-x86_64
+// build-fail
+// 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: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!("
+ invalid_instruction
+ ");
+ //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(r#"
+ invalid_instruction
+ "#);
+ //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!("
+ mov eax, eax
+ invalid_instruction
+ mov eax, eax
+ ");
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(r#"
+ mov eax, eax
+ invalid_instruction
+ mov eax, eax
+ "#);
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(concat!("invalid", "_", "instruction"));
+ //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
+ //~^ WARN: scale factor without index register is ignored
+
+ asm!(
+ "invalid_instruction",
+ );
+ //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ "mov eax, eax",
+ "invalid_instruction",
+ "mov eax, eax",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ "mov eax, eax\n",
+ "invalid_instruction",
+ "mov eax, eax",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ "mov eax, eax",
+ concat!("invalid", "_", "instruction"),
+ "mov eax, eax",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ concat!("mov eax", ", ", "eax"),
+ concat!("invalid", "_", "instruction"),
+ concat!("mov eax", ", ", "eax"),
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ // Make sure template strings get separated
+ asm!(
+ "invalid_instruction1",
+ "invalid_instruction2",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2",
+ ),
+ );
+ //~^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2",
+ ),
+ concat!(
+ "invalid", "_", "instruction3", "\n",
+ "invalid", "_", "instruction4",
+ ),
+ );
+ //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+ //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
+ //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2", "\n",
+ ),
+ concat!(
+ "invalid", "_", "instruction3", "\n",
+ "invalid", "_", "instruction4", "\n",
+ ),
+ );
+ //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+ //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
+ //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'
+
+ asm!(
+ "",
+ "\n",
+ "invalid_instruction"
+ );
+ //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+ }
+}
diff --git a/src/test/ui/asm/x86_64/srcloc.stderr b/src/test/ui/asm/x86_64/srcloc.stderr
new file mode 100644
index 000000000..8899c1b91
--- /dev/null
+++ b/src/test/ui/asm/x86_64/srcloc.stderr
@@ -0,0 +1,302 @@
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:11:15
+ |
+LL | asm!("invalid_instruction");
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:15:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:13
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:20:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:13
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:26:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:13
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:33:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:13
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:38:14
+ |
+LL | asm!(concat!("invalid", "_", "instruction"));
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+warning: scale factor without index register is ignored
+ --> $DIR/srcloc.rs:41:15
+ |
+LL | asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:23
+ |
+LL | movaps %xmm3, (%esi, 2)
+ | ^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:45:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:51:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:58:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:65:13
+ |
+LL | concat!("invalid", "_", "instruction"),
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:72:13
+ |
+LL | concat!("invalid", "_", "instruction"),
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:79:14
+ |
+LL | "invalid_instruction1",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:80:14
+ |
+LL | "invalid_instruction2",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:86:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:86:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:95:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:95:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction3'
+ --> $DIR/srcloc.rs:99:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:1
+ |
+LL | invalid_instruction3
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction4'
+ --> $DIR/srcloc.rs:99:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:5:1
+ |
+LL | invalid_instruction4
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:110:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:110:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction3'
+ --> $DIR/srcloc.rs:114:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:5:1
+ |
+LL | invalid_instruction3
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction4'
+ --> $DIR/srcloc.rs:114:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:6:1
+ |
+LL | invalid_instruction4
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:127:14
+ |
+LL | "invalid_instruction"
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:5:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 24 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/asm/x86_64/sym.rs b/src/test/ui/asm/x86_64/sym.rs
new file mode 100644
index 000000000..622365bc7
--- /dev/null
+++ b/src/test/ui/asm/x86_64/sym.rs
@@ -0,0 +1,85 @@
+// min-llvm-version: 12.0.1
+// only-x86_64
+// only-linux
+// needs-asm-support
+// run-pass
+
+#![feature(thread_local, asm_sym)]
+
+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!("call {}", sym $func,
+ out("rax") result,
+ out("rcx") _, out("rdx") _, out("rdi") _, out("rsi") _,
+ out("r8") _, out("r9") _, out("r10") _, out("r11") _,
+ out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _,
+ out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _,
+ out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,
+ out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,
+ );
+ result
+ }
+ }
+}
+
+macro_rules! static_addr {
+ ($s:expr) => {
+ unsafe {
+ let result: *const u32;
+ // LEA performs a RIP-relative address calculation and returns the address
+ asm!("lea {}, [rip + {}]", out(reg) result, sym $s);
+ result
+ }
+ }
+}
+macro_rules! static_tls_addr {
+ ($s:expr) => {
+ unsafe {
+ let result: *const u32;
+ asm!(
+ "
+ # Load TLS base address
+ mov {out}, qword ptr fs:[0]
+ # Calculate the address of sym in the TLS block. The @tpoff
+ # relocation gives the offset of the symbol from the start
+ # of the TLS block.
+ lea {out}, [{out} + {sym}@tpoff]
+ ",
+ 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/src/test/ui/asm/x86_64/target-feature-attr.rs b/src/test/ui/asm/x86_64/target-feature-attr.rs
new file mode 100644
index 000000000..14490c3e0
--- /dev/null
+++ b/src/test/ui/asm/x86_64/target-feature-attr.rs
@@ -0,0 +1,42 @@
+// only-x86_64
+
+#![feature(avx512_target_feature)]
+
+use std::arch::asm;
+
+#[target_feature(enable = "avx")]
+unsafe fn foo() {
+ let mut x = 1;
+ let y = 2;
+ asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
+ assert_eq!(x, 3);
+}
+
+unsafe fn bar() {
+ let mut x = 1;
+ let y = 2;
+ asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
+ //~^ ERROR: register class `ymm_reg` requires the `avx` target feature
+ //~| ERROR: register class `ymm_reg` requires the `avx` target feature
+ //~| ERROR: register class `ymm_reg` requires the `avx` target feature
+ assert_eq!(x, 3);
+}
+
+#[target_feature(enable = "avx512bw")]
+unsafe fn baz() {
+ let x = 1;
+ asm!("/* {0} */", in(kreg) x);
+}
+
+unsafe fn baz2() {
+ let x = 1;
+ asm!("/* {0} */", in(kreg) x);
+ //~^ ERROR: register class `kreg` requires at least one of the following target features: avx512bw, avx512f
+}
+
+fn main() {
+ unsafe {
+ foo();
+ bar();
+ }
+}
diff --git a/src/test/ui/asm/x86_64/target-feature-attr.stderr b/src/test/ui/asm/x86_64/target-feature-attr.stderr
new file mode 100644
index 000000000..c852726ee
--- /dev/null
+++ b/src/test/ui/asm/x86_64/target-feature-attr.stderr
@@ -0,0 +1,26 @@
+error: register class `ymm_reg` requires the `avx` target feature
+ --> $DIR/target-feature-attr.rs:18:40
+ |
+LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
+ | ^^^^^^^^^^^^^
+
+error: register class `ymm_reg` requires the `avx` target feature
+ --> $DIR/target-feature-attr.rs:18:55
+ |
+LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
+ | ^^^^^^^^^^^^^
+
+error: register class `ymm_reg` requires the `avx` target feature
+ --> $DIR/target-feature-attr.rs:18:70
+ |
+LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
+ | ^^^^^^^^^^^^^^^^^^
+
+error: register class `kreg` requires at least one of the following target features: avx512bw, avx512f
+ --> $DIR/target-feature-attr.rs:33:23
+ |
+LL | asm!("/* {0} */", in(kreg) x);
+ | ^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/asm/x86_64/type-check-2.rs b/src/test/ui/asm/x86_64/type-check-2.rs
new file mode 100644
index 000000000..59d8cde3f
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-2.rs
@@ -0,0 +1,87 @@
+// only-x86_64
+
+#![feature(repr_simd, never_type, asm_sym)]
+
+use std::arch::{asm, global_asm};
+
+#[repr(simd)]
+struct SimdNonCopy(f32, f32, f32, f32);
+
+fn main() {
+ unsafe {
+ // Inputs must be initialized
+
+ let x: u64;
+ asm!("{}", in(reg) x);
+ let mut y: u64;
+ asm!("{}", inout(reg) y);
+ let _ = y;
+
+ // Outputs require mutable places
+
+ let v: Vec<u64> = vec![0, 1, 2];
+ asm!("{}", in(reg) v[0]);
+ asm!("{}", out(reg) v[0]);
+ asm!("{}", inout(reg) v[0]);
+
+ // 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
+ asm!("{}", sym x);
+ //~^ ERROR invalid `sym` operand
+
+ // Register operands must be Copy
+
+ asm!("{}", in(xmm_reg) 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!("{}", in(xmm_reg) std::arch::x86_64::_mm_setzero_ps());
+ 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/src/test/ui/asm/x86_64/type-check-2.stderr b/src/test/ui/asm/x86_64/type-check-2.stderr
new file mode 100644
index 000000000..d9ca25519
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-2.stderr
@@ -0,0 +1,83 @@
+error: invalid `sym` operand
+ --> $DIR/type-check-2.rs:35:24
+ |
+LL | asm!("{}", sym x);
+ | ^ is a local variable
+ |
+ = help: `sym` operands must refer to either a function or a static
+
+error: invalid `sym` operand
+ --> $DIR/type-check-2.rs:86: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:33: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:40:32
+ |
+LL | asm!("{}", in(xmm_reg) 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:52:28: 52:36]` for inline assembly
+ --> $DIR/type-check-2.rs:52: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:54: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:56: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:58: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:66: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:69: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 10 previous errors
+
diff --git a/src/test/ui/asm/x86_64/type-check-3.rs b/src/test/ui/asm/x86_64/type-check-3.rs
new file mode 100644
index 000000000..89c849c75
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-3.rs
@@ -0,0 +1,73 @@
+// only-x86_64
+// compile-flags: -C target-feature=+avx512f
+
+#![feature(asm_const)]
+
+use std::arch::{asm, global_asm};
+
+use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
+
+fn main() {
+ unsafe {
+ // Types must be listed in the register class.
+
+ asm!("{}", in(reg) 0i128);
+ //~^ ERROR type `i128` cannot be used with this register class
+ asm!("{}", in(reg) _mm_setzero_ps());
+ //~^ ERROR type `__m128` cannot be used with this register class
+ asm!("{}", in(reg) _mm256_setzero_ps());
+ //~^ ERROR type `__m256` cannot be used with this register class
+ asm!("{}", in(xmm_reg) 0u8);
+ //~^ ERROR type `u8` cannot be used with this register class
+ asm!("{:e}", in(reg) 0i32);
+ asm!("{}", in(xmm_reg) 0i32);
+ asm!("{:e}", in(reg) 0f32);
+ asm!("{}", in(xmm_reg) 0f32);
+ asm!("{}", in(xmm_reg) _mm_setzero_ps());
+ asm!("{:x}", in(ymm_reg) _mm_setzero_ps());
+ asm!("{}", in(kreg) 0u16);
+ asm!("{}", in(kreg) 0u64);
+ //~^ ERROR `avx512bw` target feature is not enabled
+
+ // Template modifier suggestions for sub-registers
+
+ 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
+ asm!("{}", in(reg) 0i32);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(reg) 0i64);
+ asm!("{}", in(ymm_reg) 0i64);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(ymm_reg) _mm256_setzero_ps());
+ asm!("{:l}", in(reg) 0i16);
+ asm!("{:l}", in(reg) 0i32);
+ asm!("{:l}", in(reg) 0i64);
+ asm!("{:x}", in(ymm_reg) 0i64);
+ asm!("{:x}", in(ymm_reg) _mm256_setzero_ps());
+
+ // Suggest different register class for type
+
+ asm!("{}", in(reg) 0i8);
+ //~^ ERROR type `i8` cannot be used with this register class
+ asm!("{}", in(reg_byte) 0i8);
+
+ // 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!("{:r}", inout(reg) 0u16 => val_i16);
+ asm!("{:r}", inout(reg) 0u32 => val_f32);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:r}", inout(reg) 0u32 => val_ptr);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:r}", inout(reg) main => val_u32);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:r}", inout(reg) 0u64 => val_ptr);
+ asm!("{:r}", inout(reg) main => val_u64);
+ }
+}
diff --git a/src/test/ui/asm/x86_64/type-check-3.stderr b/src/test/ui/asm/x86_64/type-check-3.stderr
new file mode 100644
index 000000000..b38ea8cc4
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-3.stderr
@@ -0,0 +1,118 @@
+error: type `i128` cannot be used with this register class
+ --> $DIR/type-check-3.rs:14:28
+ |
+LL | asm!("{}", in(reg) 0i128);
+ | ^^^^^
+ |
+ = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+
+error: type `__m128` cannot be used with this register class
+ --> $DIR/type-check-3.rs:16:28
+ |
+LL | asm!("{}", in(reg) _mm_setzero_ps());
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+
+error: type `__m256` cannot be used with this register class
+ --> $DIR/type-check-3.rs:18:28
+ |
+LL | asm!("{}", in(reg) _mm256_setzero_ps());
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+
+error: type `u8` cannot be used with this register class
+ --> $DIR/type-check-3.rs:20:32
+ |
+LL | asm!("{}", in(xmm_reg) 0u8);
+ | ^^^
+ |
+ = note: register class `xmm_reg` supports these types: i32, i64, f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
+
+error: `avx512bw` target feature is not enabled
+ --> $DIR/type-check-3.rs:29:29
+ |
+LL | asm!("{}", in(kreg) 0u64);
+ | ^^^^
+ |
+ = note: this is required to use type `u64` with register class `kreg`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:34:15
+ |
+LL | asm!("{0} {0}", in(reg) 0i16);
+ | ^^^ ^^^ ---- for this argument
+ |
+ = note: `#[warn(asm_sub_register)]` on by default
+ = help: use the `x` modifier to have the register formatted as `ax`
+ = help: or use the `r` modifier to keep the default formatting of `rax`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:36:15
+ |
+LL | asm!("{0} {0:x}", in(reg) 0i16);
+ | ^^^ ---- for this argument
+ |
+ = help: use the `x` modifier to have the register formatted as `ax`
+ = help: or use the `r` modifier to keep the default formatting of `rax`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:38:15
+ |
+LL | asm!("{}", in(reg) 0i32);
+ | ^^ ---- for this argument
+ |
+ = help: use the `e` modifier to have the register formatted as `eax`
+ = help: or use the `r` modifier to keep the default formatting of `rax`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:41:15
+ |
+LL | asm!("{}", in(ymm_reg) 0i64);
+ | ^^ ---- for this argument
+ |
+ = help: use the `x` modifier to have the register formatted as `xmm0`
+ = help: or use the `y` modifier to keep the default formatting of `ymm0`
+
+error: type `i8` cannot be used with this register class
+ --> $DIR/type-check-3.rs:52:28
+ |
+LL | asm!("{}", in(reg) 0i8);
+ | ^^^
+ |
+ = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+ = help: consider using the `reg_byte` register class instead
+
+error: incompatible types for asm inout argument
+ --> $DIR/type-check-3.rs:64:33
+ |
+LL | asm!("{:r}", 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:66:33
+ |
+LL | asm!("{:r}", 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:68:33
+ |
+LL | asm!("{:r}", 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 9 previous errors; 4 warnings emitted
+
diff --git a/src/test/ui/asm/x86_64/type-check-4.rs b/src/test/ui/asm/x86_64/type-check-4.rs
new file mode 100644
index 000000000..da3b76c3d
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-4.rs
@@ -0,0 +1,29 @@
+// only-x86_64
+// compile-flags: -C target-feature=+avx512f
+
+#![feature(asm_const, asm_sym)]
+
+use std::arch::{asm, global_asm};
+
+use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
+
+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/src/test/ui/asm/x86_64/type-check-4.stderr b/src/test/ui/asm/x86_64/type-check-4.stderr
new file mode 100644
index 000000000..33f4638fb
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-4.stderr
@@ -0,0 +1,27 @@
+error[E0013]: constants cannot refer to statics
+ --> $DIR/type-check-4.rs:22: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:25: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:28: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`.
diff --git a/src/test/ui/asm/x86_64/type-check-5.rs b/src/test/ui/asm/x86_64/type-check-5.rs
new file mode 100644
index 000000000..6190e0b52
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-5.rs
@@ -0,0 +1,63 @@
+// only-x86_64
+
+#![feature(repr_simd, never_type, asm_sym)]
+
+use std::arch::asm;
+
+#[repr(simd)]
+struct SimdNonCopy(f32, f32, f32, f32);
+
+fn main() {
+ unsafe {
+ // Inputs must be initialized
+
+ let x: u64;
+ asm!("{}", in(reg) x);
+ //~^ ERROR E0381
+ let mut y: u64;
+ asm!("{}", inout(reg) y);
+ //~^ ERROR E0381
+ let _ = y;
+
+ // Outputs require mutable places
+
+ let v: Vec<u64> = vec![0, 1, 2];
+ asm!("{}", in(reg) v[0]);
+ asm!("{}", out(reg) v[0]);
+ //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+ asm!("{}", inout(reg) v[0]);
+ //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+
+ // Sym operands must point to a function or static
+
+ const C: i32 = 0;
+ static S: i32 = 0;
+ asm!("{}", sym S);
+ asm!("{}", sym main);
+
+ // Register operands must be Copy
+
+ // Register operands must be integers, floats, SIMD vectors, pointers or
+ // function pointers.
+
+ asm!("{}", in(reg) 0i64);
+ asm!("{}", in(reg) 0f64);
+ asm!("{}", in(xmm_reg) std::arch::x86_64::_mm_setzero_ps());
+ asm!("{}", in(reg) 0 as *const u8);
+ asm!("{}", in(reg) 0 as *mut u8);
+ asm!("{}", in(reg) main as fn());
+
+ // Register inputs (but not outputs) allow references and function types
+
+ let mut f = main;
+ let mut r = &mut 0;
+ asm!("{}", in(reg) f);
+ asm!("{}", in(reg) r);
+ let _ = (f, r);
+
+ // Type checks ignore never type
+
+ let u: ! = unreachable!();
+ asm!("{}", in(reg) u);
+ }
+}
diff --git a/src/test/ui/asm/x86_64/type-check-5.stderr b/src/test/ui/asm/x86_64/type-check-5.stderr
new file mode 100644
index 000000000..e9c93fea5
--- /dev/null
+++ b/src/test/ui/asm/x86_64/type-check-5.stderr
@@ -0,0 +1,38 @@
+error[E0381]: used binding `x` isn't initialized
+ --> $DIR/type-check-5.rs:15:28
+ |
+LL | let x: u64;
+ | - binding declared here but left uninitialized
+LL | asm!("{}", in(reg) x);
+ | ^ `x` used here but it isn't initialized
+
+error[E0381]: used binding `y` isn't initialized
+ --> $DIR/type-check-5.rs:18: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
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+ --> $DIR/type-check-5.rs:26:29
+ |
+LL | let v: Vec<u64> = vec![0, 1, 2];
+ | - help: consider changing this to be mutable: `mut v`
+LL | asm!("{}", in(reg) v[0]);
+LL | asm!("{}", out(reg) v[0]);
+ | ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+ --> $DIR/type-check-5.rs:28:31
+ |
+LL | let v: Vec<u64> = vec![0, 1, 2];
+ | - help: consider changing this to be mutable: `mut v`
+...
+LL | asm!("{}", inout(reg) v[0]);
+ | ^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0381, E0596.
+For more information about an error, try `rustc --explain E0381`.