diff mbox series

[COMMITTED,5/6] ada: Streamline handling of low-level peculiarities of record field layout

Message ID 20240905081056.2402112-5-poulhies@adacore.com
State New
Headers show
Series [COMMITTED,1/6] ada: Tweak assertions in Inline.Cannot_Inline | expand

Commit Message

Marc Poulhiès Sept. 5, 2024, 8:10 a.m. UTC
From: Eric Botcazou <ebotcazou@adacore.com>

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.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 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 mbox series

Patch

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))