https://gcc.gnu.org/g:72c6938f29cbeddb3220720e68add4cf09ffd794
commit r15-3472-g72c6938f29cbeddb3220720e68add4cf09ffd794 Author: Eric Botcazou <ebotca...@adacore.com> Date: Sun Aug 25 15:20:59 2024 +0200 ada: Streamline handling of low-level peculiarities of record field layout This factors out the interface to the low-level field layout machinery. gcc/ada/ * gcc-interface/gigi.h (default_field_alignment): New function. * gcc-interface/misc.cc: Include tm_p header file. (default_field_alignment): New function. * gcc-interface/trans.cc (addressable_p) <COMPONENT_REF>: Replace previous alignment klduge with call to default_field_alignment. * gcc-interface/utils.cc (finish_record_type): Likewise for the alignment based on which DECL_BIT_FIELD should be cleared. Diff: --- gcc/ada/gcc-interface/gigi.h | 4 ++++ gcc/ada/gcc-interface/misc.cc | 21 +++++++++++++++++++++ gcc/ada/gcc-interface/trans.cc | 24 +++++++----------------- gcc/ada/gcc-interface/utils.cc | 2 +- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index 40f3f0d3d13..f4b302be3e0 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -1008,6 +1008,10 @@ extern bool must_pass_by_ref (tree gnu_type); /* Return the size of the FP mode with precision PREC. */ extern int fp_prec_to_size (int prec); +/* Return the default alignment of a FIELD of TYPE declared in a record or + union type as specified by the ABI of the target architecture. */ +extern unsigned int default_field_alignment (tree field, tree type); + /* Return the precision of the FP mode with size SIZE. */ extern int fp_size_to_prec (int size); diff --git a/gcc/ada/gcc-interface/misc.cc b/gcc/ada/gcc-interface/misc.cc index 13cb39e91cb..ef5de7f5651 100644 --- a/gcc/ada/gcc-interface/misc.cc +++ b/gcc/ada/gcc-interface/misc.cc @@ -28,6 +28,7 @@ #include "coretypes.h" #include "target.h" #include "tree.h" +#include "tm_p.h" #include "diagnostic.h" #include "opts.h" #include "alias.h" @@ -1129,6 +1130,26 @@ must_pass_by_ref (tree gnu_type) && TREE_CODE (TYPE_SIZE_UNIT (gnu_type)) != INTEGER_CST)); } +/* Return the default alignment of a FIELD of TYPE declared in a record or + union type as specified by the ABI of the target architecture. */ + +unsigned int +default_field_alignment (tree ARG_UNUSED (field), tree type) +{ + /* This is modeled on layout_decl. */ + unsigned int align = TYPE_ALIGN (type); + +#ifdef BIGGEST_FIELD_ALIGNMENT + align = MIN (align, (unsigned int) BIGGEST_FIELD_ALIGNMENT); +#endif + +#ifdef ADJUST_FIELD_ALIGN + align = ADJUST_FIELD_ALIGN (field, type, align); +#endif + + return align; +} + /* This function is called by the front-end to enumerate all the supported modes for the machine, as well as some predefined C types. F is a function which is called back with the parameters as listed below, first a string, diff --git a/gcc/ada/gcc-interface/trans.cc b/gcc/ada/gcc-interface/trans.cc index c99b06670d5..9e9f5f8dcba 100644 --- a/gcc/ada/gcc-interface/trans.cc +++ b/gcc/ada/gcc-interface/trans.cc @@ -10291,23 +10291,13 @@ addressable_p (tree gnu_expr, tree gnu_type) /* Even with DECL_BIT_FIELD cleared, we have to ensure that the field is sufficiently aligned, in case it is subject to a pragma Component_Alignment. But we don't need to - check the alignment of the containing record, as it is - guaranteed to be not smaller than that of its most - aligned field that is not a bit-field. */ - && (DECL_ALIGN (TREE_OPERAND (gnu_expr, 1)) - >= TYPE_ALIGN (TREE_TYPE (gnu_expr)) -#ifdef TARGET_ALIGN_DOUBLE - /* Cope with the misalignment of doubles in records for - ancient 32-bit ABIs like that of x86/Linux. */ - || (DECL_ALIGN (TREE_OPERAND (gnu_expr, 1)) == 32 - && TYPE_ALIGN (TREE_TYPE (gnu_expr)) == 64 - && !TARGET_ALIGN_DOUBLE -#ifdef TARGET_64BIT - && !TARGET_64BIT -#endif - ) -#endif - )) + check the alignment of the containing record, since it + is guaranteed to be not smaller than that of its most + aligned field that is not a bit-field. However, we need + to cope with quirks of ABIs that may misalign fields. */ + && DECL_ALIGN (TREE_OPERAND (gnu_expr, 1)) + >= default_field_alignment (TREE_OPERAND (gnu_expr, 1), + TREE_TYPE (gnu_expr))) /* The field of a padding record is always addressable. */ || TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (gnu_expr, 0)))) && addressable_p (TREE_OPERAND (gnu_expr, 0), NULL_TREE)); diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc index 66e3192ea4f..60f36b1e50d 100644 --- a/gcc/ada/gcc-interface/utils.cc +++ b/gcc/ada/gcc-interface/utils.cc @@ -2220,7 +2220,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level, if (DECL_BIT_FIELD (field) && operand_equal_p (this_size, TYPE_SIZE (type), 0)) { - const unsigned int align = TYPE_ALIGN (type); + const unsigned int align = default_field_alignment (field, type); /* In the general case, type alignment is required. */ if (value_factor_p (pos, align))