This is a corner case that happens not to affect LTO because the "bad" value is the last one packed.
In pack_ts_type_value_fields, the last thing we pack is TYPE_ALIAS_SET, which in many cases ends up being -1. However, we request bp_pack_value to pack HOST_BITS_PER_INT (32), whereas -1 is 64 bits long on x86_64. bp_pack_value stores all 64 bits in the word, but only counts 32. Any further bit packed will simply be ignored (since they're OR'd in). I found this while packing more bits from C++ types, no matter what I packed, I would get 1s on the reading side. I fixed it by making bp_pack_value chop VAL so that only the first NBITS are stored. Alternately, we could just assert that the caller didn't send a value that overflows NBITS. Richi, do you prefer one over the other? Diego. * lto-streamer.h (bitpack_create): Only use the lower NBITS from VAL. diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 5f56fc6..0d49430 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -1190,8 +1190,19 @@ bitpack_create (struct lto_output_stream *s) static inline void bp_pack_value (struct bitpack_d *bp, bitpack_word_t val, unsigned nbits) { - bitpack_word_t word = bp->word; + bitpack_word_t mask, word; int pos = bp->pos; + + word = bp->word; + + gcc_assert (nbits > 0 && nbits <= BITS_PER_BITPACK_WORD); + + /* Make sure that VAL only has the lower NBITS set. Generate a + mask with the lower NBITS set and use it to filter the upper + bits from VAL. */ + mask = ((bitpack_word_t) 1 << nbits) - 1; + val = val & mask; + /* If val does not fit into the current bitpack word switch to the next one. */ if (pos + nbits > BITS_PER_BITPACK_WORD) -- This patch is available for review at http://codereview.appspot.com/4415044