/* C-compiler utilities for types and variables storage layout
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1996, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 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"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "tm_p.h"
#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;
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;
+/* 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. */
+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));
+#if defined (PCC_BITFIELD_TYPE_MATTERS) || defined (BITFIELD_NBYTES_LIMITED)
+static int excess_unit_span PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
+ HOST_WIDE_INT, HOST_WIDE_INT,
+ tree));
+#endif
+static unsigned int update_alignment_for_field
+ PARAMS ((record_layout_info, tree,
+ unsigned int));
extern void debug_rli PARAMS ((record_layout_info));
\f
/* 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. */
int immediate_size_expand;
+/* Show that REFERENCE_TYPES are internal and should be Pmode. Called only
+ by front end. */
+
+void
+internal_reference_types ()
+{
+ reference_types_internal = 1;
+}
+
/* Get a list of all the objects put on the pending sizes list. */
tree
return chain;
}
+/* Return nonzero if EXPR is present on the pending sizes list. */
+
+int
+is_pending_size (expr)
+ tree expr;
+{
+ tree t;
+
+ for (t = pending_sizes; t; t = TREE_CHAIN (t))
+ if (TREE_VALUE (t) == expr)
+ return 1;
+ return 0;
+}
+
+/* Add EXPR to the pending sizes list. */
+
+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);
+}
+
/* Put a chain of objects into the pending sizes list, which must be
empty. */
variable_size (size)
tree size;
{
+ tree save;
+
/* 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);
+ if (TREE_CODE (size) == MINUS_EXPR && integer_onep (TREE_OPERAND (size, 1)))
+ /* If this is the upper bound of a C array, leave the minus 1 outside
+ the SAVE_EXPR so it can be folded away. */
+ TREE_OPERAND (size, 0) = save = save_expr (TREE_OPERAND (size, 0));
+ else
+ size = save = save_expr (size);
/* If an array with a variable number of elements is declared, and
the elements require destruction, we will emit a cleanup for the
`unsaved', i.e., all SAVE_EXPRs are recalculated. However, we do
not wish to do that here; the array-size is the same in both
places. */
- if (TREE_CODE (size) == SAVE_EXPR)
- SAVE_EXPR_PERSISTENT_P (size) = 1;
+ if (TREE_CODE (save) == SAVE_EXPR)
+ SAVE_EXPR_PERSISTENT_P (save) = 1;
- if (global_bindings_p ())
+ if ((*lang_hooks.decls.global_bindings_p) ())
{
if (TREE_CONSTANT (size))
error ("type size can't be explicitly evaluated");
}
if (immediate_size_expand)
- /* 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_PTR, VOIDmode, 0),
- VOIDmode, 0);
+ expand_expr (save, const0_rtx, VOIDmode, 0);
else if (cfun != 0 && cfun->x_dont_save_pending_sizes_p)
/* The front-end doesn't want us to keep a list of the expressions
that determine sizes for variable size objects. */
;
- else if (TREE_CODE (size) == SAVE_EXPR)
- pending_sizes = tree_cons (NULL_TREE, size, pending_sizes);
+ else
+ put_pending_size (save);
return size;
}
enum mode_class class;
int limit;
{
- register enum machine_mode mode;
+ enum machine_mode mode;
if (limit && size > MAX_FIXED_MODE_SIZE)
return BLKmode;
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. */
case MODE_RANDOM:
if (mode == BLKmode)
- break;
+ break;
- /* ... fall through ... */
+ /* ... fall through ... */
case MODE_CC:
default:
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. */
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;
&& (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) = TYPE_USER_ALIGN (type);
+ DECL_USER_ALIGN (decl) = 0;
}
/* For fields, set the bit field type and update the alignment. */
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)
&& 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))
}
}
\f
+/* Hook for a front-end function that can modify the record layout as needed
+ immediately before it is finalized. */
+
+void (*lang_adjust_rli) PARAMS ((record_layout_info)) = 0;
+
+void
+set_lang_adjust_rli (f)
+ void (*f) PARAMS ((record_layout_info));
+{
+ 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. */
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;
declaration, for example) use it -- otherwise, start with a
one-byte alignment. */
rli->record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (t));
- rli->unpacked_align = rli->record_align;
+ rli->unpacked_align = rli->unpadded_align = rli->record_align;
rli->offset_align = MAX (rli->record_align, BIGGEST_ALIGNMENT);
#ifdef STRUCTURE_SIZE_BOUNDARY
/* Packed structures don't need to have minimum size. */
if (! TYPE_PACKED (t))
- rli->record_align = MAX (rli->record_align, STRUCTURE_SIZE_BOUNDARY);
+ rli->record_align = MAX (rli->record_align, (unsigned) STRUCTURE_SIZE_BOUNDARY);
#endif
rli->offset = size_zero_node;
rli->bitpos = bitsize_zero_node;
+ rli->prev_field = 0;
rli->pending_statics = 0;
rli->packed_maybe_necessary = 0;
}
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;
= 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));
}
print_node_brief (stderr, "\noffset", rli->offset, 0);
print_node_brief (stderr, " bitpos", rli->bitpos, 0);
- fprintf (stderr, "\nrec_align = %u, unpack_align = %u, off_align = %u\n",
- rli->record_align, rli->unpacked_align, rli->offset_align);
+ fprintf (stderr, "\naligns: rec = %u, unpack = %u, unpad = %u, off = %u\n",
+ rli->record_align, rli->unpacked_align, rli->unpadded_align,
+ rli->offset_align);
if (rli->packed_maybe_necessary)
fprintf (stderr, "packed may be necessary\n");
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
- /* Union must be at least as aligned as any field requires. */
- rli->record_align = MAX (rli->record_align, desired_align);
+#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)))
+ {
+ /* 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))
- rli->record_align = MAX (rli->record_align,
- TYPE_ALIGN (TREE_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)))
+ {
+ /* A zero-length bit-field affects the alignment of the next
+ field. */
+ if (!DECL_PACKED (field) && integer_zerop (DECL_SIZE (field)))
+ {
+ desired_align = TYPE_ALIGN (type);
+#ifdef ADJUST_FIELD_ALIGN
+ desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
+#endif
+ }
+
+ /* Named bit-fields cause the entire structure to have the
+ alignment implied by their type. */
+ 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);
+
+ /* The alignment of the record is increased to the maximum
+ of the current alignment, the alignment indicated on the
+ field (i.e., the alignment specified by an __aligned__
+ attribute), and the alignment indicated by the type of
+ the field. */
+ rli->record_align = MAX (rli->record_align, desired_align);
+ 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;
+
+ 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));
}
+#if defined (PCC_BITFIELD_TYPE_MATTERS) || defined (BITFIELD_NBYTES_LIMITED)
+/* A bitfield of SIZE with a required access alignment of ALIGN is allocated
+ at BYTE_OFFSET / BIT_OFFSET. Return nonzero 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));
+}
+#endif
+
/* 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;
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;
& - 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
- 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. */
-#ifdef PCC_BITFIELD_TYPE_MATTERS
- if (PCC_BITFIELD_TYPE_MATTERS && type != error_mark_node
- && 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);
-
- 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);
- if (warn_packed)
- rli->unpacked_align = MAX (rli->unpacked_align,
- TYPE_ALIGN (type));
- }
- }
- else
-#endif
- {
- rli->record_align = MAX (rli->record_align, desired_align);
- rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
- }
+
+ desired_align = update_alignment_for_field (rli, field, known_align);
if (warn_packed && DECL_PACKED (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)
HOST_WIDE_INT offset = tree_low_cst (rli->offset, 0);
HOST_WIDE_INT bit_offset = tree_low_cst (rli->bitpos, 0);
+#ifdef ADJUST_FIELD_ALIGN
+ if (! TYPE_USER_ALIGN (type))
+ type_align = ADJUST_FIELD_ALIGN (field, type_align);
+#endif
+
/* 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);
}
#endif
#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)
HOST_WIDE_INT offset = tree_low_cst (rli->offset, 0);
HOST_WIDE_INT bit_offset = tree_low_cst (rli->bitpos, 0);
+#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);
/* ??? This test is opposite the test in the containing if
/* 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);
}
#endif
+ /* 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 equivalent
+ when packing.
+
+ Note: for compatibility, 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)
+ && ((DECL_BIT_FIELD_TYPE (field) && ! DECL_PACKED (field))
+ || (rli->prev_field && ! DECL_PACKED (rli->prev_field))))
+ {
+ /* 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;
+
+ /* 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 compatibility */
+
+ /* (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);
+
+ 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. */
normalize_rli (rli);
DECL_FIELD_OFFSET (field) = rli->offset;
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;
+
/* 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
/* Assuming that all the fields have been laid out, this function uses
RLI to compute the final TYPE_SIZE, TYPE_ALIGN, etc. for the type
- inidicated by RLI. */
+ indicated by RLI. */
static void
finalize_record_size (rli)
#else
TYPE_ALIGN (rli->t) = MAX (TYPE_ALIGN (rli->t), rli->record_align);
#endif
- TYPE_USER_ALIGN (rli->t) = 1;
/* 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
unpadded_size_unit
= size_binop (PLUS_EXPR, unpadded_size_unit, size_one_node);
- /* Record the un-rounded size in the binfo node. But first we check
- the size of TYPE_BINFO to make sure that BINFO_SIZE is available. */
- if (TYPE_BINFO (rli->t) && TREE_VEC_LENGTH (TYPE_BINFO (rli->t)) > 6)
- {
- TYPE_BINFO_SIZE (rli->t) = unpadded_size;
- TYPE_BINFO_SIZE_UNIT (rli->t) = unpadded_size_unit;
- }
-
- /* Round the size up to be a multiple of the required alignment */
+ /* Round the size up to be a multiple of the required alignment */
#ifdef ROUND_TYPE_SIZE
TYPE_SIZE (rli->t) = ROUND_TYPE_SIZE (rli->t, unpadded_size,
TYPE_ALIGN (rli->t));
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))
|| (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
if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
mode = DECL_MODE (field);
-#ifdef STRUCT_FORCE_BLK
+#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 && STRUCT_FORCE_BLK (field))
+
+ if (MEMBER_TYPE_FORCES_BLK (field, mode))
return;
-#endif /* STRUCT_FORCE_BLK */
+#endif /* MEMBER_TYPE_FORCES_BLK */
}
/* If we only have one real field; use its mode. This only applies to
/* 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);
}
/* Clean up. */
- free (rli);
+ if (free_p)
+ free (rli);
}
\f
+
+/* 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
of the language-specific code. */
abort ();
- case BOOLEAN_TYPE: /* Used for Java, Pascal, and Chill. */
+ case BOOLEAN_TYPE: /* Used for Java, Pascal, and Chill. */
if (TYPE_PRECISION (type) == 0)
- TYPE_PRECISION (type) = 1; /* default to one byte/boolean. */
+ TYPE_PRECISION (type) = 1; /* default to one byte/boolean. */
- /* ... fall through ... */
+ /* ... fall through ... */
case INTEGER_TYPE:
case ENUMERAL_TYPE:
case OFFSET_TYPE:
TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
- TYPE_MODE (type) = ptr_mode;
+ /* A pointer might be MODE_PARTIAL_INT,
+ but ptrdiff_t must be integral. */
+ TYPE_MODE (type) = mode_for_size (POINTER_SIZE, MODE_INT, 0);
break;
case FUNCTION_TYPE:
case POINTER_TYPE:
case REFERENCE_TYPE:
- TYPE_MODE (type) = ptr_mode;
- TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
- TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
- TREE_UNSIGNED (type) = 1;
- TYPE_PRECISION (type) = POINTER_SIZE;
+ {
+
+ 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 (GET_MODE_SIZE (mode));
+ TREE_UNSIGNED (type) = 1;
+ TYPE_PRECISION (type) = nbits;
+ }
break;
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);
#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)
TYPE_MODE (type) = BLKmode;
if (TYPE_SIZE (type) != 0
+#ifdef MEMBER_TYPE_FORCES_BLK
+ && ! MEMBER_TYPE_FORCES_BLK (type, VOIDmode)
+#endif
/* BLKmode elements force BLKmode aggregate;
else extract/store fields may lose. */
&& (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
if (TREE_CODE (type) == QUAL_UNION_TYPE)
TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));
+ if (lang_adjust_rli)
+ (*lang_adjust_rli) (rli);
+
/* Finish laying out the record. */
- finish_record_layout (rli);
+ finish_record_layout (rli, /*free_p=*/true);
}
break;
- case SET_TYPE: /* Used by Chill and Pascal. */
+ 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
/* 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);
make_signed_type (precision)
int precision;
{
- register tree type = make_node (INTEGER_TYPE);
+ tree type = make_node (INTEGER_TYPE);
TYPE_PRECISION (type) = precision;
make_unsigned_type (precision)
int precision;
{
- register tree type = make_node (INTEGER_TYPE);
+ tree type = make_node (INTEGER_TYPE);
TYPE_PRECISION (type) = precision;
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))
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
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)
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) * BITS_PER_UNIT;
-
- /* Extract the LSB of the size. */
- alignment = alignment & -alignment;
-
- 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"