gcc miscompiles csum_tcpudp_magic() on ARMv5

Willy Tarreau w at 1wt.eu
Thu Dec 12 11:04:26 EST 2013


On Thu, Dec 12, 2013 at 03:41:10PM +0000, Russell King - ARM Linux wrote:
> One of the issues here is that internally, GCC tracks the "machine mode"
> of a register, where "mode" basically means the type of register it is.
> In this case, the register will be in "half integer" mode when it is
> passed into the assembler, and gcc does _not_ promote it.
> 
> We can see this in the RTL:
> 
> (insn 11 10 12 3 ../t.c:9 (set (reg:SI 143 [ sum ])
>         (asm_operands:SI ("mov  %0, %1") ("=&r") 0 [
>                 (subreg:HI (reg:SI 148) 0)
>             ]
>              [
>                 (asm_input:HI ("r") (null):0)
>             ]
>              [] ../t.c:12)) -1 (nil))
> 
> Note that "HI" for the input register 148.  What this means is that the
> compiler "knows" that it's supposed to be a 16-bit quantity, and has
> recorded that fact, and _will_ truncate it down to 16-bit when it needs
> to be promoted.
> 
> Since the asm() only asks for a "register", that's what we get - a
> register which _happens_ to be in HI mode containing the value.  However,
> there's no way to tell that from the assembly code itself (GCC doesn't
> have the facility to do conditional assembly generation depending on
> the argument type passed into it.)

OK so that means that it's just like having true 16-bit registers except
that it's just a temporary representation and not a feature of the CPU.
The compiler has the right to expect the asm instructions to only use
the lower 16 bits and has no way to verify that.

Then changing the type of the function argument would probably be safer!

Regards,
Willy




More information about the linux-arm-kernel mailing list