bitfields miscompiled for big-endian and optimization
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
GNU Arm Embedded Toolchain |
Fix Released
|
Medium
|
Thomas Preud'homme |
Bug Description
Version: 4.8-2014q2
Host: All
Target: Cortex-R4 big-endian (TMS570)
To reproduce, build this simple test program with -O0 and with -O1:
test.c:
---------
union U
{
const int a;
unsigned b : 20;
};
static union U u = { 0x12345678 };
int main(int argc, char * argv[])
{
return u.b;
}
The above program, when build without optimization returns value 0x12345 (20 bits starting MSB).
When build with optimization returns value 0x45678 (20 bits starting LSB).
build commands:
arm-none-eabi-gcc -c test.c -o test0be.o -O0 -march=armv7-r -mbig-endian
arm-none-eabi-gcc -c test.c -o test1be.o -O1 -march=armv7-r -mbig-endian
arm-none-
arm-none-
object dump:
test0be.o: file format elf32-bigarm
Disassembly of section .text:
00000000 <main>:
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0
8: e24dd00c sub sp, sp, #12
c: e50b0008 str r0, [fp, #-8]
10: e50b100c str r1, [fp, #-12]
14: e3003000 movw r3, #0
18: e3403000 movt r3, #0
1c: e5933000 ldr r3, [r3]
20: e7f33653 ubfx r3, r3, #12, #20 <== bitfield taken from 20 MSB bits
24: e1a00003 mov r0, r3
28: e24bd000 sub sp, fp, #0
2c: e49db004 pop {fp} ; (ldr fp, [sp], #4)
30: e12fff1e bx lr
test1be.o: file format elf32-bigarm
Disassembly of section .text:
00000000 <main>:
0: e3050678 movw r0, #22136 ; 0x5678
4: e3400004 movt r0, #4 <== value 0x45678 pre-calculated
8: e12fff1e bx lr
Changed in gcc-arm-embedded: | |
status: | New → Confirmed |
assignee: | nobody → Thomas Preud'homme (thomas-preudhomme) |
importance: | Undecided → High |
Changed in gcc-arm-embedded: | |
status: | Confirmed → Fix Committed |
Changed in gcc-arm-embedded: | |
status: | Fix Committed → Fix Released |
Although I agree the -O1 case is wrong, this code can't expect any specific value when reading b. Indeed, the initialization is made through a which is an integer but read back as a bitfield. Since the way a bitfield is stored is undefined, a given value can be stored in whatever way in a bitfield. The bit endianness could be same or different from the byte endianness for instance.