summaryrefslogtreecommitdiff
path: root/gcc/stor-layout.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/stor-layout.c')
-rw-r--r--gcc/stor-layout.c140
1 files changed, 77 insertions, 63 deletions
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index dd40ca00af..10e9a32494 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -1,5 +1,5 @@
/* C-compiler utilities for types and variables storage layout
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
+ Copyright (C) 1987-2017 Free Software Foundation, Inc.
This file is part of GCC.
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see
#include "function.h"
#include "rtl.h"
#include "tree.h"
+#include "memmodel.h"
#include "tm_p.h"
#include "stringpool.h"
#include "regs.h"
@@ -398,7 +399,7 @@ int_mode_for_mode (machine_mode mode)
if (mode == BLKmode)
break;
- /* ... fall through ... */
+ /* fall through */
case MODE_CC:
default:
@@ -565,7 +566,7 @@ do_type_align (tree type, tree decl)
{
if (TYPE_ALIGN (type) > DECL_ALIGN (decl))
{
- DECL_ALIGN (decl) = TYPE_ALIGN (type);
+ SET_DECL_ALIGN (decl, TYPE_ALIGN (type));
if (TREE_CODE (decl) == FIELD_DECL)
DECL_USER_ALIGN (decl) = TYPE_USER_ALIGN (type);
}
@@ -596,7 +597,7 @@ layout_decl (tree decl, unsigned int known_align)
return;
gcc_assert (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL
- || code == TYPE_DECL ||code == FIELD_DECL);
+ || code == TYPE_DECL || code == FIELD_DECL);
rtl = DECL_RTL_IF_SET (decl);
@@ -615,7 +616,7 @@ layout_decl (tree decl, unsigned int known_align)
DECL_UNSIGNED (decl) = TYPE_UNSIGNED (type);
if (DECL_MODE (decl) == VOIDmode)
- DECL_MODE (decl) = TYPE_MODE (type);
+ SET_DECL_MODE (decl, TYPE_MODE (type));
if (DECL_SIZE (decl) == 0)
{
@@ -658,7 +659,7 @@ layout_decl (tree decl, unsigned int known_align)
#ifdef EMPTY_FIELD_BOUNDARY
if (EMPTY_FIELD_BOUNDARY > DECL_ALIGN (decl))
{
- DECL_ALIGN (decl) = EMPTY_FIELD_BOUNDARY;
+ SET_DECL_ALIGN (decl, EMPTY_FIELD_BOUNDARY);
DECL_USER_ALIGN (decl) = 0;
}
#endif
@@ -680,8 +681,8 @@ layout_decl (tree decl, unsigned int known_align)
&& !(xalign > BITS_PER_UNIT && DECL_PACKED (decl))
&& (known_align == 0 || known_align >= xalign))
{
- DECL_ALIGN (decl) = MAX (xalign, DECL_ALIGN (decl));
- DECL_MODE (decl) = xmode;
+ SET_DECL_ALIGN (decl, MAX (xalign, DECL_ALIGN (decl)));
+ SET_DECL_MODE (decl, xmode);
DECL_BIT_FIELD (decl) = 0;
}
}
@@ -705,7 +706,7 @@ layout_decl (tree decl, unsigned int known_align)
DECL_USER_ALIGN, so we need to check old_user_align instead. */
if (packed_p
&& !old_user_align)
- DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
+ SET_DECL_ALIGN (decl, MIN (DECL_ALIGN (decl), BITS_PER_UNIT));
if (! packed_p && ! DECL_USER_ALIGN (decl))
{
@@ -713,11 +714,12 @@ layout_decl (tree decl, unsigned int known_align)
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);
+ SET_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));
+ SET_DECL_ALIGN (decl, ADJUST_FIELD_ALIGN (decl, TREE_TYPE (decl),
+ DECL_ALIGN (decl)));
#endif
}
@@ -727,7 +729,7 @@ layout_decl (tree decl, unsigned int known_align)
mfa = maximum_field_alignment;
/* Should this be controlled by DECL_USER_ALIGN, too? */
if (mfa != 0)
- DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), mfa);
+ SET_DECL_ALIGN (decl, MIN (DECL_ALIGN (decl), mfa));
}
/* Evaluate nonconstant size only once, either now or as soon as safe. */
@@ -768,17 +770,18 @@ layout_decl (tree decl, unsigned int known_align)
}
}
-/* Given a VAR_DECL, PARM_DECL or RESULT_DECL, clears the results of
- a previous call to layout_decl and calls it again. */
+/* Given a VAR_DECL, PARM_DECL, RESULT_DECL, or FIELD_DECL, clears the
+ results of a previous call to layout_decl and calls it again. */
void
relayout_decl (tree decl)
{
DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = 0;
- DECL_MODE (decl) = VOIDmode;
+ SET_DECL_MODE (decl, VOIDmode);
if (!DECL_USER_ALIGN (decl))
- DECL_ALIGN (decl) = 0;
- SET_DECL_RTL (decl, 0);
+ SET_DECL_ALIGN (decl, 0);
+ if (DECL_RTL_SET_P (decl))
+ SET_DECL_RTL (decl, 0);
layout_decl (decl, 0);
}
@@ -1030,7 +1033,7 @@ update_alignment_for_field (record_layout_info rli, tree field,
#ifdef ADJUST_FIELD_ALIGN
if (! TYPE_USER_ALIGN (type))
- type_align = ADJUST_FIELD_ALIGN (field, type_align);
+ type_align = ADJUST_FIELD_ALIGN (field, type, type_align);
#endif
/* Targets might chose to handle unnamed and hence possibly
@@ -1088,6 +1091,10 @@ place_union_field (record_layout_info rli, tree field)
if (TREE_CODE (TREE_TYPE (field)) == ERROR_MARK)
return;
+ if (AGGREGATE_TYPE_P (TREE_TYPE (field))
+ && TYPE_TYPELESS_STORAGE (TREE_TYPE (field)))
+ TYPE_TYPELESS_STORAGE (rli->t) = 1;
+
/* 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)
@@ -1136,7 +1143,7 @@ place_field (record_layout_info rli, tree field)
really like a structure field. If it is a FUNCTION_DECL, it's a
method. In both cases, all we do is lay out the decl, and we do
it *after* the record is laid out. */
- if (TREE_CODE (field) == VAR_DECL)
+ if (VAR_P (field))
{
vec_safe_push (rli->pending_statics, field);
return;
@@ -1165,17 +1172,19 @@ place_field (record_layout_info rli, tree field)
return;
}
+ if (AGGREGATE_TYPE_P (type)
+ && TYPE_TYPELESS_STORAGE (type))
+ TYPE_TYPELESS_STORAGE (rli->t) = 1;
+
/* Work out the known alignment so far. Note that A & (-A) is the
value of the least-significant bit in A that is one. */
if (! integer_zerop (rli->bitpos))
- known_align = (tree_to_uhwi (rli->bitpos)
- & - tree_to_uhwi (rli->bitpos));
+ known_align = least_bit_hwi (tree_to_uhwi (rli->bitpos));
else if (integer_zerop (rli->offset))
known_align = 0;
else if (tree_fits_uhwi_p (rli->offset))
known_align = (BITS_PER_UNIT
- * (tree_to_uhwi (rli->offset)
- & - tree_to_uhwi (rli->offset)));
+ * least_bit_hwi (tree_to_uhwi (rli->offset)));
else
known_align = rli->offset_align;
@@ -1260,7 +1269,7 @@ place_field (record_layout_info rli, tree field)
#ifdef ADJUST_FIELD_ALIGN
if (! TYPE_USER_ALIGN (type))
- type_align = ADJUST_FIELD_ALIGN (field, type_align);
+ type_align = ADJUST_FIELD_ALIGN (field, type, type_align);
#endif
/* A bit field may not span more units of alignment of its type
@@ -1303,7 +1312,7 @@ place_field (record_layout_info rli, tree field)
#ifdef ADJUST_FIELD_ALIGN
if (! TYPE_USER_ALIGN (type))
- type_align = ADJUST_FIELD_ALIGN (field, type_align);
+ type_align = ADJUST_FIELD_ALIGN (field, type, type_align);
#endif
if (maximum_field_alignment != 0)
@@ -1478,14 +1487,12 @@ place_field (record_layout_info rli, tree field)
approximate this by seeing if its position changed), lay out the field
again; perhaps we can use an integral mode for it now. */
if (! integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
- actual_align = (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
- & - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)));
+ actual_align = least_bit_hwi (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)));
else if (integer_zerop (DECL_FIELD_OFFSET (field)))
actual_align = MAX (BIGGEST_ALIGNMENT, rli->record_align);
else if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field)))
actual_align = (BITS_PER_UNIT
- * (tree_to_uhwi (DECL_FIELD_OFFSET (field))
- & - tree_to_uhwi (DECL_FIELD_OFFSET (field))));
+ * least_bit_hwi (tree_to_uhwi (DECL_FIELD_OFFSET (field))));
else
actual_align = DECL_OFFSET_ALIGN (field);
/* ACTUAL_ALIGN is still the actual alignment *within the record* .
@@ -1558,10 +1565,10 @@ finalize_record_size (record_layout_info rli)
/* Determine the desired alignment. */
#ifdef ROUND_TYPE_ALIGN
- TYPE_ALIGN (rli->t) = ROUND_TYPE_ALIGN (rli->t, TYPE_ALIGN (rli->t),
- rli->record_align);
+ SET_TYPE_ALIGN (rli->t, ROUND_TYPE_ALIGN (rli->t, TYPE_ALIGN (rli->t),
+ rli->record_align));
#else
- TYPE_ALIGN (rli->t) = MAX (TYPE_ALIGN (rli->t), rli->record_align);
+ SET_TYPE_ALIGN (rli->t, MAX (TYPE_ALIGN (rli->t), rli->record_align));
#endif
/* Compute the size so far. Be sure to allow for extra bits in the
@@ -1718,15 +1725,15 @@ finalize_type_size (tree type)
alignment of one of the fields. */
if (mode_align >= TYPE_ALIGN (type))
{
- TYPE_ALIGN (type) = mode_align;
+ SET_TYPE_ALIGN (type, mode_align);
TYPE_USER_ALIGN (type) = 0;
}
}
/* Do machine-dependent extra alignment. */
#ifdef ROUND_TYPE_ALIGN
- TYPE_ALIGN (type)
- = ROUND_TYPE_ALIGN (type, TYPE_ALIGN (type), BITS_PER_UNIT);
+ SET_TYPE_ALIGN (type,
+ ROUND_TYPE_ALIGN (type, TYPE_ALIGN (type), BITS_PER_UNIT));
#endif
/* If we failed to find a simple way to calculate the unit size
@@ -1779,7 +1786,7 @@ finalize_type_size (tree type)
valign = MAX (valign, TYPE_ALIGN (variant));
else
TYPE_USER_ALIGN (variant) = user_align;
- TYPE_ALIGN (variant) = valign;
+ SET_TYPE_ALIGN (variant, valign);
TYPE_PRECISION (variant) = precision;
SET_TYPE_MODE (variant, mode);
}
@@ -1808,6 +1815,11 @@ start_bitfield_representative (tree field)
DECL_SIZE_UNIT (repr) = DECL_SIZE_UNIT (field);
DECL_PACKED (repr) = DECL_PACKED (field);
DECL_CONTEXT (repr) = DECL_CONTEXT (field);
+ /* There are no indirect accesses to this field. If we introduce
+ some then they have to use the record alias set. This makes
+ sure to properly conflict with [indirect] accesses to addressable
+ fields of the bitfield group. */
+ DECL_NONADDRESSABLE_P (repr) = 1;
return repr;
}
@@ -1861,13 +1873,14 @@ finish_bitfield_representative (tree repr, tree field)
}
else
{
- /* ??? If you consider that tail-padding of this struct might be
- re-used when deriving from it we cannot really do the following
- and thus need to set maxsize to bitsize? Also we cannot
- generally rely on maxsize to fold to an integer constant, so
- use bitsize as fallback for this case. */
- tree maxsize = size_diffop (TYPE_SIZE_UNIT (DECL_CONTEXT (field)),
- DECL_FIELD_OFFSET (repr));
+ /* Note that if the C++ FE sets up tail-padding to be re-used it
+ creates a as-base variant of the type with TYPE_SIZE adjusted
+ accordingly. So it is safe to include tail-padding here. */
+ tree aggsize = lang_hooks.types.unit_size_without_reusable_padding
+ (DECL_CONTEXT (field));
+ tree maxsize = size_diffop (aggsize, DECL_FIELD_OFFSET (repr));
+ /* We cannot generally rely on maxsize to fold to an integer constant,
+ so use bitsize as fallback for this case. */
if (tree_fits_uhwi_p (maxsize))
maxbitsize = (tree_to_uhwi (maxsize) * BITS_PER_UNIT
- tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
@@ -1903,7 +1916,7 @@ finish_bitfield_representative (tree repr, tree field)
[0, 15] HImode for a and b, [8, 23] HImode for c. */
DECL_SIZE (repr) = bitsize_int (bitsize);
DECL_SIZE_UNIT (repr) = size_int (bitsize / BITS_PER_UNIT);
- DECL_MODE (repr) = BLKmode;
+ SET_DECL_MODE (repr, BLKmode);
TREE_TYPE (repr) = build_array_type_nelts (unsigned_char_type_node,
bitsize / BITS_PER_UNIT);
}
@@ -1912,7 +1925,7 @@ finish_bitfield_representative (tree repr, tree field)
unsigned HOST_WIDE_INT modesize = GET_MODE_BITSIZE (mode);
DECL_SIZE (repr) = bitsize_int (modesize);
DECL_SIZE_UNIT (repr) = size_int (modesize / BITS_PER_UNIT);
- DECL_MODE (repr) = mode;
+ SET_DECL_MODE (repr, mode);
TREE_TYPE (repr) = lang_hooks.types.type_for_mode (mode, 1);
}
@@ -2073,7 +2086,7 @@ finish_builtin_struct (tree type, const char *name, tree fields,
if (align_type)
{
- TYPE_ALIGN (type) = TYPE_ALIGN (align_type);
+ SET_TYPE_ALIGN (type, TYPE_ALIGN (align_type));
TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (align_type);
}
@@ -2132,8 +2145,11 @@ layout_type (tree type)
break;
case REAL_TYPE:
- SET_TYPE_MODE (type,
- mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0));
+ /* Allow the caller to choose the type mode, which is how decimal
+ floats are distinguished from binary ones. */
+ if (TYPE_MODE (type) == VOIDmode)
+ SET_TYPE_MODE (type,
+ mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0));
TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
break;
@@ -2184,7 +2200,7 @@ layout_type (tree type)
Instead, query a target hook, defaulting to natural alignment.
This prevents ABI changes depending on whether or not native
vector modes are supported. */
- TYPE_ALIGN (type) = targetm.vector_alignment (type);
+ SET_TYPE_ALIGN (type, targetm.vector_alignment (type));
/* However, if the underlying mode requires a bigger alignment than
what the target hook provides, we cannot use the mode. For now,
@@ -2196,7 +2212,7 @@ layout_type (tree type)
case VOID_TYPE:
/* This is an incomplete type and so doesn't have a size. */
- TYPE_ALIGN (type) = 1;
+ SET_TYPE_ALIGN (type, 1);
TYPE_USER_ALIGN (type) = 0;
SET_TYPE_MODE (type, VOIDmode);
break;
@@ -2241,8 +2257,6 @@ layout_type (tree type)
tree index = TYPE_DOMAIN (type);
tree element = TREE_TYPE (type);
- build_pointer_type (element);
-
/* We need to know both bounds in order to compute the size. */
if (index && TYPE_MAX_VALUE (index) && TYPE_MIN_VALUE (index)
&& TYPE_SIZE (element))
@@ -2315,7 +2329,7 @@ layout_type (tree type)
#else
align = MAX (align, BITS_PER_UNIT);
#endif
- TYPE_ALIGN (type) = align;
+ SET_TYPE_ALIGN (type, align);
SET_TYPE_MODE (type, BLKmode);
if (TYPE_SIZE (type) != 0
&& ! targetm.member_type_forces_blk (type, VOIDmode)
@@ -2334,6 +2348,8 @@ layout_type (tree type)
SET_TYPE_MODE (type, BLKmode);
}
}
+ if (AGGREGATE_TYPE_P (element))
+ TYPE_TYPELESS_STORAGE (type) = TYPE_TYPELESS_STORAGE (element);
/* When the element size is constant, check that it is at least as
large as the element alignment. */
if (TYPE_SIZE_UNIT (element)
@@ -2406,9 +2422,7 @@ min_align_of_type (tree type)
#endif
unsigned int field_align = align;
#ifdef ADJUST_FIELD_ALIGN
- tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, type);
- field_align = ADJUST_FIELD_ALIGN (field, field_align);
- ggc_free (field);
+ field_align = ADJUST_FIELD_ALIGN (NULL_TREE, type, field_align);
#endif
align = MIN (align, field_align);
}
@@ -2569,7 +2583,7 @@ initialize_sizetypes (void)
}
bprecision
- = MIN (precision + BITS_PER_UNIT_LOG + 1, MAX_FIXED_MODE_SIZE);
+ = MIN (precision + LOG2_BITS_PER_UNIT + 1, MAX_FIXED_MODE_SIZE);
bprecision
= GET_MODE_PRECISION (smallest_mode_for_size (bprecision, MODE_INT));
if (bprecision > HOST_BITS_PER_DOUBLE_INT)
@@ -2587,13 +2601,13 @@ initialize_sizetypes (void)
/* Now layout both types manually. */
SET_TYPE_MODE (sizetype, smallest_mode_for_size (precision, MODE_INT));
- TYPE_ALIGN (sizetype) = GET_MODE_ALIGNMENT (TYPE_MODE (sizetype));
+ SET_TYPE_ALIGN (sizetype, GET_MODE_ALIGNMENT (TYPE_MODE (sizetype)));
TYPE_SIZE (sizetype) = bitsize_int (precision);
TYPE_SIZE_UNIT (sizetype) = size_int (GET_MODE_SIZE (TYPE_MODE (sizetype)));
set_min_and_max_values_for_integral_type (sizetype, precision, UNSIGNED);
SET_TYPE_MODE (bitsizetype, smallest_mode_for_size (bprecision, MODE_INT));
- TYPE_ALIGN (bitsizetype) = GET_MODE_ALIGNMENT (TYPE_MODE (bitsizetype));
+ SET_TYPE_ALIGN (bitsizetype, GET_MODE_ALIGNMENT (TYPE_MODE (bitsizetype)));
TYPE_SIZE (bitsizetype) = bitsize_int (bprecision);
TYPE_SIZE_UNIT (bitsizetype)
= size_int (GET_MODE_SIZE (TYPE_MODE (bitsizetype)));
@@ -2896,13 +2910,13 @@ get_mode_bounds (machine_mode mode, int sign,
}
else if (sign)
{
- min_val = -((unsigned HOST_WIDE_INT) 1 << (size - 1));
- max_val = ((unsigned HOST_WIDE_INT) 1 << (size - 1)) - 1;
+ min_val = -(HOST_WIDE_INT_1U << (size - 1));
+ max_val = (HOST_WIDE_INT_1U << (size - 1)) - 1;
}
else
{
min_val = 0;
- max_val = ((unsigned HOST_WIDE_INT) 1 << (size - 1) << 1) - 1;
+ max_val = (HOST_WIDE_INT_1U << (size - 1) << 1) - 1;
}
*mmin = gen_int_mode (min_val, target_mode);