diff mbox series

Fix output_constructor_bitfield handling of wide bitfields (PR89037)

Message ID 87ftthueaw.fsf@arm.com
State New
Headers show
Series Fix output_constructor_bitfield handling of wide bitfields (PR89037) | expand

Commit Message

Richard Sandiford Jan. 25, 2019, 12:12 p.m. UTC
The testcase was failing because we were trying to access
TREE_INT_CST_ELT (x, 1) of a 128-bit integer that was small enough
to need only a single element.

Tested on aarch64-linux-gnu, aarch64_be-elf and x86_64-linux-gnu.
OK to install?

Richard


2019-01-25  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	PR middle-end/89037
	* varasm.c (output_constructor_bitfield): Use wi::extract_uhwi
	instead of accessing TREE_INT_CST_ELT directly.

gcc/testsuite/
	PR middle-end/89037
	* gcc.dg/pr89037.c: New test.

Comments

Richard Biener Jan. 25, 2019, 4:07 p.m. UTC | #1
On January 25, 2019 1:12:07 PM GMT+01:00, Richard Sandiford <richard.sandiford@arm.com> wrote:
>The testcase was failing because we were trying to access
>TREE_INT_CST_ELT (x, 1) of a 128-bit integer that was small enough
>to need only a single element.
>
>Tested on aarch64-linux-gnu, aarch64_be-elf and x86_64-linux-gnu.
>OK to install?

OK.. 
Richard. 

