aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/utils.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2019-06-29 07:16:37 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2019-06-29 07:16:37 +0000
commitb1af4cb2903711183e62f922fc235d48c7a738bb (patch)
treee52fb1419869e176950e8aab90f65e8e32ade6ce /gcc/ada/gcc-interface/utils.c
parent43e1e8b5b8ed9f0e4311c0974b9e459471a275b0 (diff)
downloadgcc-b1af4cb2903711183e62f922fc235d48c7a738bb.zip
gcc-b1af4cb2903711183e62f922fc235d48c7a738bb.tar.gz
gcc-b1af4cb2903711183e62f922fc235d48c7a738bb.tar.bz2
expr.c (expand_expr_real_1): Apply the big-endian adjustment for bit-fields to all aggregate types.
* expr.c (expand_expr_real_1) <BIT_FIELD_REF>: Apply the big-endian adjustment for bit-fields to all aggregate types. ada/ * gcc-interface/gigi.h (make_packable_type): Remove default value. (value_factor_p): Tweak prototype. * gcc-interface/decl.c (gnat_to_gnu_entity): Add comment. (gnat_to_gnu_component_type): Likewise. (gnat_to_gnu_field): Likewise. Fetch the position of the field earlier and simplify the condition under which the type is packed. Declare local variable is_bitfield. Pass 1 as max_align to make_packable_type if it is set to true. (copy_and_substitute_in_layout): Pass 0 to make_packable_type. * gcc-interface/utils.c (make_packable_array_type): New function. (make_packable_type): Use it to rewrite the type of array field. (maybe_pad_type): Pass align parameter to make_packable_type. (create_field_decl): Minor tweaks. (value_factor_p): Assert that FACTOR is a power of 2 and replace the modulo computation by a masking operation. From-SVN: r272810
Diffstat (limited to 'gcc/ada/gcc-interface/utils.c')
-rw-r--r--gcc/ada/gcc-interface/utils.c85
1 files changed, 65 insertions, 20 deletions
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index f2cb773..c4842b2 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -984,10 +984,45 @@ make_aligning_type (tree type, unsigned int align, tree size,
return record_type;
}
+/* TYPE is an ARRAY_TYPE that is being used as the type of a field in a packed
+ record. See if we can rewrite it as a type that has non-BLKmode, which we
+ can pack tighter in the packed record. If so, return the new type; if not,
+ return the original type. */
+
+static tree
+make_packable_array_type (tree type)
+{
+ const unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type));
+ unsigned HOST_WIDE_INT new_size;
+ unsigned int new_align;
+
+ /* No point in doing anything if the size is either zero or too large for an
+ integral mode, or if the type already has non-BLKmode. */
+ if (size == 0 || size > MAX_FIXED_MODE_SIZE || TYPE_MODE (type) != BLKmode)
+ return type;
+
+ /* Punt if the component type is an aggregate type for now. */
+ if (AGGREGATE_TYPE_P (TREE_TYPE (type)))
+ return type;
+
+ tree new_type = copy_type (type);
+
+ new_size = ceil_pow2 (size);
+ new_align = MIN (new_size, BIGGEST_ALIGNMENT);
+ SET_TYPE_ALIGN (new_type, new_align);
+
+ TYPE_SIZE (new_type) = bitsize_int (new_size);
+ TYPE_SIZE_UNIT (new_type) = size_int (new_size / BITS_PER_UNIT);
+
+ SET_TYPE_MODE (new_type, mode_for_size (new_size, MODE_INT, 1).else_blk ());
+
+ return new_type;
+}
+
/* TYPE is a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE that is being used
- as the field type of a packed record if IN_RECORD is true, or as the
- component type of a packed array if IN_RECORD is false. See if we can
- rewrite it either as a type that has non-BLKmode, which we can pack
+ as the type of a field in a packed record if IN_RECORD is true, or as
+ the component type of a packed array if IN_RECORD is false. See if we
+ can rewrite it either as a type that has non-BLKmode, which we can pack
tighter in the packed record case, or as a smaller type with at most
MAX_ALIGN alignment if the value is non-zero. If so, return the new
type; if not, return the original type. */
@@ -995,9 +1030,9 @@ make_aligning_type (tree type, unsigned int align, tree size,
tree
make_packable_type (tree type, bool in_record, unsigned int max_align)
{
- unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type));
+ const unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type));
+ const unsigned int align = TYPE_ALIGN (type);
unsigned HOST_WIDE_INT new_size;
- unsigned int align = TYPE_ALIGN (type);
unsigned int new_align;
/* No point in doing anything if the size is zero. */
@@ -1058,10 +1093,19 @@ make_packable_type (tree type, bool in_record, unsigned int max_align)
tree new_field_type = TREE_TYPE (field);
tree new_field, new_field_size;
- if (RECORD_OR_UNION_TYPE_P (new_field_type)
- && !TYPE_FAT_POINTER_P (new_field_type)
+ if (AGGREGATE_TYPE_P (new_field_type)
&& tree_fits_uhwi_p (TYPE_SIZE (new_field_type)))
- new_field_type = make_packable_type (new_field_type, true, max_align);
+ {
+ if (RECORD_OR_UNION_TYPE_P (new_field_type)
+ && !TYPE_FAT_POINTER_P (new_field_type))
+ new_field_type
+ = make_packable_type (new_field_type, true, max_align);
+ else if (in_record
+ && max_align > 0
+ && max_align < BITS_PER_UNIT
+ && TREE_CODE (new_field_type) == ARRAY_TYPE)
+ new_field_type = make_packable_array_type (new_field_type);
+ }
/* However, for the last field in a not already packed record type
that is of an aggregate type, we need to use the RM size in the
@@ -1411,7 +1455,7 @@ maybe_pad_type (tree type, tree size, unsigned int align,
different modes, a VIEW_CONVERT_EXPR will be required for converting
between them and it might be hard to overcome afterwards, including
at the RTL level when the stand-alone object is accessed as a whole. */
- if (align != 0
+ if (align > 0
&& RECORD_OR_UNION_TYPE_P (type)
&& TYPE_MODE (type) == BLKmode
&& !TYPE_BY_REFERENCE_P (type)
@@ -1422,7 +1466,7 @@ maybe_pad_type (tree type, tree size, unsigned int align,
|| (TREE_CODE (size) == INTEGER_CST
&& compare_tree_int (size, MAX_FIXED_MODE_SIZE) <= 0)))
{
- tree packable_type = make_packable_type (type, true);
+ tree packable_type = make_packable_type (type, true, align);
if (TYPE_MODE (packable_type) != BLKmode
&& align >= TYPE_ALIGN (packable_type))
type = packable_type;
@@ -2790,10 +2834,9 @@ create_field_decl (tree name, tree type, tree record_type, tree size, tree pos,
size = round_up (size, BITS_PER_UNIT);
}
- /* If we may, according to ADDRESSABLE, make a bitfield when the size is
- specified for two reasons: first if the size differs from the natural
- size; second, if the alignment is insufficient. There are a number of
- ways the latter can be true.
+ /* If we may, according to ADDRESSABLE, then make a bitfield when the size
+ is specified for two reasons: first, when it differs from the natural
+ size; second, when the alignment is insufficient.
We never make a bitfield if the type of the field has a nonconstant size,
because no such entity requiring bitfield operations should reach here.
@@ -2809,17 +2852,17 @@ create_field_decl (tree name, tree type, tree record_type, tree size, tree pos,
&& size
&& TREE_CODE (size) == INTEGER_CST
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- && (!tree_int_cst_equal (size, TYPE_SIZE (type))
+ && (packed
+ || !tree_int_cst_equal (size, TYPE_SIZE (type))
|| (pos && !value_factor_p (pos, TYPE_ALIGN (type)))
- || packed
- || (TYPE_ALIGN (record_type) != 0
+ || (TYPE_ALIGN (record_type)
&& TYPE_ALIGN (record_type) < TYPE_ALIGN (type))))
{
DECL_BIT_FIELD (field_decl) = 1;
DECL_SIZE (field_decl) = size;
if (!packed && !pos)
{
- if (TYPE_ALIGN (record_type) != 0
+ if (TYPE_ALIGN (record_type)
&& TYPE_ALIGN (record_type) < TYPE_ALIGN (type))
SET_DECL_ALIGN (field_decl, TYPE_ALIGN (record_type));
else
@@ -3001,10 +3044,12 @@ process_attributes (tree *node, struct attrib **attr_list, bool in_place,
a power of 2. */
bool
-value_factor_p (tree value, HOST_WIDE_INT factor)
+value_factor_p (tree value, unsigned HOST_WIDE_INT factor)
{
+ gcc_checking_assert (pow2p_hwi (factor));
+
if (tree_fits_uhwi_p (value))
- return tree_to_uhwi (value) % factor == 0;
+ return (tree_to_uhwi (value) & (factor - 1)) == 0;
if (TREE_CODE (value) == MULT_EXPR)
return (value_factor_p (TREE_OPERAND (value, 0), factor)