Commit 0645ba8f by Mark Mitchell Committed by Mark Mitchell

stor-layout.c (update_alignment_for_field): New function.

	* stor-layout.c (update_alignment_for_field): New function.
	(place_union_field): Use it.
	(place_field): Likewise.
	* gcc.dg/empty1.C: New test.

From-SVN: r57697
parent b4c20e52
2002-10-01 Mark Mitchell <mark@codesourcery.com>
* stor-layout.c (update_alignment_for_field): New function.
(place_union_field): Use it.
(place_field): Likewise.
2002-10-01 Nathan Sidwell <nathan@codesourcery.com> 2002-10-01 Nathan Sidwell <nathan@codesourcery.com>
* gcc.c (cc1_options): Add space on -auxbase-strip. * gcc.c (cc1_options): Add space on -auxbase-strip.
......
...@@ -60,6 +60,9 @@ static int reference_types_internal = 0; ...@@ -60,6 +60,9 @@ static int reference_types_internal = 0;
static void finalize_record_size PARAMS ((record_layout_info)); static void finalize_record_size PARAMS ((record_layout_info));
static void finalize_type_size PARAMS ((tree)); static void finalize_type_size PARAMS ((tree));
static void place_union_field PARAMS ((record_layout_info, tree)); static void place_union_field PARAMS ((record_layout_info, tree));
static unsigned int update_alignment_for_field
PARAMS ((record_layout_info, tree,
unsigned int));
extern void debug_rli PARAMS ((record_layout_info)); extern void debug_rli PARAMS ((record_layout_info));
/* SAVE_EXPRs for sizes of types and decls, waiting to be expanded. */ /* SAVE_EXPRs for sizes of types and decls, waiting to be expanded. */
...@@ -644,130 +647,23 @@ rli_size_so_far (rli) ...@@ -644,130 +647,23 @@ rli_size_so_far (rli)
return bit_from_pos (rli->offset, rli->bitpos); return bit_from_pos (rli->offset, rli->bitpos);
} }
/* Called from place_field to handle unions. */ /* 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. */
static void static unsigned int
place_union_field (rli, field) update_alignment_for_field (rli, field, known_align)
record_layout_info rli;
tree field;
{
unsigned int desired_align;
layout_decl (field, 0);
DECL_FIELD_OFFSET (field) = size_zero_node;
DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
desired_align = DECL_ALIGN (field);
#ifdef BIGGEST_FIELD_ALIGNMENT
/* Some targets (i.e. i386) limit union field alignment
to a lower boundary than alignment of variables unless
it was overridden by attribute aligned. */
if (! DECL_USER_ALIGN (field))
desired_align =
MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
#endif
#ifdef ADJUST_FIELD_ALIGN
if (! DECL_USER_ALIGN (field))
desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
#endif
TYPE_USER_ALIGN (rli->t) |= DECL_USER_ALIGN (field);
/* Union must be at least as aligned as any field requires. */
rli->record_align = MAX (rli->record_align, desired_align);
rli->unpadded_align = MAX (rli->unpadded_align, desired_align);
#ifdef PCC_BITFIELD_TYPE_MATTERS
/* On the m88000, a bit field of declare type `int' forces the
entire union to have `int' alignment. */
if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
{
unsigned int type_align = TYPE_ALIGN (TREE_TYPE (field));
#ifdef ADJUST_FIELD_ALIGN
if (! TYPE_USER_ALIGN (TREE_TYPE (field)))
type_align = ADJUST_FIELD_ALIGN (field, type_align);
#endif
rli->record_align = MAX (rli->record_align, type_align);
rli->unpadded_align = MAX (rli->unpadded_align, type_align);
TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (TREE_TYPE (field));
}
#endif
/* We assume the union's size will be a multiple of a byte so we don't
bother with BITPOS. */
if (TREE_CODE (rli->t) == UNION_TYPE)
rli->offset = size_binop (MAX_EXPR, rli->offset, DECL_SIZE_UNIT (field));
else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)
rli->offset = fold (build (COND_EXPR, sizetype,
DECL_QUALIFIER (field),
DECL_SIZE_UNIT (field), rli->offset));
}
/* RLI contains information about the layout of a RECORD_TYPE. FIELD
is a FIELD_DECL to be added after those fields already present in
T. (FIELD is not actually added to the TYPE_FIELDS list here;
callers that desire that behavior must manually perform that step.) */
void
place_field (rli, field)
record_layout_info rli; record_layout_info rli;
tree field; tree field;
unsigned int known_align;
{ {
/* The alignment required for FIELD. */ /* The alignment required for FIELD. */
unsigned int desired_align; unsigned int desired_align;
/* The alignment FIELD would have if we just dropped it into the
record as it presently stands. */
unsigned int known_align;
unsigned int actual_align;
unsigned int user_align;
/* The type of this field. */ /* The type of this field. */
tree type = TREE_TYPE (field); tree type = TREE_TYPE (field);
/* True if the field was explicitly aligned by the user. */
if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK) bool user_align;
return;
/* If FIELD is static, then treat it like a separate variable, not
really like a structure field. If it is a FUNCTION_DECL, it's a
method. In both cases, all we do is lay out the decl, and we do
it *after* the record is laid out. */
if (TREE_CODE (field) == VAR_DECL)
{
rli->pending_statics = tree_cons (NULL_TREE, field,
rli->pending_statics);
return;
}
/* Enumerators and enum types which are local to this class need not
be laid out. Likewise for initialized constant fields. */
else if (TREE_CODE (field) != FIELD_DECL)
return;
/* Unions are laid out very differently than records, so split
that code off to another function. */
else if (TREE_CODE (rli->t) != RECORD_TYPE)
{
place_union_field (rli, field);
return;
}
/* Work out the known alignment so far. Note that A & (-A) is the
value of the least-significant bit in A that is one. */
if (! integer_zerop (rli->bitpos))
known_align = (tree_low_cst (rli->bitpos, 1)
& - tree_low_cst (rli->bitpos, 1));
else if (integer_zerop (rli->offset))
known_align = BIGGEST_ALIGNMENT;
else if (host_integerp (rli->offset, 1))
known_align = (BITS_PER_UNIT
* (tree_low_cst (rli->offset, 1)
& - tree_low_cst (rli->offset, 1)));
else
known_align = rli->offset_align;
/* Lay out the field so we know what alignment it needs. For a /* Lay out the field so we know what alignment it needs. For a
packed field, use the alignment as specified, disregarding what packed field, use the alignment as specified, disregarding what
...@@ -785,13 +681,13 @@ place_field (rli, field) ...@@ -785,13 +681,13 @@ place_field (rli, field)
to a lower boundary than alignment of variables unless to a lower boundary than alignment of variables unless
it was overridden by attribute aligned. */ it was overridden by attribute aligned. */
#ifdef BIGGEST_FIELD_ALIGNMENT #ifdef BIGGEST_FIELD_ALIGNMENT
if (! user_align) if (!user_align)
desired_align desired_align
= MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT); = MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
#endif #endif
#ifdef ADJUST_FIELD_ALIGN #ifdef ADJUST_FIELD_ALIGN
if (! user_align) if (!user_align)
desired_align = ADJUST_FIELD_ALIGN (field, desired_align); desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
#endif #endif
...@@ -873,6 +769,96 @@ place_field (rli, field) ...@@ -873,6 +769,96 @@ place_field (rli, field)
rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field)); rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
} }
TYPE_USER_ALIGN (rli->t) |= user_align;
return desired_align;
}
/* Called from place_field to handle unions. */
static void
place_union_field (rli, field)
record_layout_info rli;
tree field;
{
update_alignment_for_field (rli, field, /*known_align=*/0);
DECL_FIELD_OFFSET (field) = size_zero_node;
DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
/* We assume the union's size will be a multiple of a byte so we don't
bother with BITPOS. */
if (TREE_CODE (rli->t) == UNION_TYPE)
rli->offset = size_binop (MAX_EXPR, rli->offset, DECL_SIZE_UNIT (field));
else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)
rli->offset = fold (build (COND_EXPR, sizetype,
DECL_QUALIFIER (field),
DECL_SIZE_UNIT (field), rli->offset));
}
/* RLI contains information about the layout of a RECORD_TYPE. FIELD
is a FIELD_DECL to be added after those fields already present in
T. (FIELD is not actually added to the TYPE_FIELDS list here;
callers that desire that behavior must manually perform that step.) */
void
place_field (rli, field)
record_layout_info rli;
tree field;
{
/* The alignment required for FIELD. */
unsigned int desired_align;
/* The alignment FIELD would have if we just dropped it into the
record as it presently stands. */
unsigned int known_align;
unsigned int actual_align;
/* The type of this field. */
tree type = TREE_TYPE (field);
if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
return;
/* If FIELD is static, then treat it like a separate variable, not
really like a structure field. If it is a FUNCTION_DECL, it's a
method. In both cases, all we do is lay out the decl, and we do
it *after* the record is laid out. */
if (TREE_CODE (field) == VAR_DECL)
{
rli->pending_statics = tree_cons (NULL_TREE, field,
rli->pending_statics);
return;
}
/* Enumerators and enum types which are local to this class need not
be laid out. Likewise for initialized constant fields. */
else if (TREE_CODE (field) != FIELD_DECL)
return;
/* Unions are laid out very differently than records, so split
that code off to another function. */
else if (TREE_CODE (rli->t) != RECORD_TYPE)
{
place_union_field (rli, field);
return;
}
/* Work out the known alignment so far. Note that A & (-A) is the
value of the least-significant bit in A that is one. */
if (! integer_zerop (rli->bitpos))
known_align = (tree_low_cst (rli->bitpos, 1)
& - tree_low_cst (rli->bitpos, 1));
else if (integer_zerop (rli->offset))
known_align = BIGGEST_ALIGNMENT;
else if (host_integerp (rli->offset, 1))
known_align = (BITS_PER_UNIT
* (tree_low_cst (rli->offset, 1)
& - tree_low_cst (rli->offset, 1)));
else
known_align = rli->offset_align;
desired_align = update_alignment_for_field (rli, field, known_align);
if (warn_packed && DECL_PACKED (field)) if (warn_packed && DECL_PACKED (field))
{ {
if (known_align > TYPE_ALIGN (type)) if (known_align > TYPE_ALIGN (type))
...@@ -956,7 +942,7 @@ place_field (rli, field) ...@@ -956,7 +942,7 @@ place_field (rli, field)
> tree_low_cst (TYPE_SIZE (type), 1) / type_align) > tree_low_cst (TYPE_SIZE (type), 1) / type_align)
rli->bitpos = round_up (rli->bitpos, type_align); rli->bitpos = round_up (rli->bitpos, type_align);
user_align |= TYPE_USER_ALIGN (type); TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
} }
#endif #endif
...@@ -999,7 +985,7 @@ place_field (rli, field) ...@@ -999,7 +985,7 @@ place_field (rli, field)
/ type_align)) / type_align))
rli->bitpos = round_up (rli->bitpos, type_align); rli->bitpos = round_up (rli->bitpos, type_align);
user_align |= TYPE_USER_ALIGN (type); TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
} }
#endif #endif
...@@ -1153,8 +1139,6 @@ place_field (rli, field) ...@@ -1153,8 +1139,6 @@ place_field (rli, field)
DECL_FIELD_BIT_OFFSET (field) = rli->bitpos; DECL_FIELD_BIT_OFFSET (field) = rli->bitpos;
SET_DECL_OFFSET_ALIGN (field, rli->offset_align); SET_DECL_OFFSET_ALIGN (field, rli->offset_align);
TYPE_USER_ALIGN (rli->t) |= user_align;
/* If this field ended up more aligned than we thought it would be (we /* If this field ended up more aligned than we thought it would be (we
approximate this by seeing if its position changed), lay out the field approximate this by seeing if its position changed), lay out the field
again; perhaps we can use an integral mode for it now. */ again; perhaps we can use an integral mode for it now. */
......
2002-10-01 Mark Mitchell <mark@codesourcery.com> 2002-10-01 Mark Mitchell <mark@codesourcery.com>
* gcc.dg/empty1.C: New test.
* g++.dg/tls/init-2.C: Tweak error messages. * g++.dg/tls/init-2.C: Tweak error messages.
2002-10-01 Richard Sandiford <rsandifo@redhat.com> 2002-10-01 Richard Sandiford <rsandifo@redhat.com>
......
/* { dg-do run } */
/* { dg-options "" } */
struct S { int : 0; };
union U { int : 0; };
int main () {
if (__alignof__ (struct S) != __alignof__ (union U))
return 1;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment