tm.texi (FUNCTION_ARG_REG_LITTLE_ENDIAN): New.
authorSteve Ellcey <sje@cup.hp.com>
Tue, 11 Dec 2001 23:04:36 +0000 (23:04 +0000)
committerJanis Johnson <janis@gcc.gnu.org>
Tue, 11 Dec 2001 23:04:36 +0000 (23:04 +0000)
2001-12-11  Steve Ellcey  <sje@cup.hp.com>

* doc/tm.texi (FUNCTION_ARG_REG_LITTLE_ENDIAN): New.
* defaults.h (FUNCTION_ARG_REG_LITTLE_ENDIAN): New.
* calls.c (store_unaligned_arguments_into_pseudos): Check
FUNCTION_ARG_REG_LITTLE_ENDIAN to see how structures
are passed/returned.
* expr.c (move_block_from_reg): Ditto.
(move_block_from_reg): Ditto.
(copy_blkmode_from_reg): Ditto.
* stmt.c (expand_return): Ditto.
* stor-layout.c (compute_record_mode): If
FUNCTION_ARG_REG_LITTLE_ENDIAN is set then check
MEMBER_TYPE_FORCES_BLK even if mode == VOIDmode.
* config/ia64/hpux.h (MEMBER_TYPE_FORCES_BLK): Set to true
so that Structures of one field are still treated as structures.
(FUNCTION_ARG_REG_LITTLE_ENDIAN): New, set it to true.
(FUNCTION_ARG_PADDING): Set to ia64_hpux_function_arg_padding().
(PAD_VARARGS_DOWN): Modify from default to not pad structures down.
* config/ia64/ia64-protos.h (ia64_hpux_function_arg_padding): New.
* config/ia64/ia64.c (ia64_hpux_function_arg_padding): New function
to special case handling of structure padding.

From-SVN: r47904

gcc/ChangeLog
gcc/calls.c
gcc/config/ia64/hpux.h
gcc/config/ia64/ia64-protos.h
gcc/config/ia64/ia64.c
gcc/defaults.h
gcc/doc/tm.texi
gcc/expr.c
gcc/stmt.c
gcc/stor-layout.c

index acd76f3..919f955 100644 (file)
@@ -1,3 +1,26 @@
+2001-12-11  Steve Ellcey  <sje@cup.hp.com>
+
+       * doc/tm.texi (FUNCTION_ARG_REG_LITTLE_ENDIAN): New.
+       * defaults.h (FUNCTION_ARG_REG_LITTLE_ENDIAN): New.
+       * calls.c (store_unaligned_arguments_into_pseudos): Check
+       FUNCTION_ARG_REG_LITTLE_ENDIAN to see how structures
+       are passed/returned.
+       * expr.c (move_block_from_reg): Ditto.
+       (move_block_from_reg): Ditto.
+       (copy_blkmode_from_reg): Ditto.
+       * stmt.c (expand_return): Ditto.
+       * stor-layout.c (compute_record_mode): If
+       FUNCTION_ARG_REG_LITTLE_ENDIAN is set then check 
+       MEMBER_TYPE_FORCES_BLK even if mode == VOIDmode.
+       * config/ia64/hpux.h (MEMBER_TYPE_FORCES_BLK): Set to true
+       so that Structures of one field are still treated as structures.
+       (FUNCTION_ARG_REG_LITTLE_ENDIAN): New, set it to true.
+       (FUNCTION_ARG_PADDING): Set to ia64_hpux_function_arg_padding().
+       (PAD_VARARGS_DOWN): Modify from default to not pad structures down.
+       * config/ia64/ia64-protos.h (ia64_hpux_function_arg_padding): New.
+       * config/ia64/ia64.c (ia64_hpux_function_arg_padding): New function
+       to special case handling of structure padding.
+
 2001-12-11  Daniel Berlin  <dan@cgsoftware.com>
 
        * sched-rgn.c (CONST_BASED_ADDRESS_P): CONST_INT -> CONSTANT_P.
index 2ab670b..c7f5d99 100644 (file)
@@ -1029,7 +1029,9 @@ store_unaligned_arguments_into_pseudos (args, num_actuals)
           significant byte (to the right).  On a BYTES_BIG_ENDIAN machine,
           this means we must skip the empty high order bytes when
           calculating the bit offset.  */
-       if (BYTES_BIG_ENDIAN && bytes < UNITS_PER_WORD)
+       if (BYTES_BIG_ENDIAN
+           && !FUNCTION_ARG_REG_LITTLE_ENDIAN
+           && bytes < UNITS_PER_WORD)
          big_endian_correction = (BITS_PER_WORD  - (bytes * BITS_PER_UNIT));
 
        for (j = 0; j < args[i].n_aligned_regs; j++)
