diff options
Diffstat (limited to 'gcc/stor-layout.c')
-rw-r--r-- | gcc/stor-layout.c | 128 |
1 files changed, 83 insertions, 45 deletions
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index db4c09f29f7..83fbb294d7a 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -22,6 +22,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "tree.h" #include "rtl.h" #include "tm_p.h" @@ -60,6 +62,9 @@ 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 int excess_unit_span PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT, + HOST_WIDE_INT, HOST_WIDE_INT, + tree)); static unsigned int update_alignment_for_field PARAMS ((record_layout_info, tree, unsigned int)); @@ -539,25 +544,6 @@ byte_from_pos (offset, bitpos) } void -pos_from_byte (poffset, pbitpos, off_align, pos) - tree *poffset, *pbitpos; - unsigned int off_align; - tree pos; -{ - *poffset - = size_binop (MULT_EXPR, - convert (sizetype, - size_binop (FLOOR_DIV_EXPR, pos, - bitsize_int (off_align - / BITS_PER_UNIT))), - size_int (off_align / BITS_PER_UNIT)); - *pbitpos = size_binop (MULT_EXPR, - size_binop (FLOOR_MOD_EXPR, pos, - bitsize_int (off_align / BITS_PER_UNIT)), - bitsize_unit_node); -} - -void pos_from_bit (poffset, pbitpos, off_align, pos) tree *poffset, *pbitpos; unsigned int off_align; @@ -797,6 +783,24 @@ place_union_field (rli, field) DECL_SIZE_UNIT (field), rli->offset)); } +/* A bitfield of SIZE with a required access alignment of ALIGN is allocated + at BYTE_OFFSET / BIT_OFFSET. Return non-zero if the field would span more + units of alignment than the underlying TYPE. */ +static int +excess_unit_span (byte_offset, bit_offset, size, align, type) + HOST_WIDE_INT byte_offset, bit_offset, size, align; + tree type; +{ + /* Note that the calculation of OFFSET might overflow; we calculate it so + that we still get the right result as long as ALIGN is a power of two. */ + unsigned HOST_WIDE_INT offset = byte_offset * BITS_PER_UNIT + bit_offset; + + offset = offset % align; + return ((offset + size + align - 1) / align + > ((unsigned HOST_WIDE_INT) tree_low_cst (TYPE_SIZE (type), 1) + / align)); +} + /* 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; @@ -935,11 +939,7 @@ place_field (rli, field) /* A bit field may not span more units of alignment of its type than its type itself. Advance to next boundary if necessary. */ - if ((((offset * BITS_PER_UNIT + bit_offset + field_size + - type_align - 1) - / type_align) - - (offset * BITS_PER_UNIT + bit_offset) / type_align) - > tree_low_cst (TYPE_SIZE (type), 1) / type_align) + if (excess_unit_span (offset, bit_offset, field_size, type_align, type)) rli->bitpos = round_up (rli->bitpos, type_align); TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type); @@ -978,11 +978,7 @@ place_field (rli, field) /* A bit field may not span the unit of alignment of its type. Advance to next boundary if necessary. */ - /* ??? This code should match the code above for the - PCC_BITFIELD_TYPE_MATTERS case. */ - if ((offset * BITS_PER_UNIT + bit_offset) / type_align - != ((offset * BITS_PER_UNIT + bit_offset + field_size - 1) - / type_align)) + if (excess_unit_span (offset, bit_offset, field_size, type_align, type)) rli->bitpos = round_up (rli->bitpos, type_align); TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type); @@ -993,12 +989,12 @@ place_field (rli, field) 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 + 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. + when packing. Note: for compatability, we use the type size, not the type alignment to determine alignment, since that matches the documentation */ @@ -1047,8 +1043,8 @@ place_field (rli, field) } 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 + /* 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 @@ -1070,7 +1066,7 @@ place_field (rli, field) prev_saved = NULL; } - /* Cause a new bitfield to be captured, either this time (if + /* 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))) @@ -1083,7 +1079,7 @@ place_field (rli, field) /* 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. + 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 @@ -1094,20 +1090,20 @@ place_field (rli, field) there wasn't. */ if (!DECL_BIT_FIELD_TYPE (field) - || ( prev_saved != NULL + || ( 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 + /* (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 + until we see a bitfield (and come by here again) we just skip calculating it. */ - + if (DECL_SIZE (field) != NULL) - rli->remaining_in_alignment + rli->remaining_in_alignment = TREE_INT_CST_LOW (TYPE_SIZE(TREE_TYPE(field))) - TREE_INT_CST_LOW (DECL_SIZE (field)); @@ -1500,6 +1496,46 @@ finish_record_layout (rli, free_p) free (rli); } + +/* Finish processing a builtin RECORD_TYPE type TYPE. It's name is + NAME, its fields are chained in reverse on FIELDS. + + If ALIGN_TYPE is non-null, it is given the same alignment as + ALIGN_TYPE. */ + +void +finish_builtin_struct (type, name, fields, align_type) + tree type; + const char *name; + tree fields; + tree align_type; +{ + tree tail, next; + + for (tail = NULL_TREE; fields; tail = fields, fields = next) + { + DECL_FIELD_CONTEXT (fields) = type; + next = TREE_CHAIN (fields); + TREE_CHAIN (fields) = tail; + } + TYPE_FIELDS (type) = tail; + + if (align_type) + { + TYPE_ALIGN (type) = TYPE_ALIGN (align_type); + TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (align_type); + } + + layout_type (type); +#if 0 /* not yet, should get fixed properly later */ + TYPE_NAME (type) = make_type_decl (get_identifier (name), type); +#else + TYPE_NAME (type) = build_decl (TYPE_DECL, get_identifier (name), type); +#endif + TYPE_STUB_DECL (type) = TYPE_NAME (type); + layout_decl (TYPE_NAME (type), 0); +} + /* Calculate the mode, size, and alignment for TYPE. For an array type, calculate the element separation as well. Record TYPE on the chain of permanent or temporary types @@ -1600,13 +1636,15 @@ layout_type (type) case POINTER_TYPE: case REFERENCE_TYPE: { - int nbits = ((TREE_CODE (type) == REFERENCE_TYPE - && reference_types_internal) - ? GET_MODE_BITSIZE (Pmode) : POINTER_SIZE); - TYPE_MODE (type) = nbits == POINTER_SIZE ? ptr_mode : Pmode; + enum machine_mode mode = ((TREE_CODE (type) == REFERENCE_TYPE + && reference_types_internal) + ? Pmode : TYPE_MODE (type)); + + int nbits = GET_MODE_BITSIZE (mode); + TYPE_SIZE (type) = bitsize_int (nbits); - TYPE_SIZE_UNIT (type) = size_int (nbits / BITS_PER_UNIT); + TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode)); TREE_UNSIGNED (type) = 1; TYPE_PRECISION (type) = nbits; } |