mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-12 20:16:49 +00:00
Auto merge of #86599 - Amanieu:asm_raw, r=nagisa
Add a "raw" option for asm! which ignores format string specifiers This is useful when including raw assembly snippets using `include_str!`.
This commit is contained in:
commit
e6b4c252ea
@ -1935,6 +1935,7 @@ bitflags::bitflags! {
|
||||
const NORETURN = 1 << 4;
|
||||
const NOSTACK = 1 << 5;
|
||||
const ATT_SYNTAX = 1 << 6;
|
||||
const RAW = 1 << 7;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2284,6 +2284,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);
|
||||
});
|
||||
|
@ -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,
|
||||
|
@ -1444,6 +1444,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);
|
||||
});
|
||||
|
@ -456,7 +456,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] [","] ")"
|
||||
```
|
||||
@ -781,6 +781,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.
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user