about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/ast.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs10
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs3
-rw-r--r--src/doc/unstable-book/src/library-features/asm.md3
-rw-r--r--src/test/codegen/asm-options.rs7
-rw-r--r--src/test/ui/asm/bad-options.stderr24
-rw-r--r--src/test/ui/asm/parse-error.stderr20
8 files changed, 48 insertions, 23 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index b3bac1d7ecd..352385ca1f2 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1933,6 +1933,7 @@ bitflags::bitflags! {
         const NORETURN = 1 << 4;
         const NOSTACK = 1 << 5;
         const ATT_SYNTAX = 1 << 6;
+        const RAW = 1 << 7;
     }
 }
 
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index b7bb896f318..f9b735fc69d 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -2274,6 +2274,9 @@ impl<'a> State<'a> {
                 if opts.contains(InlineAsmOptions::ATT_SYNTAX) {
                     options.push("att_syntax");
                 }
+                if opts.contains(InlineAsmOptions::RAW) {
+                    options.push("raw");
+                }
                 s.commasep(Inconsistent, &options, |s, &opt| {
                     s.word(opt);
                 });
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index b28c6f0d99c..97e07d52cc3 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -356,6 +356,8 @@ fn parse_options<'a>(
             try_set_option(p, args, sym::nostack, ast::InlineAsmOptions::NOSTACK);
         } else if p.eat_keyword(sym::att_syntax) {
             try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX);
+        } else if p.eat_keyword(kw::Raw) {
+            try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW);
         } else {
             return p.unexpected();
         }
@@ -467,6 +469,14 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
             }
         }
 
+        // Don't treat raw asm as a format string.
+        if args.options.contains(ast::InlineAsmOptions::RAW) {
+            template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string()));
+            let template_num_lines = 1 + template_str.matches('\n').count();
+            line_spans.extend(std::iter::repeat(template_sp).take(template_num_lines));
+            continue;
+        }
+
         let mut parser = parse::Parser::new(
             template_str,
             str_style,
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 2b932b7c953..ad12620c5e4 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1446,6 +1446,9 @@ impl<'a> State<'a> {
                 if opts.contains(ast::InlineAsmOptions::ATT_SYNTAX) {
                     options.push("att_syntax");
                 }
+                if opts.contains(ast::InlineAsmOptions::RAW) {
+                    options.push("raw");
+                }
                 s.commasep(Inconsistent, &options, |s, &opt| {
                     s.word(opt);
                 });
diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md
index 5503b3b4b32..2456beba486 100644
--- a/src/doc/unstable-book/src/library-features/asm.md
+++ b/src/doc/unstable-book/src/library-features/asm.md
@@ -455,7 +455,7 @@ reg_spec := <register class> / "<explicit register>"
 operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_"
 reg_operand := dir_spec "(" reg_spec ")" operand_expr
 operand := reg_operand / "const" const_expr / "sym" path
-option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax"
+option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw"
 options := "options(" option *["," option] [","] ")"
 asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," options] [","] ")"
 ```
@@ -775,6 +775,7 @@ Currently the following options are defined:
 - `noreturn`: The `asm` block never returns, and its return type is defined as `!` (never). Behavior is undefined if execution falls through past the end of the asm code. A `noreturn` asm block behaves just like a function which doesn't return; notably, local variables in scope are not dropped before it is invoked.
 - `nostack`: The `asm` block does not push data to the stack, or write to the stack red-zone (if supported by the target). If this option is *not* used then the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call.
 - `att_syntax`: This option is only valid on x86, and causes the assembler to use the `.att_syntax prefix` mode of the GNU assembler. Register operands are substituted in with a leading `%`.
+- `raw`: This causes the template string to be parsed as a raw assembly string, with no special handling for `{` and `}`. This is primarily useful when including raw assembly code from an external file using `include_str!`.
 
 The compiler performs some additional checks on options:
 - The `nomem` and `readonly` options are mutually exclusive: it is a compile-time error to specify both.
diff --git a/src/test/codegen/asm-options.rs b/src/test/codegen/asm-options.rs
index 70391661b0c..28df0f9b852 100644
--- a/src/test/codegen/asm-options.rs
+++ b/src/test/codegen/asm-options.rs
@@ -94,3 +94,10 @@ pub unsafe fn dont_remove_nonpure() {
     asm!("", options(nomem));
     asm!("", options(readonly));
 }
+
+// CHECK-LABEL: @raw
+// CHECK: call void asm sideeffect inteldialect "{} {}", ""()
+#[no_mangle]
+pub unsafe fn raw() {
+    asm!("{} {}", options(nostack, nomem, preserves_flags, raw));
+}
diff --git a/src/test/ui/asm/bad-options.stderr b/src/test/ui/asm/bad-options.stderr
index 4e27a6e2cb5..9039483be4b 100644
--- a/src/test/ui/asm/bad-options.stderr
+++ b/src/test/ui/asm/bad-options.stderr
@@ -28,41 +28,41 @@ error: asm outputs are not allowed with the `noreturn` option
 LL |         asm!("{}", out(reg) foo, options(noreturn));
    |                    ^^^^^^^^^^^^
 
-error: expected one of `)` or `att_syntax`, found `nomem`
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
   --> $DIR/bad-options.rs:20:25
    |
 LL | global_asm!("", options(nomem));
-   |                         ^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `readonly`
+error: expected one of `)`, `att_syntax`, or `raw`, found `readonly`
   --> $DIR/bad-options.rs:22:25
    |
 LL | global_asm!("", options(readonly));
-   |                         ^^^^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `noreturn`
+error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn`
   --> $DIR/bad-options.rs:24:25
    |
 LL | global_asm!("", options(noreturn));
