profile
viewpoint
Robin Lambertz roblabla @Seed-Up France, FR

PrismarineJS/mineflayer 1076

Create Minecraft bots with a powerful, stable, and high level JavaScript API.

reswitched/libtransistor 191

Open source toolchain for Switch development

MegatonHammer/megaton-hammer 50

The only tool you'll need to hit a Rusty Switch

PrismarineJS/pocket-minecraft-protocol 30

[En][de]code Minecraft packets

ProtoDef-io/node-protodef 18

Describe your protocol, and read it with ease.

h1k421/steam_controller_custom_firmware 8

A custom firmware for the Steam Controller in Rust

backupbrew/switchbrew 6

A backup of switchbrew. Click the website to go to generator ->

lpc-rs/lpc-pac 5

Peripheral Access Crates for LPC microcontrollers

reswitched/reswitched.team 4

The official website of team ReSwitched!

Gpinchon/RT42 1

Ray Tracer de l'école 42

PR opened smoltcp-rs/smoltcp

Re-export dhcp::clientv4::Config

The dhcpv4 client currently doesn't expose the Config struct returned by the poll function.

+1 -1

0 comment

1 changed file

pr created time in 12 hours

push eventroblabla/smoltcp

Robin Lambertz

commit sha 9ac75cd6c0094063fc1389b19a663b1f203c8244

Re-export dhcp::clientv4::Config The dhcpv4 client currently doesn't expose the Config struct returned by the poll function.

view details

push time in 12 hours

pull request commentsunriseos/SunriseOS

New rust-lang/rust workflow based on patches

This needs a few improvements before I'm confident with it. Currently, setup-rust will silently do nothing if the rust folder already exists. That's fairly conservative, which is a good property, but there is one case that I'd like to support before going forward: The user has done no changes to their rust repo, and the patches got updated. In this case, we should update their rust repo to the latest patches.

The other case to think about: The user has changes to their rust repo, and the patches got updated. In this case, the ideal thing to do would be to print a warning to the user telling them they need to somehow merge their patches with upstream's.

The difficulty here is that it's hard to detect if the patches got updated, especially since the user might cause a patch to change by amending an existing commit. We can probably detect unchanged patches through authorid shenanigans.

roblabla

comment created time in 3 days

push eventroblabla/KFS

roblabla

commit sha 064c913f0ed44baf42f61a153c6af023ed325f4c

New rust-lang/rust workflow based on patches

view details

push time in 3 days

PR opened sunriseos/SunriseOS

New rust-lang/rust workflow based on patches
+59 -1775305

0 comment

23632 changed files

pr created time in 3 days

create barnchroblabla/KFS

branch : rust-patches

created branch time in 3 days

issue openedsunriseos/SunriseOS

Move to new inline asm syntax

We should move to the new inline asm syntax instead of using llvm_asm, as it has a clear path to stabilization and is, in general, a lot less buggy.

Doing so will also make a lot of our code less UB "by default", as rust's inline asm defaults to making the code paranoid (e.g. it defaults to volatile, memory, etc... and has flag to disable them, instead of llvm_asm where by default the compiler assumes it can do a lot of opts that you have to manually disable).

created time in 3 days

push eventsunriseos/SunriseOS

roblabla

commit sha bf306c194d8a6dbe6b9eadabf8d865310a33ef70

Misc fixes Fixes clippy warnings in future rust version.

view details

roblabla

commit sha 1ad7b747b121299b80a83a074f347653c9dd60bb

Update to latest rust nightly

view details

roblabla

commit sha 4854c1bbd8cab812116a95f28862c09a8c544a48

Fix compat with new nightly - Removes unneeded features - Updates dependencies that don't build on new nightly. - Fix changes to unstable features. - Removes core-future-tls, as it is unneeded now.

view details

roblabla

commit sha d8d37db46e7432d95f01629b88f9da6d54a8989b

fixup! Update to latest rust nightly

view details

roblabla

commit sha 35980a9339a3ef95231f78f1b7b12da675a214b9

Move to llvm_asm macro The old asm macro got renamed llvm_asm, and asm is now the new recommended way to write inline asm. A move to the new inline asm is planned in a future PR.

view details

roblabla

commit sha e73cfe223f75b6710b68d353886b1cadd22af342

Fix documentation builds. - The doc_cfg feature is now stabilized. The cfg got replaced from cfg(rustdoc) to cfg(doc) - Fixes a ton of broken doclinks.

view details

roblabla

commit sha a3c40c3b3b5abf4416ffc17249ae5452f4db8d77

Add safety comments to all public unsafe fns

view details

roblabla

commit sha 61047b7896e6e165fa3d62c68831495528ca87d4

Simplify test makefile rule

view details

Robin Lambertz

commit sha 4e0abd8c414f736aed4bf36dcd5e9e28535b7a73

Merge pull request #584 from roblabla/update-rust-2020-05-27 Update to rust 2020-05-27

view details

push time in 3 days

PR merged sunriseos/SunriseOS

Update to rust 2020-05-27
+907636 -620492

0 comment

18973 changed files

roblabla

pr closed time in 3 days

push eventroblabla/KFS

roblabla

commit sha a3c40c3b3b5abf4416ffc17249ae5452f4db8d77

Add safety comments to all public unsafe fns

view details

roblabla

commit sha 61047b7896e6e165fa3d62c68831495528ca87d4

Simplify test makefile rule

view details

push time in 3 days

issue openeddarkreader/darkreader

[Broken Website] lkml.org is blindingly white

<!-- Thank you for taking the time to report a broken website. Please make sure there is no existing issue about this broken website. -->

Website Give the link to the website https://lkml.org/lkml/2020/5/29/1038

How to Reproduce Steps to reproduce the behavior: An example for this is

  1. Go to https://lkml.org/lkml/2020/5/29/1038 in dynamic mode
  2. Get blinded by how bright everything looks

Expected behavior I expect the website to be significantly darker. Currently, the text is white on almost white, which is borderline unreadable.

Screenshots image

System info:

  • OS: Windows
  • Browser: Firefox
  • Darkreader Version 4.9.9

created time in 4 days

push eventroblabla/KFS

roblabla

commit sha e73cfe223f75b6710b68d353886b1cadd22af342

Fix documentation builds. - The doc_cfg feature is now stabilized. The cfg got replaced from cfg(rustdoc) to cfg(doc) - Fixes a ton of broken doclinks.

view details

push time in 4 days

push eventroblabla/KFS

roblabla

commit sha 1ad7b747b121299b80a83a074f347653c9dd60bb

Update to latest rust nightly

view details

roblabla

commit sha 4854c1bbd8cab812116a95f28862c09a8c544a48

Fix compat with new nightly - Removes unneeded features - Updates dependencies that don't build on new nightly. - Fix changes to unstable features. - Removes core-future-tls, as it is unneeded now.

view details

roblabla

commit sha d8d37db46e7432d95f01629b88f9da6d54a8989b

fixup! Update to latest rust nightly

view details

roblabla

commit sha 35980a9339a3ef95231f78f1b7b12da675a214b9

Move to llvm_asm macro The old asm macro got renamed llvm_asm, and asm is now the new recommended way to write inline asm. A move to the new inline asm is planned in a future PR.

view details

push time in 4 days

push eventsunriseos/rust

roblabla

commit sha 1aea529cf21eeec37e99e02dbbdb2c4444fdb9a2

import stdarch in repo

view details

push time in 4 days

create barnchsunriseos/rust

branch : sunrise-2020-05-27

created branch time in 4 days

issue openedsunriseos/SunriseOS

Build with --locked on CI

We currently don't check that the lockfile is up to date on CI. This can easily be achieved by passing --locked to every cargo command on CI.

created time in 4 days

PR opened sunriseos/SunriseOS

Update to rust 2020-05-27
+76 -76

0 comment

34 changed files

pr created time in 4 days

create barnchroblabla/KFS

branch : update-rust-2020-05-27

created branch time in 4 days

pull request commentrust-lang/backtrace-rs

sys: Split dep-of-std and symbol prefix features

I don't think gimli is usable in no_std context, which would be necessary for integration into a libstd port. gimli-symbolize feature pulls the std feature.

roblabla

comment created time in 4 days

issue openedsunriseos/SunriseOS

Better rust-lang/rust integration strategy

Currently, we have a nearly full copy of the rust-lang repo in here. This is undesirable for multiple reason. It makes the repo heavier than it needs to be, and brings a ton of code that is actually unreachable. Besides, we only have very light patches to libstd, and a ton of "new" code for the libstd::sys.

I think we should move to a patch-based system. The idea is, we would only store a single (or maybe a couple) .patch files in the repo, that would get applied by the build system to the rust-src component. cargo make qemu would have a new step, "fork-rust", that would cp -r the rust-src module into rust/, and apply the patchfiles on top of it. A new command, cargo make create-patch, would automatically re-create the patchfile by running diff rust/ $(rust-src location)

Several benefits:

  1. It removes the current scenario where we have two sources of trust for the rust fork (sunriseos/rust and sunriseos/sunrise/rust). The fork could be kept to easily see the result of the patch, but be automatically updated through github actions, to prevent it from going out of sync.
  2. Updating to latest nightly becomes a fairly obvious and simple business: Just update the patches to make them work. No need to mess around with branches or whatever.

created time in 4 days

issue closedsunriseos/SunriseOS

Port libstd

We have a userspace. Next step is porting the libstd. This would allow us to use many of the nice interfaces from std, such as std::io, HashMaps, etc...

closed time in 4 days

roblabla

issue commentsunriseos/SunriseOS

Port libstd

This is done since #492

roblabla

comment created time in 4 days

push eventsunriseos/storage_device

roblabla

commit sha 0a7afef8936dfed2b1baef6e7a21fd8bda3370de

Address compilation failure in latest nightly. Use lru 0.5.0 to avoid unstable features.

view details

Robin Lambertz

commit sha 7b4bc4d2113242f5818d90a659a8f7c0ca4cce67

Merge pull request #27 from roblabla/latest-nightly Address compilation failure in latest nightly.

view details

push time in 5 days

PR merged sunriseos/storage_device

Address compilation failure in latest nightly.

Use lru 0.5.0 to avoid unstable features.

+87 -19

1 comment

3 changed files

roblabla

pr closed time in 5 days

pull request commentsunriseos/storage_device

Address compilation failure in latest nightly.

MFW we're still using travis-ci here.

roblabla

comment created time in 5 days

PR opened sunriseos/storage_device

Address compilation failure in latest nightly.

Use lru 0.5.0 to avoid unstable features.

+87 -19

0 comment

3 changed files

pr created time in 5 days

create barnchroblabla/storage_device

branch : latest-nightly

created branch time in 5 days

issue commentEmbarkStudios/cfg-expr

Switch away from enums towards strings in TargetInfo?

Using associated constants allows modeling an API that looks a lot like using an enum.

