diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-05-16 11:08:53 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-05-16 11:08:53 +0000 |
commit | 7214e56d097e2f6f8a554ada7f53af4ca28e2fa7 (patch) | |
tree | d15a8ba1c8aa9a9098735e4c0df5928335dae9d6 /gcc/ada/gcc-interface | |
parent | d156d6edc8c69c3202a07f18d58c7347197de8c0 (diff) | |
download | gcc-7214e56d097e2f6f8a554ada7f53af4ca28e2fa7.tar.gz |
* doc/gnat_rm/implementation_defined_attributes.rst
(Scalar_Storage_Order): Adjust restriction for packed array types.
* einfo.ads (Is_Bit_Packed_Array): Adjust description.
(Is_Packed): Likewise.
(Is_Packed_Array_Impl_Type): Likewise.
(Packed_Array_Impl_Type): Likewise.
* exp_ch4.adb (Expand_N_Indexed_Component): Do not do anything special
if the prefix is not a packed array implemented specially.
* exp_ch6.adb (Expand_Actuals): Expand indexed components only for
bit-packed array types.
* exp_pakd.adb (Install_PAT): Set Is_Packed_Array_Impl_Type flag on
the PAT before analyzing its declaration.
(Create_Packed_Array_Impl_Type): Remove redundant statements.
* freeze.adb (Check_Component_Storage_Order): Reject packed array
components only if they are bit packed.
(Freeze_Array_Type): Fix logic detecting bit packing and do not bit
pack for composite types whose size is multiple of a byte.
Create the implementation type for packed array types only when it is
needed, i.e. bit packing or packing because of holes in index types.
Make sure the Has_Non_Standard_Rep and Is_Packed flags agree.
* gcc-interface/gigi.h (make_packable_type): Add MAX_ALIGN parameter.
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Signed_Integer_Subtype>:
Call maybe_pad_type instead of building the padding type manually.
(gnat_to_gnu_entity) <E_Array_Subtype>: Do not assert that
Packed_Array_Impl_Type is present for packed arrays.
(gnat_to_gnu_component_type): Also handle known alignment for packed
types by passing it to make_packable_type.
* gcc-interface/utils.c (make_packable_type): Add MAX_ALIGN parameter
and deal with it in the array case. Adjust recursive call. Simplify
computation of new size and cap the alignment to BIGGEST_ALIGNMENT.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@236279 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/gcc-interface')
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 69 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/gigi.h | 8 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/utils.c | 71 |
3 files changed, 60 insertions, 88 deletions
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index f3d2b52671d..8f2be234f8a 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -1961,47 +1961,20 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) /* If the type we are dealing with has got a smaller alignment than the natural one, we need to wrap it up in a record type and misalign the - latter; we reuse the padding machinery for this purpose. Note that, - even if the record type is marked as packed because of misalignment, - we don't pack the field so as to give it the size of the type. */ + latter; we reuse the padding machinery for this purpose. */ else if (align > 0) { - tree gnu_field_type, gnu_field; - - /* Set the RM size before wrapping up the type. */ - SET_TYPE_RM_SIZE (gnu_type, - UI_To_gnu (RM_Size (gnat_entity), bitsizetype)); + tree gnu_size = UI_To_gnu (RM_Size (gnat_entity), bitsizetype); - /* Create a stripped-down declaration, mainly for debugging. */ - create_type_decl (gnu_entity_name, gnu_type, true, debug_info_p, - gnat_entity); + /* Set the RM size before wrapping the type. */ + SET_TYPE_RM_SIZE (gnu_type, gnu_size); - /* Now save it and build the enclosing record type. */ - gnu_field_type = gnu_type; + gnu_type + = maybe_pad_type (gnu_type, TYPE_SIZE (gnu_type), align, + gnat_entity, false, true, definition, false); - gnu_type = make_node (RECORD_TYPE); - TYPE_PADDING_P (gnu_type) = 1; - TYPE_NAME (gnu_type) = create_concat_name (gnat_entity, "PAD"); TYPE_PACKED (gnu_type) = 1; - TYPE_SIZE (gnu_type) = TYPE_SIZE (gnu_field_type); - TYPE_SIZE_UNIT (gnu_type) = TYPE_SIZE_UNIT (gnu_field_type); - SET_TYPE_ADA_SIZE (gnu_type, TYPE_RM_SIZE (gnu_field_type)); - SET_TYPE_ALIGN (gnu_type, align); - relate_alias_sets (gnu_type, gnu_field_type, ALIAS_SET_COPY); - - /* Don't declare the field as addressable since we won't be taking - its address and this would prevent create_field_decl from making - a bitfield. */ - gnu_field - = create_field_decl (get_identifier ("F"), gnu_field_type, - gnu_type, TYPE_SIZE (gnu_field_type), - bitsize_zero_node, 0, 0); - - finish_record_type (gnu_type, gnu_field, 2, false); - compute_record_mode (gnu_type); - - if (gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL) - SET_TYPE_DEBUG_TYPE (gnu_type, gnu_field_type); + SET_TYPE_ADA_SIZE (gnu_type, gnu_size); } break; @@ -2909,10 +2882,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) TREE_TYPE (TYPE_FIELDS (gnu_type)) = gnu_inner; } } - - else - /* Abort if packed array with no Packed_Array_Impl_Type. */ - gcc_assert (!Is_Packed (gnat_entity)); } break; @@ -5234,6 +5203,16 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition, const Entity_Id gnat_type = Component_Type (gnat_array); tree gnu_type = gnat_to_gnu_type (gnat_type); tree gnu_comp_size; + unsigned int max_align; + + /* If an alignment is specified, use it as a cap on the component type + so that it can be honored for the whole type. But ignore it for the + original type of packed array types. */ + if (No (Packed_Array_Impl_Type (gnat_array)) + && Known_Alignment (gnat_array)) + max_align = validate_alignment (Alignment (gnat_array), gnat_array, 0); + else + max_align = 0; /* Try to get a smaller form of the component if needed. */ if ((Is_Packed (gnat_array) || Has_Component_Size_Clause (gnat_array)) @@ -5243,7 +5222,7 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition, && RECORD_OR_UNION_TYPE_P (gnu_type) && !TYPE_FAT_POINTER_P (gnu_type) && tree_fits_uhwi_p (TYPE_SIZE (gnu_type))) - gnu_type = make_packable_type (gnu_type, false); + gnu_type = make_packable_type (gnu_type, false, max_align); if (Has_Atomic_Components (gnat_array)) check_ok_for_atomic_type (gnu_type, gnat_array, true); @@ -5276,16 +5255,6 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition, if (gnu_comp_size && !Is_Bit_Packed_Array (gnat_array)) { tree orig_type = gnu_type; - unsigned int max_align; - - /* If an alignment is specified, use it as a cap on the component type - so that it can be honored for the whole type. But ignore it for the - original type of packed array types. */ - if (No (Packed_Array_Impl_Type (gnat_array)) - && Known_Alignment (gnat_array)) - max_align = validate_alignment (Alignment (gnat_array), gnat_array, 0); - else - max_align = 0; gnu_type = make_type_from_size (gnu_type, gnu_comp_size, false); if (max_align > 0 && TYPE_ALIGN (gnu_type) > max_align) diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index 9cc744b24f2..099923d97fb 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -129,9 +129,11 @@ extern tree make_aligning_type (tree type, unsigned int align, tree size, 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 a non-BLKmode, which we can pack - tighter in the packed record case, or as a smaller type. If so, return - the new type. If not, return the original type. */ -extern tree make_packable_type (tree type, bool in_record); + 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. */ +extern tree make_packable_type (tree type, bool in_record, + unsigned int max_align = 0); /* Given a type TYPE, return a new type whose size is appropriate for SIZE. If TYPE is the best type, return it. Otherwise, make a new type. We diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 8c36149a18c..74940655c68 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -937,23 +937,24 @@ make_aligning_type (tree type, unsigned int align, tree size, /* 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 a non-BLKmode, which we can pack - tighter in the packed record case, or as a smaller type. If so, return - the new type. If not, return the original type. */ + 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. */ tree -make_packable_type (tree type, bool in_record) +make_packable_type (tree type, bool in_record, unsigned int max_align) { unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type)); unsigned HOST_WIDE_INT new_size; - tree new_type, old_field, field_list = NULL_TREE; - unsigned int align; + unsigned int align = TYPE_ALIGN (type); + unsigned int new_align; /* No point in doing anything if the size is zero. */ if (size == 0) return type; - new_type = make_node (TREE_CODE (type)); + tree new_type = make_node (TREE_CODE (type)); /* Copy the name and flags from the old type to that of the new. Note that we rely on the pointer equality created here for @@ -970,49 +971,50 @@ make_packable_type (tree type, bool in_record) type with BLKmode. */ if (in_record && size <= MAX_FIXED_MODE_SIZE) { - align = ceil_pow2 (size); - SET_TYPE_ALIGN (new_type, align); - new_size = (size + align - 1) & -align; + new_size = ceil_pow2 (size); + new_align = MIN (new_size, BIGGEST_ALIGNMENT); + SET_TYPE_ALIGN (new_type, new_align); } else { - unsigned HOST_WIDE_INT align; - /* Do not try to shrink the size if the RM size is not constant. */ if (TYPE_CONTAINS_TEMPLATE_P (type) || !tree_fits_uhwi_p (TYPE_ADA_SIZE (type))) return type; /* Round the RM size up to a unit boundary to get the minimal size - for a BLKmode record. Give up if it's already the size. */ + for a BLKmode record. Give up if it's already the size and we + don't need to lower the alignment. */ new_size = tree_to_uhwi (TYPE_ADA_SIZE (type)); new_size = (new_size + BITS_PER_UNIT - 1) & -BITS_PER_UNIT; - if (new_size == size) + if (new_size == size && (max_align == 0 || align <= max_align)) return type; - align = new_size & -new_size; - SET_TYPE_ALIGN (new_type, MIN (TYPE_ALIGN (type), align)); + new_align = MIN (new_size & -new_size, BIGGEST_ALIGNMENT); + if (max_align > 0 && new_align > max_align) + new_align = max_align; + SET_TYPE_ALIGN (new_type, MIN (align, new_align)); } TYPE_USER_ALIGN (new_type) = 1; /* Now copy the fields, keeping the position and size as we don't want to change the layout by propagating the packedness downwards. */ - for (old_field = TYPE_FIELDS (type); old_field; - old_field = DECL_CHAIN (old_field)) + tree new_field_list = NULL_TREE; + for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) { - tree new_field_type = TREE_TYPE (old_field); + tree new_field_type = TREE_TYPE (field); tree new_field, new_size; if (RECORD_OR_UNION_TYPE_P (new_field_type) && !TYPE_FAT_POINTER_P (new_field_type) && tree_fits_uhwi_p (TYPE_SIZE (new_field_type))) - new_field_type = make_packable_type (new_field_type, true); + new_field_type = make_packable_type (new_field_type, true, max_align); /* 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 packable version of the record type, see finish_record_type. */ - if (!DECL_CHAIN (old_field) + if (!DECL_CHAIN (field) && !TYPE_PACKED (type) && RECORD_OR_UNION_TYPE_P (new_field_type) && !TYPE_FAT_POINTER_P (new_field_type) @@ -1020,24 +1022,24 @@ make_packable_type (tree type, bool in_record) && TYPE_ADA_SIZE (new_field_type)) new_size = TYPE_ADA_SIZE (new_field_type); else - new_size = DECL_SIZE (old_field); + new_size = DECL_SIZE (field); new_field - = create_field_decl (DECL_NAME (old_field), new_field_type, new_type, - new_size, bit_position (old_field), + = create_field_decl (DECL_NAME (field), new_field_type, new_type, + new_size, bit_position (field), TYPE_PACKED (type), - !DECL_NONADDRESSABLE_P (old_field)); + !DECL_NONADDRESSABLE_P (field)); - DECL_INTERNAL_P (new_field) = DECL_INTERNAL_P (old_field); - SET_DECL_ORIGINAL_FIELD_TO_FIELD (new_field, old_field); + DECL_INTERNAL_P (new_field) = DECL_INTERNAL_P (field); + SET_DECL_ORIGINAL_FIELD_TO_FIELD (new_field, field); if (TREE_CODE (new_type) == QUAL_UNION_TYPE) - DECL_QUALIFIER (new_field) = DECL_QUALIFIER (old_field); + DECL_QUALIFIER (new_field) = DECL_QUALIFIER (field); - DECL_CHAIN (new_field) = field_list; - field_list = new_field; + DECL_CHAIN (new_field) = new_field_list; + new_field_list = new_field; } - finish_record_type (new_type, nreverse (field_list), 2, false); + finish_record_type (new_type, nreverse (new_field_list), 2, false); relate_alias_sets (new_type, type, ALIAS_SET_COPY); if (TYPE_STUB_DECL (type)) SET_DECL_PARALLEL_TYPE (TYPE_STUB_DECL (new_type), @@ -1054,8 +1056,7 @@ make_packable_type (tree type, bool in_record) else { TYPE_SIZE (new_type) = bitsize_int (new_size); - TYPE_SIZE_UNIT (new_type) - = size_int ((new_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT); + TYPE_SIZE_UNIT (new_type) = size_int (new_size / BITS_PER_UNIT); } if (!TYPE_CONTAINS_TEMPLATE_P (type)) @@ -1069,8 +1070,8 @@ make_packable_type (tree type, bool in_record) SET_TYPE_MODE (new_type, mode_for_size_tree (TYPE_SIZE (new_type), MODE_INT, 1)); - /* If neither the mode nor the size has shrunk, return the old type. */ - if (TYPE_MODE (new_type) == BLKmode && new_size >= size) + /* If neither mode nor size nor alignment shrunk, return the old type. */ + if (TYPE_MODE (new_type) == BLKmode && new_size >= size && max_align == 0) return type; return new_type; |