diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2019-06-29 07:16:37 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2019-06-29 07:16:37 +0000 |
commit | b1af4cb2903711183e62f922fc235d48c7a738bb (patch) | |
tree | e52fb1419869e176950e8aab90f65e8e32ade6ce /gcc/ada/gcc-interface/utils.c | |
parent | 43e1e8b5b8ed9f0e4311c0974b9e459471a275b0 (diff) | |
download | gcc-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.c | 85 |
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) |