index 6fb8f87..89b2902 100644 (file)
@@ -95,3 +95,30 @@ Boston, MA 02111-1307, USA.  */
 
 #undef TARGET_DEFAULT
 #define TARGET_DEFAULT (MASK_DWARF2_ASM | MASK_BIG_ENDIAN)
+
+/* This needs to be set to force structure arguments with a single
+   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 and that is wrong on HP-UX
+   IA64.  TARGET_STRUCT_ARG_REG_LITTLE_ENDIAN triggers the special
+   structure handling, this macro simply ensures that single field
+   structures are always treated like structures.  */
+
+#define MEMBER_TYPE_FORCES_BLK(FIELD) 1
+
+/* Override the setting of FUNCTION_ARG_REG_LITTLE_ENDIAN in
+   defaults.h.  Setting this to true means that we are not passing
+   structures in registers in the "normal" big-endian way.  See
+   See section 8.5 of the "Itanium Software Conventions and Runtime
+   Architecture", specifically Table 8-1 and the explanation of Byte 0
+   alignment and LSB alignment and a description of how structures
+   are passed.  */
+
+#define FUNCTION_ARG_REG_LITTLE_ENDIAN 1
+
+#undef FUNCTION_ARG_PADDING
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+       ia64_hpux_function_arg_padding ((MODE), (TYPE))
+
+#undef PAD_VARARGS_DOWN
+#define PAD_VARARGS_DOWN (!AGGREGATE_TYPE_P (type))
index fca7f35..c543a53 100644 (file)
@@ -134,3 +134,8 @@ extern void sdata_section PARAMS ((void));
 #ifdef SBSS_SECTION_ASM_OP
 extern void sbss_section PARAMS ((void));
 #endif
+
+#ifdef ARGS_SIZE_RTX
+/* expr.h defines ARGS_SIZE_RTX and `enum direction'.  */
+extern enum direction ia64_hpux_function_arg_padding PARAMS ((enum machine_mode, tree));
+#endif /* ARGS_SIZE_RTX */
index d282b70..b70f038 100644 (file)
@@ -7724,3 +7724,27 @@ ia64_expand_builtin (exp, target, subtarget, mode, ignore)
 
   return NULL_RTX;
 }
+
+/* For the HP-UX IA64 aggregate parameters are passed stored in the
+   most significant bits of the stack slot.  */
+
+enum direction
+ia64_hpux_function_arg_padding (mode, type)
+     enum machine_mode mode;
+     tree type;
+{
+   /* Exception to normal case for structures/unions/etc. */
+
+   if (type && AGGREGATE_TYPE_P (type)
+       && int_size_in_bytes (type) < UNITS_PER_WORD)
+     return upward;
+
+   /* This is the standard FUNCTION_ARG_PADDING with !BYTES_BIG_ENDIAN
+      hardwired to be true. */
+
+   return((mode == BLKmode
+       ? (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+          && int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT))
+       : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
+      ? downward : upward);
+}
index f23b0ab..ecfceda 100644 (file)
@@ -457,4 +457,14 @@ You Lose!  You must define PREFERRED_DEBUGGING_TYPE!
 #define PREFERRED_DEBUGGING_TYPE NO_DEBUG
 #endif
 
+/* This is set to 1 if BYTES_BIG_ENDIAN is defined but the target uses a
+   little-endian method of passing and returning structures in registers.
+   On the HP-UX IA64 and PA64 platforms structures are aligned differently
+   then integral values and setting this value to 1 will allow for the
+   special handling of structure arguments and return values in regs.  */
+
+#ifndef FUNCTION_ARG_REG_LITTLE_ENDIAN
+#define FUNCTION_ARG_REG_LITTLE_ENDIAN 0
+#endif
+
 #endif  /* ! GCC_DEFAULTS_H */
index beae6e5..5e97e91 100644 (file)
@@ -3435,6 +3435,14 @@ nonzero, the caller does not make a copy.  Instead, it passes a pointer to the
 determined that the value won't be modified, it need not make a copy;
 otherwise a copy must be made.
 
