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 <[EMAIL PROTECTED]> * 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));