aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2014-05-23 11:33:42 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2014-05-23 11:33:42 +0000
commit4adf63f9c73ae13fb4b382a6b98d673e94a56e7b (patch)
tree29cdea61d06d772e3fcd03646094a0000fce52cf /gcc/varasm.c
parent0aadce73310807081b7df2b2310f6463e2379e00 (diff)
downloadgcc-4adf63f9c73ae13fb4b382a6b98d673e94a56e7b.zip
gcc-4adf63f9c73ae13fb4b382a6b98d673e94a56e7b.tar.gz
gcc-4adf63f9c73ae13fb4b382a6b98d673e94a56e7b.tar.bz2
* varasm.c (output_constructor_bitfield): Fix thinkos in latest change.
From-SVN: r210856
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c38
1 files changed, 20 insertions, 18 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 6781096..57b33d7 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -5082,24 +5082,27 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
this_time = MIN (end_offset - next_offset, BITS_PER_UNIT - next_bit);
if (BYTES_BIG_ENDIAN)
{
- /* On big-endian machine, take the most significant bits
- first (of the bits that are significant)
- and put them into bytes from the most significant end. */
+ /* On big-endian machine, take the most significant bits (of the
+ bits that are significant) first and put them into bytes from
+ the most significant end. */
shift = end_offset - next_offset - this_time;
/* Don't try to take a bunch of bits that cross
- the word boundary in the INTEGER_CST. We can
- only select bits from the LOW or HIGH part
- not from both. */
+ the word boundary in the INTEGER_CST. We can
+ only select bits from one element. */
if ((shift / HOST_BITS_PER_WIDE_INT)
- != ((shift + this_time) / HOST_BITS_PER_WIDE_INT))
- this_time = (shift + this_time) & (HOST_BITS_PER_WIDE_INT - 1);
+ != ((shift + this_time - 1) / HOST_BITS_PER_WIDE_INT))
+ {
+ const int end = shift + this_time - 1;
+ shift = end & -HOST_BITS_PER_WIDE_INT;
+ 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);
- /* Get the result. This works only when:
+ /* 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))
@@ -5107,25 +5110,24 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
}
else
{
- /* On little-endian machines,
- take first the least significant bits of the value
- and pack them starting at the least significant
+ /* On little-endian machines, take the least significant bits of
+ the value first and pack them starting at the least significant
bits of the bytes. */
shift = next_offset - byte_relative_ebitpos;
/* Don't try to take a bunch of bits that cross
- the word boundary in the INTEGER_CST. We can
- only select bits from the LOW or HIGH part
- not from both. */
+ the word boundary in the INTEGER_CST. We can
+ only select bits from one element. */
if ((shift / HOST_BITS_PER_WIDE_INT)
- != ((shift + this_time) / HOST_BITS_PER_WIDE_INT))
- this_time = (HOST_BITS_PER_WIDE_INT - shift);
+ != ((shift + this_time - 1) / HOST_BITS_PER_WIDE_INT))
+ 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);
- /* Get the result. This works only when:
+ /* 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))