pub struct Vendor<'a>(&'a str);
impl Vendor {
    pub const pc: Vendor<'static> = Vendor("pc");
    pub const unknown: Vendor<'static> = "unknown";
    pub const uwp: Vendor<'static> = "uwp";
    pub const nvidia: Vendor<'static> = "nvidia";
    pub const sun: Vendor<'static> = "sun";
    pub const fortanix: Vendor<'static> = "fortanix";
    pub const wrs: Vendor<'static> = "wrs";
    pub const rumprun: Vendor<'static> = "rumprun";
    pub const apple: Vendor<'static> = "apple";
}

This allows using it almost exactly like an enum: it can be used when pattern matching, creating an instance of the Vendor type, etc...

match vendor {
    Vendor::wrs => (),
    Vendor::apple => (),
sunshowers

comment created time in 5 days

PR opened rust-lang/backtrace-rs

sys: Split dep-of-std and symbol prefix features

When building a libstd port out-of-tree using xargo's staged build system, libstd dependencies are allowed to rely on the presence of libcore, compiler-builtins, etc... in the sysroot. Such builds will thus want to remove the rustc-dep-of-std feature from libstd dependencies. Doing so for backtrace-sys, however, risks causing duplicate symbols between the sysroot and normal libraries. This is because backtrace-sys links in the libbacktrace library, and has some special logic associated with the rustc-dep-of-std feature to rename the symbols.

In order to better support such libstd crates, this commit splits the symbol renaming logic into its own feature, and makes that feature a dependency of rustc-dep-of-std.

+6 -2

0 comment

2 changed files

pr created time in 5 days

create barnchsunriseos/backtrace-rs

branch : xargo-dep-of-std

created branch time in 5 days

push eventsunriseos/lru-rs

roblabla

commit sha 2f887ec349395639fc77fcff31bb4691570be6f1

Fix compilation in default-features = false case

view details

push time in 5 days

push eventsunriseos/lru-rs

roblabla

commit sha af3b389581e18f2dd40000f54aa07ce9627491a9

Fix compilation in default-features = false case

view details

push time in 5 days

push eventsunriseos/lru-rs

roblabla

commit sha a6cbea4a2c373ba08e3b5146bf3ae355b31bcde4

Fix compilation in default-features = false case

view details

push time in 5 days

PR opened jeromefroe/lru-rs

Always use alloc crate, it's stable now

Alloc has been stable since 1.36.0, this crate's MSRV is 1.36.0. Therefore, there is no point in gating access to the alloc crate behind the nightly flag.

This change allows using this crate in no_std environment on stable rust.

+1 -5

0 comment

1 changed file

pr created time in 5 days

push eventsunriseos/lru-rs

roblabla

commit sha dd06cbd1f7dbdbae2fb5f96256acb60817eeb424

Always use alloc crate, it's stable now Alloc has been stable since 1.35.0, this crate's MSRV is 1.36.0. Therefore, there is no point in gating access to the alloc crate behind the nightly flag.

view details

push time in 5 days

fork roblabla/lru-rs

An implementation of a LRU cache

https://docs.rs/lru/

fork in 5 days

issue commentEmbarkStudios/cfg-expr

Switch away from enums towards strings in TargetInfo?

So my use-case is a custom OS I'm working on. I wanted to use cargo-guppy to find out why a feature gets pulled in one of my libstd dependencies. cargo-guppy uses this crate to parse cfg() expression found in Cargo.toml.

In my libstd fork, I use cfg(target_os = "sunrise") to add a custom that is only used when building for my custom target. cfg-expr chokes on it with the following error:

Error while computing package graph: for package 'std 0.0.0 (path+file:///home/roblabla/Dropbox/dev/src/rust/kfs-rust/src/libstd)': for dependency 'lazy_static', parsing target 'cfg(target_os = "sunrise")' failed: invalid cfg() expression: target_os = "sunrise"
             ^^^^^^^ expected one of `haiku`, `openbsd`, `freebsd`, `redox`, `vxworks`, `uefi`, `emscripten`, `netbsd`, `fuchsia`, `cloudabi`, `wasi`, `solaris`, `cuda`, `dragonfly`, `l4re`, `android`, `macos`, `hermit`, `linux`, `windows`, `unknown`, `ios` here
Aborting...

A lot of people working in embedded environment have to use custom targets.

sunshowers

comment created time in 5 days

create barnchsunriseos/libc

branch : sunrise-2020-05-27

created branch time in 6 days

create barnchsunriseos/compiler-builtins

branch : sunrise-2020-05-27

created branch time in 6 days

issue openedrust-lang/rust

Inline asm errors don't report file/line no information

<!-- Thank you for filing a bug report! 🐛 Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. -->

When an error within the assembly body of an inline asm happens (such as an invalid opcode), rust reports the error without pointing which inline asm instance (e.g. which file/line) caused it to happen. For instance:

#![feature(asm)]
fn main() {
    unsafe {asm!("out al, dx");}
}

The above "wrong" inline asm (on x86 32-bit) will report the following:

  Compiling playground v0.0.1 (/playground)
error: <inline asm>:2:2: error: invalid operand for instruction
        out al, dx
        ^

This makes it hard to track down where the error is caused.

Playground link.

Meta

rustc version: 1.45.0-nightly(2020-05-26 5239f5c57bb6eb9e8940)

created time in 6 days

issue commentrust-lang/rust

Tracking issue for RFC 2523, `#[cfg(version(..))]`

#[cfg(accessible)] has been prototyped and is available in nightly. It is accessible as #[cfg_accessible], see the implementation PR and the tracking issue.

It apparently has some limitations, though I haven't played with it enough to know what exactly the limitations are.

Centril

comment created time in 6 days

push eventsunriseos/compiler-builtins

Alex Crichton

commit sha 5e06435c291211a6443d3b29b948faa3ccaaa180

Merge pull request #299 from varkor/0.1.16 Bump to 0.1.16

view details

Ralf Jung

commit sha ebeace71ce4734b4382904db4b3aa619ac9fef16

avoid ptr::write which might panic in debug mode

view details

Ralf Jung

commit sha 25edd204fa324b00836dcd2d2cea362eeb627096

remove unused imports

view details

Ralf Jung

commit sha 65dacd7150f7e510881773ce603bba5b9395ffeb

avoid bare trait objects

view details

bjorn3

commit sha 783430e6ae1ccb0bf6265e4ec81f7c1596dd3eb0

Replace {u,i}128_* lang items with __rust_{u,i}128_* unmangled functions The -Zlower-128bit-ops feature is completely broken, as libcore needs those lang items to compile with this feature, but they are only provided by compiler_builtins, which itself depends on libcore. According to rust-lang/rust#58969 the feature never got finished. This commit removes the associated lang items and replaces them with normal unmangled functions, when there is no existing intrinsic. This makes it easier for alternative codegen backends to implement 128bit integer support.

view details

bjorn3

commit sha 7b716e628529ef33f731ef85a22477428299ca42

Fix tests

view details

Alex Crichton

commit sha 1ace96125747dd86fdfa6115b717e2ea9a76457a

Merge pull request #300 from RalfJung/panic avoid ptr::write which might panic in debug mode

view details

Alex Crichton

commit sha 18f2d2d4ce84e24fd4d63c7cf6178fd9f360a0c8

Bump to 0.1.17

view details

Alex Crichton

commit sha 56f5b5d898c2b4069c012b73c87c924fbb7c01da

Merge pull request #301 from RalfJung/dyn avoid bare trait objects

view details

Alex Crichton

commit sha e578d47247470935ebcc2bbfc81430b94f31ffd8

Merge pull request #302 from bjorn3/no_128bit_lang_items Replace {u,i}128_* lang items with __rust_{u,i}128_* unmangled functions

view details

Alex Crichton

commit sha 79a6a1603d5672cbb9187ff41ff4d9b5048ac1cb

Bump to 0.1.18

view details

Dan Aloni

commit sha 985a43095c82822e928e08ba3d12fad90ef8d59e

probestack: add frame pointers for easier traceback This turns the following backtrace, ``` >> bt #0 0x0000555555576f73 in __rust_probestack () at /cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.14/src/probestack.rs:55 Backtrace stopped: Cannot access memory at address 0x7fffff7fedf0 ``` To this: ``` >>> bt #0 0x0000555555574e47 in __rust_probestack () #1 0x00005555555595ba in test::main () #2 0x00005555555594f3 in std::rt::lang_start::{{closure}} () #3 0x0000555555561ae3 in std::panicking::try::do_call () #4 0x000055555556595a in __rust_maybe_catch_panic () #5 0x000055555555af9b in std::rt::lang_start_internal () #6 0x00005555555594d5 in std::rt::lang_start () #7 0x000055555555977b in main () ```

view details

Alex Crichton

commit sha c8b08eb47013a77a9f5e642195fe4855da7fe4f7

Merge pull request #306 from da-x/probestack-frame-pointer probestack: add frame pointers for easier traceback

view details

Alex Crichton

commit sha 36da64f20e96206ac279f700586817c8abe3bdf8

Bump to 0.1.19

view details

Joel Galenson

commit sha ca423fe49a9cb90baf5dd3cfefc13c11d6c1eb02

Support deterministic builds by remapping the __FILE__ prefix if the compiler supports it.

view details

Alex Crichton

commit sha 332220adea3177532af66e7757a2fbc46f1540ec

Modernize the `testcrate` slighty * Update `rand` dependency * Drop `cast` in favor of explicit casting or crate-defined * Move build script to 2018 edition

view details

Joel Galenson

commit sha c8f79289169e7cce857fc04c5ec02c820b9dbf48

Update comment to mention where the __FILE__ macro is used.

view details

Alex Crichton

commit sha f0b43234ddffdf11a3a61ec0ec843f784d10ac94

Merge pull request #309 from jgalenson/file-prefix-map Support deterministic builds by remapping the __FILE__ prefix if the …

view details

Alex Crichton

commit sha 1060f3434231c6884ffd44f35252ab67a02a390b

Merge pull request #310 from alexcrichton/modernize Modernize the `testcrate` slighty

view details

Benjamin Saunders

commit sha 997b86d76742843f6a209e98de003e3c5a378f47

Implement LLVM's elementwise unordered atomic memory intrinsics Allows uses of intrinsics of the form llvm.(memcpy|memmove|memset).element.unordered.atomic.* to be linked.

view details

push time in 6 days

create barnchsunriseos/compiler-builtins

branch : sunrise-2019-07-15

created branch time in 6 days

create barnchroblabla/compiler-builtins

branch : sunrise

created branch time in 6 days

create barnchroblabla/compiler-builtins

branch : sunrise-2019-07-15

created branch time in 6 days

create barnchsunriseos/rust

branch : sunrise-2019-07-15

created branch time in 6 days

push eventroblabla/ubuntu-installer

roblabla

commit sha 01d4fa4d4f22ab607de80fb48e9e48762295e235

Remove bindings/target folder

view details

roblabla

commit sha 407d1a8655bdbb1258976d1333d8218ec5f95827

Implement listing of volumes and ISO download Listing of volume is currently done through a combination of winrt and win32 API calls. This works, but is a bit fragile. Furthermore, it makes it hard to find the relationship between various volumes (e.g. if they're on the same drive). Ideally, we should move to using the WMI with the new Windows Storage Management API. Downloading the ISO uses reqwest on a separate thread, and communicates with the main thread through WizardEvents. This works-ish. It has abyssal performance (should probably throttle the events to only happen once every 500ms or something). A much better system would be to use BackgroundDownloader from the WinRT APIs. Unfortunately, I was unable to make it work. I believe it can only be done from an AppContainer (MSIX), and not from a normal exe. I wonder if it's possible to generate a temporary AppContainer from a .exe or something...

view details

push time in 6 days

issue openedmicrosoft/winrt-rs

Nuget example writes files outside OUT_DIR

Currently, the example build.rs for nuget packages writes outside build.rs, as seen here. This is a problem for two reason:

  1. Build scripts should not write to any files outside OUT_DIR, as documented here. In fact, even stronger languaged is found in the build script example, where it says:

    In general, build scripts should not modify any files outside of OUT_DIR. It may seem fine on the first blush, but it does cause problems when you use such crate as a dependency, because there's an implicit invariant that sources in .cargo/registry should be immutable. cargo won't allow such scripts when packaging.

  2. The script currently hardcodes the path to target, even though it's possible to relocate the target folder, see build.target-dir.


Unfortunately, I don't really have a simple solution. At the very least, the second problem can be addressed by using cargo_metadata to find the target folder, instead of hardcoding the path in the build.rs and the import macro.

In fact, cargo metadata is already used in the import macro, but it looks for the workspace root instead of using the target_path.


For the first point (avoiding writing to OUT_DIR), I thought a bit about the potential solutions, and here's the cleanest one I could think of: Use cargo.rustc-env to create an environment variable per winmd file, specifying the path where it can be found. E.G.

fn main() {
    let out_dir = std::env::var("OUT_DIR").unwrap();
    let src = current.join("nuget");
    for item in std::fs::read_dir(src) {
        println!("cargo:rustc-env=NUGET_DEP_{}={}", item.unwrap().file_name().into_string().unwrap(), out_dir);
    }
}

The nuget path resolver would then use std::env::var("NUGET_DEP_{}") to find where the winmd is. This could all be abstracted away behind a dep-dependency to simplify the implementation.

created time in 7 days

issue commentstkb/Rewrap

Feature Request: Select delimiter for unknown file extensions

In my project, we have a system that works like

// TODO: Issue name
// BODY: Content of the issue that can span multiple
// BODY: lines without issue

It'd be nice for rewrap to support arbitrary, user-supplied delimiters so I can have it automatically insert the // BODY: upon wrapping.

k0nker

comment created time in 8 days

issue openedrust-lang/rust

Passing function argument to new inline asm causes link-time errors

<!-- Thank you for filing a bug report! 🐛 Please provide a short summary of the bug, along with any information you feel relevant to replicating the bug. -->

#![feature(asm)]
fn main() {
    unsafe { asm!("call {}", sym test); }
}
extern fn test() {}

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=4c66087def8876f1661239ca3b06c976

I expected to see this happen: Compiles and runs properly.

Instead, this happened:

Compiling playground v0.0.1 (/playground)
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/playground/target/debug/deps/playground-61e6f3655c9a6266.playground.emtqmcym-cgu.0.rcgu.o" "-o" "/playground/target/debug/deps/playground-61e6f3655c9a6266" "/playground/target/debug/deps/playground-61e6f3655c9a6266.5cim9a2phvmas1o7.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-nodefaultlibs" "-L" "/playground/target/debug/deps" "-L" "/playground/target/debug/build/backtrace-sys-2c2318cf76eaa6fb/out" "-L" "/playground/target/debug/build/libsqlite3-sys-9220e77262ec64eb/out" "-L" "/playground/target/debug/build/ring-4d36d8941c8a810b/out" "-L" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,--start-group" "-Wl,-Bstatic" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-265ff16c7b6b86f9.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-e1b9e36b805e60e6.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-cad809dd31a6a599.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-8df8fedea90a4f43.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace-80ea260fe87a3015.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace_sys-07193842d2b8653a.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-455fbbd57f0ec4a9.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-af3c39aa14f4a8e2.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-d9a2bda701b5264b.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-ac41f78688451395.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-0465b718f70412d8.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-428d15b56101bdc7.rlib" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-941f7f6bc622e313.rlib" "-Wl,--end-group" "/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-a1755b3e88842f5d.rlib" "-Wl,-Bdynamic" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-ldl" "-lutil"
  = note: /playground/target/debug/deps/playground-61e6f3655c9a6266.playground.emtqmcym-cgu.0.rcgu.o: In function `playground::main':
          /playground/src/main.rs:3: undefined reference to `playground::test'
          collect2: error: ld returned 1 exit status
          

error: aborting due to previous error

Meta

<!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. -->

rustc --version --verbose: 1.45.0-nightly (2020-05-21 9310e3bd4f425f84fc27)

created time in 10 days

issue commentrust-lang/rust

inline-asm immediate constraint with fn argument crashes LLVM

@Amanieu The obvious equivalent in the new asm,

#![feature(asm)]
fn main() {
    unsafe { asm!("call {}", sym test); }
}
extern fn test() {}

Fails with a linking error. See https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=4c66087def8876f1661239ca3b06c976 . Should I open a new issue?

roblabla

comment created time in 10 days

issue commentmicrosoft/winrt-rs

Type Safety of ABI

This was fixed by https://github.com/microsoft/winrt-rs/pull/97

rylev

comment created time in 11 days

push eventroblabla/winrt-rs

roblabla

commit sha d2fc1eb85238bc4cfd9a532ebb9eb64a1f8f226f

Fix stack overflow in From<HString> for String impl

view details

push time in 13 days

PR opened microsoft/winrt-rs

Fix stack overflow in From<HString> for String impl

The current impl does an infinite recursion into itself, eventually leading to a stack overflow. I suppose the implementation was supposed to call the impl From<&HString> for String defined above.

+6 -1

0 comment

1 changed file

pr created time in 13 days

create barnchroblabla/winrt-rs

branch : fix-hstring-conversion

created branch time in 13 days

issue commentProtoDef-io/node-protodef

Try reusing the IIFE compiling concept to produce a protodef compiler for another language

A big part of what made the other compiler implementations more complex is that they support more than one datatype. For instance, in protodefc, custom datatype implementations generate an AST that is then lowered by the backend. This has the advantage that adding a custom datatype only needs to be done once (to generate the AST), and can directly be used in every language supported by protodefc.

In contrast, node-protodef compiler directly generates javascript code for custom datatypes that are parametrizable. This means that if we add another language, we need to rewrite those datatype definitions. This would quickly cause gigantic code duplication.

That's not, per se, a bad thing. I think this compiler is great because of how simple it is, which should make hacking on protodef very easy. But if we want to support more languages, I think we'll want to think of a simple AST that would then be turned by the language backend.

rom1504

comment created time in 13 days

issue commentkahole/edamagit

Show untracked files in magit status

Also note that it's possible to do git.untrackedChanges: "hide" in which case the git extension will completely ignore the untracked changes, making magit unable to see them at all! This makes me doubly think this is a defect in vscode. The git.status() API shouldn't be impacted by UI settings...

roblabla

comment created time in 13 days

issue commentkahole/edamagit

Show untracked files in magit status

TLDR: I managed to track down how to reproduce the issue. It's caused by the git.untrackedChanges: "separate" setting. It appears to be a defect in the VSCode git API, I'm not sure we can work around it.


So I ran the code under the vscode debugger, and managed to get a clearer view of what's going on. https://github.com/kahole/edamagit/blob/develop/src/commands/statusCommands.ts#L77 the git ls-files command is only run if repository.state.workingTreeChanges contains UNTRACKED changes. However, for some reason, repository.state does not contain any of the UNTRACKED changes on my computer. It appears to only contain MODIFIED changes.

I dug a bit into how vscode's status function is implemented. It calls git status -z -u (see https://github.com/microsoft/vscode/blob/master/extensions/git/src/git.ts#L1726). This output then gets parsed by Repository.status. The untracked file shows up as an ?? prefix: https://github.com/microsoft/vscode/blob/master/extensions/git/src/repository.ts#L1564

Here's the thing: I enabled the git.untrackedChanges: "separate" option (which separates the untracked files from the rest of the changes in the vscode "Source Control" view). This option also affects the Git API! When enabling this option, the untracked file changes don't go in workingTreeChanges like the rest, but in a untrackedChanges list.

I'm not entirely sure it's possible to actually access that list through the public API... This feels like a defect in vscode. Should we open an issue on the vscode tracker?

roblabla

comment created time in 13 days

issue openedmicrosoft/winrt-rs

Use-after-free in safe code through delegate support

The way delegates work right now, it's possible to pass a closure that takes references to the local stack frame that will be invalidated when the closure is called. For instance:

use winit::event_loop::EventLoopProxy;
use bindings::windows::ui::xaml::controls::{Button, IButtonFactory};
use bindings::windows::ui::xaml::RoutedEventHandler;
use winrt::Object;
fn new_btn(el_proxy: EventLoopProxy<()>) -> winrt::Result<Button> {
    let next_btn = winrt::factory::<Button, IButtonFactory>()?.create_instance(Object::default(), &mut Object::default())?;
    next_btn.click(RoutedEventHandler::new(|_, _| {
        let _ = el_proxy.send_event(());
        Ok(())
    }))?;
}

When the next_btn is clicked, the closure will try to call send_event on el_proxy through a reference (since closures take by reference by default, el_proxy will still be owned by the new_btn stack frame and not moved to the closure). But el_proxy goes out of scope once that function returns, and now the Button has a click handler that will cause a use-after-free when it's called, all in safe code!

There's a full reproducer of the crash is at https://github.com/roblabla/ubuntu-installer/tree/crash-reproducer . Doing cargo run and clicking the button causes an access violation.

I believe this needs to be fixed by giving a lifetime to delegates (e.g. the *Handler types) and tying the closure lifetime to the delegate lifetime. Most functions would then require the handlers to have a 'static lifetime.

created time in 13 days

push eventroblabla/ubuntu-installer

roblabla

commit sha e3ace1f05dde9c45ef34dfbfaf81aab95505b0c4

Use winrt-rs from git

view details

push time in 13 days

create barnchroblabla/ubuntu-installer

branch : crash-reproducer

created branch time in 13 days

pull request commentmicrosoft/winrt-rs

Add basic build crate for build.rss support

I can definitely say that putting bindings in a separate crate is a huge boon on recompilation speed. In https://github.com/roblabla/ubuntu-installer, if I move the bindings (which takes a whooping 75MiB...) in the main crate, it takes ~10 minutes to build the main crate on my machine, even with incremental compilation. By splitting the bindings in their own crate, I got compile time way down to a second or two after the bindings crate is compiled.

rylev

comment created time in 13 days

issue commentmicrosoft/winrt-rs

Support for Xaml Island

I've got a working XAML Island, see https://github.com/roblabla/ubuntu-installer

In particular the DesktopWindowXamlSource can be created with winrt::factory, see https://github.com/roblabla/ubuntu-installer/blob/master/src/main.rs#L33

06393993

comment created time in 14 days

issue commentkahole/edamagit

Show untracked files in magit status

E:\dev\projects\ubuntu-installer> git ls-files --others --exclude-standard --directory
bindings/target/debug/build/
bindings/target/debug/deps/
bindings/target/debug/examples/
bindings/target/debug/incremental/winrt-i3qifj4o32hd/s-fniqinkuht-sqp1ij-working/
src/wizard.rs
ui-research/
roblabla

comment created time in 14 days

issue commentkahole/edamagit

Show untracked files in magit status

It's on windows. $ is empty. Here's a screenshot showing the issue: image

roblabla

comment created time in 14 days

create barnchroblabla/ubuntu-installer

branch : master

created branch time in 14 days

created repositoryroblabla/ubuntu-installer

Why is installing linux so stupid complicated? It needn't be that way!

created time in 14 days

push eventroblabla/winrt-rs

Ryan Levick

commit sha 6dc3513f0c474fff37c2fe64714f025d187473a8

Add section to README about platform support (#145)

view details

Ryan Levick

commit sha 53a4a457abd3f1706cf8773a5c8e5dfd057ab2ec

Do not derive Default and PartialEq (#146) Co-authored-by: Kenny Kerr <kekerr@microsoft.com>

view details

Kenny Kerr

commit sha cdc8f236bc539e6ff4ed17cfd731ea09e894e20a

Update README.md

view details

Robin Lambertz

commit sha 0ee3479e41c44e4e9bf6f589b1a736e6bdda5d5f

Merge branch 'master' into restricted-error

view details

push time in 14 days

push eventroblabla/winrt-rs

roblabla

commit sha 52f9a126ac8cd9f910e808bb8045e31a66e685ec

Format code

view details

push time in 14 days

push eventroblabla/winrt-rs

roblabla

commit sha dd6e25446f16e2dbda4ba23c176b5c823ec83b43

Acquire extended information on errors. Call GetRestrictedErrorInfo() to acquire full error description when an error occurs. This change also adds an FFI wrapper around the BSTR type, and manual bindings to the IRestrictedErrorInfo COM object.

view details

push time in 14 days

PR opened microsoft/winrt-rs

Acquire extended information when an error occurs

Call GetRestrictedErrorInfo() to acquire full error description when an error occurs. This change also adds an FFI wrapper around the BSTR type, and manual bindings to the IRestrictedErrorInfo COM object.

This makes printing the errors a lot more useful, giving detailed information. Here's an example of a detailed error I acquired while working on a project:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { code: ErrorCode(-2147418113), info: Some(IRestrictedErrorInfo { description: "Catastrophic failure\r\n", error_code: ErrorCode(-2147418113), restricted_description: "WindowsXamlManager and DesktopWindowXamlSource are supported for apps targeting Windows version 10.0.18226.0 and later.  Please check either the application manifest or package manifest and ensure the MaxTestedVersion property is updated.", capability_sid: "" }) }', src\main.rs:31:26
+169 -3

0 comment

3 changed files

pr created time in 14 days

create barnchroblabla/winrt-rs

branch : restricted-error

created branch time in 14 days

fork roblabla/winrt-rs

Rust/WinRT is a Rust language projection for the Windows Runtime

fork in 14 days

issue openedkahole/edamagit

Show untracked files in magit status

Emacs magit has an option to allow showing a tree of untracked files in the magit status:

It'd be nice if edamagit could have an option to show those as well.

created time in 14 days

issue commentcaddyserver/caddy

superfluous response.WriteHeader after writing from an authentication module

@freman I don't understand why you're talking about configuration. My strategy doesn't require the user to configure anything unless they're using raw JSON (and if they're doing this, I expect them to want this kind of flexibility).

My strategy involves the plugin adding the error hadnling route itself, when converting from Caddyfile to JSON.

freman

comment created time in 14 days

issue commentcaddyserver/caddy

superfluous response.WriteHeader after writing from an authentication module

@freman what's wrong with using an error route? I suppose your users are using a Caddyfile (instead of using the JSON directly). When you go from caddyfile to JSON, it's possible to create multiple routes, such that your authentication module is wrapped in an error handling routine.

Look at https://github.com/caddyserver/caddy/issues/2894#issuecomment-589303660 and https://github.com/roblabla/caddy-jwt/blob/caddy2/config.go#L294

freman

comment created time in 15 days

issue commentcaddyserver/caddy

superfluous response.WriteHeader after writing from an authentication module

So, what I did in my JWT plugin is handle the redirection separately from the authentication, through the use of an error route. This is much better IMO, as it allows the end-user to have full flexibility over what happens in the case of an authentication failure if they so wish. You can easily generate a default error route in the JSON yourself in the parseDirective.

freman

comment created time in 15 days

issue commentProtoDef-io/ProtoDef

Add half-precision floating-point type

As a general rule, the vision I have for protodef is to have a very lean/minimal core that is mostly focused on generic containers and universal datatypes to enable 90% of the use-cases (in that sense, varint support in protodef was a mistake). More niche datatypes can exist as pluggable extensions, like how NMP adds UUID. This reduces maintenance of the core library and more easily allows experimentation (e.g. with compilers and such) since they don't initially have to worry about every weird datatype.

f16 feels extremely niche - I've never seen it used outside deep learning frameworks. Most languages don't natively support it (e.g. nodejs doesn't have a function on Buffer to read a half-float, Rust doesn't natively support f16, etc...), which would mean we'd have to roll our own. IMO this likely means that it'd be better suited as an out-of-tree extension.

Saiv46

comment created time in 16 days

pull request commentkahole/vscode-magit

Allow commiting without having code in PATH on win32 and linux

This is now tested in VSCode Insiders - Remote SSH (with linux on the remote side) and it works properly.

roblabla

comment created time in 20 days

push eventroblabla/vscode-magit

roblabla

commit sha 53ae4cb85c9de28c6c7a1fdb5620a5e75bb96163

Properly support linux

view details

push time in 20 days

push eventroblabla/vscode-magit

roblabla

commit sha f246d5559586d3abe75ad48ce265664a2acf7806

Properly support linux

view details

push time in 20 days

push eventroblabla/vscode-magit

roblabla

commit sha a8e09f74cbb6ea759a952a1de323ea67a9b12aad

Add support for code insiders

view details

roblabla

commit sha 21f03292f6fcaf1c2b3d87f06449bba3a2e3ebe2

Automatically find the code binary on win32/linux

view details

push time in 20 days

PR opened kahole/vscode-magit

Allow commiting without having code in PATH on win32 and linux

This PR fixes the commit flow to work in more situation:

  • On windows and linux, it will look for the code wrapper script in the correct places
  • When code-insiders is used, it will use the correct script name "code-insiders"

This should additionally make it work seamlessly when using vscode in Remote SSH mode, where the code/code-insiders script is unlikely to be in the PATH, but is untested until I can figure out how to load an extension from outside the marketplace on the remote server.

+13 -3

0 comment

1 changed file

pr created time in 20 days

push eventroblabla/vscode-magit

roblabla

commit sha e5f107e84676acc68650d89055213a199ce7fd7e

Add support for code insiders

view details

roblabla

commit sha d4ec41d2bcc56bf6843b6d4c14b0240b0054a47d

Automatically find the code binary on win32/linux

view details

push time in 20 days

issue commentrust-lang/rust

Tracking issue for RFC 2504, "Fix the Error trait"

@Nemo157 but that would cause coherence issues? Or are you suggesting adding a coherence exception to Backtrace as well?

Centril

comment created time in 22 days

issue commentrust-lang/rust

Tracking issue for RFC 2523, `#[cfg(version(..))]`

@dekellum Does cfg(accessible) not work for your use-case? It'd help to know what you're using cfg(version) to gate your code for.

Centril

comment created time in a month

pull request commentrust-lang/rust

Implement new asm! syntax from RFC 2850

I am hesitant to enforce the same strict rules as the borrow checker because it would disallow useful code that uses array indicies

This can be expressed with slice::split_at_mut, or, since this is unsafe anyways, with get_unchecked. This feels like a more general rust problem, the same problem shows up when you try to call a function with array members as arguments, e.g. call_fn(&mut a[0], &mut a[1]);

Amanieu

comment created time in a month

issue commentrust-lang/rust

Tracking issue for RFC 2504, "Fix the Error trait"

@yaahc the coherence issue is around the downcast method implemented on dyn Error: https://doc.rust-lang.org/stable/std/error/trait.Error.html#method.downcast

Basically, dyn Error has a function that depends on Box. This means Error cannot move to libcore - at best it can move to liballoc.

Centril

comment created time in a month

issue commentrust-lang/rust

Tracking issue for RFC 2523, `#[cfg(version(..))]`

Isn't there a way to combine this with cfg test(s) for "train", e.g. beta or nightly and unstable feature gates?

Not currently, and I don't think it'd be a good idea anyways. Rust 1.45.0-nightly can refer to many different nightlies with many different implemented features.

IMO to target nightly and beta, cfg(accessible) is a better alternative when possible. Otherwise, the only way to write robust code that spans multiple nightlies would be to select build dates.

Centril

comment created time in a month

issue commentrust-lang/rust

Tracking issue for RFC 2523, `#[cfg(version(..))]`

The RFC had an unresolved question about how this feature would interact with nightly/beta. Should #[cfg(version("1.45.0"))] return true or false for nightly/beta 1.45.0?

Currently, the implementation returns true. E.G. for rustc 1.45.0-nightly, the following code prints Yes:

#![feature(cfg_version)]
fn main() {
    test();
}

#[cfg(version("1.45.0"))]
fn test() {
    println!("Yes")
}

#[cfg(not(version("1.45.0")))]
fn test() {
    println!("No")
}

IMO, this is a mistake. The main use-case for cfg(version), at least for me, is to allow use of new features that are known to be stable at a given version. For instance, in the core-error crate, I was planning to use cfg(version) to implement my custom core::error::Error trait on the various error structures of libcore/liballoc automatically, based on cfg(version). Unfortunately, this is not possible as it will certainly cause breakage in the in-between nightly versions that are reported as implementing a version, whilst not having all the types associated with it.

Centril

comment created time in a month

issue commentrust-lang/rust

Tracking issue for RFC 2504, "Fix the Error trait"

enum Backtrace {
    Empty,
    Raw(Vec<usize>),
    Resolved(Vec<(String, u32, u32)>), // (file, line, column)
}

This proposal wouldn't allow Backtrace in libcore though. It would allow it in liballoc, but that's really not ideal. Error really belongs in libcore.

Centril

comment created time in a month

issue commentlpc-rs/lpc-pac

USART.FCR register missing from lpc11uxx

Well, look at the doc link I sent. That's the latest master afaik, and access is definitely possible from safe code. It's generated as function calls doing pointer arithmetics and casting: https://github.com/lpc-rs/lpc-pac/blob/master/lpc11uxx/src/usart.rs#L45-L72

roblabla

comment created time in a month

Pull request review commentrust-lang/rfcs

Inline assembly

 fn mul(a: u64, b: u64) -> u128 { } ``` +## Use AT&T syntax by default on x86

This title says it uses AT&T syntax by default, but the paragraph says the RFC chooses to use Intel syntax by default.

Amanieu

comment created time in a month

issue commentlpc-rs/lpc-pac

USART.FCR register missing from lpc11uxx

Sure! FWIW I started some work on a embedded-hal impl for the lpc11uxx series, with impls for the Serial, SPI, and I2C, and some facilities to do type-safe pinmuxing and clock configuration (not currently on github, will push a WIP soon-ish). I also did some bindings to access the various ROM APIs (like the USB driver and the IAP).

WRT the registers, the APIs in master generate those registers that overlap just fine, but I think the way it exposes them is unsound. For instance, in USART, dll, thr and rbr all share the same register address. The way it works is that a bit in the lcr register (the DLAB bit) decides whether accesses to that address gives dll or rbr/thr.

This means that accessing dll with DLAB=0, or rbr/thr with DLAB=1, is UB. But the way the API is generated, those accesses are allowed and safe. Now I guess this is more of an svd2rust issue? it should probably generate unsafe accessors if there's some overlaps or something.

roblabla

comment created time in a month

Pull request review commentrust-lang/rfcs

Inline assembly

+- Feature Name: `asm`+- Start Date: (fill me in with today's date, YYYY-MM-DD)+- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)+- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)++# Summary+[summary]: #summary++This RFC specifies a new syntax for inline assembly which is suitable for eventual stabilization.++The initial implementation of this feature will focus on the ARM, x86 and RISC-V architectures. Support for more architectures will be added based on user demand.++The transition from the existing `asm!` macro is described in RFC [2843][rfc-llvm-asm]. The existing `asm!` macro will be renamed to `llvm_asm!` to provide an easy way to maintain backwards-compatibility with existing code using inline asm. However `llvm_asm!` is not intended to ever be stabilized.++[rfc-llvm-asm]: https://github.com/rust-lang/rfcs/pull/2843++# Motivation+[motivation]: #motivation++In systems programming some tasks require dropping down to the assembly level. The primary reasons are for performance, precise timing, and low level hardware access. Using inline assembly for this is sometimes convenient, and sometimes necessary to avoid function call overhead.++The inline assembler syntax currently available in nightly Rust is very ad-hoc. It provides a thin wrapper over the inline assembly syntax available in LLVM IR. For stabilization a more user-friendly syntax that lends itself to implementation across various backends is preferable.++Inline assembly is widely used in the Rust community and is one of the top reasons keeping people on the nightly toolchain. Examples of crates using inline assembly include `cortex-m`, `x86`, `riscv`, `parking_lot`, `libprobe`, `msp430`, etc. A collection of use cases for inline asm can also be found in [this repository][catalogue].++[catalogue]: https://github.com/bjorn3/inline_asm_catalogue/++# Guide-level explanation+[guide-level-explanation]: #guide-level-explanation++Rust provides support for inline assembly via the `asm!` macro.+It can be used to embed handwritten assembly in the assembly output generated by the compiler.+Generally this should not be necessary, but might be where the required performance or timing+cannot be otherwise achieved. Accessing low level hardware primitives, e.g. in kernel code, may also demand this functionality.++> Note: the examples here are given in x86/x86-64 assembly, but ARM, AArch64 and RISC-V are also supported.++## Basic usage++Let us start with the simplest possible example:++```rust+unsafe {+    asm!("nop");+}+```++This will insert a NOP (no operation) instruction into the assembly generated by the compiler.+Note that all `asm!` invocations have to be inside an `unsafe` block, as they could insert+arbitrary instructions and break various invariants. The instructions to be inserted are listed+in the first argument of the `asm!` macro as a string literal.++## Inputs and outputs++Now inserting an instruction that does nothing is rather boring. Let us do something that+actually acts on data:++```rust+let x: u64;+unsafe {+    asm!("mov {}, 5", out(reg) x);+}+assert_eq!(x, 5);+```++This will write the value `5` into the `u64` variable `x`.+You can see that the string literal we use to specify instructions is actually a template string.+It is governed by the same rules as Rust [format strings][format-syntax].+The arguments that are inserted into the template however look a bit different then you may+be familiar with. First we need to specify if the variable is an input or an output of the+inline assembly. In this case it is an output. We declared this by writing `out`.+We also need to specify in what kind of register the assembly expects the variable.+In this case we put it in an arbitrary general purpose register by specifying `reg`.+The compiler will choose an appropriate register to insert into+the template and will read the variable from there after the inline assembly finishes executing.++Let us see another example that also uses an input:++```rust+let i: u64 = 3;+let o: u64;+unsafe {+    asm!("+        mov {0}, {1}+        add {0}, {number}+    ", out(reg) o, in(reg) i, number = const 5);+}+assert_eq!(o, 8);+```++This will add `5` to the input in variable `i` and write the result to variable `o`.+The particular way this assembly does this is first copying the value from `i` to the output,+and then adding `5` to it.++The example shows a few things:++First we can see that inputs are declared by writing `in` instead of `out`.++Second one of our operands has a type we haven't seen yet, `const`.+This tells the compiler to expand this argument to value directly inside the assembly template.+This is only possible for constants and literals.++Third we can see that we can specify an argument number, or name as in any format string.+For inline assembly templates this is particularly useful as arguments are often used more than once.+For more complex inline assembly using this facility is generally recommended, as it improves+readability, and allows reordering instructions without changing the argument order.++We can further refine the above example to avoid the `mov` instruction:++```rust+let mut x: u64 = 3;+unsafe {+    asm!("add {0}, {number}", inout(reg) x, number = const 5);+}+assert_eq!(x, 8);+```++We can see that `inout` is used to specify an argument that is both input and output.+This is different from specifying an input and output separately in that it is guaranteed to assign both to the same register.++It is also possible to specify different variables for the input and output parts of an `inout` operand:++```rust+let x: u64 = 3;+let y: u64;+unsafe {+    asm!("add {0}, {number}", inout(reg) x => y, number = const 5);+}+assert_eq!(y, 8);+```++## Late output operands++The Rust compiler is conservative with its allocation of operands. It is assumed that an `out`+can be written at any time, and can therefore not share its location with any other argument.+However, to guarantee optimal performance it is important to use as few registers as possible,+so they won't have to be saved and reloaded around the inline assembly block.+To achieve this Rust provides a `lateout` specifier. This can be used on any output that is+written only after all inputs have been consumed.+There is also a `inlateout` variant of this specifier.++Here is an example where `inlateout` *cannot* be used:++```rust+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);+}+assert_eq!(a, 12);+```++Here the compiler is free to allocate the same register for inputs `b` and `c` since it knows they have the same value. However it must allocate a separate register for `a` since it uses `inout` and not `inlateout`. If `inlateout` was used, then `a` and `c` could be allocated to the same register, in which case the first instruction to overwrite the value of `c` and cause the assembly code to produce the wrong result.++However the following example can use `inlateout` since the output is only modified after all input registers have been read:++```rust+let mut a: u64 = 4;+let b: u64 = 4;+unsafe {+    asm!("add {0}, {1}", inlateout(reg) a, in(reg) b);+}+assert_eq!(a, 8);+```++As you can see, this assembly fragment will still work correctly if `a` and `b` are assigned to the same register.++## Explicit register operands++Some instructions require that the operands be in a specific register.+Therefore, Rust inline assembly provides some more specific constraint specifiers.+While `reg` is generally available on any architecture, these are highly architecture specific. E.g. for x86 the general purpose registers `eax`, `ebx`, `ecx`, `edx`, `ebp`, `esi`, and `edi`+among others can be addressed by their name.++```rust+unsafe {+    asm!("out 0x64, rax", in("rax") cmd);+}+```++In this example we call the `out` instruction to output the content of the `cmd` variable+to port `0x64`. Since the `out` instruction only accepts `rax` (and its sub registers) as operand+we had to use the `rax` constraint specifier.++Note that unlike other operand types, explicit register operands cannot be used in the template string: you can't use `{}` and should write the register name directly instead. Also, they must appear at the end of the operand list after all other operand types.++Consider this example which uses the x86 `mul` instruction:++```rust+fn mul(a: u64, b: u64) -> u128 {+    let lo: u64;+    let hi: u64;++    unsafe {+        asm!(+            // The x86 mul instruction takes rax as an implicit input and writes+            // the 128-bit result of the multiplication to rax:rdx.+            "mul {}",+            in(reg) a,+            inlateout("rax") b => lo,+            lateout("rdx") hi+        );+    }++    hi as u128 << 64 + lo as u128+}+```++This uses the `mul` instruction to multiply two 64-bit inputs with a 128-bit result.+The only explicit operand is a register, that we fill from the variable `a`.+The second operand is implicit, and must be the `rax` register, which we fill from the variable `b`.+The lower 64 bits of the result are stored in `rax` from which we fill the variable `lo`.+The higher 64 bits are stored in `rdx` from which we fill the variable `hi`.++## Clobbered registers++In many cases inline assembly will modify state that is not needed as an output.+Usually this is either because we have to use a scratch register in the assembly,+or instructions modify state that we don't need to further examine.+This state is generally referred to as being "clobbered".+We need to tell the compiler about this since it may need to save and restore this state+around the inline assembly block.++```rust+let ebx: u64;+let ecx: u64;++unsafe {+    asm!(+        "cpuid",+        // EAX 4 selects the "Deterministic Cache Parameters" CPUID leaf+        inout("eax") 4 => _,+        // ECX 0 selects the L0 cache information.+        inout("ecx") 0 => ecx,+        lateout("ebx") ebx,+        lateout("edx") _+    );+}++println!(+    "L1 Cache: {}",+    ((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1)+);+```++In the example above we use the `cpuid` instruction to get the L1 cache size.+This instruction writes to `eax`, `ebx`, `ecx`, and `edx`, but for the cache size we only care about the contents of `ebx` and `ecx`.++However we still need to tell the compiler that `eax` and `edx` have been modified so that it can save any values that were in these registers before the asm. This is done by declaring these as outputs but with `_` instead of a variable name, which indicates that the output value is to be discarded.++This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code:++```rust+// 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) _);+}+assert_eq!(x, 4 * 6);+```++## Symbol operands++A special operand type, `sym`, allows you to use the symbol name of a `fn` or `static` in inline assembly code.+This allows you to call a function or access a global variable without needing to keep its address in a register.++```rust+extern "C" fn foo(arg: i32) {+    println!("arg = {}", arg);+}++fn call_foo(arg: i32) {+    unsafe {+        asm!(+            "call {}"+            sym foo,+            // 1st argument in rdi, which is caller-saved+            inout("rdi") arg => _,+            // All caller-saved registers must be marked as clobberred+            out("rax") _, out("rcx") _, out("rdx") _, out("rsi") _,+            out("r8") _, out("r9") _, out("r10") _, out("r11") _,+            out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _,+            out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _,+            out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,+            out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,+        )+    }+}+```++Note that the `fn` or `static` item does not need to be public or `#[no_mangle]`:+the compiler will automatically insert the appropriate mangled symbol name into the assembly code.++## Register template modifiers++In some cases, fine control is needed over the way a register name is formatted when inserted into the template string. This is needed when an architecture's assembly language has several names for the same register, each typically being a "view" over a subset of the register (e.g. the low 32 bits of a 64-bit register).++By default the compiler will always choose the name that refers to the full register size (e.g. `rax` on x86-64, `eax` on x86, etc).++This default can be overriden by using modifiers on the template string operands, just like you would with format strings:++```rust+let mut x: u16 = 0xab;++unsafe {+    asm!("mov {0:h}, {0:b}", inout(reg_abcd) x);+}++assert_eq!(x, 0xabab);+```++In this example, we use the `reg_abcd` register class to restrict the register allocator to the 4 legacy x86 register (`ax`, `bx`, `cx`, `dx`) of which the first two bytes can be addressed independently.++Let us assume that the register allocator has chosen to allocate `x` in the `ax` register.+The `h` modifier will emit the register name for the high byte of that register and the `b` modifier will emit the register name for the low byte. The asm code will therefore be expanded as `mov ah, al` which copies the low byte of the value into the high byte.++If you use a smaller data type (e.g. `u16`) with an operand and forget the use template modifiers, the compiler will emit a warning and suggest the correct modifier to use.++## Options++By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However in many cases, it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.++Let's take our previous example of an `add` instruction:++```rust+let mut a: u64 = 4;+let b: u64 = 4;+unsafe {+    asm!(+        "add {0}, {1}",+        inlateout(reg) a, in(reg) b,+        options(pure, nomem, nostack)+    );+}+assert_eq!(a, 8);+```++Options can be provided as an optional final argument to the `asm!` macro. We specified three options here:+- `pure` means that the asm code has no observable side effects and that its output depends only on its inputs. This allows the compiler optimizer to call the inline asm fewer times or even eliminate it entirely.+- `nomem` means that the asm code does not read or write to memory. By default the compiler will assume that inline assembly can read or write any memory address that is accessible to it (e.g. through a pointer passed as an operand, or a global).+- `nostack` means that the asm code does not push any data onto the stack. This allows the compiler to use optimizations such as the stack red zone on x86-64 to avoid stack pointer adjustments.++These allow the compiler to better optimize code using `asm!`, for example by eliminating pure `asm!` blocks whose outputs are not needed.++See the reference for the full list of available options and their effects.++# Reference-level explanation+[reference-level-explanation]: #reference-level-explanation++Inline assembler is implemented as an unsafe macro `asm!()`.+The first argument to this macro is a template string literal used to build the final assembly.+The following arguments specify input and output operands.+When required, options are specified as the final argument.++The following ABNF specifies the general syntax:++```+dir_spec := "in" / "out" / "lateout" / "inout" / "inlateout"+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"+options := "options(" option *["," option] [","] ")"+asm := "asm!(" 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++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.++As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after any named arguments if any. Explicit register operands cannot be used by placeholders in the template string. All other operands must appear at least once in the template string, otherwise a compiler error is generated.++The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler.++The 4 targets specified in this RFC (x86, ARM, AArch64, RISC-V) all use the assembly code syntax of the GNU assembler (GAS). On x86, the `.intel_syntax noprefix` mode of GAS is used. On ARM, the `.syntax unified` mode is used. These targets impose an additional restriction on the assembly code: any assembler state (e.g. the current section which can be changed with `.section`) must be restored to its original value at the end of the asm string. Assembly code that does not conform to the GAS syntax will result in assembler-specific behavior.++[rfc-2795]: https://github.com/rust-lang/rfcs/pull/2795++## Operand type++Several types of operands are supported:++* `in(<reg>) <expr>`+  - `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.+  - The allocated register will contain the value of `<expr>` at the start of the asm code.+  - The allocated register must contain the same value at the end of the asm code (except if a `lateout` is allocated to the same register).+* `out(<reg>) <expr>`+  - `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.+  - The allocated register will contain an undefined value at the start of the asm code.+  - `<expr>` must be a (possibly uninitialized) place expression, to which the contents of the allocated register is written to at the end of the asm code.+  - An underscore (`_`) may be specified instead of an expression, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber).+* `lateout(<reg>) <expr>`+  - Identical to `out` except that the register allocator can reuse a register allocated to an `in`.+  - You should only write to the register after all inputs are read, otherwise you may clobber an input.+* `inout(<reg>) <expr>`+  - `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.+  - The allocated register will contain the value of `<expr>` at the start of the asm code.+  - `<expr>` must be an initialized place expression, to which the contents of the allocated register is written to at the end of the asm code.+* `inout(<reg>) <in expr> => <out expr>`+  - Same as `inout` except that the initial value of the register is taken from the value of `<in expr>`.+  - `<out expr>` must be a (possibly uninitialized) place expression, to which the contents of the allocated register is written to at the end of the asm code.+  - An underscore (`_`) may be specified instead of an expression for `<out expr>`, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber).+  - `<in expr>` and `<out expr>` may have different types.+* `inlateout(<reg>) <expr>` / `inlateout(<reg>) <in expr> => <out expr>`+  - Identical to `inout` except that the register allocator can reuse a register allocated to an `in` (this can happen if the compiler knows the `in` has the same initial value as the `inlateout`).+  - You should only write to the register after all inputs are read, otherwise you may clobber an input.+* `const <expr>`+  - `<expr>` must be an integer or floating-point constant expression.+  - The value of the expression is formatted as a string and substituted directly into the asm template string.+* `sym <path>`+  - `<path>` must refer to a `fn` or `static`.+  - A mangled symbol name referring to the item is substituted into the asm template string.+  - The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc).+  - `<path>` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@TPOFF`) to read from thread-local data.++## Register operands++Input and output operands can be specified either as an explicit register or as a register class from which the register allocator can select a register. Explicit registers are specified as string literals (e.g. `"eax"`) while register classes are specified as identifiers (e.g. `reg`). Using string literals for register names enables support for architectures that use special characters in register names, such as MIPS (`$0`, `$1`, etc).++Note that explicit registers treat register aliases (e.g. `r14` vs `lr` on ARM) and smaller views of a register (e.g. `eax` vs `rax`) as equivalent to the base register. It is a compile-time error to use the same explicit register for two input operands or two output operands. Additionally, it is also a compile-time error to use overlapping registers (e.g. ARM VFP) in input operands or in output operands.++Only the following types are allowed as operands for inline assembly:+- Integers (signed and unsigned)+- Floating-point numbers+- Pointers (thin only)+- Function pointers+- SIMD vectors (structs defined with `#[repr(simd)]` and which implement `Copy`)++Here is the list of currently supported register classes:++| Architecture | Register class | Registers | LLVM constraint code |+| ------------ | -------------- | --------- | -------------------- |+| x86 | `reg` | `ax`, `bx`, `cx`, `dx`, `si`, `di`, `r[8-15]` (x86-64 only) | `r` |+| x86 | `reg_abcd` | `ax`, `bx`, `cx`, `dx` | `Q` |+| x86 | `reg_byte` | `al`, `ah`, `bl`, `bh`, `cl`, `ch`, `dl`, `dh` <br> `sil` (x86-64 only), `dil`, (x86-64 only) `r[8-15]b` (x86-64 only) | `r` |+| x86 | `xmm_reg` | `xmm[0-7]` (x86) `xmm[0-15]` (x86-64) | `x` |+| x86 | `ymm_reg` | `ymm[0-7]` (x86) `ymm[0-15]` (x86-64) | `x` |+| x86 | `zmm_reg` | `zmm[0-7]` (x86) `zmm[0-31]` (x86-64) | `v` |+| x86 | `kreg` | `k[1-7]` | `Yk` |+| AArch64 | `reg` | `x[0-28]`, `x30` | `r` |+| AArch64 | `vreg` | `v[0-31]` | `w` |+| AArch64 | `vreg_low16` | `v[0-15]` | `x` |+| ARM | `reg` | `r[0-r10]`, `r12`, `r14` | `r` |+| ARM (Thumb) | `reg_thumb` | `r[0-r7]` | `l` |+| ARM (ARM) | `reg_thumb` | `r[0-r10]`, `r12`, `r14` | `l` |+| ARM | `sreg` | `s[0-31]` | `t` |+| ARM | `sreg_low16` | `s[0-15]` | `x` |+| ARM | `dreg` | `d[0-31]` | `w` |+| ARM | `dreg_low16` | `d[0-15]` | `t` |+| ARM | `dreg_low8` | `d[0-8]` | `x` |+| ARM | `qreg` | `q[0-15]` | `w` |+| ARM | `qreg_low8` | `q[0-7]` | `t` |+| ARM | `qreg_low4` | `q[0-3]` | `x` |+| RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` |+| RISC-V | `freg` | `f[0-31]` | `f` |++> Note: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register.++Additional register classes may be added in the future based on demand (e.g. MMX, x87, etc).++Each register class has constraints on which value types they can be used with. This is necessary because the way a value is loaded into a register depends on its type. For example, on big-endian systems, loading a `i32x4` and a `i8x16` into a SIMD register may result in different register contents even if the byte-wise memory representation of both values is identical. The availability of supported types for a particular register class may depend on what target features are currently enabled.++| Architecture | Register class | Target feature | Allowed types |+| ------------ | -------------- | -------------- | ------------- |+| x86-32 | `reg` | None | `i16`, `i32`, `f32` |+| x86-64 | `reg` | None | `i16`, `i32`, `f32`, `i64`, `f64` |+| x86 | `reg_byte` | None | `i8` |+| x86 | `xmm_reg` | `sse` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |+| x86 | `ymm_reg` | `avx` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` <br> `i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` |+| x86 | `zmm_reg` | `avx512f` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` <br> `i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` <br> `i8x64`, `i16x32`, `i32x16`, `i64x8`, `f32x16`, `f64x8` |+| x86 | `kreg` | `axv512f` | `i8`, `i16` |+| x86 | `kreg` | `axv512bw` | `i32`, `i64` |+| AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |+| AArch64 | `vreg` | `fp` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |+| ARM | `reg` | None | `i8`, `i16`, `i32`, `f32` |+| ARM | `sreg` | `vfp2` | `i32`, `f32` |+| ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` |+| ARM | `qreg` | `neon` | `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4` |+| RISC-V32 | `reg` | None | `i8`, `i16`, `i32`, `f32` |+| RISC-V64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |+| RISC-V | `freg` | `f` | `f32` |+| RISC-V | `freg` | `d` | `f64` |++> Note: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target).++If a value is of a smaller size than the register it is allocated in then the upper bits of that register will have an undefined value for inputs and will be ignored for outputs. The only exception is the `freg` register class on RISC-V where `f32` values are NaN-boxed in a `f64` as required by the RISC-V architecture.++When separate input and output expressions are specified for an `inout` operand, both expressions must have the same type. The only exception is if both operands are pointers or integers, in which case they are only required to have the same size. This restriction exists because the register allocators in LLVM and GCC sometimes cannot handle tied operands with different types.++## Register names++Some registers have multiple names. These are all treated by the compiler as identical to the base register name. Here is the list of all supported register aliases:++| Architecture | Base register | Aliases |+| ------------ | ------------- | ------- |+| x86 | `ax` | `eax`, `rax` |+| x86 | `bx` | `ebx`, `rbx` |+| x86 | `cx` | `ecx`, `rcx` |+| x86 | `dx` | `edx`, `rdx` |+| x86 | `si` | `esi`, `rsi` |+| x86 | `di` | `edi`, `rdi` |+| x86 | `bp` | `bpl`, `ebp`, `rbp` |+| x86 | `sp` | `spl`, `esp`, `rsp` |+| x86 | `ip` | `eip`, `rip` |+| x86 | `st(0)` | `st` |+| x86 | `r[8-15]` | `r[8-15]b`, `r[8-15]w`, `r[8-15]d` |+| x86 | `xmm[0-31]` | `ymm[0-31]`, `zmm[0-31]` |+| AArch64 | `x[0-30]` | `w[0-30]` |+| AArch64 | `x29` | `fp` |+| AArch64 | `x30` | `lr` |+| AArch64 | `sp` | `wsp` |+| AArch64 | `xzr` | `wzr` |+| AArch64 | `v[0-31]` | `b[0-31]`, `h[0-31]`, `s[0-31]`, `d[0-31]`, `q[0-31]` |+| ARM | `r[0-3]` | `a[1-4]` |+| ARM | `r[4-9]` | `v[1-6]` |+| ARM | `r9` | `rfp` |+| ARM | `r10` | `sl` |+| ARM | `r11` | `fp` |+| ARM | `r12` | `ip` |+| ARM | `r13` | `sp` |+| ARM | `r14` | `lr` |+| ARM | `r15` | `pc` |+| RISC-V | `x0` | `zero` |+| RISC-V | `x1` | `ra` |+| RISC-V | `x2` | `sp` |+| RISC-V | `x3` | `gp` |+| RISC-V | `x4` | `tp` |+| RISC-V | `x[5-7]` | `t[0-2]` |+| RISC-V | `x8` | `fp`, `s0` |+| RISC-V | `x9` | `s1` |+| RISC-V | `x[10-17]` | `a[0-7]` |+| RISC-V | `x[18-27]` | `s[2-11]` |+| RISC-V | `x[28-31]` | `t[3-6]` |+| RISC-V | `f[0-7]` | `ft[0-7]` |+| RISC-V | `f[8-9]` | `fs[0-1]` |+| RISC-V | `f[10-17]` | `fa[0-7]` |+| RISC-V | `f[18-27]` | `fs[2-11]` |+| RISC-V | `f[28-31]` | `ft[8-11]` |++Some registers cannot be used for input or output operands:++| Architecture | Unsupported register | Reason |+| ------------ | -------------------- | ------ |+| All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. |+| All | `bp` (x86), `r11` (ARM), `x29` (AArch64), `x8` (RISC-V) | The frame pointer cannot be used as an input or output. |+| x86 | `k0` | This is a constant zero register which can't be modified. |+| x86 | `ip` | This is the program counter, not a real register. |+| x86 | `mm[0-7]` | MMX registers are not currently supported (but may be in the future). |+| x86 | `st([0-7])` | x87 registers are not currently supported (but may be in the future). |+| AArch64 | `xzr` | This is a constant zero register which can't be modified. |+| ARM | `pc` | This is the program counter, not a real register. |+| RISC-V | `x0` | This is a constant zero register which can't be modified. |+| RISC-V | `gp`, `tp` | These registers are reserved and cannot be used as inputs or outputs. |++## Template modifiers++The placeholders can be augmented by modifiers which are specified after the `:` in the curly braces. These modifiers do not affect register allocation, but change the way operands are formatted when inserted into the template string. Only one modifier is allowed per template placeholder.++The supported modifiers are a subset of LLVM's (and GCC's) [asm template argument modifiers][llvm-argmod], but do not use the same letter codes.++| Architecture | Register class | Modifier | Example output | LLVM modifier |+| ------------ | -------------- | -------- | -------------- | ------------- |+| x86-32 | `reg` | None | `eax` | `k` |+| x86-64 | `reg` | None | `rax` | `q` |+| x86-32 | `reg_abcd` | `l` | `al` | `b` |+| x86-64 | `reg` | `l` | `al` | `b` |+| x86 | `reg_abcd` | `h` | `ah` | `h` |+| x86 | `reg` | `x` | `ax` | `w` |+| x86 | `reg` | `e` | `eax` | `k` |+| x86-64 | `reg` | `r` | `rax` | `q` |+| x86 | `reg_byte` | None | `al` / `ah` | None |+| x86 | `xmm_reg` | None | `xmm0` | `x` |+| x86 | `ymm_reg` | None | `ymm0` | `t` |+| x86 | `zmm_reg` | None | `zmm0` | `g` |+| x86 | `*mm_reg` | `x` | `xmm0` | `x` |+| x86 | `*mm_reg` | `y` | `ymm0` | `t` |+| x86 | `*mm_reg` | `z` | `zmm0` | `g` |+| x86 | `kreg` | None | `k1` | None |+| AArch64 | `reg` | None | `x0` | `x` |+| AArch64 | `reg` | `w` | `w0` | `w` |+| AArch64 | `reg` | `x` | `x0` | `x` |+| AArch64 | `vreg` | None | `v0` | None |+| AArch64 | `vreg` | `v` | `v0` | None |+| AArch64 | `vreg` | `b` | `b0` | `b` |+| AArch64 | `vreg` | `h` | `h0` | `h` |+| AArch64 | `vreg` | `s` | `s0` | `s` |+| AArch64 | `vreg` | `d` | `d0` | `d` |+| AArch64 | `vreg` | `q` | `q0` | `q` |+| ARM | `reg` | None | `r0` | None |+| ARM | `sreg` | None | `s0` | None |+| ARM | `dreg` | None | `d0` | `P` |+| ARM | `qreg` | None | `q0` | `q` |+| ARM | `qreg` | `e` / `f` | `d0` / `d1` | `e` / `f` |+| RISC-V | `reg` | None | `x1` | None |+| RISC-V | `freg` | None | `f0` | None |++> Notes:+> - on ARM `e` / `f`: this prints the low or high doubleword register name of a NEON quad (128-bit) register.+> - on x86: our behavior for `reg` with no modifiers differs from what GCC does. GCC will infer the modifier based on the operand value type, while we default to the full register size.+> - on x86 `xmm_reg`: the `x`, `t` and `g` LLVM modifiers are not yet implemented in LLVM (they are supported by GCC only), but this should be a simple change.++As stated in the previous section, passing an input value smaller than the register width will result in the upper bits of the register containing undefined values. This is not a problem if the inline asm only accesses the lower bits of the register, which can be done by using a template modifier to use a subregister name in the asm code (e.g. `ax` instead of `rax`). Since this an easy pitfall, the compiler will suggest a template modifier to use where appropriate given the input type. If all references to an operand already have modifiers then the warning is suppressed for that operand.++[llvm-argmod]: http://llvm.org/docs/LangRef.html#asm-template-argument-modifiers++## Options++Flags are used to further influence the behavior of the inline assembly block.+Currently the following options are defined:+- `pure`: The `asm` block has no side effects, and its outputs depend only on its direct inputs (i.e. the values themselves, not what they point to) or values read from memory (unless the `nomem` options is also set). This allows the compiler to execute the `asm` block fewer times than specified in the program (e.g. by hoisting it out of a loop) or even eliminate it entirely if the outputs are not used.+- `nomem`: The `asm` blocks does not read or write to any memory. This allows the compiler to cache the values of modified global variables in registers across the `asm` block since it knows that they are not read or written to by the `asm`.+- `readonly`: The `asm` block does not write to any memory. This allows the compiler to cache the values of unmodified global variables in registers across the `asm` block since it knows that they are not written to by the `asm`.+- `preserves_flags`: The `asm` block does not modify the flags register (defined in the [rules][rules] below). This allows the compiler to avoid recomputing the condition flags after the `asm` block.+- `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.++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.+- The `pure` option must be combined with either the `nomem` or `readonly` options, otherwise a compile-time error is emitted.+- It is a compile-time error to specify `pure` on an asm block with no outputs or only discarded outputs (`_`).+- It is a compile-time error to specify `noreturn` on an asm block with outputs.++## Mapping to LLVM IR++The direction specification maps to a LLVM constraint specification as follows (using a `reg` operand as an example):++* `in(reg)` => `r`+* `out(reg)` => `=&r` (Rust's outputs are early-clobber outputs in LLVM/GCC terminology)+* `inout(reg)` => `=&r,0` (an early-clobber output with an input tied to it, `0` here is a placeholder for the position of the output)+* `lateout(reg)` => `=r` (Rust's late outputs are regular outputs in LLVM/GCC terminology)+* `inlateout(reg)` => `=r,0` (cf. `inout` and `lateout`)++If an `inout` is used where the output type is smaller than the input type then some special handling is needed to avoid LLVM issues. See [this bug][issue-65452].++As written this RFC requires architectures to map from Rust constraint specifications to LLVM [constraint codes][llvm-constraint]. This is in part for better readability on Rust's side and in part for independence of the backend:++* Register classes are mapped to the appropriate constraint code as per the table above.+* `const` operands are formatted and injected directly into the asm string.+* `sym` is mapped to the `s` constraint code. We automatically insert the `c` modifier which removes target-specific modifiers from the value (e.g. `#` on ARM).+* a register name `r1` is mapped to `{r1}`+* If the `nomem` option is not set then `~{memory}` is added to the clobber list. (Although this is currently ignored by LLVM)+* If the `preserves_flags` option is not set then the following are added to the clobber list:+  - (x86) `~{dirflag},~{flags},~{fpsr}`+  - (ARM/AArch64) `~{cc}`++Additionally, the following attributes are added to the LLVM `asm` statement:++* The `nounwind` attribute is always added: unwinding from an inline asm block is not allowed (and not supported by LLVM anyways).+* If the `nomem` and `pure` options are both set then the `readnone` attribute is added to the LLVM `asm` statement.+* If the `readonly` and `pure` options are both set then the `readonly` attribute is added to the LLVM `asm` statement.+* If the `nomem` option is set without the `pure` option then the `inaccessiblememonly` attribute is added to the LLVM `asm` statement.+* If the `pure` option is not set then the `sideeffect` flag is added the LLVM `asm` statement.+* If the `nostack` option is not set then the `alignstack` flag is added the LLVM `asm` statement.+* On x86 the `inteldialect` flag is added the LLVM `asm` statement so that the Intel syntax is used instead of the AT&T syntax.++If the `noreturn` option is set then an `unreachable` LLVM instruction is inserted after the asm invocation.++> Note that `alignstack` is not currently supported by GCC, so we will need to implement support in GCC if Rust ever gets a GCC back-end.++[llvm-constraint]: http://llvm.org/docs/LangRef.html#supported-constraint-code-list+[issue-65452]: https://github.com/rust-lang/rust/issues/65452++## Supporting back-ends without inline assembly++While LLVM supports inline assembly, rustc may gain alternative backends such as Cranelift or GCC. If a back-end does not support inline assembly natively then we can fall back to invoking an external assembler. The intent is that support for `asm!` should be independent of the rustc back-end used: it should always work, but with lower performance if the backend does not support inline assembly.++Take the following (AArch64) asm block as an example:++```rust+unsafe fn foo(mut a: i32, b: i32) -> (i32, i32)+{+    let c;+    asm!("<some asm code>", inout(reg) a, in("x0") b, out("x20") c);+    (a, c)+}+```++This could be expanded to an external asm file with the following contents:++```+# Function prefix directives+.section ".text.foo_inline_asm"+.globl foo_inline_asm+.p2align 2+.type foo_inline_asm, @function+foo_inline_asm:++// If necessary, save callee-saved registers to the stack here.+str x20, [sp, #-16]!++// Move the pointer to the argument out of the way since x0 is used.+mov x1, x0++// Load inputs values+ldr w2, [x1, #0]+ldr w0, [x1, #4]++<some asm code>++// Store output values+str w2, [x1, #0]+str w20, [x1, #8]++// If necessary, restore callee-saved registers here.+ldr x20, [sp], #16++ret++# Function suffix directives+.size foo_inline_asm, . - foo_inline_asm+```++And the following Rust code:++```rust+unsafe fn foo(mut a: i32, b: i32) -> (i32, i32)+{+    let c;+    {+        #[repr(C)]+        struct foo_inline_asm_args {+            a: i32,+            b: i32,+            c: i32,+        }+        extern "C" {+            fn foo_inline_asm(args: *mut foo_inline_asm_args);+        }+        let mut args = foo_inline_asm_args {+            a: a,+            b: b,+            c: mem::uninitialized(),+        };+        foo_inline_asm(&mut args);+        a = args.a;+        c = args.c;+    }+    (a, c)+}+```++## Rules for inline assembly+[rules]: #rules++- Any registers not specified as inputs will contain an undefined value on entry to the asm block.+  - An "undefined value" in the context of this RFC means that the register can (non-deterministically) have any one of the possible values allowed by the architecture. Notably it is not the same as an LLVM `undef` which can have a different value every time you read it (since such a concept does not exist in assembly code).+- Any registers not specified as outputs must have the same value upon exiting the asm block as they had on entry, otherwise behavior is undefined.+  - This only applies to registers which can be specified as an input or output. Other registers follow target-specific rules and are outside the scope of this RFC.+  - Note that a `lateout` may be allocated to the same register as an `in`, in which case this rule does not apply. Code should not rely on this however since it depends on the results of register allocation.+- Behavior is undefined if execution unwinds out of an asm block.+  - This also applies if the assembly code calls a function which then unwinds.+- The set of memory locations that assembly code is allowed the read and write are the same as those allowed for an FFI function.+  - Refer to the unsafe code guidelines for the exact rules.+  - If the `readonly` option is set, then only memory reads are allowed.+  - If the `nomem` option is set then no reads or writes to memory are allowed.+  - These rules do not apply to memory which is private to the asm code, such as stack space allocated within the asm block.+- The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed.+  - This effectively means that the compiler must treat the `asm!` as a black box and only take the interface specification into account, not the instructions themselves.+  - Runtime code patching is allowed, via target-specific mechanisms (outside the scope of this RFC).+- Unless the `nostack` option is set, asm code is allowed to use stack space below the stack pointer.+  - On entry to the asm block the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call.+  - You are responsible for making sure you don't overflow the stack (e.g. use stack probing to ensure you hit a guard page).+  - You should adjust the stack pointer when allocating stack memory as required by the target ABI.+  - The stack pointer must be restored to its original value before leaving the asm block.+- If the `noreturn` option is set then behavior is undefined if execution falls through to the end of the asm block.+- If the `pure` option is set then behavior is undefined if the `asm` has side-effects other than its direct outputs. Behavior is also undefined if two executions of the `asm` code with the same inputs result in different outputs.+  - When used with the `nomem` option, "inputs" are just the direct inputs of the `asm!`.+  - When used with the `readonly` option, "inputs" comprise the direct inputs of the `asm!` and any memory that the `asm!` block is allowed to read.+- These flags registers must be restored upon exiting the asm block if the `preserves_flags` option is set:+  - x86+    - Status flags in `EFLAGS` (CF, PF, AF, ZF, SF, OF).+    - Direction flag in `EFLAGS` (DF).+    - Floating-point status word (all).+    - Floating-point exception flags in `MXCSR` (PE, UE, OE, ZE, DE, IE).+  - ARM+    - Condition flags in `CPSR` (N, Z, C, V)+    - Saturation flag in `CPSR` (Q)+    - Greater than or equal flags in `CPSR` (GE).+    - Condition flags in `FPSCR` (N, Z, C, V)+    - Saturation flag in `FPSCR` (QC)+    - Floating-point exception flags in `FPSCR` (IDC, IXC, UFC, OFC, DZC, IOC).+  - AArch64+    - Condition flags (`NZCV` register).+    - Floating-point status (`FPSR` register).+  - RISC-V+    - Floating-point exception flags in `fcsr` (`fflags`).+- The requirement of restoring the stack pointer and non-output registers to their original value only applies when exiting an `asm!` block.+  - This means that `asm!` blocks that never return (even if not marked `noreturn`) don't need to preserve these registers.+  - When returning to a different `asm!` block than you entered (e.g. for context switching), these registers must contain the value they had upon entering the `asm!` block that you are *exiting*.+    - You cannot exit an `asm!` block that has not been entered. Neither can you exit an `asm!` block that has already been exited.+    - You are responsible for switching any target-specific state (e.g. thread-local storage, stack bounds).+    - The set of memory locations that you may access is the intersection of those allowed by the `asm!` blocks you entered and exited.++> Note: As a general rule, these are the flags which are *not* preserved when performing a function call.++# Drawbacks+[drawbacks]: #drawbacks++## Unfamiliarity++This RFC proposes a completely new inline assembly format.+It is not possible to just copy examples of GCC-style inline assembly and re-use them.+There is however a fairly trivial mapping between the GCC-style and this format that could be documented to alleviate this.++Additionally, this RFC proposes using the Intel asm syntax on x86 instead of the AT&T syntax. We believe this syntax will be more familiar to most users, but may be surprising for users used to GCC-style asm.

The intel syntax is the one sanctioned in the intel x86 documentation, and most of the inline asm I've seen in Rust sets the intel flag instead of keeping the AT&T default. MSVC does support assembly through the MASM tool (not inline asm though), and MASM defaults to intel syntax. 32-bit x86 in MSVC also defaults to intel syntax.

Amanieu

comment created time in a month

issue commentrust-lang/cargo

Proc macros can cause non-json output in stdout despite message-format=json

Tools should only interpret a line as JSON if it starts with {. I thought that was documented, but it is not.

In fact, documentation explicitly says otherwise:

When passing --message-format=json, Cargo will output the following information during the build:

  • compiler errors and warnings,
  • produced artifacts,
  • results of the build scripts (for example, native dependencies).

The output goes to stdout in the JSON object per line format. The reason field distinguishes different kinds of messages.

The way I understand this is that stdout will only contain JSON. It'd definitely be worth it to make the phrasing a lot less ambiguous here.


Wouldn't it be possible to redirect stdout to stderr when running proc-macros, and back when exiting it? I know it's possible on unix with dup2, and on windows with some mix of SetStdHandle and _open_osfhandle. It's not a great solution, but it'd be a pretty good stopgap :shrug:.

roblabla

comment created time in a month

pull request commentoli-obk/cargo_metadata

Robust message parsing

I've been thinking about this for a bit. I think this PR is fine for inclusion as-is. There are two separate problems with cargo-metadata and JSON parsing that it helps with:

  1. During the cargo build, there will sometimes be non-JSON output interspersed in stdout, despite using message-format=json. IMO this is a cargo/rustc bug - when --message-format=json is passed to cargo, stdout shouldn't have any non-JSON output at least during the build. I opened a cargo issue, https://github.com/rust-lang/cargo/issues/8179

    Still, even though it's a cargo bug, having this PR in is a good idea: it allows us to gracefully recover when a stray print happens. It work on cargo as it exists today, it avoids problems if cargo regresses later, and it allows cargo-metadata to work on outdated cargo versions when the problem is fixed.

    The current PR doesn't provide a mechanism to recover the message that failed to parse as JSON. IMO this is fine, since ultimately this is caused by a cargo bug that needs to be fixed upstream. I don't think the lost message will cause all that much problem - I'm highly doubtful there's any tools relying on the stdout output of proc-macros.

  2. After the build is done, there isn't any guarantee that the stdout will contain JSON, e.g. when doing cargo run. At this point, the rest of the data can be just about anything. This is linked to #102.

    In this use-case, this PR avoids a crash, but it doesn't provide a mechanism to recover the data that failed to parse to JSON, which might be necessary for some tools to parse. For instance, the rest of the data could be another JSON stream (for instance, when running cargo test -- --format json) or it could be binary data/invalid utf8, etc...

    Attempting to recover the "lost" message in the error type here doesn't make sense. The output might not be a line, it might be of arbitrary size, it might be invalid utf8.

    To help deal with this, ehuss added a build-finished message type to cargo (https://github.com/rust-lang/cargo/pull/8069), signaling the end of a cargo build and the rest of the output stream is arbitrary. IMO, the ideal solution would be for cargo-metadata to stop deserializing messages after the marker, and allow the user to extract the std::io::Read instance passed to parse_stream. The user would then be free to do what they need to do with the std::io::Read (write the rest of the stream to disk, parse it, etc...).

    This PR lays some groundwork for this. First of all, parse_stream introduces its own type that can have arbitrary logic, so it allows us to add some logic to stop parsing messages after the build-finished marker is reached, and adding our own functions to recover the BufRead after iteration is done, without introducing a breaking change.

So, no, I don't think this PR is problematic.

matklad

comment created time in a month

issue openedrust-lang/cargo

Proc macros can cause non-json output in stdout despite message-format=json

<!-- Thanks for filing a 🐛 bug report 😄! -->

Problem

When proc macros print to stdout, the output is reflected in the cargo output. For instance, the following proc macro will cause Hello to be printed in the compiler output, even when message-format=json is passed, even though it's not a valid JSON object. This will cause various tools (such as cargo-metadata, rust-analyzer, jq...) to fail to parse the message, and give up.

extern crate proc_macro;
use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn hello(_attr: TokenStream, item: TokenStream) -> TokenStream {
    println!("Hello");
    item
}

I'm not sure if this is considered a cargo or a rustc bug ^^'.

Steps <!-- The steps to reproduce the bug. -->

  1. Install jq
  2. git clone https://github.com/roblabla/cargo-proc-macro-print-bug
  3. cargo build --message-format=json | jq .

This will cause jq to error with "parse error: Invalid numeric literal at line 3, column 0", which is caused by the string "Hello", printed by the proc macro, to appear in stdout.

Possible Solution(s) I imagine the proc macro output could be:

  • Ignored/silenced
  • Wrapped in a CompilerMessage JSON object
  • Wrapped in a new kind of JSON object, maybe a GenericMessage?

Notes

cargo 1.42.0 (86334295e 2020-01-31) rustc 1.42.0 (b8cedc004 2020-03-09)

created time in a month

create barnchroblabla/cargo-proc-macro-print-bug

branch : master

created branch time in a month

more