X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fstor-layout.c;h=8569ca2538dc8d00d9dcba757bd0e1454576a282;hp=39c30c5a9127e7f720ba41c27778f355147ee909;hb=160b212363ad6cd0735e94edc7fe5e6aa00c3a7d;hpb=1be87b7252bb4b5936fc2ebebdcb9f18bed35bae diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 39c30c5a912..8569ca2538d 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -1,23 +1,23 @@ /* C-compiler utilities for types and variables storage layout Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1996, 1998, - 1999, 2000, 2001 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +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. */ #include "config.h" @@ -30,6 +30,8 @@ Boston, MA 02111-1307, USA. */ #include "expr.h" #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; @@ -62,7 +64,7 @@ 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. */ @@ -114,6 +116,13 @@ void put_pending_size (expr) tree expr; { + /* Strip any simple arithmetic from EXPR to see if it has an underlying + SAVE_EXPR. */ + while (TREE_CODE_CLASS (TREE_CODE (expr)) == '1' + || (TREE_CODE_CLASS (TREE_CODE (expr)) == '2' + && TREE_CONSTANT (TREE_OPERAND (expr, 1)))) + expr = TREE_OPERAND (expr, 0); + if (TREE_CODE (expr) == SAVE_EXPR) pending_sizes = tree_cons (NULL_TREE, expr, pending_sizes); } @@ -140,9 +149,11 @@ variable_size (size) { /* If the language-processor is to take responsibility for variable-sized items (e.g., languages which have elaboration procedures like Ada), - just return SIZE unchanged. Likewise for self-referential sizes. */ + 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); @@ -158,7 +169,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"); @@ -169,7 +180,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); @@ -198,7 +209,7 @@ mode_for_size (size, class, limit) enum mode_class class; int limit; { - register enum machine_mode mode; + enum machine_mode mode; if (limit && size > MAX_FIXED_MODE_SIZE) return BLKmode; @@ -238,7 +249,7 @@ smallest_mode_for_size (size, class) unsigned int size; enum mode_class class; { - register enum machine_mode mode; + enum machine_mode mode; /* Get the first mode which has at least this size, in the specified class. */ @@ -272,7 +283,7 @@ int_mode_for_mode (mode) case MODE_RANDOM: if (mode == BLKmode) - break; + break; /* ... fall through ... */ @@ -327,8 +338,8 @@ layout_decl (decl, known_align) tree decl; unsigned int known_align; { - register tree type = TREE_TYPE (decl); - register enum tree_code code = TREE_CODE (decl); + tree type = TREE_TYPE (decl); + enum tree_code code = TREE_CODE (decl); if (code == CONST_DECL) return; @@ -370,7 +381,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; } @@ -381,14 +392,22 @@ layout_decl (decl, known_align) DECL_BIT_FIELD_TYPE (decl) = DECL_BIT_FIELD (decl) ? type : 0; if (maximum_field_alignment != 0) DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment); - else if (DECL_PACKED (decl)) + + /* If the field is of variable size, we can't misalign it since we + have no way to make a temporary to align the result. But this + isn't an issue if the decl is not addressable. Likewise if it + is of unknown size. */ + else if (DECL_PACKED (decl) + && (DECL_NONADDRESSABLE_P (decl) + || DECL_SIZE_UNIT (decl) == 0 + || TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST)) { DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT); DECL_USER_ALIGN (decl) = 0; } } - /* 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) @@ -396,7 +415,7 @@ layout_decl (decl, known_align) && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT) { - register enum machine_mode xmode + enum machine_mode xmode = mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1); if (xmode != BLKmode && known_align >= GET_MODE_ALIGNMENT (xmode)) @@ -459,7 +478,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. */ @@ -467,7 +486,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; @@ -487,6 +506,7 @@ start_record_layout (t) rli->offset = size_zero_node; rli->bitpos = bitsize_zero_node; + rli->prev_field = 0; rli->pending_statics = 0; rli->packed_maybe_necessary = 0; @@ -567,7 +587,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)); } @@ -634,7 +654,7 @@ place_union_field (rli, 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); @@ -650,6 +670,12 @@ place_union_field (rli, field) MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT); #endif +#ifdef ADJUST_FIELD_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); @@ -659,7 +685,7 @@ place_union_field (rli, field) entire union to have `int' alignment. */ if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field)) { - rli->record_align = MAX (rli->record_align, + rli->record_align = MAX (rli->record_align, TYPE_ALIGN (TREE_TYPE (field))); rli->unpadded_align = MAX (rli->unpadded_align, TYPE_ALIGN (TREE_TYPE (field))); @@ -671,7 +697,7 @@ place_union_field (rli, 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 (build (COND_EXPR, sizetype, + rli->offset = fold (build (COND_EXPR, sizetype, DECL_QUALIFIER (field), DECL_SIZE_UNIT (field), rli->offset)); } @@ -695,7 +721,7 @@ place_field (rli, field) 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; @@ -765,8 +791,26 @@ place_field (rli, field) /* 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))) { @@ -856,6 +900,7 @@ place_field (rli, field) variable-sized fields, we need not worry about compatibility. */ #ifdef PCC_BITFIELD_TYPE_MATTERS if (PCC_BITFIELD_TYPE_MATTERS + && ! (* targetm.ms_bitfield_layout_p) (rli->t) && TREE_CODE (field) == FIELD_DECL && type != error_mark_node && DECL_BIT_FIELD (field) @@ -885,6 +930,7 @@ place_field (rli, field) #ifdef BITFIELD_NBYTES_LIMITED if (BITFIELD_NBYTES_LIMITED + && ! (* targetm.ms_bitfield_layout_p) (rli->t) && TREE_CODE (field) == FIELD_DECL && type != error_mark_node && DECL_BIT_FIELD_TYPE (field) @@ -918,12 +964,58 @@ place_field (rli, field) } #endif + /* See the docs for TARGET_MS_BITFIELD_LAYOUT_P for details. */ + 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))))) + { + unsigned int type_align = TYPE_ALIGN (type); + + 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))); + + if (maximum_field_alignment != 0) + type_align = MIN (type_align, maximum_field_alignment); + + rli->bitpos = round_up (rli->bitpos, type_align); + } + /* Offset so far becomes the position of this field after normalizing. */ normalize_rli (rli); DECL_FIELD_OFFSET (field) = rli->offset; 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. */ @@ -942,6 +1034,8 @@ place_field (rli, field) if (known_align != actual_align) layout_decl (field, actual_align); + 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 adjust the offset, resetting the bit position. Otherwise, apportion the @@ -993,7 +1087,6 @@ finalize_record_size (rli) #else TYPE_ALIGN (rli->t) = MAX (TYPE_ALIGN (rli->t), rli->record_align); #endif - TYPE_USER_ALIGN (rli->t) = 0; /* Compute the size so far. Be sure to allow for extra bits in the size in bytes. We have guaranteed above that it will be no more @@ -1028,7 +1121,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)) @@ -1110,11 +1203,12 @@ compute_record_mode (type) || (TYPE_MODE (TREE_TYPE (field)) == BLKmode && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field))) || ! host_integerp (bit_position (field), 1) + || DECL_SIZE (field) == 0 || ! host_integerp (DECL_SIZE (field), 1)) 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 @@ -1133,7 +1227,17 @@ compute_record_mode (type) #ifdef MEMBER_TYPE_FORCES_BLK /* With some targets, eg. c4x, it is sub-optimal to access an aligned BLKmode structure as a scalar. */ - if (mode == VOIDmode && MEMBER_TYPE_FORCES_BLK (field)) + + /* 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)) return; #endif /* MEMBER_TYPE_FORCES_BLK */ } @@ -1389,8 +1493,8 @@ layout_type (type) case ARRAY_TYPE: { - register tree index = TYPE_DOMAIN (type); - register tree element = TREE_TYPE (type); + tree index = TYPE_DOMAIN (type); + tree element = TREE_TYPE (type); build_pointer_type (element); @@ -1453,6 +1557,7 @@ layout_type (type) #else TYPE_ALIGN (type) = MAX (TYPE_ALIGN (element), BITS_PER_UNIT); #endif + TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element); #ifdef ROUND_TYPE_SIZE if (TYPE_SIZE (type) != 0) @@ -1479,8 +1584,13 @@ layout_type (type) && (TYPE_MODE (TREE_TYPE (type)) != BLKmode || TYPE_NO_FORCE_BLK (TREE_TYPE (type)))) { - TYPE_MODE (type) - = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1); + /* One-element arrays get the component type's mode. */ + if (simple_cst_equal (TYPE_SIZE (type), + TYPE_SIZE (TREE_TYPE (type)))) + TYPE_MODE (type) = TYPE_MODE (TREE_TYPE (type)); + else + TYPE_MODE (type) + = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1); if (TYPE_MODE (type) != BLKmode && STRICT_ALIGNMENT && TYPE_ALIGN (type) < BIGGEST_ALIGNMENT @@ -1528,7 +1638,7 @@ layout_type (type) case SET_TYPE: /* Used by Chill and Pascal. */ if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST) - abort(); + abort (); else { #ifndef SET_WORD_SIZE @@ -1570,7 +1680,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); @@ -1595,7 +1705,7 @@ tree make_signed_type (precision) int precision; { - register tree type = make_node (INTEGER_TYPE); + tree type = make_node (INTEGER_TYPE); TYPE_PRECISION (type) = precision; @@ -1609,7 +1719,7 @@ tree make_unsigned_type (precision) int precision; { - register tree type = make_node (INTEGER_TYPE); + tree type = make_node (INTEGER_TYPE); TYPE_PRECISION (type) = precision; @@ -1713,9 +1823,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)) @@ -1740,7 +1847,13 @@ void fixup_signed_type (type) tree type; { - register int precision = TYPE_PRECISION (type); + int precision = TYPE_PRECISION (type); + + /* We can not represent properly constants greater then + 2 * HOST_BITS_PER_WIDE_INT, still we need the types + as they are used by i386 vector extensions and friends. */ + if (precision > HOST_BITS_PER_WIDE_INT * 2) + precision = HOST_BITS_PER_WIDE_INT * 2; TYPE_MIN_VALUE (type) = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0 @@ -1772,7 +1885,13 @@ void fixup_unsigned_type (type) tree type; { - register int precision = TYPE_PRECISION (type); + int precision = TYPE_PRECISION (type); + + /* We can not represent properly constants greater then + 2 * HOST_BITS_PER_WIDE_INT, still we need the types + as they are used by i386 vector extensions and friends. */ + if (precision > HOST_BITS_PER_WIDE_INT * 2) + precision = HOST_BITS_PER_WIDE_INT * 2; TYPE_MIN_VALUE (type) = build_int_2 (0, 0); TYPE_MAX_VALUE (type) @@ -1859,27 +1978,4 @@ get_best_mode (bitsize, bitpos, align, largest_mode, volatilep) 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 = GET_MODE_UNIT_SIZE (mode); - - /* Extract the LSB of the size. */ - alignment = alignment & -alignment; - alignment *= BITS_PER_UNIT; - - alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment)); - return alignment; -} - -/* 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"