/* C-compiler utilities for types and variables storage layout
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
+#include "fold-const.h"
#include "stor-layout.h"
#include "stringpool.h"
#include "varasm.h"
#include "rtl.h"
#include "tm_p.h"
#include "flags.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "machmode.h"
#include "hard-reg-set.h"
-#include "input.h"
#include "function.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "stmt.h"
#include "expr.h"
#include "diagnostic-core.h"
#include "target.h"
#include "langhooks.h"
#include "regs.h"
#include "params.h"
-#include "hash-map.h"
-#include "is-a.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
#include "cgraph.h"
#include "tree-inline.h"
#include "tree-dump.h"
static void finalize_record_size (record_layout_info);
static void finalize_type_size (tree);
static void place_union_field (record_layout_info, tree);
-#if defined (PCC_BITFIELD_TYPE_MATTERS) || defined (BITFIELD_NBYTES_LIMITED)
static int excess_unit_span (HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
-#endif
extern void debug_rli (record_layout_info);
\f
/* Show that REFERENCE_TYPES are internal and should use address_mode.
/* An array of functions used for self-referential size computation. */
static GTY(()) vec<tree, va_gc> *size_functions;
+/* Return true if T is a self-referential component reference. */
+
+static bool
+self_referential_component_ref_p (tree t)
+{
+ if (TREE_CODE (t) != COMPONENT_REF)
+ return false;
+
+ while (REFERENCE_CLASS_P (t))
+ t = TREE_OPERAND (t, 0);
+
+ return (TREE_CODE (t) == PLACEHOLDER_EXPR);
+}
+
/* Similar to copy_tree_r but do not copy component references involving
PLACEHOLDER_EXPRs. These nodes are spotted in find_placeholder_in_expr
and substituted in substitute_in_expr. */
}
/* Default case: the component reference. */
- else if (code == COMPONENT_REF)
+ else if (self_referential_component_ref_p (*tp))
{
- tree inner;
- for (inner = TREE_OPERAND (*tp, 0);
- REFERENCE_CLASS_P (inner);
- inner = TREE_OPERAND (inner, 0))
- ;
-
- if (TREE_CODE (inner) == PLACEHOLDER_EXPR)
- {
- *walk_subtrees = 0;
- return NULL_TREE;
- }
+ *walk_subtrees = 0;
+ return NULL_TREE;
}
/* We're not supposed to have them in self-referential size trees
/* Do not factor out simple operations. */
t = skip_simple_constant_arithmetic (size);
- if (TREE_CODE (t) == CALL_EXPR)
+ if (TREE_CODE (t) == CALL_EXPR || self_referential_component_ref_p (t))
return size;
/* Collect the list of self-references in the expression. */
fntype = build_function_type (return_type, param_type_list);
/* Build the function declaration. */
- sprintf (buf, "SZ"HOST_WIDE_INT_PRINT_UNSIGNED, fnno++);
+ sprintf (buf, "SZ" HOST_WIDE_INT_PRINT_UNSIGNED, fnno++);
fnname = get_file_function_name (buf);
fndecl = build_decl (input_location, FUNCTION_DECL, fnname, fntype);
for (t = param_decl_list; t; t = DECL_CHAIN (t))
set_cfun (NULL);
dump_function (TDI_original, fndecl);
gimplify_function_tree (fndecl);
- dump_function (TDI_generic, fndecl);
cgraph_node::finalize_function (fndecl, false);
}
{
zero_bitfield = true;
packed_p = false;
-#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))
rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
}
}
-#ifdef PCC_BITFIELD_TYPE_MATTERS
else if (is_bitfield && PCC_BITFIELD_TYPE_MATTERS)
{
/* Named bit-fields cause the entire structure to have the
user_align |= TYPE_USER_ALIGN (type);
}
}
-#endif
else
{
rli->record_align = MAX (rli->record_align, desired_align);
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. */
return ((offset + size + align - 1) / align
> tree_to_uhwi (TYPE_SIZE (type)) / 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
/* Handle compatibility with PCC. Note that if the record has any
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
if (! DECL_PACKED (field))
TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
}
-#endif
#ifdef BITFIELD_NBYTES_LIMITED
if (BITFIELD_NBYTES_LIMITED
unpadded_size_unit
= size_binop (PLUS_EXPR, unpadded_size_unit, size_one_node);
- if (TREE_CODE (unpadded_size_unit) == INTEGER_CST
- && !TREE_OVERFLOW (unpadded_size_unit)
- && !valid_constant_size_p (unpadded_size_unit))
- error ("type %qT is too large", rli->t);
-
/* 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)
However, where strict alignment is not required, avoid
over-aligning structures, since most compilers do not do this
alignment. */
-
- if (TYPE_MODE (type) != BLKmode && TYPE_MODE (type) != VOIDmode
- && (STRICT_ALIGNMENT
- || (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE
- && TREE_CODE (type) != QUAL_UNION_TYPE
- && TREE_CODE (type) != ARRAY_TYPE)))
+ if (TYPE_MODE (type) != BLKmode
+ && TYPE_MODE (type) != VOIDmode
+ && (STRICT_ALIGNMENT || !AGGREGATE_TYPE_P (type)))
{
unsigned mode_align = GET_MODE_ALIGNMENT (TYPE_MODE (type));
{
TYPE_SIZE (variant) = size;
TYPE_SIZE_UNIT (variant) = size_unit;
- TYPE_ALIGN (variant) = align;
+ unsigned valign = align;
+ if (TYPE_USER_ALIGN (variant))
+ valign = MAX (valign, TYPE_ALIGN (variant));
+ else
+ TYPE_USER_ALIGN (variant) = user_align;
+ TYPE_ALIGN (variant) = valign;
TYPE_PRECISION (variant) = precision;
- TYPE_USER_ALIGN (variant) = user_align;
SET_TYPE_MODE (variant, mode);
}
}
if (type == error_mark_node)
return;
+ /* We don't want finalize_type_size to copy an alignment attribute to
+ variants that don't have it. */
+ type = TYPE_MAIN_VARIANT (type);
+
/* Do nothing if type has been laid out before. */
if (TYPE_SIZE (type))
return;
/* Now round the alignment and size,
using machine-dependent criteria if any. */
+ unsigned align = TYPE_ALIGN (element);
+ if (TYPE_USER_ALIGN (type))
+ align = MAX (align, TYPE_ALIGN (type));
+ else
+ TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element);
#ifdef ROUND_TYPE_ALIGN
- TYPE_ALIGN (type)
- = ROUND_TYPE_ALIGN (type, TYPE_ALIGN (element), BITS_PER_UNIT);
+ align = ROUND_TYPE_ALIGN (type, align, BITS_PER_UNIT);
#else
- TYPE_ALIGN (type) = MAX (TYPE_ALIGN (element), BITS_PER_UNIT);
+ align = MAX (align, BITS_PER_UNIT);
#endif
- TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element);
+ TYPE_ALIGN (type) = align;
SET_TYPE_MODE (type, BLKmode);
if (TYPE_SIZE (type) != 0
&& ! targetm.member_type_forces_blk (type, VOIDmode)
/* 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
- && TREE_CODE (type) != UNION_TYPE
- && TREE_CODE (type) != QUAL_UNION_TYPE)
+ if (!RECORD_OR_UNION_TYPE_P (type))
finalize_type_size (type);
/* We should never see alias sets on incomplete aggregates. And we
min_align_of_type (tree type)
{
unsigned int align = TYPE_ALIGN (type);
- align = MIN (align, BIGGEST_ALIGNMENT);
if (!TYPE_USER_ALIGN (type))
{
+ align = MIN (align, BIGGEST_ALIGNMENT);
#ifdef BIGGEST_FIELD_ALIGNMENT
align = MIN (align, BIGGEST_FIELD_ALIGNMENT);
#endif