[ was: Re: [committed][nvptx] Fix printing of 128-bit constant ] On 9/10/20 10:26 PM, Jakub Jelinek wrote: > On Thu, Sep 10, 2020 at 09:31:33PM +0200, Tom de Vries wrote: >> Currently, for this code from c-c++-common/spec-barrier-1.c: >> ... >> __int128 g = 9; >> ... >> we generate: >> ... >> // BEGIN GLOBAL VAR DEF: g >> .visible .global .align 8 .u64 g[2] = { 9, 9 }; >> ... >> and consequently the test-case fails in execution. >> >> The problem is caused by a shift in nvptx_assemble_value: >> ... >> val >>= part * BITS_PER_UNIT; >> ... >> where the shift amount is equal to the number of bits in val, which is >> undefined behaviour. >> >> Fix this by detecting the situation and setting val to 0. > > Actually, looking more at it, is nvptx_assemble_value called from > nvptx_assemble_integer with the CONST_INT and size of 16? > Then > val &= ((unsigned HOST_WIDE_INT)2 << (size * BITS_PER_UNIT - 1)) - 1; > will invoke UB too (perhaps it can just do: > if (size * BITS_PER_UNIT < HOST_BITS_PER_WIDE_INT) > val &= HOST_WIDE_INT_1U << (size * BITS_PER_UNIT); > ?),
Done in patch attached below, committed. Thanks, -Tom
[nvptx] Fix UB in nvptx_assemble_value When nvptx_assemble_value is called with size == 16, this bitshift runs into UB: ... val &= ((unsigned HOST_WIDE_INT)2 << (size * BITS_PER_UNIT - 1)) - 1; ... Fix this by checking the shift amount. Tested on nvptx. gcc/ChangeLog: * config/nvptx/nvptx.c (nvptx_assemble_value): Fix undefined behaviour. --- gcc/config/nvptx/nvptx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c index 4fca0ed76d9..0c590d8d1f6 100644 --- a/gcc/config/nvptx/nvptx.c +++ b/gcc/config/nvptx/nvptx.c @@ -2053,7 +2053,9 @@ nvptx_assemble_value (unsigned HOST_WIDE_INT val, unsigned size) bool negative_p = val & (HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1)); - val &= ((unsigned HOST_WIDE_INT)2 << (size * BITS_PER_UNIT - 1)) - 1; + /* Avoid undefined behaviour. */ + if (size * BITS_PER_UNIT < HOST_BITS_PER_WIDE_INT) + val &= (HOST_WIDE_INT_1U << (size * BITS_PER_UNIT)) - 1; for (unsigned part = 0; size; size -= part) {