}
/* FIELD is about to be added to RLI->T. The alignment (in bits) of
- the next available location is given by KNOWN_ALIGN. Update the
- variable alignment fields in RLI, and return the alignment to give
- the FIELD. */
+ the next available location within the record is given by KNOWN_ALIGN.
+ Update the variable alignment fields in RLI, and return the alignment
+ to give the FIELD. */
unsigned int
update_alignment_for_field (record_layout_info rli, tree field,
type_align = MIN (type_align, maximum_field_alignment);
rli->record_align = MAX (rli->record_align, type_align);
rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+ /* If we start a new run, make sure we start it properly aligned. */
+ if ((!rli->prev_field
+ || integer_zerop (DECL_SIZE (field))
+ || integer_zerop (DECL_SIZE (rli->prev_field))
+ || !host_integerp (DECL_SIZE (rli->prev_field), 0)
+ || !host_integerp (TYPE_SIZE (type), 0)
+ || !simple_cst_equal (TYPE_SIZE (type),
+ TYPE_SIZE (TREE_TYPE (rli->prev_field)))
+ || (rli->remaining_in_alignment
+ < tree_low_cst (DECL_SIZE (field), 0)))
+ && desired_align < type_align)
+ desired_align = type_align;
}
}
#ifdef PCC_BITFIELD_TYPE_MATTERS
known_align = (tree_low_cst (rli->bitpos, 1)
& - tree_low_cst (rli->bitpos, 1));
else if (integer_zerop (rli->offset))
- known_align = BIGGEST_ALIGNMENT;
+ known_align = 0;
else if (host_integerp (rli->offset, 1))
known_align = (BITS_PER_UNIT
* (tree_low_cst (rli->offset, 1)
known_align = rli->offset_align;
desired_align = update_alignment_for_field (rli, field, known_align);
+ if (known_align == 0)
+ known_align = MAX (BIGGEST_ALIGNMENT, rli->record_align);
if (warn_packed && DECL_PACKED (field))
{
if (rli->remaining_in_alignment < bitsize)
{
- /* out of bits; bump up to next 'word'. */
- rli->offset = DECL_FIELD_OFFSET (rli->prev_field);
- rli->bitpos
- = size_binop (PLUS_EXPR, TYPE_SIZE (type),
- DECL_FIELD_BIT_OFFSET (rli->prev_field));
- rli->prev_field = field;
- rli->remaining_in_alignment
- = tree_low_cst (TYPE_SIZE (type), 0);
+ /* If PREV_FIELD is packed, and we haven't lumped
+ non-packed bitfields with it, treat this as if PREV_FIELD
+ was not a bitfield. This avoids anomalies where a packed
+ bitfield with long long base type can take up more
+ space than a same-size bitfield with base type short. */
+ if (rli->prev_packed)
+ rli->prev_field = prev_saved = NULL;
+ else
+ {
+ /* out of bits; bump up to next 'word'. */
+ rli->offset = DECL_FIELD_OFFSET (rli->prev_field);
+ rli->bitpos
+ = size_binop (PLUS_EXPR, TYPE_SIZE (type),
+ DECL_FIELD_BIT_OFFSET (rli->prev_field));
+ rli->prev_field = field;
+ rli->remaining_in_alignment
+ = tree_low_cst (TYPE_SIZE (type), 0) - bitsize;
+ }
}
-
- rli->remaining_in_alignment -= bitsize;
+ else
+ rli->remaining_in_alignment -= bitsize;
}
+ else if (rli->prev_packed)
+ rli->prev_field = prev_saved = NULL;
else
{
/* End of a run: if leaving a run of bitfields of the same type
{
tree type_size = TYPE_SIZE (TREE_TYPE (rli->prev_field));
- rli->bitpos
- = size_binop (PLUS_EXPR, type_size,
- DECL_FIELD_BIT_OFFSET (rli->prev_field));
+ /* If the desired alignment is greater or equal to TYPE_SIZE,
+ we have already adjusted rli->bitpos / rli->offset above.
+ */
+ if ((unsigned HOST_WIDE_INT) tree_low_cst (type_size, 0)
+ > desired_align)
+ rli->bitpos
+ = size_binop (PLUS_EXPR, type_size,
+ DECL_FIELD_BIT_OFFSET (rli->prev_field));
}
else
/* We "use up" size zero fields; the code below should behave
rli->prev_field = NULL;
}
+ rli->prev_packed = 0;
normalize_rli (rli);
}
actual_align = (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
& - tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1));
else if (integer_zerop (DECL_FIELD_OFFSET (field)))
- actual_align = BIGGEST_ALIGNMENT;
+ actual_align = MAX (BIGGEST_ALIGNMENT, rli->record_align);
else if (host_integerp (DECL_FIELD_OFFSET (field), 1))
actual_align = (BITS_PER_UNIT
* (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
& - tree_low_cst (DECL_FIELD_OFFSET (field), 1)));
else
actual_align = DECL_OFFSET_ALIGN (field);
+ /* ACTUAL_ALIGN is still the actual alignment *within the record* .
+ store / extract bit field operations will check the alignment of the
+ record against the mode of bit fields. */
if (known_align != actual_align)
layout_decl (field, actual_align);
- /* Only the MS bitfields use this. */
- if (rli->prev_field == NULL && DECL_BIT_FIELD_TYPE(field))
- rli->prev_field = field;
+ if (DECL_BIT_FIELD_TYPE (field))
+ {
+ unsigned int type_align = TYPE_ALIGN (type);
+
+ /* Only the MS bitfields use this. We used to also put any kind of
+ packed bit fields into prev_field, but that makes no sense, because
+ an 8 bit packed bit field shouldn't impose more restriction on
+ following fields than a char field, and the alignment requirements
+ are also not fulfilled.
+ There is no sane value to set rli->remaining_in_alignment to when
+ a packed bitfield in prev_field is unaligned. */
+ if (maximum_field_alignment != 0)
+ type_align = MIN (type_align, maximum_field_alignment);
+ gcc_assert (rli->prev_field
+ || actual_align >= type_align || DECL_PACKED (field)
+ || integer_zerop (DECL_SIZE (field))
+ || !targetm.ms_bitfield_layout_p (rli->t));
+ if (rli->prev_field == NULL && actual_align >= type_align
+ && !integer_zerop (DECL_SIZE (field)))
+ {
+ rli->prev_field = field;
+ /* rli->remaining_in_alignment has not been set if the bitfield
+ has size zero, or if it is a packed bitfield. */
+ rli->remaining_in_alignment
+ = (tree_low_cst (TYPE_SIZE (TREE_TYPE (field)), 0)
+ - tree_low_cst (DECL_SIZE (field), 0));
+ rli->prev_packed = DECL_PACKED (field);
+
+ }
+ else if (rli->prev_field && DECL_PACKED (field))
+ {
+ HOST_WIDE_INT bitsize = tree_low_cst (DECL_SIZE (field), 0);
+
+ if (rli->remaining_in_alignment < bitsize)
+ rli->prev_field = NULL;
+ else
+ rli->remaining_in_alignment -= bitsize;
+ }
+ }
/* Now add size of this field to the size of the record. If the size is
not constant, treat the field as being a multiple of bytes and just