Message ID | 20170324192759.GS11094@tucnak |
---|---|
State | New |
Headers | show |
On 03/24/2017 01:27 PM, Jakub Jelinek wrote: > Hi! > > I'm not aware of any target that would support sign extension of > something that can't be folded in the compiler into some type > larger than word/pointer. Zero extension is doable and assemble_variable > is able to deal with it by emitting low/high subregs of it (where the > low one will contain some expression that needs to be computed by assembler > or even have relocation and upper part will be all zeros), but for > sign extension we'd need assembler support that would for some > asm expression shift it arithmetically right. > > So, this patch just rejects it in initializers (in C++ handles through > dynamic initialization) in that case. clang also rejects it, ICC silently > miscompiles (performs zero extension). > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2017-03-24 Jakub Jelinek <jakub@redhat.com> > > PR middle-end/80163 > * varasm.c (initializer_constant_valid_p_1): Disallow sign-extending > conversions to integer types wider than word and pointer. > > * gcc.dg/pr80163.c: New test. FWIW, the old PA 32 bit SOM model had relocations that would allow supporting this case. We never exposed them as never seemed worth the effort, given it's a relatively obscure issue on a dead platform, I don't think it's worth trying to do anything to support it there. OK for the trunk. jeff
--- gcc/varasm.c.jj 2017-01-01 12:45:37.000000000 +0100 +++ gcc/varasm.c 2017-03-24 13:03:37.489529361 +0100 @@ -4472,8 +4472,15 @@ initializer_constant_valid_p_1 (tree val return initializer_constant_valid_p_1 (src, endtype, cache); /* Allow conversions between other integer types only if - explicit value. */ - if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type)) + explicit value. Don't allow sign-extension to a type larger + than word and pointer, there aren't relocations that would + allow to sign extend it to a wider type. */ + if (INTEGRAL_TYPE_P (dest_type) + && INTEGRAL_TYPE_P (src_type) + && (TYPE_UNSIGNED (src_type) + || TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type) + || TYPE_PRECISION (dest_type) <= BITS_PER_WORD + || TYPE_PRECISION (dest_type) <= POINTER_SIZE)) { tree inner = initializer_constant_valid_p_1 (src, endtype, cache); if (inner == null_pointer_node) --- gcc/testsuite/gcc.dg/pr80163.c.jj 2017-03-24 13:02:37.827295587 +0100 +++ gcc/testsuite/gcc.dg/pr80163.c 2017-03-24 13:05:12.465309614 +0100 @@ -0,0 +1,22 @@ +/* PR middle-end/80163 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O0" } */ + +void bar (void); + +__int128_t * +foo (void) +{ +a: + bar (); +b:; + static __int128_t d = (long) &&a - (long) &&b; /* { dg-error "initializer element is not computable at load time" } */ + return &d; +} + +__int128_t * +baz (void) +{ + static __int128_t d = (long) (3 * 4); + return &d; +}