From eaaa0bcf2643985aa0c5ecb0135888d7748a3954 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 25 May 2020 01:48:50 -0700 Subject: [PATCH 01/11] Blog post on new inline assembly syntax --- .../inside-rust/2020-05-25-new-inline-asm.md | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 posts/inside-rust/2020-05-25-new-inline-asm.md diff --git a/posts/inside-rust/2020-05-25-new-inline-asm.md b/posts/inside-rust/2020-05-25-new-inline-asm.md new file mode 100644 index 000000000..d86bc10b7 --- /dev/null +++ b/posts/inside-rust/2020-05-25-new-inline-asm.md @@ -0,0 +1,130 @@ +--- +layout: post +title: "New inline assembly syntax available in nightly" +author: Josh Triplett +description: "Rust has a new inline assembly syntax in nightly, please test" +team: the language team +--- + +In the course of optimization, OS or embedded development, or other kinds of +low-level programming, you may sometimes need to write native assembly code for +the processor you're running on. "Inline assembly" provides a simple way to +integrate some assembly instructions into a Rust program, feeding Rust +expressions in as input registers, and getting output directly into Rust +variables. We've introduced a new syntax for inline assembly in nightly Rust, +and we're seeking feedback on it; we believe this new syntax has a path to +stabilization in the future. + +Nightly Rust has had a syntax for "inline assembly" (`asm!`) for a long time; +however, this syntax just exposed a very raw version of LLVM's assembly +construct, with no safeguards to help developers use it. Getting any detail of +this syntax even slightly wrong tended to produce an Internal Compiler Error +(ICE) rather than the kind of friendly error message you've come to expect from +rustc. This syntax also had little to no hope of being supported on any +non-LLVM backend. As a result of these limitations, the `asm!` syntax was +highly unlikely to ever graduate from nightly to stable Rust, despite it being +one of the most requested features. + +In an effort to improve `asm!` and bring it to more users, [Amanieu +d'Antras](https://github.com/Amanieu) designed and implemented a new, +friendlier syntax for `asm!`. This syntax has had a long road: +- The proposal first started as a [pre-RFC on + internals](https://internals.rust-lang.org/t/pre-rfc-2-inline-assembly/11310). +- Inline assembly became the language team's first [project + group](https://github.com/rust-lang/rfcs/blob/master/text/2836-project-asm.md), + and iteratively designed RFCs in [the project group + repository](https://github.com/rust-lang/project-inline-asm/). +- [RFC 2873](https://github.com/rust-lang/rfcs/pull/2873) (still under + discussion) provides a specification for the syntax and its interaction with + the Rust language. +- We [renamed the existing `asm!` to + `llvm_asm!`](https://github.com/rust-lang/rust/pull/68404), so that people + currently using inline assembly on nightly can continue to use the existing + syntax for now. (We plan to remove this syntax eventually, given its fragile + ICE-happy nature, but while evaluating the new syntax we want the old syntax + available for comparison and alternatives.) +- [PR 69171](https://github.com/rust-lang/rust/pull/69171) (also by Amanieu) + implemented the new `asm!` syntax in nightly. + +Here's an example of using the new inline assembly syntax, to print a message +to standard output using a direct [`write` +syscall](https://man7.org/linux/man-pages/man2/write.2.html) on x86-64 Linux: + +```rust +#![feature(asm)] + +fn main() { + let buf = "Hello from asm!\n"; + let ret: i32; + unsafe { + asm!( + "syscall", + in("rax") 1, // syscall number + in("rdi") 1, // fd + in("rsi") buf.as_ptr(), + in("rdx") buf.len(), + out("rcx") _, // clobbered by syscalls + out("r11") _, // clobbered by syscalls + lateout("rax") ret, + ); + } + println!("write returned: {}", ret); +} +``` + +(You can [try this example on the +playground](https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=e983a5f5cffa51f4320f1176465d3a56).) + +The example above specifies the exact inputs, outputs, and clobbers required by +the Linux syscall calling convention. You can also provide inputs and outputs +via arbitrary registers, and the compiler will select appropriate registers for +you. The following example uses [bit manipulation +instructions](https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets) +to compute the bit numbers of all set bits in a value, and stores them in a +slice of memory: + +```rust +#![feature(asm)] + +fn main() { + let mut bits = [0u8; 64]; + for value in 0..=1024u64 { + let popcnt; + unsafe { + asm!(" + popcnt {popcnt}, {v} + 2: + blsi rax, {v} + jz 1f + xor {v}, rax + tzcnt rax, rax + stosb + jmp 2b + 1: + ", + v = inout(reg) value => _, + popcnt = out(reg) popcnt, + out("rax") _, // scratch + inout("rdi") bits.as_mut_ptr() => _, + ); + } + println!("bits of {}: {:?}", value, &bits[0..popcnt]); + } +} +``` + +(You can [try this example on the +playground](https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=38874735e48aa20289f23f5a3cbeae0c). +Note that this code serves to demonstrate inline assembly, not to demonstrate +an efficient implementation of any particular algorithm.) + +Notice that `value` and `popcnt` have registers selected for them, while +`bits.as_mut_ptr()` must go in the `rdi` register for use with the `stosb` +instruction. + +For full details on the new `asm!` syntax, see [RFC +2873](https://github.com/Amanieu/rfcs/blob/inline-asm/text/0000-inline-asm.md). +Please try it out, and [report any bugs via the rust issue +tracker](https://github.com/rust-lang/rust/issues/) with the tag `F-asm`. You +can also [report your experiences on the tracking +issue](https://github.com/rust-lang/rust/issues/72016). From db01c816f9079e5bc7229c4cebf159c016069c03 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 25 May 2020 15:42:24 -0700 Subject: [PATCH 02/11] Drop link to the tracking issue --- posts/inside-rust/2020-05-25-new-inline-asm.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/posts/inside-rust/2020-05-25-new-inline-asm.md b/posts/inside-rust/2020-05-25-new-inline-asm.md index d86bc10b7..e2c613439 100644 --- a/posts/inside-rust/2020-05-25-new-inline-asm.md +++ b/posts/inside-rust/2020-05-25-new-inline-asm.md @@ -125,6 +125,4 @@ instruction. For full details on the new `asm!` syntax, see [RFC 2873](https://github.com/Amanieu/rfcs/blob/inline-asm/text/0000-inline-asm.md). Please try it out, and [report any bugs via the rust issue -tracker](https://github.com/rust-lang/rust/issues/) with the tag `F-asm`. You -can also [report your experiences on the tracking -issue](https://github.com/rust-lang/rust/issues/72016). +tracker](https://github.com/rust-lang/rust/issues/) with the tag `F-asm`. From 43746507046ba21ca4d2ccbf6e18369069c49339 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 25 May 2020 15:42:36 -0700 Subject: [PATCH 03/11] Encourage people to translate inline assembly to the new syntax --- posts/inside-rust/2020-05-25-new-inline-asm.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/posts/inside-rust/2020-05-25-new-inline-asm.md b/posts/inside-rust/2020-05-25-new-inline-asm.md index e2c613439..9b3b93a38 100644 --- a/posts/inside-rust/2020-05-25-new-inline-asm.md +++ b/posts/inside-rust/2020-05-25-new-inline-asm.md @@ -124,5 +124,6 @@ instruction. For full details on the new `asm!` syntax, see [RFC 2873](https://github.com/Amanieu/rfcs/blob/inline-asm/text/0000-inline-asm.md). -Please try it out, and [report any bugs via the rust issue +Please try it out (including translating existing inline assembly to the new +syntax), and [report any bugs via the rust issue tracker](https://github.com/rust-lang/rust/issues/) with the tag `F-asm`. From 6b114d2be51ad54e1d1e0ccd1a5070d3f643819e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 25 May 2020 15:43:21 -0700 Subject: [PATCH 04/11] Improve prose --- posts/inside-rust/2020-05-25-new-inline-asm.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/posts/inside-rust/2020-05-25-new-inline-asm.md b/posts/inside-rust/2020-05-25-new-inline-asm.md index 9b3b93a38..712219ca5 100644 --- a/posts/inside-rust/2020-05-25-new-inline-asm.md +++ b/posts/inside-rust/2020-05-25-new-inline-asm.md @@ -27,7 +27,8 @@ one of the most requested features. In an effort to improve `asm!` and bring it to more users, [Amanieu d'Antras](https://github.com/Amanieu) designed and implemented a new, -friendlier syntax for `asm!`. This syntax has had a long road: +friendlier syntax for `asm!`. This syntax has had a long road from concept to +compiler implementation: - The proposal first started as a [pre-RFC on internals](https://internals.rust-lang.org/t/pre-rfc-2-inline-assembly/11310). - Inline assembly became the language team's first [project From 746757aafcd7e895202c23b9bc574342c8337787 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 25 May 2020 15:43:40 -0700 Subject: [PATCH 05/11] Slight copyedit --- posts/inside-rust/2020-05-25-new-inline-asm.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/posts/inside-rust/2020-05-25-new-inline-asm.md b/posts/inside-rust/2020-05-25-new-inline-asm.md index 712219ca5..139713eec 100644 --- a/posts/inside-rust/2020-05-25-new-inline-asm.md +++ b/posts/inside-rust/2020-05-25-new-inline-asm.md @@ -22,8 +22,8 @@ this syntax even slightly wrong tended to produce an Internal Compiler Error (ICE) rather than the kind of friendly error message you've come to expect from rustc. This syntax also had little to no hope of being supported on any non-LLVM backend. As a result of these limitations, the `asm!` syntax was -highly unlikely to ever graduate from nightly to stable Rust, despite it being -one of the most requested features. +highly unlikely to ever graduate from nightly to stable Rust, despite being one +of the most requested features. In an effort to improve `asm!` and bring it to more users, [Amanieu d'Antras](https://github.com/Amanieu) designed and implemented a new, From 36efb2b632722013252876cb577d3e90f1a689f2 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 25 May 2020 15:45:24 -0700 Subject: [PATCH 06/11] Point people to Zulip --- posts/inside-rust/2020-05-25-new-inline-asm.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/posts/inside-rust/2020-05-25-new-inline-asm.md b/posts/inside-rust/2020-05-25-new-inline-asm.md index 139713eec..05e455322 100644 --- a/posts/inside-rust/2020-05-25-new-inline-asm.md +++ b/posts/inside-rust/2020-05-25-new-inline-asm.md @@ -127,4 +127,7 @@ For full details on the new `asm!` syntax, see [RFC 2873](https://github.com/Amanieu/rfcs/blob/inline-asm/text/0000-inline-asm.md). Please try it out (including translating existing inline assembly to the new syntax), and [report any bugs via the rust issue -tracker](https://github.com/rust-lang/rust/issues/) with the tag `F-asm`. +tracker](https://github.com/rust-lang/rust/issues/) with the tag `F-asm`. You +can also discuss inline assembly by creating a topic on [the project-inline-asm +stream in +Zulip](https://rust-lang.zulipchat.com/#narrow/stream/216763-project-inline-asm). From 99055a7d856336b771ecbddf526f66a279c589ce Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 25 May 2020 23:14:26 -0700 Subject: [PATCH 07/11] the first -> one of the first --- posts/inside-rust/2020-05-25-new-inline-asm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posts/inside-rust/2020-05-25-new-inline-asm.md b/posts/inside-rust/2020-05-25-new-inline-asm.md index 05e455322..7a1e9b28e 100644 --- a/posts/inside-rust/2020-05-25-new-inline-asm.md +++ b/posts/inside-rust/2020-05-25-new-inline-asm.md @@ -31,7 +31,7 @@ friendlier syntax for `asm!`. This syntax has had a long road from concept to compiler implementation: - The proposal first started as a [pre-RFC on internals](https://internals.rust-lang.org/t/pre-rfc-2-inline-assembly/11310). -- Inline assembly became the language team's first [project +- Inline assembly became one of the language team's first [project group](https://github.com/rust-lang/rfcs/blob/master/text/2836-project-asm.md), and iteratively designed RFCs in [the project group repository](https://github.com/rust-lang/project-inline-asm/). From edd036d1d46c2c8763ad671a43fe4e5b5bb1a322 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 25 May 2020 23:17:29 -0700 Subject: [PATCH 08/11] Mention differences between LLVM and GCC syntax --- posts/inside-rust/2020-05-25-new-inline-asm.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/posts/inside-rust/2020-05-25-new-inline-asm.md b/posts/inside-rust/2020-05-25-new-inline-asm.md index 7a1e9b28e..fa8d5f66a 100644 --- a/posts/inside-rust/2020-05-25-new-inline-asm.md +++ b/posts/inside-rust/2020-05-25-new-inline-asm.md @@ -20,10 +20,12 @@ however, this syntax just exposed a very raw version of LLVM's assembly construct, with no safeguards to help developers use it. Getting any detail of this syntax even slightly wrong tended to produce an Internal Compiler Error (ICE) rather than the kind of friendly error message you've come to expect from -rustc. This syntax also had little to no hope of being supported on any -non-LLVM backend. As a result of these limitations, the `asm!` syntax was -highly unlikely to ever graduate from nightly to stable Rust, despite being one -of the most requested features. +rustc. This syntax was also error-prone for another reason: it looks similar to +GCC's inline assembly syntax, but has subtle differences (such as the names in +register constraints). This syntax also had little to no hope of being +supported on any non-LLVM backend. As a result of all these limitations, the +`asm!` syntax was highly unlikely to ever graduate from nightly to stable Rust, +despite being one of the most requested features. In an effort to improve `asm!` and bring it to more users, [Amanieu d'Antras](https://github.com/Amanieu) designed and implemented a new, From cc2509ab692e28ab8dbb9631adf1ceea5fc071fe Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 25 May 2020 23:18:11 -0700 Subject: [PATCH 09/11] Improve comment in syscall example: fd 1 is stdout --- posts/inside-rust/2020-05-25-new-inline-asm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posts/inside-rust/2020-05-25-new-inline-asm.md b/posts/inside-rust/2020-05-25-new-inline-asm.md index fa8d5f66a..0e74a4701 100644 --- a/posts/inside-rust/2020-05-25-new-inline-asm.md +++ b/posts/inside-rust/2020-05-25-new-inline-asm.md @@ -63,7 +63,7 @@ fn main() { asm!( "syscall", in("rax") 1, // syscall number - in("rdi") 1, // fd + in("rdi") 1, // fd (stdout) in("rsi") buf.as_ptr(), in("rdx") buf.len(), out("rcx") _, // clobbered by syscalls From b1fb3b4f2f2161f9070cb5e1ab8a34de45b47bee Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 26 May 2020 15:26:27 -0700 Subject: [PATCH 10/11] Typo fix --- posts/inside-rust/2020-05-25-new-inline-asm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posts/inside-rust/2020-05-25-new-inline-asm.md b/posts/inside-rust/2020-05-25-new-inline-asm.md index 0e74a4701..a113fd676 100644 --- a/posts/inside-rust/2020-05-25-new-inline-asm.md +++ b/posts/inside-rust/2020-05-25-new-inline-asm.md @@ -34,7 +34,7 @@ compiler implementation: - The proposal first started as a [pre-RFC on internals](https://internals.rust-lang.org/t/pre-rfc-2-inline-assembly/11310). - Inline assembly became one of the language team's first [project - group](https://github.com/rust-lang/rfcs/blob/master/text/2836-project-asm.md), + groups](https://github.com/rust-lang/rfcs/blob/master/text/2836-project-asm.md), and iteratively designed RFCs in [the project group repository](https://github.com/rust-lang/project-inline-asm/). - [RFC 2873](https://github.com/rust-lang/rfcs/pull/2873) (still under From 28e3167657057bf32ffa7991d5c59467cd45b746 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 8 Jun 2020 16:52:14 -0400 Subject: [PATCH 11/11] Rename 2020-05-25-new-inline-asm.md to 2020-06-08-new-inline-asm.md --- ...{2020-05-25-new-inline-asm.md => 2020-06-08-new-inline-asm.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename posts/inside-rust/{2020-05-25-new-inline-asm.md => 2020-06-08-new-inline-asm.md} (100%) diff --git a/posts/inside-rust/2020-05-25-new-inline-asm.md b/posts/inside-rust/2020-06-08-new-inline-asm.md similarity index 100% rename from posts/inside-rust/2020-05-25-new-inline-asm.md rename to posts/inside-rust/2020-06-08-new-inline-asm.md