This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Modify MEMBER_TYPE_FORCES_BLK on IA-64/HP-UX


Hi,

As previously discussed, we would need to modify MEMBER_TYPE_FORCES_BLK on 
IA-64/HP-UX to make the Ada compiler work there.  The typical testcase is:

   package z is

      type Integer_3_Spec is range -2..2;
      for Integer_3_Spec'Size use 3;

      type Enum_2_Spec is (Red, Orange, Yellow);
      for Enum_2_Spec'Size use 2;

      type Rec_3_Spec is record
         x,y,z : Boolean;
      end record;
      pragma Pack(Rec_3_Spec);
      for Rec_3_Spec'Size use 3;

      type Rec_10_Spec is
         record
            B1, B2, B3, B4, B5, B6, B7, B8, B9, B10: Boolean;
         end record;
      pragma Pack(Rec_10_Spec);
      for Rec_10_Spec'Size use 10;

      type Rec_27_Spec is
         record
            X1, X2, X3: Rec_3_Spec;
            X4, X5: Integer_3_Spec;
            Two_Bits: Enum_2_Spec;
            Ten_Bits: Rec_10_Spec;
         end record;
      pragma Pack(Rec_27_Spec);
      for Rec_27_Spec'Size use 27;

   end z;

Currently this doesn't compile on IA-64/HP-UX because the compiler cannot 
fulfill the size representation clause for Rec_27_Spec, as it cannot 
sufficiently pack the components of the record type.  Technically this 
happens because some of them are given BLKmode and BLKmode basically means 
alignment on byte boundaries.


The main change would read:

--- config/ia64/hpux.h	25 Jun 2005 01:21:26 -0000	1.53
+++ config/ia64/hpux.h	7 Jul 2005 10:37:07 -0000
@@ -106,14 +106,7 @@ do {							\
 #define TARGET_DEFAULT \
   (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32)
 
-/* This needs to be set to force structure arguments with a single
-   integer field to be treated as structures and not as the type of
-   their field.  Without this a structure with a single char will be
-   returned just like a char variable, instead of being returned at the
-   top of the register as specified for big-endian IA64.  */
-
-#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \
-  (!FLOAT_MODE_P (MODE) || (MODE) == TFmode)
+#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) ((MODE) == TFmode)

Running the gcc.dg/compat/compat.exp testsuite between the unpatched and the 
patched mainline compiler shows no failures; that's sufficient to prove that 
the first part of the macro is now useless to implement the big-endian 
calling conventions.

Running the gcc.dg/compat/struct-layout-1 testsuite between the unpatched and 
the patched mainline compiler shows several failures, but most of them are 
duplicates of the existing failures

FAIL: tmpdir-gcc.dg-struct-layout-1/t005 c_compat_x_tst.o-c_compat_y_tst.o 
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t007 c_compat_x_tst.o-c_compat_y_tst.o 
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t008 c_compat_x_tst.o-c_compat_y_tst.o 
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t013 c_compat_x_tst.o-c_compat_y_tst.o 
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t021 c_compat_x_tst.o-c_compat_y_tst.o 
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t024 c_compat_x_tst.o-c_compat_y_tst.o 
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t025 c_compat_x_tst.o-c_compat_y_tst.o 
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t027 c_compat_x_tst.o-c_compat_y_tst.o 
execute
FAIL: tmpdir-gcc.dg-struct-layout-1/t028 c_compat_x_tst.o-c_compat_y_tst.o 
execute

that are present even when the unpatched mainline compiler is confronted with 
itself.

There are a few new failures though, which pertain to the calling conventions 
for structures containing zero-sized unions and structures and a unique FP 
field:

struct { struct {} a; float f; };

They are currently passed in general registers (because they are given BLKmode 
by compute_record_mode), they would now be passed in FP registers (because 
they would be given FP mode).

This kind of structures are GNU extensions (the HP compiler rejects them) so 
it could be deemed acceptable to break binary compatibility here.  However it 
is relatively easy to patch ia64_function_arg to counter the macro change.

The patch was bootstrapped/regtested/compat-regtested on ia64-hp-hpux11.23.


2005-07-07  Eric Botcazou <ebotcazou@adacore.com>

	* config/ia64/hpux.h (MEMBER_TYPE_FORCES_BLK): Only force
	TFmode to BLKmode.
	* config/ia64/ia64.c (force_general_reg): New function.
	(ia64_function_arg): Pass the argument in general regs
	if force_general_reg returns true.


-- 
Eric Botcazou
Index: config/ia64/hpux.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/hpux.h,v
retrieving revision 1.53
diff -u -p -r1.53 hpux.h
--- config/ia64/hpux.h	25 Jun 2005 01:21:26 -0000	1.53
+++ config/ia64/hpux.h	7 Jul 2005 11:34:32 -0000
@@ -106,14 +106,7 @@ do {							\
 #define TARGET_DEFAULT \
   (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32)
 
-/* This needs to be set to force structure arguments with a single
-   integer field to be treated as structures and not as the type of
-   their field.  Without this a structure with a single char will be
-   returned just like a char variable, instead of being returned at the
-   top of the register as specified for big-endian IA64.  */
-
-#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \
-  (!FLOAT_MODE_P (MODE) || (MODE) == TFmode)
+#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) ((MODE) == TFmode)
 
 /* ASM_OUTPUT_EXTERNAL_LIBCALL defaults to just a globalize_label call,
    but that doesn't put out the @function type information which causes
Index: config/ia64/ia64.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64.c,v
retrieving revision 1.387
diff -u -p -r1.387 ia64.c
--- config/ia64/ia64.c	2 Jul 2005 10:55:27 -0000	1.387
+++ config/ia64/ia64.c	7 Jul 2005 11:34:34 -0000
@@ -3773,6 +3773,43 @@ ia64_function_arg_offset (CUMULATIVE_ARG
     return words > 1;
 }
 
+/* Return whether a value of MODE and TYPE should be passed/returned
+   in general registers.  */
+
+static bool
+force_general_reg (enum machine_mode mode, tree type)
+{
+#if TARGET_HPUX
+  /* ??? A hack to account for the revised MEMBER_TYPE_FORCES_BLK macro.
+     Previously the macro would have forced every structure type to BLKmode
+     except if it contained a unique field whose mode is FLOAT_MODE_P; now
+     it would not anymore.
+
+     This makes a difference here in one case (a GNU extension): structures
+     containing empty structures or unions and a unique FLOAT_MODE_P field.
+     They were previously given BLKmode, they are now given FLOAT_MODE_P.  */
+
+  if (FLOAT_MODE_P (mode)
+      && type
+      && TREE_CODE (type) == RECORD_TYPE)
+    {
+      tree field;
+
+      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+	{
+	  if (TREE_CODE (field) != FIELD_DECL
+	      || DECL_SIZE (field) == 0
+	      || ! host_integerp (DECL_SIZE (field), 1))
+	    continue;
+
+	  if (integer_zerop (DECL_SIZE (field)))
+	    return true;
+	}
+    }
+#endif
+  return false;
+}
+
 /* Return rtx for register where argument is passed, or zero if it is passed
    on the stack.  */
 /* ??? 128-bit quad-precision floats are always passed in general
@@ -3881,7 +3918,8 @@ ia64_function_arg (CUMULATIVE_ARGS *cum,
      FR registers, then FP values must also go in general registers.  This can
      happen when we have a SFmode HFA.  */
   else if (mode == TFmode || mode == TCmode
-	   || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
+	   || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS)
+	   || force_general_reg (mode, type))
     {
       int byte_size = ((mode == BLKmode)
                        ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]