/* 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.
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "tm_p.h"
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. */
{
/* 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);
+ expr = skip_simple_arithmetic (expr);
if (TREE_CODE (expr) == SAVE_EXPR)
pending_sizes = tree_cons (NULL_TREE, expr, pending_sizes);
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 and
|| 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 ((*lang_hooks.decls.global_bindings_p) ())
{
}
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_RTX, 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
- put_pending_size (size);
+ put_pending_size (save);
return size;
}
int limit;
{
if (TREE_CODE (size) != INTEGER_CST
+ || TREE_OVERFLOW (size)
/* What we really want to say here is that the size can fit in a
host integer, but we know there's no way we'd find a mode for
this many bits, so there's no point in doing the precise test. */
|| compare_tree_int (size, 1000) > 0)
return BLKmode;
else
- return mode_for_size (TREE_INT_CST_LOW (size), class, limit);
+ return mode_for_size (tree_low_cst (size, 1), class, limit);
}
/* Similar, but never return BLKmode; return the narrowest mode that
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. */
return size_binop (MULT_EXPR, size_binop (FLOOR_DIV_EXPR, value, arg), arg);
}
\f
+/* Subroutine of layout_decl: Force alignment required for the data type.
+ But if the decl itself wants greater alignment, don't override that. */
+
+static inline void
+do_type_align (tree type, tree decl)
+{
+ if (TYPE_ALIGN (type) > DECL_ALIGN (decl))
+ {
+ DECL_ALIGN (decl) = TYPE_ALIGN (type);
+ DECL_USER_ALIGN (decl) = TYPE_USER_ALIGN (type);
+ }
+}
+
/* Set the size, mode and alignment of a ..._DECL node.
TYPE_DECL does need this for C++.
Note that LABEL_DECL and CONST_DECL nodes do not need this,
{
tree type = TREE_TYPE (decl);
enum tree_code code = TREE_CODE (decl);
+ rtx rtl = NULL_RTX;
if (code == CONST_DECL)
return;
&& code != TYPE_DECL && code != FIELD_DECL)
abort ();
+ rtl = DECL_RTL_IF_SET (decl);
+
if (type == error_mark_node)
type = void_type_node;
DECL_SIZE (decl) = TYPE_SIZE (type);
DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
}
- else
+ else if (DECL_SIZE_UNIT (decl) == 0)
DECL_SIZE_UNIT (decl)
= convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
bitsize_unit_node));
- /* Force alignment required for the data type.
- But if the decl itself wants greater alignment, don't override that.
- Likewise, if the decl is packed, don't override it. */
- if (! (code == FIELD_DECL && DECL_BIT_FIELD (decl))
- && (DECL_ALIGN (decl) == 0
- || (! (code == FIELD_DECL && DECL_PACKED (decl))
- && TYPE_ALIGN (type) > DECL_ALIGN (decl))))
+ if (code != FIELD_DECL)
+ /* For non-fields, update the alignment from the type. */
+ do_type_align (type, decl);
+ else
+ /* For fields, it's a bit more complicated... */
{
- DECL_ALIGN (decl) = TYPE_ALIGN (type);
- DECL_USER_ALIGN (decl) = 0;
- }
+ if (DECL_BIT_FIELD (decl))
+ {
+ DECL_BIT_FIELD_TYPE (decl) = type;
- /* For fields, set the bit field type and update the alignment. */
- if (code == FIELD_DECL)
- {
- 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);
+ /* A zero-length bit-field affects the alignment of the next
+ field. */
+ if (integer_zerop (DECL_SIZE (decl))
+ && ! DECL_PACKED (decl)
+ && ! (*targetm.ms_bitfield_layout_p) (DECL_FIELD_CONTEXT (decl)))
+ {
+#ifdef PCC_BITFIELD_TYPE_MATTERS
+ if (PCC_BITFIELD_TYPE_MATTERS)
+ do_type_align (type, decl);
+ else
+#endif
+ {
+#ifdef EMPTY_FIELD_BOUNDARY
+ if (EMPTY_FIELD_BOUNDARY > DECL_ALIGN (decl))
+ {
+ DECL_ALIGN (decl) = EMPTY_FIELD_BOUNDARY;
+ DECL_USER_ALIGN (decl) = 0;
+ }
+#endif
+ }
+ }
+
+ /* 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 (TYPE_SIZE (type) != 0
+ && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+ && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
+ {
+ enum machine_mode xmode
+ = mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
+
+ if (xmode != BLKmode && known_align >= GET_MODE_ALIGNMENT (xmode))
+ {
+ DECL_ALIGN (decl) = MAX (GET_MODE_ALIGNMENT (xmode),
+ DECL_ALIGN (decl));
+ DECL_MODE (decl) = xmode;
+ DECL_BIT_FIELD (decl) = 0;
+ }
+ }
+
+ /* Turn off DECL_BIT_FIELD if we won't need it set. */
+ if (TYPE_MODE (type) == BLKmode && DECL_MODE (decl) == BLKmode
+ && known_align >= TYPE_ALIGN (type)
+ && DECL_ALIGN (decl) >= TYPE_ALIGN (type))
+ DECL_BIT_FIELD (decl) = 0;
+ }
+ else if (DECL_PACKED (decl) && DECL_USER_ALIGN (decl))
+ /* Don't touch DECL_ALIGN. For other packed fields, go ahead and
+ round up; we'll reduce it again below. */;
+ else
+ do_type_align (type, 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.
- 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)
- && TYPE_SIZE (type) != 0
- && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
- {
- enum machine_mode xmode
- = mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
-
- if (xmode != BLKmode && known_align >= GET_MODE_ALIGNMENT (xmode))
+ if (DECL_PACKED (decl)
+ && !DECL_USER_ALIGN (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);
+
+ /* Should this be controlled by DECL_USER_ALIGN, too? */
+ if (maximum_field_alignment != 0)
+ DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);
+ if (! DECL_USER_ALIGN (decl))
{
- DECL_ALIGN (decl) = MAX (GET_MODE_ALIGNMENT (xmode),
- DECL_ALIGN (decl));
- DECL_MODE (decl) = xmode;
- DECL_BIT_FIELD (decl) = 0;
+ /* 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
+ DECL_ALIGN (decl)
+ = MIN (DECL_ALIGN (decl), (unsigned) BIGGEST_FIELD_ALIGNMENT);
+#endif
+#ifdef ADJUST_FIELD_ALIGN
+ DECL_ALIGN (decl) = ADJUST_FIELD_ALIGN (decl, DECL_ALIGN (decl));
+#endif
}
}
- /* Turn off DECL_BIT_FIELD if we won't need it set. */
- if (code == FIELD_DECL && DECL_BIT_FIELD (decl)
- && TYPE_MODE (type) == BLKmode && DECL_MODE (decl) == BLKmode
- && known_align >= TYPE_ALIGN (type)
- && DECL_ALIGN (decl) >= TYPE_ALIGN (type)
- && DECL_SIZE_UNIT (decl) != 0)
- DECL_BIT_FIELD (decl) = 0;
-
/* Evaluate nonconstant size only once, either now or as soon as safe. */
if (DECL_SIZE (decl) != 0 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
DECL_SIZE (decl) = variable_size (DECL_SIZE (decl));
if (size != 0 && TREE_CODE (size) == INTEGER_CST
&& compare_tree_int (size, larger_than_size) > 0)
{
- unsigned int size_as_int = TREE_INT_CST_LOW (size);
+ int size_as_int = TREE_INT_CST_LOW (size);
if (compare_tree_int (size, size_as_int) == 0)
warning_with_decl (decl, "size of `%s' is %d bytes", size_as_int);
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);
+ }
}
\f
/* Hook for a front-end function that can modify the record layout as needed
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->unpadded_align = rli->record_align;
+ rli->unpacked_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;
}
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;
print_node_brief (stderr, "\noffset", rli->offset, 0);
print_node_brief (stderr, " bitpos", rli->bitpos, 0);
- fprintf (stderr, "\naligns: rec = %u, unpack = %u, unpad = %u, off = %u\n",
- rli->record_align, rli->unpacked_align, rli->unpadded_align,
+ fprintf (stderr, "\naligns: rec = %u, unpack = %u, off = %u\n",
+ rli->record_align, rli->unpacked_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;
+ bool is_bitfield;
- 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. */
+ layout_decl (field, known_align);
desired_align = DECL_ALIGN (field);
+ user_align = DECL_USER_ALIGN (field);
-#ifdef BIGGEST_FIELD_ALIGNMENT
- /* Some targets (i.e. i386) limit union 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);
-#endif
-
-#ifdef ADJUST_FIELD_ALIGN
- if (! DECL_USER_ALIGN (field))
- 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);
+ is_bitfield = (type != error_mark_node
+ && DECL_BIT_FIELD_TYPE (field)
+ && ! integer_zerop (TYPE_SIZE (type)));
+ /* Record must have at least as much alignment as any field.
+ Otherwise, the alignment of the field within the record is
+ meaningless. */
+ if (is_bitfield && (* targetm.ms_bitfield_layout_p) (rli->t))
+ {
+ /* 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));
+ }
+ }
#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))
+ else if (is_bitfield && PCC_BITFIELD_TYPE_MATTERS)
{
- unsigned int type_align = TYPE_ALIGN (TREE_TYPE (field));
+ /* 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 (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);
+
+ /* 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);
+
+ if (warn_packed)
+ rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+ user_align |= TYPE_USER_ALIGN (type);
+ }
}
#endif
+ else
+ {
+ rli->record_align = MAX (rli->record_align, desired_align);
+ rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+ }
+
+ 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. */
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);
& - 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)))
- {
- /* 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
- 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))
{
- if (known_align > TYPE_ALIGN (type))
+ if (known_align >= TYPE_ALIGN (type))
{
if (TYPE_ALIGN (type) > desired_align)
{
/* 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);
- user_align |= TYPE_USER_ALIGN (type);
+ TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
}
#endif
/* 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);
- user_align |= TYPE_USER_ALIGN (type);
+ TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
}
#endif
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.
+ record, this is the same as using alignment, but not equivalent
+ when packing.
- Note: for compatability, we use the type size, not the type alignment
+ 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)
|| (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. */
+ (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. */)
+ 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
if (DECL_BIT_FIELD_TYPE (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))) )
+ 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));
+ HOST_WIDE_INT bitsize = tree_low_cst (DECL_SIZE (field), 0);
if (rli->remaining_in_alignment < bitsize)
{
- /* out of bits; bump up to next 'word'. */
- rli->bitpos = size_binop (PLUS_EXPR,
- type_size,
- DECL_FIELD_BIT_OFFSET(rli->prev_field));
+ /* 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_INT_CST_LOW (type_size);
+ rli->remaining_in_alignment
+ = tree_low_cst (TYPE_SIZE (type), 0);
}
+
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
+ /* 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
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));
+ 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;
- }
+ /* 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. */
+ /* 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;
- }
+ 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.
+ 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
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)) ))
+ TYPE_SIZE (TREE_TYPE (prev_saved)))
+ : !integer_zerop (DECL_SIZE (field)) ))
{
- unsigned int type_align = 8; /* Never below 8 for compatability */
+ /* Never smaller than a byte for compatibility. */
+ unsigned int type_align = BITS_PER_UNIT;
- /* (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
- = 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_SIZE (field) != NULL
+ && host_integerp (TYPE_SIZE (TREE_TYPE (field)), 0)
+ && host_integerp (DECL_SIZE (field), 0))
+ rli->remaining_in_alignment
+ = tree_low_cst (TYPE_SIZE (TREE_TYPE(field)), 0)
+ - tree_low_cst (DECL_SIZE (field), 0);
+
+ /* Now align (conventionally) for the new type. */
if (!DECL_PACKED(field))
- type_align = MAX(TYPE_ALIGN (type), type_align);
+ type_align = MAX(TYPE_ALIGN (type), type_align);
if (prev_saved
&& DECL_BIT_FIELD_TYPE (prev_saved)
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. */
+ to undo that. */
rli->prev_field = NULL;
}
}
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. */
if (known_align != actual_align)
layout_decl (field, actual_align);
- /* Only the MS bitfields use this. */
+ /* Only the MS bitfields use this. */
if (rli->prev_field == NULL && DECL_BIT_FIELD_TYPE(field))
rli->prev_field = field;
rli->offset
= size_binop (PLUS_EXPR, rli->offset, DECL_SIZE_UNIT (field));
rli->bitpos = bitsize_zero_node;
- rli->offset_align = MIN (rli->offset_align, DECL_ALIGN (field));
+ rli->offset_align = MIN (rli->offset_align, desired_align);
}
else
{
/* 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)
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 */
-#ifdef ROUND_TYPE_SIZE
- TYPE_SIZE (rli->t) = ROUND_TYPE_SIZE (rli->t, unpadded_size,
- TYPE_ALIGN (rli->t));
- TYPE_SIZE_UNIT (rli->t)
- = ROUND_TYPE_SIZE_UNIT (rli->t, unpadded_size_unit,
- TYPE_ALIGN (rli->t) / BITS_PER_UNIT);
-#else
+ /* Round the size up to be a multiple of the required alignment */
TYPE_SIZE (rli->t) = round_up (unpadded_size, TYPE_ALIGN (rli->t));
TYPE_SIZE_UNIT (rli->t) = round_up (unpadded_size_unit,
TYPE_ALIGN (rli->t) / BITS_PER_UNIT);
-#endif
if (warn_padded && TREE_CONSTANT (unpadded_size)
&& simple_cst_equal (unpadded_size, TYPE_SIZE (rli->t)) == 0)
rli->unpacked_align = MAX (TYPE_ALIGN (rli->t), rli->unpacked_align);
#endif
-#ifdef ROUND_TYPE_SIZE
- unpacked_size = ROUND_TYPE_SIZE (rli->t, TYPE_SIZE (rli->t),
- rli->unpacked_align);
-#else
unpacked_size = round_up (TYPE_SIZE (rli->t), rli->unpacked_align);
-#endif
-
if (simple_cst_equal (unpacked_size, TYPE_SIZE (rli->t)))
{
TYPE_PACKED (rli->t) = 0;
if (bitpos / BITS_PER_WORD
!= ((tree_low_cst (DECL_SIZE (field), 1) + bitpos - 1)
/ BITS_PER_WORD)
- /* But there is no problem if the field is entire words. */
- && tree_low_cst (DECL_SIZE (field), 1) % BITS_PER_WORD != 0)
+ /* But there is no problem if the field is entire words
+ or bigger than a word. */
+ && ! (tree_low_cst (DECL_SIZE (field), 1) % BITS_PER_WORD == 0
+ || compare_tree_int (DECL_SIZE (field), BITS_PER_WORD) > 0))
return;
/* If this field is the whole struct, remember its mode so
if (TYPE_SIZE (type) != 0)
{
-#ifdef ROUND_TYPE_SIZE
- TYPE_SIZE (type)
- = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
- TYPE_SIZE_UNIT (type)
- = ROUND_TYPE_SIZE_UNIT (type, TYPE_SIZE_UNIT (type),
- TYPE_ALIGN (type) / BITS_PER_UNIT);
-#else
TYPE_SIZE (type) = round_up (TYPE_SIZE (type), TYPE_ALIGN (type));
TYPE_SIZE_UNIT (type)
= round_up (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type) / BITS_PER_UNIT);
-#endif
}
/* Evaluate nonconstant sizes only once, either now or as soon as safe. */
/* 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
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;
}
element_size = integer_one_node;
}
+ /* If neither bound is a constant and sizetype is signed, make
+ sure the size is never negative. We should really do this
+ if *either* bound is non-constant, but this is the best
+ compromise between C and Ada. */
+ if (! TREE_UNSIGNED (sizetype)
+ && TREE_CODE (TYPE_MIN_VALUE (index)) != INTEGER_CST
+ && TREE_CODE (TYPE_MAX_VALUE (index)) != INTEGER_CST)
+ length = size_binop (MAX_EXPR, length, size_zero_node);
+
TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size,
convert (bitsizetype, length));
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)
- {
- tree tmp
- = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
-
- /* If the rounding changed the size of the type, remove any
- pre-calculated TYPE_SIZE_UNIT. */
- if (simple_cst_equal (TYPE_SIZE (type), tmp) != 1)
- TYPE_SIZE_UNIT (type) = NULL;
-
- TYPE_SIZE (type) = tmp;
- }
-#endif
-
TYPE_MODE (type) = BLKmode;
if (TYPE_SIZE (type) != 0
#ifdef MEMBER_TYPE_FORCES_BLK
(*lang_adjust_rli) (rli);
/* Finish laying out the record. */
- finish_record_layout (rli);
+ finish_record_layout (rli, /*free_p=*/true);
}
break;
#endif
unsigned int alignment
= set_alignment ? set_alignment : SET_WORD_SIZE;
- int size_in_bits
- = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
- - TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) + 1);
- int rounded_size
+ HOST_WIDE_INT size_in_bits
+ = (tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
+ - tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0) + 1);
+ HOST_WIDE_INT rounded_size
= ((size_in_bits + alignment - 1) / alignment) * alignment;
if (rounded_size > (int) alignment)