>Richard
>
>
>2019-01-25  Richard Sandiford  <richard.sandiford@arm.com>
>
>gcc/
>	PR middle-end/89037
>	* varasm.c (output_constructor_bitfield): Use wi::extract_uhwi
>	instead of accessing TREE_INT_CST_ELT directly.
>
>gcc/testsuite/
>	PR middle-end/89037
>	* gcc.dg/pr89037.c: New test.
>
>Index: gcc/varasm.c
>===================================================================
>--- gcc/varasm.c	2019-01-04 11:39:27.182246717 +0000
>+++ gcc/varasm.c	2019-01-25 12:10:23.969006336 +0000
>@@ -5349,7 +5349,7 @@ output_constructor_bitfield (oc_local_st
>     {
>       int this_time;
>       int shift;
>-      HOST_WIDE_INT value;
>+      unsigned HOST_WIDE_INT value;
>       HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
>       HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
> 
>@@ -5381,15 +5381,13 @@ output_constructor_bitfield (oc_local_st
> 	      this_time = end - shift + 1;
> 	    }
> 
>-	  /* Now get the bits from the appropriate constant word.  */
>-	  value = TREE_INT_CST_ELT (local->val, shift /
>HOST_BITS_PER_WIDE_INT);
>-	  shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
>+	  /* Now get the bits we want to insert.  */
>+	  value = wi::extract_uhwi (wi::to_widest (local->val),
>+				    shift, this_time);
> 
> 	  /* Get the result.  This works only when:
> 	     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
>-	  local->byte |= (((value >> shift)
>-			   & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
>-			  << (BITS_PER_UNIT - this_time - next_bit));
>+	  local->byte |= value << (BITS_PER_UNIT - this_time - next_bit);
> 	}
>       else
> 	{
>@@ -5406,15 +5404,13 @@ output_constructor_bitfield (oc_local_st
> 	    this_time
>	      = HOST_BITS_PER_WIDE_INT - (shift & (HOST_BITS_PER_WIDE_INT -
>1));
> 
>-	  /* Now get the bits from the appropriate constant word.  */
>-	  value = TREE_INT_CST_ELT (local->val, shift /
>HOST_BITS_PER_WIDE_INT);
>-	  shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
>+	  /* Now get the bits we want to insert.  */
>+	  value = wi::extract_uhwi (wi::to_widest (local->val),
>+				    shift, this_time);
> 
> 	  /* Get the result.  This works only when:
> 	     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
>-	  local->byte |= (((value >> shift)
>-			   & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
>-			  << next_bit);
>+	  local->byte |= value << next_bit;
> 	}
> 
>       next_offset += this_time;
>Index: gcc/testsuite/gcc.dg/pr89037.c
>===================================================================
>--- /dev/null	2019-01-24 08:42:49.147091464 +0000
>+++ gcc/testsuite/gcc.dg/pr89037.c	2019-01-25 12:10:23.965006370 +0000
>@@ -0,0 +1,24 @@
>+/* { dg-do run { target int128 } } */
>+/* { dg-options "" } */
>+
>+struct s
>+{
>+  __int128 y : 66;
>+};
>+typedef struct s T;
>+T a[] = { 1, 10000, 0x12345, 0xff000001, 1ULL << 63, (__int128) 1 <<
>64,
>+	  ((__int128) 1 << 64) | 1 };
>+
>+int
>+main (void)
>+{
>+  if (a[0].y != 1
>+      || a[1].y != 10000
>+      || a[2].y != 0x12345
>+      || a[3].y != 0xff000001
>+      || a[4].y != (1ULL << 63)
>+      || a[5].y != ((__int128) 1 << 64)
>+      || a[6].y != (((__int128) 1 << 64) | 1))
>+    __builtin_abort ();
>+  return 0;
>+}
diff mbox series

Patch

Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	2019-01-04 11:39:27.182246717 +0000
+++ gcc/varasm.c	2019-01-25 12:10:23.969006336 +0000
@@ -5349,7 +5349,7 @@  output_constructor_bitfield (oc_local_st
     {
       int this_time;
       int shift;
-      HOST_WIDE_INT value;
+      unsigned HOST_WIDE_INT value;
       HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
       HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
 
@@ -5381,15 +5381,13 @@  output_constructor_bitfield (oc_local_st
 	      this_time = end - shift + 1;
 	    }
 
-	  /* Now get the bits from the appropriate constant word.  */
-	  value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
-	  shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
+	  /* Now get the bits we want to insert.  */
+	  value = wi::extract_uhwi (wi::to_widest (local->val),
+				    shift, this_time);
 
 	  /* Get the result.  This works only when:
 	     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
-	  local->byte |= (((value >> shift)
-			   & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
-			  << (BITS_PER_UNIT - this_time - next_bit));
+	  local->byte |= value << (BITS_PER_UNIT - this_time - next_bit);
 	}
       else
 	{
@@ -5406,15 +5404,13 @@  output_constructor_bitfield (oc_local_st
 	    this_time
 	      = HOST_BITS_PER_WIDE_INT - (shift & (HOST_BITS_PER_WIDE_INT - 1));
 
-	  /* Now get the bits from the appropriate constant word.  */
-	  value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
-	  shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
+	  /* Now get the bits we want to insert.  */
+	  value = wi::extract_uhwi (wi::to_widest (local->val),
+				    shift, this_time);
 
 	  /* Get the result.  This works only when:
 	     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
-	  local->byte |= (((value >> shift)
-			   & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
-			  << next_bit);
+	  local->byte |= value << next_bit;
 	}
 
       next_offset += this_time;
Index: gcc/testsuite/gcc.dg/pr89037.c
===================================================================
--- /dev/null	2019-01-24 08:42:49.147091464 +0000
+++ gcc/testsuite/gcc.dg/pr89037.c	2019-01-25 12:10:23.965006370 +0000
@@ -0,0 +1,24 @@ 
+/* { dg-do run { target int128 } } */
+/* { dg-options "" } */
+
+struct s
+{
+  __int128 y : 66;
+};
+typedef struct s T;
+T a[] = { 1, 10000, 0x12345, 0xff000001, 1ULL << 63, (__int128) 1 << 64,
+	  ((__int128) 1 << 64) | 1 };
+
+int
+main (void)
+{
+  if (a[0].y != 1
+      || a[1].y != 10000
+      || a[2].y != 0x12345
+      || a[3].y != 0xff000001
+      || a[4].y != (1ULL << 63)
+      || a[5].y != ((__int128) 1 << 64)
+      || a[6].y != (((__int128) 1 << 64) | 1))
+    __builtin_abort ();
+  return 0;
+}