On 10/11/11 03:57, Joey Ye wrote:
> Trunk gcc mis-handles following volatile bitfield case on ARM target:
>
> $ cat a.c
> extern void check(int);
> typedef struct {
> volatile unsigned short a:8, b:8;
> } BitStruct;
> BitStruct bits = {1, 2};
> int main ()
> {
> check(bits.a);
> return 0;
> }
> $ arm-none-eabi-gcc -v 2>&1 |grep "gcc version"
> gcc version 4.7.0 20111024 (experimental) [trunk revision 180388] (GCC)
> $ arm-none-eabi-gcc -S a.c -mthumb -mcpu=cortex-m3
> $ grep -v "^\s*\." a.s
> bits:
> main:
> @ args = 0, pretend = 0, frame = 0
> @ frame_needed = 1, uses_anonymous_args = 0
> push {r7, lr}
> add r7, sp, #0
> movw r3, #:lower16:bits
> movt r3, #:upper16:bits
> ldrh r3, [r3, #0] @ movhi
> uxth r3, r3 // Should be uxtb here. As a result,
> // the output becomes 2056, instead of 8 as expected
> mov r0, r3
> bl check
> mov r3, #0
> mov r0, r3
> pop {r7, pc}
>
> Root cause is that when restrict-volatile-bitfields is enabled, which is ARM
> default. Volatile bitfields isn't loaded as bitfield even if bitfield size
> is less than load size.
>
> It is actually a regression introduced by:
> http://gcc.gnu.org/ml/gcc-patches/2011-03/msg01477.html
>
>
> Patch to fix this:
> 2011-11-10 Joey Ye <[email protected]>
>
> Fix volatile bitfield load
> * gcc/expr.c (expand_expr_real_1): Check bitfield size
> smaller than mode size.
Normally it would be best to write
* expr.c (expand_expr_real_1): Correctly handle strict volatile
bitfield loads smaller than mode size.
>
> Testcase:
> 2011-11-10 Joey Ye <[email protected]>
>
> * gcc.dg/volatile-bitfields-1.c: New.
>
OK.
R.