+@findex FUNCTION_ARG_REG_LITTLE_ENDIAN
+@item FUNCTION_ARG_REG_LITTLE_ENDIAN
+If defined TRUE on a big-endian system then structure arguments passed
+(and returned) in registers are passed in a little-endian manner instead of
+the big-endian manner.  On the HP-UX IA64 and PA64 platforms structures are
+aligned differently then integral values and setting this value to true will
+allow for the special handling of structure arguments and return values.
+
 @findex CUMULATIVE_ARGS
 @item CUMULATIVE_ARGS
 A C type for declaring a variable that is used as the first argument of
index 051dc20..5320805 100644 (file)
@@ -1868,7 +1868,8 @@ move_block_from_reg (regno, x, nregs, size)
   /* If SIZE is that of a mode no bigger than a word, just use that
      mode's store operation.  */
   if (size <= UNITS_PER_WORD
-      && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode)
+      && (mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0)) != BLKmode
+      && !FUNCTION_ARG_REG_LITTLE_ENDIAN)
     {
       emit_move_insn (adjust_address (x, mode, 0), gen_rtx_REG (mode, regno));
       return;
@@ -1877,7 +1878,9 @@ move_block_from_reg (regno, x, nregs, size)
   /* Blocks smaller than a word on a BYTES_BIG_ENDIAN machine must be aligned
      to the left before storing to memory.  Note that the previous test
      doesn't handle all cases (e.g. SIZE == 3).  */
-  if (size < UNITS_PER_WORD && BYTES_BIG_ENDIAN)
+  if (size < UNITS_PER_WORD
+      && BYTES_BIG_ENDIAN
+      && !FUNCTION_ARG_REG_LITTLE_ENDIAN)
     {
       rtx tem = operand_subword (x, 0, 1, BLKmode);
       rtx shift;
@@ -2162,15 +2165,25 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
 
   /* This code assumes srcreg is at least a full word.  If it isn't,
      copy it into a new pseudo which is a full word.  */
+
+  /* If FUNCTION_ARG_REG_LITTLE_ENDIAN is set and convert_to_mode does
+     a copy, the wrong part of the register gets copied so we fake
+     a type conversion in place.  */
+     
   if (GET_MODE (srcreg) != BLKmode
       && GET_MODE_SIZE (GET_MODE (srcreg)) < UNITS_PER_WORD)
-    srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
+    if (FUNCTION_ARG_REG_LITTLE_ENDIAN)
+       srcreg = simplify_gen_subreg (word_mode, srcreg, GET_MODE (srcreg), 0);
+    else
+       srcreg = convert_to_mode (word_mode, srcreg, TREE_UNSIGNED (type));
 
   /* Structures whose size is not a multiple of a word are aligned
      to the least significant byte (to the right).  On a BYTES_BIG_ENDIAN
      machine, this means we must skip the empty high order bytes when
      calculating the bit offset.  */
-  if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
+  if (BYTES_BIG_ENDIAN
+      && !FUNCTION_ARG_REG_LITTLE_ENDIAN
+      && bytes % UNITS_PER_WORD)
     big_endian_correction
       = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT));
 
index 8d51a2c..3c4ccd1 100644 (file)
@@ -3197,7 +3197,9 @@ expand_return (retval)
         to the least significant byte (to the right).  On a BYTES_BIG_ENDIAN
         machine, this means we must skip the empty high order bytes when
         calculating the bit offset.  */
-      if (BYTES_BIG_ENDIAN && bytes % UNITS_PER_WORD)
+      if (BYTES_BIG_ENDIAN
+         && !FUNCTION_ARG_REG_LITTLE_ENDIAN
+         && bytes % UNITS_PER_WORD)
        big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
                                                  * BITS_PER_UNIT));
 
index 05eaf24..f657463 100644 (file)
@@ -1149,7 +1149,17 @@ compute_record_mode (type)
 #ifdef MEMBER_TYPE_FORCES_BLK
       /* With some targets, eg. c4x, it is sub-optimal
         to access an aligned BLKmode structure as a scalar.  */
-      if (mode == VOIDmode && MEMBER_TYPE_FORCES_BLK (field))
+
+      /* On ia64-*-hpux we need to ensure that we don't change the
+        mode of a structure containing a single field or else we
+        will pass it incorrectly.  Since a structure with a single
+        field causes mode to get set above we can't allow the
+        check for mode == VOIDmode in this case.  Perhaps
+        MEMBER_TYPE_FORCES_BLK should be extended to include mode
+        as an argument and the check could be put in there for c4x.  */
+
+      if ((mode == VOIDmode || FUNCTION_ARG_REG_LITTLE_ENDIAN)
+         && MEMBER_TYPE_FORCES_BLK (field))
        return;
 #endif /* MEMBER_TYPE_FORCES_BLK  */
     }