Skip to content

Commit

Permalink
RFC 2873 (asm!): Allow multiple template strings; interpret them as n…
Browse files Browse the repository at this point in the history
…ewline-separated
  • Loading branch information
joshtriplett committed Jun 15, 2020
1 parent 087ac5c commit 12017eb
Showing 1 changed file with 35 additions and 17 deletions.
52 changes: 35 additions & 17 deletions text/0000-inline-asm.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,13 @@ Let us see another example that also uses an input:
let i: u64 = 3;
let o: u64;
unsafe {
asm!("
mov {0}, {1}
add {0}, {number}
", out(reg) o, in(reg) i, number = const 5);
asm!(
"mov {0}, {1}",
"add {0}, {number}",
out(reg) o,
in(reg) i,
number = const 5,
);
}
assert_eq!(o, 8);
```
Expand Down Expand Up @@ -146,10 +149,13 @@ let mut a: u64 = 4;
let b: u64 = 4;
let c: u64 = 4;
unsafe {
asm!("
add {0}, {1}
add {0}, {2}
", inout(reg) a, in(reg) b, in(reg) c);
asm!(
"add {0}, {1}",
"add {0}, {2}",
inout(reg) a,
in(reg) b,
in(reg) c,
);
}
assert_eq!(a, 12);
```
Expand Down Expand Up @@ -259,12 +265,14 @@ This can also be used with a general register class (e.g. `reg`) to obtain a scr
// Multiply x by 6 using shifts and adds
let mut x: u64 = 4;
unsafe {
asm!("
mov {tmp}, {x}
shl {tmp}, 1
shl {x}, 2
add {x}, {tmp}
", x = inout(reg) x, tmp = out(reg) _);
asm!(
"mov {tmp}, {x}",
"shl {tmp}, 1",
"shl {x}, 2",
"add {x}, {tmp}",
x = inout(reg) x,
tmp = out(reg) _,
);
}
assert_eq!(x, 4 * 6);
```
Expand Down Expand Up @@ -372,17 +380,19 @@ reg_operand := dir_spec "(" reg_spec ")" operand_expr
operand := reg_operand / "const" const_expr / "sym" path
option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "att_syntax"
options := "options(" option *["," option] [","] ")"
asm := "asm!(" format_string *("," [ident "="] operand) ["," options] [","] ")"
asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," options] [","] ")"
```

The macro will initially be supported only on ARM, AArch64, x86, x86-64 and RISC-V targets. Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target.

[format-syntax]: https://doc.rust-lang.org/std/fmt/#syntax

## Template string
## Template strings

The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported.

An `asm!` invocation may have one or more template string arguments; an `asm!` with multiple template string arguments is treated as if the template strings were concatenated with a `\n` between them. The expected usage is for each template string argument to correspond to a line of assembly code. All template string arguments must appear before any other arguments.

As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after named arguments if any.

Explicit register operands cannot be used by placeholders in the template string. All other named and positional operands must appear at least once in the template string, otherwise a compiler error is generated.
Expand Down Expand Up @@ -1007,6 +1017,12 @@ Including the name of the target architecture as part of the `asm!` invocation c

The operands could be placed before the template string, which could make the asm easier to read in some cases. However we decided against it because the benefits are small and the syntax would no longer mirror that of Rust format string.

## Operands interleaved with template string arguments

An asm directive could contain a series of template string arguments, each followed by the operands referenced in that template string. This could potentially simplify long blocks of assembly. However, this could introduce significant complexity and difficulty of reading, due to the numbering of positional arguments, and the possibility of referencing named or numbered arguments other than those that appear grouped with a given template string.

Experimentation with such mechanisms could take place in wrapper macros around `asm!`, rather than in `asm!` itself.

# Prior art
[prior-art]: #prior-art

Expand Down Expand Up @@ -1043,7 +1059,9 @@ GCC supports passing C labels (the ones used with `goto`) to an inline asm block
This could be supported by allowing code blocks to be specified as operand types. The following code will print `a` if the input value is `42`, or print `b` otherwise.

```rust
asm!("cmp {}, 42; jeq {}",
asm!(
"cmp {}, 42",
"jeq {}",
in(reg) val,
label { println!("a"); },
fallthrough { println!("b"); }
Expand Down

0 comments on commit 12017eb

Please sign in to comment.