about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-05-13 22:17:43 +0000
committerbors <bors@rust-lang.org>2021-05-13 22:17:43 +0000
commit17f30e5451f581d753899d2f628e5be354df33cd (patch)
tree58252137260855f9c5791b84bda1dcdb4d90407b /src
parent6d395a1c2946c79966490f5b1e6e619d3a713e6b (diff)
parenta7ed6a5196996f00dd78a391a44af51ee8088058 (diff)
downloadrust-17f30e5451f581d753899d2f628e5be354df33cd.tar.gz
rust-17f30e5451f581d753899d2f628e5be354df33cd.zip
Auto merge of #84107 - Amanieu:global_asm2, r=nagisa
Add support for const operands and options to global_asm!

On x86, the default syntax is also switched to Intel to match asm!.

Currently `global_asm!` only supports `const` operands and the `att_syntax` option. In the future, `sym` operands will also be supported. However there is no plan to support any of the other operand types or options since they don't make sense in the context of `global_asm!`.

r? `@nagisa`
Diffstat (limited to 'src')
-rw-r--r--src/doc/unstable-book/src/library-features/global-asm.md69
-rw-r--r--src/test/assembly/asm/global_asm.rs14
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs2
-rw-r--r--src/test/ui/asm/bad-arch.rs9
-rw-r--r--src/test/ui/asm/bad-arch.stderr14
-rw-r--r--src/test/ui/asm/bad-options.rs15
-rw-r--r--src/test/ui/asm/bad-options.stderr38
-rw-r--r--src/test/ui/asm/bad-template.rs21
-rw-r--r--src/test/ui/asm/bad-template.stderr87
-rw-r--r--src/test/ui/asm/const.rs6
-rw-r--r--src/test/ui/asm/duplicate-options.fixed5
-rw-r--r--src/test/ui/asm/duplicate-options.rs5
-rw-r--r--src/test/ui/asm/duplicate-options.stderr8
-rw-r--r--src/test/ui/asm/inline-syntax.arm.stderr28
-rw-r--r--src/test/ui/asm/inline-syntax.rs8
-rw-r--r--src/test/ui/asm/inline-syntax.x86_64.stderr24
-rw-r--r--src/test/ui/asm/parse-error.rs36
-rw-r--r--src/test/ui/asm/parse-error.stderr108
-rw-r--r--src/test/ui/asm/type-check-2.rs10
-rw-r--r--src/test/ui/asm/type-check-2.stderr8
-rw-r--r--src/test/ui/asm/type-check-3.rs20
-rw-r--r--src/test/ui/asm/type-check-3.stderr27
-rw-r--r--src/test/ui/macros/global-asm.rs4
-rw-r--r--src/test/ui/macros/global-asm.stderr6
24 files changed, 514 insertions, 58 deletions
diff --git a/src/doc/unstable-book/src/library-features/global-asm.md b/src/doc/unstable-book/src/library-features/global-asm.md
index ce1155a977c..146d17b4638 100644
--- a/src/doc/unstable-book/src/library-features/global-asm.md
+++ b/src/doc/unstable-book/src/library-features/global-asm.md
@@ -8,12 +8,9 @@ The tracking issue for this feature is: [#35119]
 
 The `global_asm!` macro allows the programmer to write arbitrary
 assembly outside the scope of a function body, passing it through
-`rustc` and `llvm` to the assembler. The macro is a no-frills
-interface to LLVM's concept of [module-level inline assembly]. That is,
-all caveats applicable to LLVM's module-level inline assembly apply
-to `global_asm!`.
-
-[module-level inline assembly]: http://llvm.org/docs/LangRef.html#module-level-inline-assembly
+`rustc` and `llvm` to the assembler. That is to say, `global_asm!` is
+equivalent to assembling the asm with an external assembler and then
+linking the resulting object file with the current crate.
 
 `global_asm!` fills a role not currently satisfied by either `asm!`
 or `#[naked]` functions. The programmer has _all_ features of the
@@ -38,11 +35,11 @@ And a more complicated usage looks like this:
 # mod x86 {
 
 pub mod sally {
-    global_asm!(r#"
-        .global foo
-      foo:
-        jmp baz
-    "#);
+    global_asm!(
+        ".global foo",
+        "foo:",
+        "jmp baz",
+    );
 
     #[no_mangle]
     pub unsafe extern "C" fn baz() {}
@@ -56,11 +53,11 @@ extern "C" {
 }
 
 pub mod harry {
-    global_asm!(r#"
-        .global bar
-      bar:
-        jmp quux
-    "#);
+    global_asm!(
+        ".global bar",
+        "bar:",
+        "jmp quux",
+    );
 
     #[no_mangle]
     pub unsafe extern "C" fn quux() {}
@@ -69,8 +66,44 @@ pub mod harry {
 ```
 
 You may use `global_asm!` multiple times, anywhere in your crate, in
-whatever way suits you. The effect is as if you concatenated all
-usages and placed the larger, single usage in the crate root.
+whatever way suits you. However, you should not rely on assembler state
+(e.g. assembler macros) defined in one `global_asm!` to be available in
+another one. It is implementation-defined whether the multiple usages
+are concatenated into one or assembled separately.
+
+`global_asm!` also supports `const` operands like `asm!`, which allows
+constants defined in Rust to be used in assembly code:
+
+```rust,no_run
+#![feature(global_asm)]
+# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
+# mod x86 {
+const C: i32 = 1234;
+global_asm!(
+    ".global bar",
+    "bar: .word {c}",
+    c = const C,
+);
+# }
+```
+
+The syntax for passing operands is the same as `asm!` except that only
+`const` operands are allowed. Refer to the [asm](asm.md) documentation
+for more details.
+
+On x86, the assembly code will use intel syntax by default. You can
+override this by adding `options(att_syntax)` at the end of the macro
+arguments list:
+
+```rust,no_run
+#![feature(global_asm)]
+# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
+# mod x86 {
+global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
+// is equivalent to
+global_asm!("mov ecx, {}", const 5);
+# }
+```
 
 ------------------------
 
diff --git a/src/test/assembly/asm/global_asm.rs b/src/test/assembly/asm/global_asm.rs
new file mode 100644
index 00000000000..3a7f2fa1efb
--- /dev/null
+++ b/src/test/assembly/asm/global_asm.rs
@@ -0,0 +1,14 @@
+// min-llvm-version: 10.0.1
+// only-x86_64
+// assembly-output: emit-asm
+// compile-flags: -C llvm-args=--x86-asm-syntax=intel
+
+#![feature(asm, global_asm)]
+#![crate_type = "rlib"]
+
+// CHECK: mov eax, eax
+global_asm!("mov eax, eax");
+// CHECK: mov ebx, 5
+global_asm!("mov ebx, {}", const 5);
+// CHECK: mov ecx, 5
+global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs
index 8e91a8d842c..791dec2ed69 100644
--- a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs
@@ -8,7 +8,7 @@ rust_plus_one_global_asm:
     movl (%rdi), %eax
     inc %eax
     retq
-"# );
+"#, options(att_syntax));
 
 extern {
     fn cc_plus_one_c(arg : &u32) -> u32;
diff --git a/src/test/ui/asm/bad-arch.rs b/src/test/ui/asm/bad-arch.rs
index 763b5fe5cca..3eeb76f3d00 100644
--- a/src/test/ui/asm/bad-arch.rs
+++ b/src/test/ui/asm/bad-arch.rs
@@ -8,12 +8,19 @@
 macro_rules! asm {
     () => {};
 }
+#[rustc_builtin_macro]
+macro_rules! global_asm {
+    () => {};
+}
 #[lang = "sized"]
 trait Sized {}
 
 fn main() {
     unsafe {
         asm!("");
-        //~^ ERROR asm! is unsupported on this target
+        //~^ 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.stderr b/src/test/ui/asm/bad-arch.stderr
index cb876f28650..6094643b038 100644
--- a/src/test/ui/asm/bad-arch.stderr
+++ b/src/test/ui/asm/bad-arch.stderr
@@ -1,8 +1,16 @@
-error[E0472]: asm! is unsupported on this target
-  --> $DIR/bad-arch.rs:16:9
+error[E0472]: inline assembly is unsupported on this target
+  --> $DIR/bad-arch.rs:20:9
    |
 LL |         asm!("");
    |         ^^^^^^^^^
 
-error: aborting due to previous error
+error[E0472]: inline assembly is unsupported on this target
+  --> $DIR/bad-arch.rs:25: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-options.rs b/src/test/ui/asm/bad-options.rs
index 755fc2ca238..923d65bfd96 100644
--- a/src/test/ui/asm/bad-options.rs
+++ b/src/test/ui/asm/bad-options.rs
@@ -1,6 +1,6 @@
 // only-x86_64
 
-#![feature(asm)]
+#![feature(asm, global_asm)]
 
 fn main() {
     let mut foo = 0;
@@ -16,3 +16,16 @@ fn main() {
         //~^ ERROR asm outputs are not allowed with the `noreturn` option
     }
 }
+
+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/bad-options.stderr b/src/test/ui/asm/bad-options.stderr
index c5e8e2ccf44..4e27a6e2cb5 100644
--- a/src/test/ui/asm/bad-options.stderr
+++ b/src/test/ui/asm/bad-options.stderr
@@ -28,5 +28,41 @@ error: asm outputs are not allowed with the `noreturn` option
 LL |         asm!("{}", out(reg) foo, options(noreturn));
    |                    ^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: expected one of `)` or `att_syntax`, found `nomem`
+  --> $DIR/bad-options.rs:20:25
+   |
+LL | global_asm!("", options(nomem));
+   |                         ^^^^^ expected one of `)` or `att_syntax`
+
+error: expected one of `)` or `att_syntax`, found `readonly`
+  --> $DIR/bad-options.rs:22:25
+   |
+LL | global_asm!("", options(readonly));
+   |                         ^^^^^^^^ expected one of `)` or `att_syntax`
+
+error: expected one of `)` or `att_syntax`, found `noreturn`
+  --> $DIR/bad-options.rs:24:25
+   |
+LL | global_asm!("", options(noreturn));
+   |                         ^^^^^^^^ expected one of `)` or `att_syntax`
+
+error: expected one of `)` or `att_syntax`, found `pure`
+  --> $DIR/bad-options.rs:26:25
+   |
+LL | global_asm!("", options(pure));
+   |                         ^^^^ expected one of `)` or `att_syntax`
+
+error: expected one of `)` or `att_syntax`, found `nostack`
+  --> $DIR/bad-options.rs:28:25
+   |
+LL | global_asm!("", options(nostack));
+   |                         ^^^^^^^ expected one of `)` or `att_syntax`
+
+error: expected one of `)` or `att_syntax`, found `preserves_flags`
+  --> $DIR/bad-options.rs:30:25
+   |
+LL | global_asm!("", options(preserves_flags));
+   |                         ^^^^^^^^^^^^^^^ expected one of `)` or `att_syntax`
+
+error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/asm/bad-template.rs b/src/test/ui/asm/bad-template.rs
index 21ce8c6236d..4404be4fa3a 100644
--- a/src/test/ui/asm/bad-template.rs
+++ b/src/test/ui/asm/bad-template.rs
@@ -1,6 +1,6 @@
 // only-x86_64
 
-#![feature(asm)]
+#![feature(asm, global_asm)]
 
 fn main() {
     let mut foo = 0;
@@ -26,3 +26,22 @@ fn main() {
         //~^ 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.stderr b/src/test/ui/asm/bad-template.stderr
index 1aea7467ed0..d95663d2a73 100644
--- a/src/test/ui/asm/bad-template.stderr
+++ b/src/test/ui/asm/bad-template.stderr
@@ -98,5 +98,90 @@ LL |         asm!("", in(reg) 0, in(reg) 1);
    |
    = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
 
-error: aborting due to 11 previous errors
+error: invalid reference to argument at index 0
+  --> $DIR/bad-template.rs:31:14
+   |
+LL | global_asm!("{}");
+   |              ^^ from here
+   |
+   = note: no arguments were given
+
+error: invalid reference to argument at index 1
+  --> $DIR/bad-template.rs:33:14
+   |
+LL | global_asm!("{1}", const FOO);
+   |              ^^^ from here
+   |
+   = note: there is 1 argument
+
+error: argument never used
+  --> $DIR/bad-template.rs:33: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:36:14
+   |
+LL | global_asm!("{a}");
+   |              ^^^
+
+error: invalid reference to argument at index 0
+  --> $DIR/bad-template.rs:38: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:38:19
+   |
+LL | global_asm!("{}", a = const FOO);
+   |                   ^^^^^^^^^^^^^
+
+error: named argument never used
+  --> $DIR/bad-template.rs:38: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:41: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:41: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:44:16
+   |
+LL | global_asm!("{:foo}", const FOO);
+   |                ^^^
+
+error: multiple unused asm arguments
+  --> $DIR/bad-template.rs:46: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} */"`
+
+error: aborting due to 21 previous errors
 
