diff mbox

Reject > word sign extensions in initializers (PR middle-end/80163)

Message ID 20170324192759.GS11094@tucnak
State New
Headers show

Commit Message

Jakub Jelinek March 24, 2017, 7:27 p.m. UTC
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.


	Jakub

Comments

Jeff Law March 27, 2017, 3:44 p.m. UTC | #1
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
diff mbox

Patch

--- 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;
+}