thumbv6m-none-eabi compiler builtin ABI bug #39056
Labels
A-LLVM
Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.
O-Arm
Target: 32-bit Arm processors (armv6, armv7, thumb...), including 64-bit Arm in AArch32 state
P-low
Low priority
T-compiler
Relevant to the compiler team, which will review and decide on the PR/issue.
I'm helping to build a small operating system to run on Cortex-M0 processors. I'm compiling for the
thumbv6m-none-eabi
target. When using the compiler builtin function__aeabi_lmul
it seems that the compiler is passing in the arguments to the wrong registers. For example, this piece of code:Gets compiled down to:
According the the ARM ABI Documentation (Section 5.1.1.1), passing a 64bit value as an argument should store them in registers
r0
andr1
orr2
andr3
as a pair. With the low bits being stored inr0/2
and the high bits stored inr1/3
.Looking at the dissasembled code, the first argument, which was initially stored in
r0
gets its low and high bits split intor0
andr3
respectively, not the expectedr0
andr1
. The second argument also gets split intor2
andr1
for its low and high bits. So it appears that the high bits for the two values have been swapped.Because the values are sign extended from 32 bits, this is only an issue if the signs of the two arguments differ. If they're the same the high bit registers will happen to be the same. But when the signs differ the function returns a wrong result in the
r1
register. This causes a panic if overflow checking is enabled.I've not noticed this issue anywhere else, but it could possibly be hidden around in some of the other compiler builtins.
I've created a sample repo here that shows off the bug. You'll need an ARM toolchain to actually compile it down to a binary, but you should still be able to cross compile it into a static library. (the command I was using was
xargo build --target=thumbv6m-none-eabi
)Version info:
The text was updated successfully, but these errors were encountered: