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
Unaligned access on aarch64 wih "+strict-align" on debug using enum #66897
Comments
I think this might be an LLVM bug, rustc correctly records in the IR that the access is underaligned. LLVM backends must lower underaligned accesses correctly, even (especially) when compiling for a target where unaligned accesses are not OK. It seems the AArch64 backend is not doing that in this case, assuming that the function However, independently of that, the setup you're using in the reproduction repo (standard target triple and Cargo invocation, only adding |
Yes, the strict-align feature is correctly enabled for Yes you are right. The standard library will not be correctly compiled. I have put the minimal code together quite quickly and did not iron it out properly. Still, my own file should be compiled correctly and my bare-metal code is using a custom json target file and uses xbuild to cross-compile the core library, so I should be covered there. I am not proficient with LLVM so my first interpretation might really be wrong. I'm happy to report this as a bug on LLVM if someone can confirm that indeed the llvm-ir should not translate to the provided assembly when strict-align is enabled. |
Hm, I did a little digging and found tests which test exactly this scenario and indicate it should work. I also observe the same codegen with the target triple and function attributes indicated by the IR you uploaded. So something else is going wrong and someone will have to reduce the Rust code (and the process of compiling it) to figure out where it happens. |
Some good first reduction steps to try would probably be to:
|
My first steps reducing code is probably suboptimal : https://github.com/christophcharles/rust_unalign/tree/reduced_code I did not understand how you would reproduce the bug using Still I stumbled on something weird. My debian install only has llvm-8, but I tried feeding the llvm-ir directly into it using Is there some attribute I am not sending to llc when using it directly through the command line (or through godbolt) with the ir output from rustc? |
Are you saying the LLVM IR contained
That is very weird indeed! |
Ah, this was the key. As far as I can tell (my ARM assembly is not great), I let rustc generate an IR file that does nothing more than The above LLVM IR is the output after optimizations when compiling this simple function: pub unsafe fn load_unaligned(p: *const i64) -> i64 {
ptr::read_unaligned(p)
} When building without optimizations, I believe I can see the same bug ( |
Ok! Thank you! So this is definitely an LLVM bug. I will report it to the LLVM project after a bit more testing (with the latest build) and reducing it to a small test case. For me, this is also quite nice as I can at least solve my problem in the meantime, by compiling with O1 for my bare metal code. |
I went ahead and reported this upstream: https://bugs.llvm.org/show_bug.cgi?id=44246 |
FWIW looks like the upstream issue was fixed and this probably can be closed. |
I think so. Godbolt for reference: https://rust.godbolt.org/z/8vEPo3Kcj |
I may have stumbled on a bug regarding aligned access on aarch64: when using enum as return values, in some cases, the rust compiler produces code accessing 64-bit value with 32-bit alignement only, even if "+string-align" is selected. The problem is difficult to catch as it really is an issue only if the MMU is disabled (so bare-metal code).
This is the minimal code I was able to produce that shows the problem:
It is directly inspired from bare metal code that I want to run on aarch64 without the MMU enabled. As such, I am compiling in debug, using "+strict-align". Using the target
aarch64-unknown-linux-gnu
, this produces the following assembly for the functiontest
:The instruction at
3c04
is the problematic one as it is accessing a 64-bit value at a 32-bit aligned address (sp is 8-byte aligned).The only way I was able to reproduce this, but I am not sure my search was extensive enough, was by using
enum
. If the discriminant and the stored value naturally fit in two 32-bit fields, rust seems to pack them into a single 64-bit register but forgets to correctly align the access.struct
does not seem to have this problem.The problem already appears in the llvm-ir produced by
cargo rustc --target aarch64-unknown-linux-gnu -- --emit=llvm-ir
:Here we can see that the return value is loaded through an
i64
with 4-byte alignement which translates to the wrong alignement in the final assembly.Here is a link to the source to reproduce the bug:
https://github.com/christophcharles/rust_unalign
I have put the assembly outputs of various stages and platforms in the asm folder.
I am not savvy enough to dabble into the rust source code but it seems to affect both stable and nightly rust. All the examples here though are using stable.
Meta
rustc --version --verbose
(used for these outputs):The text was updated successfully, but these errors were encountered: