-
Notifications
You must be signed in to change notification settings - Fork 13k
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
wasm u128
/i128
is improperly aligned
#133991
Comments
Quite a few non-wasm targets have eight byte alignment for u128 and i128 (e.g., 32-bit Arm and RISC-V targets). I don't know of any that are tier 1 right now, but tiers can change over time, tier 1 is a very high bar, and many tier 2 targets are widely used. In fact, some tier 1 targets had 8-byte-aligned u128 until earlier this year. So I would strongly advice against assuming any particular alignment for those types. That said, in general i128 and u128 should be interoperable with C's 128-bit integer types when they exist. I don't know when Clang started supporting these types in wasm, but WebAssembly/tool-conventions#240 indicates that they're supported now with 16 byte alignment. So Rust may have to increase the alignment of these types on the wasm targets anyway for interop with C code that's also compiled to wasm. That doesn't change the fact that non-wasm code shouldn't assume it agrees with wasm code on the alignment.
Another solution is to use |
The reason I mention Tier 1 targets is that wasm is a bit "special", especially wasi, in that it often needs to interop with host functions. Different alignments between x86 and idk PowerPC are unlikely to matter, whereas wasm is by necessity embedded in another target. |
Sure, but the host code isn't limited to tier 1 Rust targets. As a concrete example, wasmtime explicitly supports several targets that are or were tier 2 in rustc (currently Linux s390x and Linux riscv64, also macOS aarch64 was only promoted to Rust tier 1 recently). Rust target tiers are basically never relevant for "do I need to worry about this target when writing portable code?" because the tiers don't have any inherent meaning, they only reflect how much a target is currently tested in rust-lang/rust CI. |
Yes. We do not intend to alter our wasm ABI conformance based on non-wasm targets. We do have to alter the alignment to match the ABI documented by tool-conventions. |
cc @sunfishcode and @alexcrichton Should this be done upstream in LLVM? Like was done in llvm/llvm-project@dbad963 for SPARC. |
Clang [defaults to aligning `__int128_t` to 16 bytes], while LLVM `datalayout` strings [default to aligning `i128` to 8 bytes]. Wasm is currently using the defaults for both, so it's inconsistent. Fix this by adding `-i128:128` to Wasm's `datalayout` string so that it aligns `i28` to 16 bytes too. This is similar to dbad963 for SPARC. This fixes rust-lang/rust#133991; see that issue for further discussion. [defaults to aligning `__int128_t` to 16 bytes]: https://github.com/llvm/llvm-project/blob/f8b4182f076f8fe55f9d5f617b5a25008a77b22f/clang/lib/Basic/TargetInfo.cpp#L77 [default to aligning `i128` to 8 bytes]: https://llvm.org/docs/LangRef.html#langref-datalayout
Clang [defaults to aligning `__int128_t` to 16 bytes], while LLVM `datalayout` strings [default to aligning `i128` to 8 bytes]. Wasm is currently using the defaults for both, so it's inconsistent. Fix this by adding `-i128:128` to Wasm's `datalayout` string so that it aligns `i28` to 16 bytes too. This is similar to llvm/llvm-project@dbad963 for SPARC. This fixes rust-lang/rust#133991; see that issue for further discussion. [defaults to aligning `__int128_t` to 16 bytes]: https://github.com/llvm/llvm-project/blob/f8b4182f076f8fe55f9d5f617b5a25008a77b22f/clang/lib/Basic/TargetInfo.cpp#L77 [default to aligning `i128` to 8 bytes]: https://llvm.org/docs/LangRef.html#langref-datalayout
Clang [defaults to aligning `__int128_t` to 16 bytes], while LLVM `datalayout` strings [default to aligning `i128` to 8 bytes]. Wasm is currently using the defaults for both, so it's inconsistent. Fix this by adding `-i128:128` to Wasm's `datalayout` string so that it aligns `i128` to 16 bytes too. This is similar to llvm/llvm-project@dbad963 for SPARC. This fixes rust-lang/rust#133991; see that issue for further discussion. [defaults to aligning `__int128_t` to 16 bytes]: https://github.com/llvm/llvm-project/blob/f8b4182f076f8fe55f9d5f617b5a25008a77b22f/clang/lib/Basic/TargetInfo.cpp#L77 [default to aligning `i128` to 8 bytes]: https://llvm.org/docs/LangRef.html#langref-datalayout
It seems the situation is that Clang defaults to aligning It appears the fix for SPARC was to add an explicit Another option would be to change clang, to align So overall, adding |
Thanks! |
Clang [defaults to aligning `__int128_t` to 16 bytes], while LLVM `datalayout` strings [default to aligning `i128` to 8 bytes]. Wasm is currently using the defaults for both, so it's inconsistent. Fix this by adding `-i128:128` to Wasm's `datalayout` string so that it aligns `i128` to 16 bytes too. This is similar to llvm/llvm-project@dbad963 for SPARC. This fixes rust-lang/rust#133991; see that issue for further discussion. [defaults to aligning `__int128_t` to 16 bytes]: https://github.com/llvm/llvm-project/blob/f8b4182f076f8fe55f9d5f617b5a25008a77b22f/clang/lib/Basic/TargetInfo.cpp#L77 [default to aligning `i128` to 8 bytes]: https://llvm.org/docs/LangRef.html#langref-datalayout
Clang [defaults to aligning `__int128_t` to 16 bytes], while LLVM `datalayout` strings [default to aligning `i128` to 8 bytes]. Wasm is currently using the defaults for both, so it's inconsistent. Fix this by adding `-i128:128` to Wasm's `datalayout` string so that it aligns `i128` to 16 bytes too. This is similar to llvm/llvm-project@dbad963 for SPARC. This fixes rust-lang/rust#133991; see that issue for further discussion. [defaults to aligning `__int128_t` to 16 bytes]: https://github.com/llvm/llvm-project/blob/f8b4182f076f8fe55f9d5f617b5a25008a77b22f/clang/lib/Basic/TargetInfo.cpp#L77 [default to aligning `i128` to 8 bytes]: https://llvm.org/docs/LangRef.html#langref-datalayout
Clang [defaults to aligning `__int128_t` to 16 bytes], while LLVM `datalayout` strings [default to aligning `i128` to 8 bytes]. Wasm is currently using the defaults for both, so it's inconsistent. Fix this by adding `-i128:128` to Wasm's `datalayout` string so that it aligns `i128` to 16 bytes too. This is similar to [dbad963](dbad963) for SPARC. This fixes rust-lang/rust#133991; see that issue for further discussion. [defaults to aligning `__int128_t` to 16 bytes]: https://github.com/llvm/llvm-project/blob/f8b4182f076f8fe55f9d5f617b5a25008a77b22f/clang/lib/Basic/TargetInfo.cpp#L77 [default to aligning `i128` to 8 bytes]: https://llvm.org/docs/LangRef.html#langref-datalayout
Clang [defaults to aligning `__int128_t` to 16 bytes], while LLVM `datalayout` strings [default to aligning `i128` to 8 bytes]. Wasm is currently using the defaults for both, so it's inconsistent. Fix this by adding `-i128:128` to Wasm's `datalayout` string so that it aligns `i128` to 16 bytes too. This is similar to [llvm/llvm-project@dbad963](llvm@dbad963) for SPARC. This fixes rust-lang/rust#133991; see that issue for further discussion. [defaults to aligning `__int128_t` to 16 bytes]: https://github.com/llvm/llvm-project/blob/f8b4182f076f8fe55f9d5f617b5a25008a77b22f/clang/lib/Basic/TargetInfo.cpp#L77 [default to aligning `i128` to 8 bytes]: https://llvm.org/docs/LangRef.html#langref-datalayout
The
u128
andi128
types on the wasm targets has alignment of 8. This is inconsistent with the alignment on all Tier-1 targets.Compile this code:
Godbolt link.
The body of this function on all Tier-1 targets is "return 16", while on
wasm32-unknown-unknown
,wasm32-unknown-emscripten
, andwasm32-wasi
it compiles to "return 8".This causes arrays that are aligned on wasm to no longer be aligned when pointers are passed through FFI to the host. For example, creating a
Vec<u128>
in wasm and returning it as slice to the host causes misalignment.I am not sure if this is a compiler bug or if this is for some reason intentional, but it is very annoying. A workaround is to declare your own this wrapper to force alignment and use it throughout:
however that doesn't play well with external libraries that use
u128
.Meta
This happens both on stable 1.83 (see the Godbolt link above) and my nightly from 2024-12-05
rustc --version --verbose
:The text was updated successfully, but these errors were encountered: