Fix output_constructor_bitfield handling of wide bitfields (PR89037)

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.

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.

From-SVN: r268272
This commit is contained in:
Richard Sandiford 2019-01-25 16:57:32 +00:00 committed by Richard Sandiford
parent 62fa42ce81
commit 3c35efc322
4 changed files with 44 additions and 13 deletions

View file

@ -1,3 +1,9 @@
2019-01-25 Richard Sandiford <richard.sandiford@arm.com>
PR middle-end/89037
* varasm.c (output_constructor_bitfield): Use wi::extract_uhwi
instead of accessing TREE_INT_CST_ELT directly.
2019-01-25 Christophe Lyon <christophe.lyon@linaro.org>
* doc/sourcebuild.texi (Environment attributes): Add fenv and

View file

@ -1,3 +1,8 @@
2019-01-25 Richard Sandiford <richard.sandiford@arm.com>
PR middle-end/89037
* gcc.dg/pr89037.c: New test.
2019-01-25 Christophe Lyon <christophe.lyon@linaro.org>
* lib/target-supports.exp (check_effective_target_fenv): New.

View file

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

View file

@ -5349,7 +5349,7 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
{
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_state *local, unsigned int bit_offset)
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_state *local, unsigned int bit_offset)
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;