diff options
Diffstat (limited to 'contrib/gcc/stor-layout.c')
-rw-r--r-- | contrib/gcc/stor-layout.c | 540 |
1 files changed, 332 insertions, 208 deletions
diff --git a/contrib/gcc/stor-layout.c b/contrib/gcc/stor-layout.c index c330fb6..4fb2908 100644 --- a/contrib/gcc/stor-layout.c +++ b/contrib/gcc/stor-layout.c @@ -1,6 +1,6 @@ /* C-compiler utilities for types and variables storage layout Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1996, 1998, - 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GCC. @@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "toplev.h" #include "ggc.h" #include "target.h" +#include "langhooks.h" /* Set to one when set_sizetype has been called. */ static int sizetype_set; @@ -47,7 +48,7 @@ tree sizetype_tab[(int) TYPE_KIND_LAST]; The value is measured in bits. */ unsigned int maximum_field_alignment; -/* If non-zero, the alignment of a bitstring or (power-)set value, in bits. +/* If nonzero, the alignment of a bitstring or (power-)set value, in bits. May be overridden by front-ends. */ unsigned int set_alignment = 0; @@ -59,11 +60,14 @@ static int reference_types_internal = 0; static void finalize_record_size PARAMS ((record_layout_info)); static void finalize_type_size PARAMS ((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)); /* SAVE_EXPRs for sizes of types and decls, waiting to be expanded. */ -static tree pending_sizes; +static GTY(()) tree pending_sizes; /* Nonzero means cannot safely call expand_expr now, so put variable sizes onto `pending_sizes' instead. */ @@ -95,7 +99,7 @@ get_pending_sizes () return chain; } -/* Return non-zero if EXPR is present on the pending sizes list. */ +/* Return nonzero if EXPR is present on the pending sizes list. */ int is_pending_size (expr) @@ -151,7 +155,8 @@ variable_size (size) just return SIZE unchanged. Likewise for self-referential sizes and constant sizes. */ if (TREE_CONSTANT (size) - || global_bindings_p () < 0 || contains_placeholder_p (size)) + || (*lang_hooks.decls.global_bindings_p) () < 0 + || contains_placeholder_p (size)) return size; size = save_expr (size); @@ -167,7 +172,7 @@ variable_size (size) if (TREE_CODE (size) == SAVE_EXPR) SAVE_EXPR_PERSISTENT_P (size) = 1; - if (global_bindings_p ()) + if ((*lang_hooks.decls.global_bindings_p) ()) { if (TREE_CONSTANT (size)) error ("type size can't be explicitly evaluated"); @@ -178,7 +183,7 @@ variable_size (size) } if (immediate_size_expand) - /* NULL_RTX is not defined; neither is the rtx type. + /* NULL_RTX is not defined; neither is the rtx type. Also, we would like to pass const0_rtx here, but don't have it. */ expand_expr (size, expand_expr (integer_zero_node, NULL_RTX, VOIDmode, 0), VOIDmode, 0); @@ -281,7 +286,7 @@ int_mode_for_mode (mode) case MODE_RANDOM: if (mode == BLKmode) - break; + break; /* ... fall through ... */ @@ -293,6 +298,29 @@ int_mode_for_mode (mode) return mode; } +/* Return the alignment of MODE. This will be bounded by 1 and + BIGGEST_ALIGNMENT. */ + +unsigned int +get_mode_alignment (mode) + enum machine_mode mode; +{ + unsigned int alignment; + + if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT + || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT) + alignment = GET_MODE_UNIT_SIZE (mode); + else + alignment = GET_MODE_SIZE (mode); + + /* Extract the LSB of the size. */ + alignment = alignment & -alignment; + alignment *= BITS_PER_UNIT; + + alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment)); + return alignment; +} + /* Return the value of VALUE, rounded up to a multiple of DIVISOR. This can only be applied to objects of a sizetype. */ @@ -338,6 +366,7 @@ layout_decl (decl, known_align) { tree type = TREE_TYPE (decl); enum tree_code code = TREE_CODE (decl); + rtx rtl = NULL_RTX; if (code == CONST_DECL) return; @@ -345,6 +374,8 @@ layout_decl (decl, known_align) && code != TYPE_DECL && code != FIELD_DECL) abort (); + rtl = DECL_RTL_IF_SET (decl); + if (type == error_mark_node) type = void_type_node; @@ -379,7 +410,7 @@ layout_decl (decl, known_align) && (DECL_ALIGN (decl) == 0 || (! (code == FIELD_DECL && DECL_PACKED (decl)) && TYPE_ALIGN (type) > DECL_ALIGN (decl)))) - { + { DECL_ALIGN (decl) = TYPE_ALIGN (type); DECL_USER_ALIGN (decl) = 0; } @@ -405,7 +436,7 @@ layout_decl (decl, known_align) } } - /* See if we can use an ordinary integer mode for a bit-field. + /* See if we can use an ordinary integer mode for a bit-field. Conditions are: a fixed size that is correct for another mode and occupying a complete byte or bytes on proper boundary. */ if (code == FIELD_DECL && DECL_BIT_FIELD (decl) @@ -459,6 +490,15 @@ layout_decl (decl, known_align) larger_than_size); } } + + /* If the RTL was already set, update its mode and mem attributes. */ + if (rtl) + { + PUT_MODE (rtl, DECL_MODE (decl)); + SET_DECL_RTL (decl, 0); + set_mem_attributes (rtl, decl, 1); + SET_DECL_RTL (decl, rtl); + } } /* Hook for a front-end function that can modify the record layout as needed @@ -476,7 +516,7 @@ set_lang_adjust_rli (f) /* Begin laying out type T, which may be a RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE. Return a pointer to a struct record_layout_info which is to be passed to all other layout functions for this record. It is the - responsibility of the caller to call `free' for the storage returned. + responsibility of the caller to call `free' for the storage returned. Note that garbage collection is not permitted until we finish laying out the record. */ @@ -484,7 +524,7 @@ record_layout_info start_record_layout (t) tree t; { - record_layout_info rli + record_layout_info rli = (record_layout_info) xmalloc (sizeof (struct record_layout_info_s)); rli->t = t; @@ -585,7 +625,7 @@ normalize_offset (poffset, pbitpos, off_align) = size_binop (PLUS_EXPR, *poffset, size_binop (MULT_EXPR, convert (sizetype, extra_aligns), size_int (off_align / BITS_PER_UNIT))); - + *pbitpos = size_binop (FLOOR_MOD_EXPR, *pbitpos, bitsize_int (off_align)); } @@ -642,66 +682,154 @@ rli_size_so_far (rli) 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 -place_union_field (rli, field) +static unsigned int +update_alignment_for_field (rli, field, known_align) record_layout_info rli; tree field; + unsigned int known_align; { + /* The alignment required for FIELD. */ unsigned int desired_align; + /* The type of this field. */ + tree type = TREE_TYPE (field); + /* True if the field was explicitly aligned by the user. */ + bool user_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); - + /* Lay out the field so we know what alignment it needs. For a + packed field, use the alignment as specified, disregarding what + the type would want. */ desired_align = DECL_ALIGN (field); + user_align = DECL_USER_ALIGN (field); + layout_decl (field, known_align); + if (! DECL_PACKED (field)) + { + desired_align = DECL_ALIGN (field); + user_align = DECL_USER_ALIGN (field); + } -#ifdef BIGGEST_FIELD_ALIGNMENT - /* Some targets (i.e. i386) limit union field alignment + /* Some targets (i.e. i386, VMS) limit struct 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); +#ifdef BIGGEST_FIELD_ALIGNMENT + if (!user_align) + desired_align + = MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT); #endif #ifdef ADJUST_FIELD_ALIGN - if (! DECL_USER_ALIGN (field)) + if (!user_align) 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); - + /* Record must have at least as much alignment as any field. + Otherwise, the alignment of the field within the record is + meaningless. */ + if ((* targetm.ms_bitfield_layout_p) (rli->t) + && type != error_mark_node + && DECL_BIT_FIELD_TYPE (field) + && ! integer_zerop (TYPE_SIZE (type))) + { + /* Here, the alignment of the underlying type of a bitfield can + affect the alignment of a record; even a zero-sized field + can do this. The alignment should be to the alignment of + the type, except that for zero-size bitfields this only + applies if there was an immediately prior, nonzero-size + bitfield. (That's the way it is, experimentally.) */ + if (! integer_zerop (DECL_SIZE (field)) + ? ! DECL_PACKED (field) + : (rli->prev_field + && DECL_BIT_FIELD_TYPE (rli->prev_field) + && ! integer_zerop (DECL_SIZE (rli->prev_field)))) + { + unsigned int type_align = TYPE_ALIGN (type); + type_align = MAX (type_align, desired_align); + if (maximum_field_alignment != 0) + 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)); + rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field)); + } + else + desired_align = 1; + } + else #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)) + if (PCC_BITFIELD_TYPE_MATTERS && type != error_mark_node + && ! (* targetm.ms_bitfield_layout_p) (rli->t) + && DECL_BIT_FIELD_TYPE (field) + && ! integer_zerop (TYPE_SIZE (type))) { - unsigned int type_align = TYPE_ALIGN (TREE_TYPE (field)); + /* For these machines, a zero-length field does not + affect the alignment of the structure as a whole. + It does, however, affect the alignment of the next field + within the structure. */ + if (! integer_zerop (DECL_SIZE (field))) + rli->record_align = MAX (rli->record_align, desired_align); + else if (! DECL_PACKED (field) && !user_align) + desired_align = TYPE_ALIGN (type); + + /* A named bit field of declared type `int' + forces the entire structure to have `int' alignment. */ + if (DECL_NAME (field) != 0) + { + unsigned int type_align = TYPE_ALIGN (type); #ifdef ADJUST_FIELD_ALIGN - if (! TYPE_USER_ALIGN (TREE_TYPE (field))) - type_align = ADJUST_FIELD_ALIGN (field, type_align); + if (! TYPE_USER_ALIGN (type)) + 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)); + + if (maximum_field_alignment != 0) + type_align = MIN (type_align, maximum_field_alignment); + else if (DECL_PACKED (field)) + type_align = MIN (type_align, BITS_PER_UNIT); + + rli->record_align = MAX (rli->record_align, type_align); + rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field)); + if (warn_packed) + rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type)); + user_align |= TYPE_USER_ALIGN (type); + } } + else #endif + { + rli->record_align = MAX (rli->record_align, desired_align); + rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type)); + rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field)); + } + + TYPE_USER_ALIGN (rli->t) |= user_align; + + DECL_ALIGN (field) = desired_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, + rli->offset = fold (build (COND_EXPR, sizetype, DECL_QUALIFIER (field), DECL_SIZE_UNIT (field), rli->offset)); } @@ -722,10 +850,9 @@ place_field (rli, field) record as it presently stands. */ unsigned int known_align; unsigned int actual_align; - unsigned int user_align; /* The type of this field. */ tree type = TREE_TYPE (field); - + if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK) return; @@ -766,98 +893,8 @@ place_field (rli, field) & - 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 - packed field, use the alignment as specified, disregarding what - the type would want. */ - desired_align = DECL_ALIGN (field); - user_align = DECL_USER_ALIGN (field); - layout_decl (field, known_align); - if (! DECL_PACKED (field)) - { - desired_align = DECL_ALIGN (field); - user_align = DECL_USER_ALIGN (field); - } - - /* Some targets (i.e. i386, VMS) limit struct field alignment - to a lower boundary than alignment of variables unless - it was overridden by attribute aligned. */ -#ifdef BIGGEST_FIELD_ALIGNMENT - if (! user_align) - desired_align - = MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT); -#endif - -#ifdef ADJUST_FIELD_ALIGN - if (! user_align) - desired_align = ADJUST_FIELD_ALIGN (field, desired_align); -#endif - - /* Record must have at least as much alignment as any field. - Otherwise, the alignment of the field within the record is - meaningless. */ - if ((* targetm.ms_bitfield_layout_p) (rli->t) - && type != error_mark_node - && DECL_BIT_FIELD_TYPE (field) - && ! integer_zerop (TYPE_SIZE (type)) - && integer_zerop (DECL_SIZE (field))) - { - if (rli->prev_field - && DECL_BIT_FIELD_TYPE (rli->prev_field) - && ! integer_zerop (DECL_SIZE (rli->prev_field))) - { - rli->record_align = MAX (rli->record_align, desired_align); - rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type)); - } - else - desired_align = 1; - } - else -#ifdef PCC_BITFIELD_TYPE_MATTERS - if (PCC_BITFIELD_TYPE_MATTERS && type != error_mark_node - && ! (* targetm.ms_bitfield_layout_p) (rli->t) - && DECL_BIT_FIELD_TYPE (field) - && ! integer_zerop (TYPE_SIZE (type))) - { - /* For these machines, a zero-length field does not - affect the alignment of the structure as a whole. - It does, however, affect the alignment of the next field - within the structure. */ - if (! integer_zerop (DECL_SIZE (field))) - rli->record_align = MAX (rli->record_align, desired_align); - else if (! DECL_PACKED (field)) - desired_align = TYPE_ALIGN (type); - - /* A named bit field of declared type `int' - forces the entire structure to have `int' alignment. */ - if (DECL_NAME (field) != 0) - { - unsigned int type_align = TYPE_ALIGN (type); - -#ifdef ADJUST_FIELD_ALIGN - if (! TYPE_USER_ALIGN (type)) - type_align = ADJUST_FIELD_ALIGN (field, type_align); -#endif - - if (maximum_field_alignment != 0) - type_align = MIN (type_align, maximum_field_alignment); - else if (DECL_PACKED (field)) - type_align = MIN (type_align, BITS_PER_UNIT); - - rli->record_align = MAX (rli->record_align, type_align); - rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field)); - if (warn_packed) - rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type)); - user_align |= TYPE_USER_ALIGN (type); - } - } - else -#endif - { - rli->record_align = MAX (rli->record_align, desired_align); - rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type)); - rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field)); - } + + desired_align = update_alignment_for_field (rli, field, known_align); if (warn_packed && DECL_PACKED (field)) { @@ -942,7 +979,7 @@ place_field (rli, field) > tree_low_cst (TYPE_SIZE (type), 1) / 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 @@ -985,52 +1022,153 @@ place_field (rli, field) / 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 - /* See the docs for TARGET_MS_BITFIELD_LAYOUT_P for details. */ + /* See the docs for TARGET_MS_BITFIELD_LAYOUT_P for details. + A subtlety: + When a bit field is inserted into a packed record, the whole + size of the underlying type is used by one or more same-size + adjacent bitfields. (That is, if its long:3, 32 bits is + used in the record, and any additional adjacent long bitfields are + packed into the same chunk of 32 bits. However, if the size + changes, a new field of that size is allocated.) In an unpacked + record, this is the same as using alignment, but not eqivalent + when packing. + + Note: for compatability, we use the type size, not the type alignment + to determine alignment, since that matches the documentation */ + if ((* targetm.ms_bitfield_layout_p) (rli->t) - && TREE_CODE (field) == FIELD_DECL - && type != error_mark_node - && ! DECL_PACKED (field) - && rli->prev_field - && DECL_SIZE (field) - && host_integerp (DECL_SIZE (field), 1) - && DECL_SIZE (rli->prev_field) - && host_integerp (DECL_SIZE (rli->prev_field), 1) - && host_integerp (rli->offset, 1) - && host_integerp (TYPE_SIZE (type), 1) - && host_integerp (TYPE_SIZE (TREE_TYPE (rli->prev_field)), 1) - && ((DECL_BIT_FIELD_TYPE (rli->prev_field) - && ! integer_zerop (DECL_SIZE (rli->prev_field))) - || (DECL_BIT_FIELD_TYPE (field) - && ! integer_zerop (DECL_SIZE (field)))) - && (! simple_cst_equal (TYPE_SIZE (type), - TYPE_SIZE (TREE_TYPE (rli->prev_field))) - /* If the previous field was a zero-sized bit-field, either - it was ignored, in which case we must ensure the proper - alignment of this field here, or it already forced the - alignment of this field, in which case forcing the - alignment again is harmless. So, do it in both cases. */ - || (DECL_BIT_FIELD_TYPE (rli->prev_field) - && integer_zerop (DECL_SIZE (rli->prev_field))))) + && ((DECL_BIT_FIELD_TYPE (field) && ! DECL_PACKED (field)) + || (rli->prev_field && ! DECL_PACKED (rli->prev_field)))) { - unsigned int type_align = TYPE_ALIGN (type); + /* At this point, either the prior or current are bitfields, + (possibly both), and we're dealing with MS packing. */ + tree prev_saved = rli->prev_field; - if (rli->prev_field - && DECL_BIT_FIELD_TYPE (rli->prev_field) - /* If the previous bit-field is zero-sized, we've already - accounted for its alignment needs (or ignored it, if - appropriate) while placing it. */ - && ! integer_zerop (DECL_SIZE (rli->prev_field))) - type_align = MAX (type_align, - TYPE_ALIGN (TREE_TYPE (rli->prev_field))); + /* Is the prior field a bitfield? If so, handle "runs" of same + type size fields. */ + if (rli->prev_field /* necessarily a bitfield if it exists. */) + { + /* If both are bitfields, nonzero, and the same size, this is + the middle of a run. Zero declared size fields are special + and handled as "end of run". (Note: it's nonzero declared + size, but equal type sizes!) (Since we know that both + the current and previous fields are bitfields by the + time we check it, DECL_SIZE must be present for both.) */ + if (DECL_BIT_FIELD_TYPE (field) + && !integer_zerop (DECL_SIZE (field)) + && !integer_zerop (DECL_SIZE (rli->prev_field)) + && simple_cst_equal (TYPE_SIZE (type), + TYPE_SIZE (TREE_TYPE (rli->prev_field))) ) + { + /* We're in the middle of a run of equal type size fields; make + sure we realign if we run out of bits. (Not decl size, + type size!) */ + int bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)); + tree type_size = TYPE_SIZE(TREE_TYPE(rli->prev_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, + DECL_FIELD_BIT_OFFSET(rli->prev_field)); + rli->prev_field = field; + rli->remaining_in_alignment = TREE_INT_CST_LOW (type_size); + } + rli->remaining_in_alignment -= bitsize; + } + else + { + /* End of a run: if leaving a run of bitfields of the same type + size, we have to "use up" the rest of the bits of the type + size. + + Compute the new position as the sum of the size for the prior + type and where we first started working on that type. + Note: since the beginning of the field was aligned then + of course the end will be too. No round needed. */ + + if (!integer_zerop (DECL_SIZE (rli->prev_field))) + { + 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)); + } + else + { + /* We "use up" size zero fields; the code below should behave + as if the prior field was not a bitfield. */ + prev_saved = NULL; + } + + /* Cause a new bitfield to be captured, either this time (if + currently a bitfield) or next time we see one. */ + if (!DECL_BIT_FIELD_TYPE(field) + || integer_zerop (DECL_SIZE (field))) + { + rli->prev_field = NULL; + } + } + normalize_rli (rli); + } + + /* If we're starting a new run of same size type bitfields + (or a run of non-bitfields), set up the "first of the run" + fields. + + That is, if the current field is not a bitfield, or if there + was a prior bitfield the type sizes differ, or if there wasn't + a prior bitfield the size of the current field is nonzero. + + Note: we must be sure to test ONLY the type size if there was + a prior bitfield and ONLY for the current field being zero if + there wasn't. */ + + if (!DECL_BIT_FIELD_TYPE (field) + || ( prev_saved != NULL + ? !simple_cst_equal (TYPE_SIZE (type), + TYPE_SIZE (TREE_TYPE (prev_saved))) + : !integer_zerop (DECL_SIZE (field)) )) + { + unsigned int type_align = 8; /* Never below 8 for compatability */ + + /* (When not a bitfield), we could be seeing a flex array (with + no DECL_SIZE). Since we won't be using remaining_in_alignment + until we see a bitfield (and come by here again) we just skip + calculating it. */ + + if (DECL_SIZE (field) != NULL) + rli->remaining_in_alignment + = TREE_INT_CST_LOW (TYPE_SIZE(TREE_TYPE(field))) + - TREE_INT_CST_LOW (DECL_SIZE (field)); + + /* Now align (conventionally) for the new type. */ + if (!DECL_PACKED(field)) + type_align = MAX(TYPE_ALIGN (type), type_align); + + if (prev_saved + && DECL_BIT_FIELD_TYPE (prev_saved) + /* If the previous bit-field is zero-sized, we've already + accounted for its alignment needs (or ignored it, if + appropriate) while placing it. */ + && ! integer_zerop (DECL_SIZE (prev_saved))) + type_align = MAX (type_align, + TYPE_ALIGN (TREE_TYPE (prev_saved))); - if (maximum_field_alignment != 0) - type_align = MIN (type_align, maximum_field_alignment); + if (maximum_field_alignment != 0) + type_align = MIN (type_align, maximum_field_alignment); - rli->bitpos = round_up (rli->bitpos, type_align); + rli->bitpos = round_up (rli->bitpos, type_align); + /* If we really aligned, don't allow subsequent bitfields + to undo that. */ + rli->prev_field = NULL; + } } /* Offset so far becomes the position of this field after normalizing. */ @@ -1039,8 +1177,6 @@ place_field (rli, field) DECL_FIELD_BIT_OFFSET (field) = rli->bitpos; 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 approximate this by seeing if its position changed), lay out the field again; perhaps we can use an integral mode for it now. */ @@ -1059,7 +1195,9 @@ place_field (rli, field) if (known_align != actual_align) layout_decl (field, actual_align); - rli->prev_field = field; + /* Only the MS bitfields use this. */ + if (rli->prev_field == NULL && DECL_BIT_FIELD_TYPE(field)) + rli->prev_field = field; /* 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 @@ -1146,7 +1284,7 @@ finalize_record_size (rli) if (warn_padded && TREE_CONSTANT (unpadded_size) && simple_cst_equal (unpadded_size, TYPE_SIZE (rli->t)) == 0) warning ("padding struct size to alignment boundary"); - + if (warn_packed && TREE_CODE (rli->t) == RECORD_TYPE && TYPE_PACKED (rli->t) && ! rli->packed_maybe_necessary && TREE_CONSTANT (unpadded_size)) @@ -1233,7 +1371,7 @@ compute_record_mode (type) return; bitpos = int_bit_position (field); - + /* Must be BLKmode if any field crosses a word boundary, since extract_bit_field can't handle that in registers. */ if (bitpos / BITS_PER_WORD @@ -1253,16 +1391,7 @@ compute_record_mode (type) /* With some targets, eg. c4x, it is sub-optimal to access an aligned BLKmode structure as a scalar. */ - /* On ia64-*-hpux we need to ensure that we don't change the - mode of a structure containing a single field or else we - will pass it incorrectly. Since a structure with a single - field causes mode to get set above we can't allow the - check for mode == VOIDmode in this case. Perhaps - MEMBER_TYPE_FORCES_BLK should be extended to include mode - as an argument and the check could be put in there for c4x. */ - - if ((mode == VOIDmode || FUNCTION_ARG_REG_LITTLE_ENDIAN) - && MEMBER_TYPE_FORCES_BLK (field)) + if (MEMBER_TYPE_FORCES_BLK (field, mode)) return; #endif /* MEMBER_TYPE_FORCES_BLK */ } @@ -1377,11 +1506,14 @@ finalize_type_size (type) /* Do all of the work required to layout the type indicated by RLI, once the fields have been laid out. This function will call `free' - for RLI. */ + for RLI, unless FREE_P is false. Passing a value other than false + for FREE_P is bad practice; this option only exists to support the + G++ 3.2 ABI. */ void -finish_record_layout (rli) +finish_record_layout (rli, free_p) record_layout_info rli; + int free_p; { /* Compute the final size. */ finalize_record_size (rli); @@ -1401,7 +1533,8 @@ finish_record_layout (rli) } /* Clean up. */ - free (rli); + if (free_p) + free (rli); } /* Calculate the mode, size, and alignment for TYPE. @@ -1602,7 +1735,7 @@ layout_type (type) TYPE_MODE (type) = BLKmode; if (TYPE_SIZE (type) != 0 #ifdef MEMBER_TYPE_FORCES_BLK - && ! MEMBER_TYPE_FORCES_BLK (type) + && ! MEMBER_TYPE_FORCES_BLK (type, VOIDmode) #endif /* BLKmode elements force BLKmode aggregate; else extract/store fields may lose. */ @@ -1656,7 +1789,7 @@ layout_type (type) (*lang_adjust_rli) (rli); /* Finish laying out the record. */ - finish_record_layout (rli); + finish_record_layout (rli, /*free_p=*/true); } break; @@ -1705,7 +1838,7 @@ layout_type (type) /* Compute the final TYPE_SIZE, TYPE_ALIGN, etc. for TYPE. For records and unions, finish_record_layout already called this function. */ - if (TREE_CODE (type) != RECORD_TYPE + if (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE && TREE_CODE (type) != QUAL_UNION_TYPE) finalize_type_size (type); @@ -1848,9 +1981,6 @@ set_sizetype (type) TYPE_REFERENCE_TO (sizetype_tab[i]) = 0; } - ggc_add_tree_root ((tree *) &sizetype_tab, - sizeof sizetype_tab / sizeof (tree)); - /* Go down each of the types we already made and set the proper type for the sizes in them. */ for (t = early_type_list; t != 0; t = TREE_CHAIN (t)) @@ -2006,10 +2136,4 @@ get_best_mode (bitsize, bitpos, align, largest_mode, volatilep) return mode; } -/* This function is run once to initialize stor-layout.c. */ - -void -init_stor_layout_once () -{ - ggc_add_tree_root (&pending_sizes, 1); -} +#include "gt-stor-layout.h" |