-   |                         ^^^^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `pure`
+error: expected one of `)`, `att_syntax`, or `raw`, found `pure`
   --> $DIR/bad-options.rs:26:25
    |
 LL | global_asm!("", options(pure));
-   |                         ^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `nostack`
+error: expected one of `)`, `att_syntax`, or `raw`, found `nostack`
   --> $DIR/bad-options.rs:28:25
    |
 LL | global_asm!("", options(nostack));
-   |                         ^^^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `preserves_flags`
+error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags`
   --> $DIR/bad-options.rs:30:25
    |
 LL | global_asm!("", options(preserves_flags));
-   |                         ^^^^^^^^^^^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/asm/parse-error.stderr b/src/test/ui/asm/parse-error.stderr
index afd262b851c..33dca61dc8e 100644
--- a/src/test/ui/asm/parse-error.stderr
+++ b/src/test/ui/asm/parse-error.stderr
@@ -64,11 +64,11 @@ error: argument to `sym` must be a path expression
 LL |         asm!("{}", sym foo + bar);
    |                        ^^^^^^^^^
 
-error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo`
+error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
   --> $DIR/parse-error.rs:31:26
    |
 LL |         asm!("", options(foo));
-   |                          ^^^ expected one of 8 possible tokens
+   |                          ^^^ expected one of 9 possible tokens
 
 error: expected one of `)` or `,`, found `foo`
   --> $DIR/parse-error.rs:33:32
@@ -76,11 +76,11 @@ error: expected one of `)` or `,`, found `foo`
 LL |         asm!("", options(nomem foo));
    |                                ^^^ expected one of `)` or `,`
 
-error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo`
+error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
   --> $DIR/parse-error.rs:35:33
    |
 LL |         asm!("", options(nomem, foo));
-   |                                 ^^^ expected one of 8 possible tokens
+   |                                 ^^^ expected one of 9 possible tokens
 
 error: arguments are not allowed after options
   --> $DIR/parse-error.rs:37:31
@@ -200,23 +200,23 @@ error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
 LL | global_asm!("{}", const(reg) FOO);
    |                              ^^^ expected one of `,`, `.`, `?`, or an operator
 
-error: expected one of `)` or `att_syntax`, found `FOO`
+error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
   --> $DIR/parse-error.rs:81:25
    |
 LL | global_asm!("", options(FOO));
-   |                         ^^^ expected one of `)` or `att_syntax`
+   |                         ^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `nomem`
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
   --> $DIR/parse-error.rs:83:25
    |
 LL | global_asm!("", options(nomem FOO));
-   |                         ^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: expected one of `)` or `att_syntax`, found `nomem`
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
   --> $DIR/parse-error.rs:85:25
    |
 LL | global_asm!("", options(nomem, FOO));
-   |                         ^^^^^ expected one of `)` or `att_syntax`
+   |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: arguments are not allowed after options
   --> $DIR/parse-error.rs:87:30