X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fstor-layout.c;h=7b81abf5aee474f4091ec6b342561b0d9c77e112;hb=f7449ceb0875fd2f633356e0060ae12cf83bc6b6;hp=c86dd549700229d211281e6f92b1750ba4f8500f;hpb=5d7ed6c775004db0b03ae47d20effa3b4bf6e5ed;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index c86dd549700..7b81abf5aee 100644 --- a/gcc/stor-layout.c +++ b/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, 2003, 2004 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GCC. @@ -16,8 +16,8 @@ for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ #include "config.h" @@ -30,6 +30,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "flags.h" #include "function.h" #include "expr.h" +#include "output.h" #include "toplev.h" #include "ggc.h" #include "target.h" @@ -47,10 +48,6 @@ unsigned int maximum_field_alignment = TARGET_DEFAULT_PACK_STRUCT * BITS_PER_UNI /* ... and its original value in bytes, specified via -fpack-struct=. */ unsigned int initial_max_fld_align = TARGET_DEFAULT_PACK_STRUCT; -/* If nonzero, the alignment of a bitstring or (power-)set value, in bits. - May be overridden by front-ends. */ -unsigned int set_alignment = 0; - /* Nonzero if all REFERENCE_TYPEs are internal and hence should be allocated in Pmode, not ptr_mode. Set only by internal_reference_types called only by a front end. */ @@ -455,10 +452,10 @@ layout_decl (tree decl, unsigned int known_align) int size_as_int = TREE_INT_CST_LOW (size); if (compare_tree_int (size, size_as_int) == 0) - warning ("%Jsize of %qD is %d bytes", decl, decl, size_as_int); + warning (0, "size of %q+D is %d bytes", decl, size_as_int); else - warning ("%Jsize of %qD is larger than %d bytes", - decl, decl, larger_than_size); + warning (0, "size of %q+D is larger than %wd bytes", + decl, larger_than_size); } } @@ -489,7 +486,7 @@ relayout_decl (tree decl) /* Hook for a front-end function that can modify the record layout as needed immediately before it is finalized. */ -void (*lang_adjust_rli) (record_layout_info) = 0; +static void (*lang_adjust_rli) (record_layout_info) = 0; void set_lang_adjust_rli (void (*f) (record_layout_info)) @@ -638,9 +635,9 @@ rli_size_so_far (record_layout_info rli) } /* 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, @@ -686,6 +683,18 @@ 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 @@ -750,9 +759,9 @@ place_union_field (record_layout_info rli, tree field) 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 (build3 (COND_EXPR, sizetype, - DECL_QUALIFIER (field), - DECL_SIZE_UNIT (field), rli->offset)); + rli->offset = fold_build3 (COND_EXPR, sizetype, + DECL_QUALIFIER (field), + DECL_SIZE_UNIT (field), rli->offset); } #if defined (PCC_BITFIELD_TYPE_MATTERS) || defined (BITFIELD_NBYTES_LIMITED) @@ -791,9 +800,19 @@ place_field (record_layout_info rli, tree field) /* The type of this field. */ tree type = TREE_TYPE (field); - if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK) - return; + gcc_assert (TREE_CODE (field) != ERROR_MARK); + if (TREE_CODE (type) == ERROR_MARK) + { + if (TREE_CODE (field) == FIELD_DECL) + { + DECL_FIELD_OFFSET (field) = size_int (0); + DECL_FIELD_BIT_OFFSET (field) = bitsize_int (0); + } + + 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 @@ -824,7 +843,7 @@ place_field (record_layout_info rli, tree field) 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) @@ -833,6 +852,8 @@ place_field (record_layout_info rli, tree field) 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)) { @@ -841,11 +862,11 @@ place_field (record_layout_info rli, tree field) if (TYPE_ALIGN (type) > desired_align) { if (STRICT_ALIGNMENT) - warning ("%Jpacked attribute causes inefficient alignment " - "for %qD", field, field); + warning (OPT_Wattributes, "packed attribute causes " + "inefficient alignment for %q+D", field); else - warning ("%Jpacked attribute is unnecessary for %qD", - field, field); + warning (OPT_Wattributes, "packed attribute is " + "unnecessary for %q+D", field); } } else @@ -859,8 +880,7 @@ place_field (record_layout_info rli, tree field) /* No, we need to skip space before this field. Bump the cumulative size to multiple of field alignment. */ - if (warn_padded) - warning ("%Jpadding struct to align %qD", field, field); + warning (OPT_Wpadded, "padding struct to align %q+D", field); /* If the alignment is still within offset_align, just align the bit position. */ @@ -1005,18 +1025,30 @@ place_field (record_layout_info rli, tree 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 @@ -1032,9 +1064,14 @@ place_field (record_layout_info rli, tree 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)); + /* 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 @@ -1048,6 +1085,7 @@ place_field (record_layout_info rli, tree field) rli->prev_field = NULL; } + rli->prev_packed = 0; normalize_rli (rli); } @@ -1120,20 +1158,59 @@ place_field (record_layout_info rli, tree field) 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 @@ -1200,9 +1277,9 @@ finalize_record_size (record_layout_info rli) TYPE_SIZE_UNIT (rli->t) = round_up (unpadded_size_unit, TYPE_ALIGN_UNIT (rli->t)); - if (warn_padded && TREE_CONSTANT (unpadded_size) + if (TREE_CONSTANT (unpadded_size) && simple_cst_equal (unpadded_size, TYPE_SIZE (rli->t)) == 0) - warning ("padding struct size to alignment boundary"); + warning (OPT_Wpadded, "padding struct size to alignment boundary"); if (warn_packed && TREE_CODE (rli->t) == RECORD_TYPE && TYPE_PACKED (rli->t) && ! rli->packed_maybe_necessary @@ -1232,17 +1309,19 @@ finalize_record_size (record_layout_info rli) name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (rli->t))); if (STRICT_ALIGNMENT) - warning ("packed attribute causes inefficient " + warning (OPT_Wpacked, "packed attribute causes inefficient " "alignment for %qs", name); else - warning ("packed attribute is unnecessary for %qs", name); + warning (OPT_Wpacked, + "packed attribute is unnecessary for %qs", name); } else { if (STRICT_ALIGNMENT) - warning ("packed attribute causes inefficient alignment"); + warning (OPT_Wpacked, + "packed attribute causes inefficient alignment"); else - warning ("packed attribute is unnecessary"); + warning (OPT_Wpacked, "packed attribute is unnecessary"); } } } @@ -1298,14 +1377,15 @@ compute_record_mode (tree type) #endif /* MEMBER_TYPE_FORCES_BLK */ } - TYPE_MODE (type) = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1); - /* If we only have one real field; use its mode if that mode's size matches the type's size. This only applies to RECORD_TYPE. This does not apply to unions. */ if (TREE_CODE (type) == RECORD_TYPE && mode != VOIDmode - && GET_MODE_SIZE (mode) == GET_MODE_SIZE (TYPE_MODE (type))) + && host_integerp (TYPE_SIZE (type), 1) + && GET_MODE_BITSIZE (mode) == TREE_INT_CST_LOW (TYPE_SIZE (type))) TYPE_MODE (type) = mode; + else + TYPE_MODE (type) = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1); /* If structure's known alignment is less than what the scalar mode would need, and it matters, then stick with BLKmode. */ @@ -1338,8 +1418,15 @@ finalize_type_size (tree type) && TREE_CODE (type) != QUAL_UNION_TYPE && TREE_CODE (type) != ARRAY_TYPE))) { - TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type)); - TYPE_USER_ALIGN (type) = 0; + unsigned mode_align = GET_MODE_ALIGNMENT (TYPE_MODE (type)); + + /* Don't override a larger alignment requirement coming from a user + alignment of one of the fields. */ + if (mode_align >= TYPE_ALIGN (type)) + { + TYPE_ALIGN (type) = mode_align; + TYPE_USER_ALIGN (type) = 0; + } } /* Do machine-dependent extra alignment. */ @@ -1408,6 +1495,8 @@ finalize_type_size (tree type) void finish_record_layout (record_layout_info rli, int free_p) { + tree field; + /* Compute the final size. */ finalize_record_size (rli); @@ -1417,6 +1506,15 @@ finish_record_layout (record_layout_info rli, int free_p) /* Perform any last tweaks to the TYPE_SIZE, etc. */ finalize_type_size (rli->t); + /* We might be able to clear DECL_PACKED on any members that happen + to be suitably aligned (not forgetting the alignment of the type + itself). */ + for (field = TYPE_FIELDS (rli->t); field; field = TREE_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field) + && DECL_OFFSET_ALIGN (field) >= TYPE_ALIGN (TREE_TYPE (field)) + && TYPE_ALIGN (rli->t) >= TYPE_ALIGN (TREE_TYPE (field))) + DECL_PACKED (field) = 0; + /* Lay out any static members. This is done now because their type may use the record's type. */ while (rli->pending_statics) @@ -1576,6 +1674,10 @@ layout_type (tree type) nunits_tree, 0); TYPE_SIZE (type) = int_const_binop (MULT_EXPR, TYPE_SIZE (innertype), nunits_tree, 0); + + /* Always naturally align vectors. This prevents ABI changes + depending on whether or not native vector modes are supported. */ + TYPE_ALIGN (type) = tree_low_cst (TYPE_SIZE (type), 0); break; } @@ -1641,9 +1743,9 @@ layout_type (tree type) that (possible) negative values are handled appropriately. */ length = size_binop (PLUS_EXPR, size_one_node, fold_convert (sizetype, - fold (build2 (MINUS_EXPR, - TREE_TYPE (lb), - ub, lb)))); + fold_build2 (MINUS_EXPR, + TREE_TYPE (lb), + ub, lb))); /* Special handling for arrays of bits (for Chill). */ element_size = TYPE_SIZE (element); @@ -1725,6 +1827,12 @@ layout_type (tree type) TYPE_MODE (type) = BLKmode; } } + if (TYPE_SIZE_UNIT (element) + && TREE_CODE (TYPE_SIZE_UNIT (element)) == INTEGER_CST + && !integer_zerop (TYPE_SIZE_UNIT (element)) + && compare_tree_int (TYPE_SIZE_UNIT (element), + TYPE_ALIGN_UNIT (element)) < 0) + error ("alignment of array elements is greater than element size"); break; } @@ -1759,48 +1867,6 @@ layout_type (tree type) } break; - case SET_TYPE: /* Used by Chill and Pascal. */ - { - unsigned int alignment; - HOST_WIDE_INT size_in_bits; - HOST_WIDE_INT rounded_size; - - gcc_assert (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) - == INTEGER_CST); - gcc_assert (TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) - == INTEGER_CST); - -#ifndef SET_WORD_SIZE -#define SET_WORD_SIZE BITS_PER_WORD -#endif - alignment = set_alignment ? set_alignment : SET_WORD_SIZE; - size_in_bits - = (tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0) - - tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0) + 1); - rounded_size - = ((size_in_bits + alignment - 1) / alignment) * alignment; - - if (rounded_size > (int) alignment) - TYPE_MODE (type) = BLKmode; - else - TYPE_MODE (type) = mode_for_size (alignment, MODE_INT, 1); - - TYPE_SIZE (type) = bitsize_int (rounded_size); - TYPE_SIZE_UNIT (type) = size_int (rounded_size / BITS_PER_UNIT); - TYPE_ALIGN (type) = alignment; - TYPE_USER_ALIGN (type) = 0; - TYPE_PRECISION (type) = size_in_bits; - } - break; - - case FILE_TYPE: - /* The size may vary in different languages, so the language front end - should fill in the size. */ - TYPE_ALIGN (type) = BIGGEST_ALIGNMENT; - TYPE_USER_ALIGN (type) = 0; - TYPE_MODE (type) = BLKmode; - break; - default: gcc_unreachable (); } @@ -1916,8 +1982,10 @@ set_sizetype (tree type) TYPE_PRECISION (t) = precision; TYPE_UID (t) = TYPE_UID (bitsizetype); TYPE_IS_SIZETYPE (t) = 1; + /* Replace our original stub bitsizetype. */ memcpy (bitsizetype, t, tree_size (bitsizetype)); + TYPE_MAIN_VARIANT (bitsizetype) = bitsizetype; if (TYPE_UNSIGNED (type)) { @@ -2127,8 +2195,8 @@ get_mode_bounds (enum machine_mode mode, int sign, max_val = ((unsigned HOST_WIDE_INT) 1 << (size - 1) << 1) - 1; } - *mmin = GEN_INT (trunc_int_for_mode (min_val, target_mode)); - *mmax = GEN_INT (trunc_int_for_mode (max_val, target_mode)); + *mmin = gen_int_mode (min_val, target_mode); + *mmax = gen_int_mode (max_val, target_mode); } #include "gt-stor-layout.h"