Stream: t-lang/wg-unsafe-code-guidelines

Topic: How does `repr(simd)` really work?


Lokathor (Jul 13 2019 at 04:45, on Zulip):
RalfJ (Jul 13 2019 at 07:46, on Zulip):

cc @gnzlbg

RalfJ (Jul 13 2019 at 07:46, on Zulip):

but also @Lokathor have you read https://github.com/rust-lang/unsafe-code-guidelines/blob/master/reference/src/layout/packed-simd-vectors.md ?

RalfJ (Jul 13 2019 at 07:47, on Zulip):

or I guess https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html is a better location

RalfJ (Jul 13 2019 at 07:47, on Zulip):

some of these questions seem like they would be answered there

gnzlbg (Jul 13 2019 at 08:00, on Zulip):

I think all questions are answered there

gnzlbg (Jul 13 2019 at 08:45, on Zulip):

@Lokathor if you have further questions or something is not answered there feel free to ping me or open an issue

Lokathor (Jul 13 2019 at 21:51, on Zulip):

Oh, right, of course. I somehow temporarily forgot that the book already has some content in it.

Okay, having read that and also having played around with it a bit in the playground, I'm going to conclude that we're in a good place for now, and then I'll add sanity tests to my crate to make sure that things stay good, and also subscribe to issue https://github.com/rust-lang/unsafe-code-guidelines/issues/36 in case of updates.

Lokathor (Jul 13 2019 at 22:37, on Zulip):

It appears that miri falls down when I try to run my basic sanity tests through it, https://pastebin.com/mjiVZuRp (test code was https://gist.github.com/rust-play/c97f79a6c5ee81b82d044349cd267acb)

I don't know if this is miri just not knowing what to do or what, but it's pointing the finger at stdimd, which I trust to have gotten the x86_64 stuff correct.

Lokathor (Jul 13 2019 at 23:04, on Zulip):

Ah, yeah, miri just isn't smart enough to handle this yet I guess. From the README

Miri runs the program as a platform-independent interpreter, so the program has no access to any platform-specific APIs or FFI. A few APIs have been implemented (such as printing to stdout) but most have not: for example, Miri currently does not support concurrency, or networking, or file system access, or gathering entropy from the system.

RalfJ (Jul 14 2019 at 07:30, on Zulip):

Yeah I should add SIMD to that list

RalfJ (Jul 14 2019 at 07:30, on Zulip):

the problem with SIMD is that it consists of hundreds of intrinsics (thousands really but I guess not all of them are important)

RalfJ (Jul 14 2019 at 07:30, on Zulip):

and they would have have to be implemented manually in Miri...

RalfJ (Jul 14 2019 at 07:31, on Zulip):

maybe there's a way to be smarter about them, by "parsing" the name of the intrinsic or so

RalfJ (Jul 14 2019 at 07:31, on Zulip):

but generally it's a lot of work and nobody has taken that on yet

RalfJ (Jul 14 2019 at 07:32, on Zulip):

However, the error is curious:

Miri evaluation error: tried to call a function with ABI RustIntrinsic using caller ABI PlatformIntrinsic

@eddyb @gnzlbg is an ABI mismatch like that expected for SIMD?

gnzlbg (Jul 14 2019 at 07:39, on Zulip):

well, kind of

gnzlbg (Jul 14 2019 at 07:39, on Zulip):

many SIMD intrinsics end up calling a platform intrinsic

gnzlbg (Jul 14 2019 at 07:40, on Zulip):

let me get you what's probably the offending code

gnzlbg (Jul 14 2019 at 07:40, on Zulip):

miri would need to at least support all of these: https://github.com/rust-lang/stdarch/blob/master/crates/core_arch/src/simd_llvm.rs#L5

gnzlbg (Jul 14 2019 at 07:41, on Zulip):

note that the ABI of these is PlatformIntrinsic

gnzlbg (Jul 14 2019 at 07:41, on Zulip):

I don't think that miri should support more than these, at least not initially

RalfJ (Jul 14 2019 at 07:54, on Zulip):

Im not even talking about implementing the intrinsic

RalfJ (Jul 14 2019 at 07:54, on Zulip):

usually its an error if the ABI that the caller and callee used are not the same

RalfJ (Jul 14 2019 at 07:55, on Zulip):

