-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rust Wasm ABI treats two-field structs like scalars and doesn't require padding #657
Comments
This same problem does not occur for the equivalent C++ code: https://godbolt.org/z/eda34jq15, though for whatever reason the C++ code also doesn't seem to handle padding at all. |
wasm_bindgen does not appear to support passing structs over FFI directly, it always handles them similar to opaques |
wasm_bindgen doesn't even do layout calculations, it generates getter/setter methods for each field. huh |
Some potentially related issues: rust-lang/rust#115666, rust-lang/rust#81386, rust-lang/rust#81388 Similar issue: rust-lang/rust#121408 |
So the reason this happens would be for say, tuples of exactly two elements? |
yeah, I think the Rust ABI has special handling for scalar pairs and for whatever reason that gets enabled for Wasm as well |
I think this is enough for us to be able to assume that Option, at least, is not affected by this, which makes my life easier though it doesn't fix the problem. |
Note: the Rust behavior doesn't match the tool conventions. |
Upstream bug filed at rust-lang/rust#129486 . It is most likely to lead to better documentation. |
Looks like they're working on matching the tool conventions in rust-lang/rust#129486 The flag is |
In the long run rustc plans to move to For now I'm going to stick to the legacy mode but sometime soon we should move codegen over. |
This fixes rust-diplomat#656 but not rust-diplomat#657 The scalarpair struct part of the second test happens to pass since rust-diplomat#657 is only relevant for argument passing
Partially handles rust-diplomat#657
When single-field structs are passed down over Wasm, they're treated as a single parameter. Multi-field structs are passed down as multiple parameters.
Except not quite: multi-field structs can have padding. A struct
(u8, u32)
has 3 bytes of padding after theu8
, represented in llvm as[3 x i8]
.(u16, u32)
has two bytes of padding, represented in llvm as[1 x i16]
.In the JS/Wasm backend, of course we need to deal with padding when deciphering returned structs (since we read them from memory with their layout). However, we also need to deal with padding when passing structs over Wasm, because each entry of padding is one argument.
This means that in the following setup:
foo()
gets called asfoo(a, 0, 0, 0, b, c)
.We already have this behavior implemented in #643, except currently it assumes all padding bytes are
i8
, whereas it appears that they match the lowest alignment of the previous unaligned section. Or something like that ((u8, u8, u32)
and(u16, u32)
have differently segmented padding sections). This is a separate bug to be fixed (#656).However, there appears to be strangeness even when dealing with padding. The Wasm tool conventions claim that structs with single scalar fields are passed as scalars, and structs with multiple are passed as aggregates, however in the following code:
the resultant LLVM IR looks something like this:
where
Small
is split into two scalar parameters in the function. The functionsmall()
in WASM is correctly invoked assmall(a, b)
, with no padding.With a bunch of experimentation it seems like this consistently happens for structs that (transitively) contain two scalar fields. The sizes of the fields are irrelevant, but adding a third field always turns it into a separate
type {...}
thing that may contain padding.We should figure out where this heuristic is coming from, and either get it fixed (it doesn't match the documented conventions) or write code to handle it. This may unfortunately require making
_intoFFI()
conditional on cases with and without padding, but that won't be too hard.The text was updated successfully, but these errors were encountered: