/* 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 Free Software Foundation, Inc.
This file is part of GNU CC.
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));
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 non-zero 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;
+{
+ 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. */
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),
+ expand_expr (size, expand_expr (integer_zero_node, NULL_RTX, VOIDmode, 0),
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
- pending_sizes = tree_cons (NULL_TREE, size, pending_sizes);
+ put_pending_size (size);
return size;
}
case MODE_COMPLEX_INT:
case MODE_COMPLEX_FLOAT:
case MODE_FLOAT:
+ case MODE_VECTOR_INT:
+ case MODE_VECTOR_FLOAT:
mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
break;
user_align = DECL_USER_ALIGN (field);
}
-#ifdef BIGGEST_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. */
+#ifdef BIGGEST_FIELD_ALIGNMENT
if (! user_align)
- desired_align =
- MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
+ desired_align
+ = MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
#endif
+
#ifdef ADJUST_FIELD_ALIGN
desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
#endif
is printed in finish_struct. */
if (DECL_SIZE (field) == 0)
/* Do nothing. */;
- else if (! TREE_CONSTANT (DECL_SIZE_UNIT (field)))
+ else if (TREE_CODE (DECL_SIZE_UNIT (field)) != INTEGER_CST
+ || TREE_CONSTANT_OVERFLOW (DECL_SIZE_UNIT (field)))
{
rli->offset
= size_binop (PLUS_EXPR, rli->offset,
/* If this field is the whole struct, remember its mode so
that, say, we can put a double in a class into a DF
- register instead of forcing it to live in the stack. However,
- we don't support using such a mode if there is no integer mode
- of the same size, so don't set it here. */
- if (field == TYPE_FIELDS (type) && TREE_CHAIN (field) == 0
- && int_mode_for_mode (DECL_MODE (field)) != BLKmode
- && operand_equal_p (DECL_SIZE (field), TYPE_SIZE (type), 1))
+ register instead of forcing it to live in the stack. */
+ 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 (mode == VOIDmode && MEMBER_TYPE_FORCES_BLK (field))
return;
-#endif /* STRUCT_FORCE_BLK */
+#endif /* MEMBER_TYPE_FORCES_BLK */
}
- if (mode != VOIDmode)
- /* We only have one real field; use its mode. */
+ /* If we only have one real field; use its mode. This only applies to
+ RECORD_TYPE. This does not apply to unions. */
+ if (TREE_CODE (type) == RECORD_TYPE && mode != VOIDmode)
TYPE_MODE (type) = mode;
else
TYPE_MODE (type) = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
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;
+ {
+ 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;
+ TYPE_SIZE (type) = bitsize_int (nbits);
+ TYPE_SIZE_UNIT (type) = size_int (nbits / BITS_PER_UNIT);
+ TREE_UNSIGNED (type) = 1;
+ TYPE_PRECISION (type) = nbits;
+ }
break;
case ARRAY_TYPE:
TYPE_MODE (type) = BLKmode;
if (TYPE_SIZE (type) != 0
+#ifdef MEMBER_TYPE_FORCES_BLK
+ && ! MEMBER_TYPE_FORCES_BLK (type)
+#endif
/* BLKmode elements force BLKmode aggregate;
else extract/store fields may lose. */
&& (TYPE_MODE (TREE_TYPE (type)) != BLKmode
record it so set_sizetype can fix it up. */
if (! sizetype_set)
early_type_list = tree_cons (NULL_TREE, type, early_type_list);
+
+ /* If an alias set has been set for this aggregate when it was incomplete,
+ force it into alias set 0.
+ This is too conservative, but we cannot call record_component_aliases
+ here because some frontends still change the aggregates after
+ layout_type. */
+ if (AGGREGATE_TYPE_P (type) && TYPE_ALIAS_SET_KNOWN_P (type))
+ TYPE_ALIAS_SET (type) = 0;
}
\f
/* Create and return a type for signed integers of PRECISION bits. */