this is the insta-UB kind of error

RalfJ (Jul 14 2019 at 07:55, on Zulip):

but here it seems okay? what is the difference between the RustIntrinsic and PlatformIntrinsic call ABIs?

RalfJ (Jul 14 2019 at 07:56, on Zulip):

(if e.g. one ABI was C and the other Rust, that would definitely be UB)

gnzlbg (Jul 14 2019 at 08:41, on Zulip):

@RalfJ where is the ABI difference? - the intrinsics are PlatformIntrinsic

gnzlbg (Jul 14 2019 at 08:42, on Zulip):

If you declare the intrinsics as extern "C" and call them, that is UB - you need to declare them as "platform-intrinsic"

gnzlbg (Jul 14 2019 at 08:42, on Zulip):

AFAICT, they are declared as "platform-intrinsic" everywhere in all Rust code

gnzlbg (Jul 14 2019 at 08:43, on Zulip):

usually its an error if the ABI that the caller and callee used are not the same

I suppose that by this you mean that the ABI of a declaration must match the ABI of the definition

gnzlbg (Jul 14 2019 at 08:43, on Zulip):

It is possible to call an extern "C" function from an extern "Rust" function

gnzlbg (Jul 14 2019 at 08:44, on Zulip):

what cannot be done is call an extern "Rust" function via a declaration that says this function is extern "C"

eddyb (Jul 14 2019 at 09:07, on Zulip):

@RalfJ these ABIs are just a hack, RustCall and RustIntrinsic and PlatformIntrinsic are all Rust

eddyb (Jul 14 2019 at 09:08, on Zulip):

someone needs to go and clean that mess up and it's not high priority enough to actually happen :(

RalfJ (Jul 14 2019 at 09:54, on Zulip):

@eddyb I see, so there's no "good" reason for these to be separate ABIs?

eddyb (Jul 14 2019 at 09:54, on Zulip):

yeah it's just used to signal that something is an intrinsic

RalfJ (Jul 14 2019 at 09:54, on Zulip):

what cannot be done is call an extern "Rust" function via a declaration that says this function is extern "C"

yes. every fn call has two ABIs: the ABI the caller assumes this fn has, and the ABI the fn really has. the error says that they are not the same.

RalfJ (Jul 14 2019 at 09:55, on Zulip):

this is an error similar in kind to "you called a 5-param function with 3 params"

RalfJ (Jul 14 2019 at 09:59, on Zulip):

@eddyb https://github.com/rust-lang/rust/pull/62674

RalfJ (Jul 14 2019 at 10:03, on Zulip):

once that lands., the error message should be better for when a SIMD intrinsic is used

RalfJ (Jul 14 2019 at 10:03, on Zulip):

should be something like "intrinsic not implemented: simd_add"

eddyb (Jul 14 2019 at 10:04, on Zulip):

and then someone can go in and implement all of them :P

eddyb (Jul 14 2019 at 10:04, on Zulip):

you can get the vector shape from layout.abi being Abi::Vector and then compute element offsets like an array

eddyb (Jul 14 2019 at 10:05, on Zulip):

like, this would be a fun project IMO, at least for the platform-independent ones (like simd_add)

gnzlbg (Jul 14 2019 at 10:12, on Zulip):

FWIW I'm actually working on making repr(simd) types support an array right now

gnzlbg (Jul 14 2019 at 10:13, on Zulip):

I just discovered that we also support, e.g., #[repr(simd)] struct Rgba { r: f32, g: f32, b: f32, a: f32 }, as well as #[repr(simd)] types of non-power-of-two sizes

Lokathor (Jul 15 2019 at 17:24, on Zulip):

Now that you mention it, the "Layout of packed SIMD vectors" page in the UCG says that the Packed SIMD types are #[repr(simd)]with an example definition and says that they always have a power of two number of lanes, but it doesn't say that you can't apply repr(simd) to other things.

gnzlbg (Jul 15 2019 at 17:25, on Zulip):

You can't apply repr(simd) to anything, only the compiler can do that, so the point is a bit moot :P

Lokathor (Jul 15 2019 at 17:26, on Zulip):

you just said you put it on a RGBA struct :P

gnzlbg (Jul 16 2019 at 11:03, on Zulip):

in the compiler :P

Last update: Nov 19 2019 at 18:00UTC