Ensure shift instrinsic arguments match width of compiler-rt's.#522
Conversation
|
Interesting... well, Just to be clear, the tests pass on my local Linux box: DebugRelease |
|
Can you rebase now that #524 is merged, which should fix CI? |
|
@Amanieu Done, and CI is green :D! |
| pub extern "C" fn __ashldi3(a: u64, b: core::ffi::c_uint) -> u64 { | ||
| a.ashl(b as u32) |
There was a problem hiding this comment.
Drive by comment:
While this appears to follow the calling convention that LLVM uses, it does not follow the calling convention that avr-gcc uses: https://godbolt.org/z/azq4749hd
b is only a single byte on avr-gcc.
(I also see now that the C implementation in compiler-rt has the same bug, but only realized it now).
There was a problem hiding this comment.
AIUI, these code paths are skipped when compiling for avr, precisely because there's a pass which gets rid of these types of shifts in LLVM. So I made no accommodations for its nonstandard calling conventions in this PR.
That being said, I don't know what a proper fix should look like that fixes avr, msp430, and everything-else.
There was a problem hiding this comment.
because there's a pass which gets rid of these types of shifts in LLVM
I know, because I wrote that pass ;)
But it only works for 32-bit values.__ashldi3 is a 64-bit shift function, which is emitted as a regular compiler-rt call. Proof: https://godbolt.org/z/zqWfE6ndq
Anyway, it doesn't really matter as LLVM uses i16 and not i8 like avr-gcc does. This PR would only be buggy for avr-gcc, right now it is safe with LLVM (but this could in theory change as i8 is more efficient).
There was a problem hiding this comment.
Minddump for future-me follows:
b is only a single byte on avr-gcc.
- According to gcc docs,
__ashldi3'sbargument is supposed to take anint, which must be at least 16 bits. But indeed, your GCC code snippet is only sending a byte to__ashldi3, while the LLVM version sends 16 bits (theclr r17line is clearing the top-most bits). - On the other hand,
gcc's docs also says__ashldi3is supposed to return along, and__ashlti3is the function that is supposed to return along long. - On the other _other hand,
compiler-rtdoesn't seem to support thetversions of functions, and tends to hardcode a 64/32-bit int in places gcc's builtins do not1. In addition tocompiler-rtusesunsignedin args where gcc's builtins aresigned.
In other words, it seems like both gcc compiler-rt builtins tend to do their own things and aren't directly compatible with each other. avr using a byte in for the gcc __ashldi3 b arg, but 2 bytes for compiler-rt's __ashldi3 b arg is just one example of this. It's not going to be fun :P. Unifying compiler-rt's and gcc's builtins in terms of compiler_builtins might be necessary due to the gcc backend though.
- The shift functions'
bargs notwithstanding :P.
There was a problem hiding this comment.
But it only works for 32-bit values. __ashldi3 is a 64-bit shift function, which is emitted as a regular compiler-rt call.
How does this not break for Rust code, where all the shift functions are skipped for AVR (avr_skip)?
Update compiler-builtins to 0.1.91 to bring in msp430 shift primitive… … fixes. This fixes unsoundness on MSP430 where `compiler-builtins` and LLVM didn't agree on the width of the shift amount argument of the shifting primitives (4 bytes vs 2 bytes). See rust-lang/compiler-builtins#522 for more details.
Update compiler-builtins to 0.1.91 to bring in msp430 shift primitive… … fixes. This fixes unsoundness on MSP430 where `compiler-builtins` and LLVM didn't agree on the width of the shift amount argument of the shifting primitives (4 bytes vs 2 bytes). See rust-lang/compiler-builtins#522 for more details.
Update compiler-builtins to 0.1.91 to bring in msp430 shift primitive… … fixes. This fixes unsoundness on MSP430 where `compiler-builtins` and LLVM didn't agree on the width of the shift amount argument of the shifting primitives (4 bytes vs 2 bytes). See rust-lang/compiler-builtins#522 for more details.
Update compiler-builtins to 0.1.91 to bring in msp430 shift primitive… … fixes. This fixes unsoundness on MSP430 where `compiler-builtins` and LLVM didn't agree on the width of the shift amount argument of the shifting primitives (4 bytes vs 2 bytes). See rust-lang/compiler-builtins#522 for more details.
This fixes #520. I tested this locally and confirmed this fixes my issue, along with the additional changes listed in the below sections just for testing.
I realized while working on this patch that as far as
compiler-builtinsis concerned, only the shift instrinsics are affected by 16-bit vs 32-bit mismatch. This dates back to a patch by @aykevl in 2020.It is very possible that the msp430 backend generates code w/ incorrect width for other instrinsics changed in the above patch. However, I don't know a good way to sift these out w/ tests, Rust or otherwise. Perhaps rust-lang/rust#107612 could be useful here?
mspdebughas a simulator; it's how I was able to get a test case for #520.compiler-builtinspatchesWithout this, for some reason Rust bails with
-D warnings, due to rust-lang/rust#96472 when I'm usingcompiler-builtinsas a path dep (but not when using a crates.io dep... huh...).rustpatchesUse local
compiler-builtinswith my patch, work around some unrelated LLVM assertion failures atopt-level=3.