On Fri, 30 Mar 2012, Eric Botcazou wrote: > > > May I apply the patch I posted? It boostrapped/regtested fine on > > > x86-64/Linux. > > > > Yes. > > Thanks. Unfortunately, while this was the last identified problem on x86, > another issue is visible on x86-64 as a miscompilation of XML/Ada at -O0. > Reduced testcase attached: > > gnat.dg/pack18.adb > gnat.dg/pack18_pkg.ads > > The executable segfaults because it attempts a read at 0x2000000000000000. > > The scenario is a follows: Rec is packed record so its fields are bit fields, > N > being at bit offset 129. The representative is at offset 0. > > get_bit_range is invoked on N with a bitpos of 1, because there is variable > offset and its DECL_FIELD_OFFFSET is added to it instead of bitpos. Hence > > bitpos - bitoffset > > is (unsigned HOST_WIDE_INT) -128. This value enters unchanged the new code > in > store_bit_field and the division: > > offset = bitregion_start / BITS_PER_UNIT; > > yields the problematic big number. > > It would therefore appear that bitstart and bitend need to be signed offsets, > at least until they are adjusted by store_bit_field.
Hmm, yeah. Or something like Index: expr.c =================================================================== --- expr.c (revision 186082) +++ expr.c (working copy) @@ -4490,8 +4490,8 @@ get_bit_range (unsigned HOST_WIDE_INT *b bitoffset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1) - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); - *bitstart = bitpos - bitoffset; - *bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1) - 1; + *bitstart = bitpos < (HOST_WIDE_INT) bitoffset ? 0 : bitpos - bitoffset; + *bitend = bitpos + tree_low_cst (DECL_SIZE (repr), 1) - bitoffset - 1; } /* Returns true if the MEM_REF REF refers to an object that does not which conservatively truncates the bitrange. Richard.