diff --git a/src/test/ui/asm/const.rs b/src/test/ui/asm/const.rs
index 0f6a7cd4474..fd940173c42 100644
--- a/src/test/ui/asm/const.rs
+++ b/src/test/ui/asm/const.rs
@@ -2,7 +2,7 @@
 // only-x86_64
 // run-pass
 
-#![feature(asm)]
+#![feature(asm, global_asm)]
 
 fn const_generic<const X: usize>() -> usize {
     unsafe {
@@ -34,3 +34,7 @@ fn main() {
     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/duplicate-options.fixed b/src/test/ui/asm/duplicate-options.fixed
index f4672a50fd0..d4444e9c6cc 100644
--- a/src/test/ui/asm/duplicate-options.fixed
+++ b/src/test/ui/asm/duplicate-options.fixed
@@ -1,7 +1,7 @@
 // only-x86_64
 // run-rustfix
 
-#![feature(asm)]
+#![feature(asm, global_asm)]
 
 fn main() {
     unsafe {
@@ -24,3 +24,6 @@ fn main() {
         );
     }
 }
+
+global_asm!("", options(att_syntax, ));
+//~^ ERROR the `att_syntax` option was already provided
diff --git a/src/test/ui/asm/duplicate-options.rs b/src/test/ui/asm/duplicate-options.rs
index 80292d7521a..fd28311984b 100644
--- a/src/test/ui/asm/duplicate-options.rs
+++ b/src/test/ui/asm/duplicate-options.rs
@@ -1,7 +1,7 @@
 // only-x86_64
 // run-rustfix
 
-#![feature(asm)]
+#![feature(asm, global_asm)]
 
 fn main() {
     unsafe {
@@ -24,3 +24,6 @@ fn main() {
         );
     }
 }
+
+global_asm!("", options(att_syntax, att_syntax));
+//~^ ERROR the `att_syntax` option was already provided
diff --git a/src/test/ui/asm/duplicate-options.stderr b/src/test/ui/asm/duplicate-options.stderr
index cd8d743e031..53edf8fb91c 100644
--- a/src/test/ui/asm/duplicate-options.stderr
+++ b/src/test/ui/asm/duplicate-options.stderr
@@ -52,5 +52,11 @@ error: the `noreturn` option was already provided
 LL |             options(noreturn),
    |                     ^^^^^^^^ this option was already provided
 
-error: aborting due to 9 previous errors
+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/inline-syntax.arm.stderr b/src/test/ui/asm/inline-syntax.arm.stderr
index bcae1d565f1..b1685bd4e02 100644
--- a/src/test/ui/asm/inline-syntax.arm.stderr
+++ b/src/test/ui/asm/inline-syntax.arm.stderr
@@ -1,5 +1,19 @@
 error: unknown directive
-  --> $DIR/inline-syntax.rs:25:15
+.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:29:15
    |
 LL |         asm!(".intel_syntax noprefix", "nop");
    |               ^
@@ -11,7 +25,7 @@ LL |     .intel_syntax noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:28:15
+  --> $DIR/inline-syntax.rs:32:15
    |
 LL |         asm!(".intel_syntax aaa noprefix", "nop");
    |               ^
@@ -23,7 +37,7 @@ LL |     .intel_syntax aaa noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:31:15
+  --> $DIR/inline-syntax.rs:35:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
    |               ^
@@ -35,7 +49,7 @@ LL |     .att_syntax noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:34:15
+  --> $DIR/inline-syntax.rs:38:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
    |               ^
@@ -47,7 +61,7 @@ LL |     .att_syntax bbb noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:37:15
+  --> $DIR/inline-syntax.rs:41:15
    |
 LL |         asm!(".intel_syntax noprefix; nop");
    |               ^
@@ -59,7 +73,7 @@ LL |     .intel_syntax noprefix; nop
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:43:13
+  --> $DIR/inline-syntax.rs:47:13
    |
 LL |             .intel_syntax noprefix
    |             ^
@@ -70,5 +84,5 @@ note: instantiated into assembly here
 LL |             .intel_syntax noprefix
    |             ^
 
-error: aborting due to 6 previous errors
+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
index 13ded19cfea..2d54ef7bd6b 100644
--- a/src/test/ui/asm/inline-syntax.rs
+++ b/src/test/ui/asm/inline-syntax.rs
@@ -16,6 +16,10 @@
 macro_rules! asm {
     () => {};
 }
+#[rustc_builtin_macro]
+macro_rules! global_asm {
+    () => {};
+}
 
 #[lang = "sized"]
 trait Sized {}
@@ -47,3 +51,7 @@ pub fn main() {
         //[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
index 02b29b09013..59c95194322 100644
--- a/src/test/ui/asm/inline-syntax.x86_64.stderr
+++ b/src/test/ui/asm/inline-syntax.x86_64.stderr
@@ -1,40 +1,46 @@
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:25:15
+  --> $DIR/inline-syntax.rs:55:14
    |
-LL |         asm!(".intel_syntax noprefix", "nop");
-   |               ^^^^^^^^^^^^^^^^^^^^^^
+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:28:15
+  --> $DIR/inline-syntax.rs:29:15
+   |
+LL |         asm!(".intel_syntax noprefix", "nop");
+   |               ^^^^^^^^^^^^^^^^^^^^^^
+
+warning: avoid using `.intel_syntax`, Intel syntax is the default
+  --> $DIR/inline-syntax.rs:32:15
    |
 LL |         asm!(".intel_syntax aaa noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
-  --> $DIR/inline-syntax.rs:31:15
+  --> $DIR/inline-syntax.rs:35:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
-  --> $DIR/inline-syntax.rs:34:15
+  --> $DIR/inline-syntax.rs:38:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:37:15
+  --> $DIR/inline-syntax.rs:41:15
    |
 LL |         asm!(".intel_syntax noprefix; nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:43:13
+  --> $DIR/inline-syntax.rs:47:13
    |
 LL |             .intel_syntax noprefix
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
-warning: 6 warnings emitted
+warning: 7 warnings emitted
 
diff --git a/src/test/ui/asm/parse-error.rs b/src/test/ui/asm/parse-error.rs
index f2e9d9ca08b..e62e6668415 100644
--- a/src/test/ui/asm/parse-error.rs
+++ b/src/test/ui/asm/parse-error.rs
@@ -1,6 +1,6 @@
 // only-x86_64
 
-#![feature(asm)]
+#![feature(asm, global_asm)]
 
 fn main() {
     let mut foo = 0;
@@ -63,3 +63,37 @@ fn main() {
         //~^ ERROR asm template must be a string literal
     }
 }
+
+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!("{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/parse-error.stderr b/src/test/ui/asm/parse-error.stderr
index 74918e1c400..afd262b851c 100644
--- a/src/test/ui/asm/parse-error.stderr
+++ b/src/test/ui/asm/parse-error.stderr
@@ -164,6 +164,112 @@ 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: requires at least a template string argument
+  --> $DIR/parse-error.rs:69:1
+   |
+LL | global_asm!();
+   | ^^^^^^^^^^^^^^
+
+error: asm template must be a string literal
+  --> $DIR/parse-error.rs:71:13
+   |
+LL | global_asm!(FOO);
+   |             ^^^
+
+error: expected token: `,`
+  --> $DIR/parse-error.rs:73:18
+   |
+LL | global_asm!("{}" FOO);
+   |                  ^^^ expected `,`
+
+error: expected operand, options, or additional template string
+  --> $DIR/parse-error.rs:75:19
+   |
+LL | global_asm!("{}", FOO);
+   |                   ^^^ expected operand, options, or additional template string
+
+error: expected expression, found end of macro arguments
+  --> $DIR/parse-error.rs:77:24
+   |
+LL | global_asm!("{}", const);
+   |                        ^ expected expression
+
+error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
+  --> $DIR/parse-error.rs:79:30
+   |
+LL | global_asm!("{}", const(reg) FOO);
+   |                              ^^^ expected one of `,`, `.`, `?`, or an operator
+
+error: expected one of `)` or `att_syntax`, found `FOO`
+  --> $DIR/parse-error.rs:81:25
+   |
+LL | global_asm!("", options(FOO));
+   |                         ^^^ expected one of `)` or `att_syntax`
+
+error: expected one of `)` or `att_syntax`, found `nomem`
+  --> $DIR/parse-error.rs:83:25
+   |
+LL | global_asm!("", options(nomem FOO));
+   |                         ^^^^^ expected one of `)` or `att_syntax`
+
+error: expected one of `)` or `att_syntax`, found `nomem`
+  --> $DIR/parse-error.rs:85:25
+   |
+LL | global_asm!("", options(nomem, FOO));
+   |                         ^^^^^ expected one of `)` or `att_syntax`
+
+error: arguments are not allowed after options
+  --> $DIR/parse-error.rs:87:30
+   |
+LL | global_asm!("{}", options(), const FOO);
+   |                   ---------  ^^^^^^^^^ argument
+   |                   |
+   |                   previous options
+
+error: duplicate argument named `a`
+  --> $DIR/parse-error.rs:89:35
+   |
+LL | global_asm!("{a}", a = const FOO, a = const BAR);
+   |                    -------------  ^^^^^^^^^^^^^ duplicate argument
+   |                    |
+   |                    previously here
+
+error: argument never used
+  --> $DIR/parse-error.rs:89: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 `const` or `options`, found `""`
+  --> $DIR/parse-error.rs:92:28
+   |
+LL | global_asm!("", options(), "");
+   |                            ^^ expected one of `const` or `options`
+
+error: expected one of `const` or `options`, found `"{}"`
+  --> $DIR/parse-error.rs:94:30
+   |
+LL | global_asm!("{}", const FOO, "{}", const FOO);
+   |                              ^^^^ expected one of `const` or `options`
+
+error: asm template must be a string literal
+  --> $DIR/parse-error.rs:96: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:98: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:37:37
    |
@@ -218,6 +324,6 @@ LL |     let mut bar = 0;
 LL |         asm!("{1}", in("eax") foo, const bar);
    |                                          ^^^ non-constant value
 
-error: aborting due to 31 previous errors
+error: aborting due to 47 previous errors
 
 For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/asm/type-check-2.rs b/src/test/ui/asm/type-check-2.rs
index 0677167ccfe..060a88fc937 100644
--- a/src/test/ui/asm/type-check-2.rs
+++ b/src/test/ui/asm/type-check-2.rs
@@ -1,6 +1,6 @@
 // only-x86_64
 
-#![feature(asm, repr_simd, never_type)]
+#![feature(asm, global_asm, repr_simd, never_type)]
 
 #[repr(simd)]
 struct SimdNonCopy(f32, f32, f32, f32);
@@ -90,3 +90,11 @@ fn main() {
         asm!("{}", in(reg) u);
     }
 }
+
+// Const operands must be integer or floats, and must be constants.
+
+global_asm!("{}", const 0);
+global_asm!("{}", const 0i32);
+global_asm!("{}", const 0f32);
+global_asm!("{}", const 0 as *mut u8);
+//~^ ERROR asm `const` arguments must be integer or floating-point values
diff --git a/src/test/ui/asm/type-check-2.stderr b/src/test/ui/asm/type-check-2.stderr
index c152560a64f..f61f690bdb4 100644
--- a/src/test/ui/asm/type-check-2.stderr
+++ b/src/test/ui/asm/type-check-2.stderr
@@ -61,6 +61,12 @@ LL |         asm!("{}", inout(reg) r);
    |
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
+error: asm `const` arguments must be integer or floating-point values
+  --> $DIR/type-check-2.rs:99:19
+   |
+LL | global_asm!("{}", const 0 as *mut u8);
+   |                   ^^^^^^^^^^^^^^^^^^
+
 error: asm `sym` operand must point to a fn or static
   --> $DIR/type-check-2.rs:47:24
    |
@@ -103,7 +109,7 @@ LL |         let v: Vec<u64> = vec![0, 1, 2];
 LL |         asm!("{}", inout(reg) v[0]);
    |                               ^ cannot borrow as mutable
 
-error: aborting due to 14 previous errors
+error: aborting due to 15 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/type-check-3.rs b/src/test/ui/asm/type-check-3.rs
index 6890baead81..c2c1885ff16 100644
--- a/src/test/ui/asm/type-check-3.rs
+++ b/src/test/ui/asm/type-check-3.rs
@@ -1,7 +1,7 @@
 // only-x86_64
 // compile-flags: -C target-feature=+avx512f
 
-#![feature(asm)]
+#![feature(asm, global_asm)]
 
 use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
 
@@ -69,3 +69,21 @@ fn main() {
         asm!("{:r}", inout(reg) main => val_u64);
     }
 }
+
+// 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/type-check-3.stderr b/src/test/ui/asm/type-check-3.stderr
index 42497456ac3..9f6989ca03d 100644
--- a/src/test/ui/asm/type-check-3.stderr
+++ b/src/test/ui/asm/type-check-3.stderr
@@ -114,5 +114,30 @@ LL |         asm!("{:r}", inout(reg) main => val_u32);
    |
    = 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
+error[E0013]: constants cannot refer to statics
+  --> $DIR/type-check-3.rs:82: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-3.rs:85: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-3.rs:88: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 12 previous errors; 4 warnings emitted
 
+For more information about this error, try `rustc --explain E0013`.
diff --git a/src/test/ui/macros/global-asm.rs b/src/test/ui/macros/global-asm.rs
index 8402afa5085..b8903e07cfd 100644
--- a/src/test/ui/macros/global-asm.rs
+++ b/src/test/ui/macros/global-asm.rs
@@ -1,7 +1,7 @@
 #![feature(global_asm)]
 
 fn main() {
-    global_asm!();  //~ ERROR requires a string literal as an argument
+    global_asm!();  //~ ERROR requires at least a template string argument
     global_asm!(struct); //~ ERROR expected expression
-    global_asm!(123); //~ ERROR inline assembly must be a string literal
+    global_asm!(123); //~ ERROR asm template must be a string literal
 }
diff --git a/src/test/ui/macros/global-asm.stderr b/src/test/ui/macros/global-asm.stderr
index c43bf83fe19..a8621a0c518 100644
--- a/src/test/ui/macros/global-asm.stderr
+++ b/src/test/ui/macros/global-asm.stderr
@@ -1,8 +1,8 @@
-error: macro requires a string literal as an argument
+error: requires at least a template string argument
   --> $DIR/global-asm.rs:4:5
    |
 LL |     global_asm!();
-   |     ^^^^^^^^^^^^^^ string literal required
+   |     ^^^^^^^^^^^^^^
 
 error: expected expression, found keyword `struct`
   --> $DIR/global-asm.rs:5:17
@@ -10,7 +10,7 @@ error: expected expression, found keyword `struct`
 LL |     global_asm!(struct);
    |                 ^^^^^^ expected expression
 
-error: inline assembly must be a string literal
+error: asm template must be a string literal
   --> $DIR/global-asm.rs:6:17
    |
 LL |     global_asm!(123);