-
Notifications
You must be signed in to change notification settings - Fork 13.3k
u64 calculation incorrect on ARMv5 #31796
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
Comments
You could try emitting IR and then use your ARM system's |
I tried using llc on the llvm ir, but it failed: These are the respective llvm-irs: |
I think it could be related to the datalayout; my
which produces correct results, whereas the custom target's Should the different alignment values lead to this error? You could try putting clang's datalayout in your json file to see if it helps. |
I've recompiled rust and the test program with the "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" datalayout, unfortunately with the same result. |
I've compiled your rust IR file with a compatible llc:
If you don't see any problems with that command line, you can try the following on your ARM system: $ as rust_u64.s -o rust_u64.o
$ gcc rust_u64.o -L path_to_your_libstd-*.so -o rust_u64
$ ./rust_u64 |
It was a bit trickier, but I managed to get it to link and run and it reports |
Haven't we just exonerated llvm and implicated your cross-toolchain? I simply used llvm 3.8 from my last Rust build to match your built-in stuff. (it ends up in |
What I meant was that we showed that the llvm-ir created by my rust is valid, but the binary is not, so the error is somewhere between llvm-ir and binary on my setup. I thought it is probably llvm, since llvm is responsible for that part. I was able to create the exact same assembler output using the llvm from my rust build. This would suggest that my cross-toolchain setup is indeed wrong in some way. Since the llvm in my rust build can create correct binaries, I think that this is probably an error in my target json. What do you think? |
Unfortunately using "armv4t-unknown-linux-gnueabi" as llvm-target and arm7tdmi as processor had the same results |
Yeah, the llvm target is fine. Have you tried dumping assembly instead? The bundled llvm source was recently updated - as a last resort you could try building rust against an older local version (or even use a 1.6 source tarball) to see if the problem lies outside of llvm and rust. |
Any news on this? @joerg-krause You were having trouble with your armv5 target, any ideas where this could be coming from? |
So to test if the assembler is the problem I used the llc with "-filetype=obj" and used the cross-toolchain gcc on my x86_64 to link this file. This generates the correct result. |
Provided you do have a cross gas on x86_64, could you try doing it in one go, with: On the other hand, if you could reproduce the bug by manually assembling with |
Compiling it with using -C no-integrated-as seems to work (although gcc is given the wrong path to the .o file during linking. I fixed that using a symlink) |
Ok, so it really looks like the the built-in assembler was to blame. I advise showing the material you've gathered to LLVM devs at https://llvm.org/bugs/ |
Well I was able to use the llc compiler with -filetype=obj to generate a binary that was correct or does llc use an external as? |
That's why my guess was llvm bitcode generation could be wrong as we've already proven going through intermediate steps of |
I can confirm this issue with my custom armv5te-unknown-linux-musl.json target:
Output on ARMv5: @petevine Can you post the necessary commands to get the llvm bitcode, please. I'm not very experienced with LLVM. |
Sure, to get Or even |
Somehow, this does not work:
I guess I'm doing it in the wrong way... |
Nope, it's probably just using your system's llc which seems incompatible for some reason. However, if you're going to try again maybe use Do you still have the |
No. Bootstraping the Rust cross-compiler for ARMv5 was to time-consuming, so I am cross-compiling the Rust libraries only. Does Rust hacks LLVM in a special way or can I just use the system ones? I update my system LLVM to:
Running main on the ARMv5 target: Is rust generating wrong bytecode? |
I compiled the main.c from above (without "Hello world") with Clang:
And I compiled the main.rs from above (without "Hello world") with Rust:
The generated IR shows that Rust calculates the right value: |
Thanks so much for persevering @joerg-krause ! I believe you've clearly demonstrated generating May we have a look at both versions side by side? These two |
I adapted the example to: fn main() {
const FNV_PRIME: u64 = 1099511628211;
let mut h = 14695981039346656037;
h = (h ^ (10 as u64)).wrapping_mul(FNV_PRIME);
h = (h ^ (50 as u64)).wrapping_mul(FNV_PRIME);
h = (h ^ (60 as u64)).wrapping_mul(FNV_PRIME);
println!("{}", h == 3470322685770408467);
} Cross-compiling:
Running on ARMv5 target:
So, the calculation is correct. However, the correct result is not displayed. |
OK, so it's a different bug than we'd thought but still, it should be evident in the two assembly versions. |
Please have a look: bc and asm. For the record: bc:
asm:
EDIT: Re-run compilation steps... |
To clarify, clang.s is supposed to be the equivalent of rust's EDIT: |
To recap, after emitting the following:
assembling with gas every time. |
I've re-run the compilation step (see above) and updated the previous gist files. |
You need to ditch clang, and rerun the |
Sorry, I'm afraid I do not understand what you want me to do. Can you provide the command, please? I've re-run the test with a simpler main.rs: fn main() {
let h = 10;
println!("h:{} h==10:{}", h, h==10);
} Compiling with cargo:
Running on target:
Weird! |
I'm talking about the first experiment you already conducted today. You then proceeded to assemble and link the binary which printed the wrong result. |
Printing a loop: fn main() {
for x in 0..255 {
println!("{}", x); // x: i32
}
}
Looks like data alignment or byte ordering is messed up... |
Indeed, nice demonstration - that doesn't happen with gas though. |
I see! I re-run the compilation steps. Please have a look at my previous comment #31796 (comment). EDIT: |
Darn! I thought we were getting somewhere but it seems I was comparing the results from two different people :) Are you sure your target is equivalent to @returntoreality 's? If you look at this comment, it worked for him: |
|
Yeah, you already tried that manually. Either your json target is slightly different or your cross-gas is to blame. I've run out of ideas - if you have a working armv5 native toolset you could try the above as well. Or maybe it's tangentially related to issue #32049 (comment) ? At least the alignment values differ too... |
@returntoreality I've just remembered you rebuilt your armv5 cross-compiler with clang's datalayout - were you using it ever since or rather the original? |
I was able to fix this issue by adding @petevine Many thanks for all your help! |
Well, you found the culprit so the thanks should go to you! Anyway, this probably means armv5 is fit to become the default target of |
@petevine I used the "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" datalayout, which was used by the armv5 systems clang and your armv7 toolchain. |
I just tested adding +strict-align, which sadly did not fix it. |
Okay I had to rebuild rustlib aswell, now it works! Thank you @petevine and @joerg-krause ! |
Cool, it was starting to look really crazy otherwise :) Time to close, eh? |
Yeah. You can close it then. |
It's your issue, I don't possess any special powers. |
The |
I've built a cross rust compiler for armv5tel-unknown-linux-gnueabi and using this target json
and this mk/cfg/armv5tel-unknown-linux-gnueabi.mk:
I've run into problems with the regex crate, where an assertion ( assert!(start <= end); ByteClassSet::set_range(&mut self, start: u8, end: u8) in src/compile.rs ) failed when compiling a regex, which worked fine on x86_64. I saw the hash function that is implemented near the assertion, so I wanted to see if the u64 calculations are correct (the armv5 is 32bit). Here is the original function:
I tried this code:
Which has different results on x86_64 and armv5
x86_64:
Hello, world! 3470322685770408467
armv5:
Hello, world! 3642012766597943866
I used clang on the armv5 device to compile this simple C program which does the same calculations:
Code:
Result:
Hello, world! 3470322685770408467
Meta
rustc 1.8.0-dev (15611f7 2016-02-19)
binary: rustc
commit-hash: 15611f7
commit-date: 2016-02-19
host: x86_64-unknown-linux-gnu
release: 1.8.0-dev
The text was updated successfully, but these errors were encountered: