Patch to fix several compat failures on irix6.5

Richard Sandiford rsandifo@redhat.com
Mon Aug 25 13:05:00 GMT 2003


Richard Sandiford <rsandifo@redhat.com> writes:
> Also, since we're breaking the ABI anyway, maybe we should sort out the
> other (known) problems with NewABI structure passing.

Here's a patch.  Warning first-up that it has two target-independent changes.


To recap: when using big-endian n32 & n64, structures passed in
registers should be padded at the least-significant end.  At the
moment, we pad subword structures at the most significant end.

It's much easier to get this right if we get rid of the structure
shifts in mips.c and use the new (much cleaner!) BLOCK_REG_PADDING
macro instead.

In fact, BLOCK_REG_PADDING worked out of the box for o32 & o64.  But
with n32 & n64, the caller doesn't allocate stack space for register
arguments.  That means they never get passed to locate_and_pad_parm:

      /* Compute the stack-size of this argument.  */
      if (args[i].reg == 0 || args[i].partial != 0
          || reg_parm_stack_space > 0
          || args[i].pass_on_stack)
        locate_and_pad_parm (mode, type,
                             ...

and their padding remains "none".

The patch uses BLOCK_REG_PADDING to set the padding for such arguments.
After this change, everything seems to be correctly padded for all ABIs.


However, there were some problems with the way incoming arguments
were handled.  If we have a subword structure that needs shifting,
we'll use the following code in functions.c:assign_parms:

              if (stack_parm == 0)
                {
 A --->           stack_parm
                    = assign_stack_local (GET_MODE (entry_parm),
                                          size_stored, 0);
                  set_mem_attributes (stack_parm, parm, 1);
                }

              else if (PARM_BOUNDARY % BITS_PER_WORD != 0)
                abort ();

              mem = validize_mem (stack_parm);
              ...
                      rtx tem, x;
                      int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
                      rtx reg = gen_rtx_REG (word_mode, REGNO (entry_parm));

                      x = expand_binop (word_mode, ashl_optab, reg,
                                        GEN_INT (by), 0, 1, OPTAB_WIDEN);
 B --->               tem = change_address (mem, word_mode, 0);
 B --->               emit_move_insn (tem, x);


The stack slot allocated by [A] isn't always suitable for [B].  Say we have
a 2-byte structure and entry_parm's mode is HImode.  On a strict alignment
target, assign_stack_local is only guaranteed to give us a 2-byte-aligned
slot, not a word-aligned one.

Also, on big-endian targets, assign_stack_local will return the last
HImode in the slot.  That's because of this code in assign_stack_local_1:

  /* On a big-endian machine, if we are allocating more space than we will use,
     use the least significant bytes of those that are allocated.  */
  if (BYTES_BIG_ENDIAN && mode != BLKmode)
    bigend_correction = size - GET_MODE_SIZE (mode);

It's easy to side-step both problems by allocating a BLKmode slot instead.
This has the disadvantage that small power-of-2-sized structures might be
overaligned.  But it brings the handling of such structures in line with
the non-power-of-2 case.


As well as the padding issue, there was another ABI incompatibility.
We would always use float registers to pass one-float structures such as:

    struct s { float f; };

But we should be using GPRs for everything except EABI.

As for one-double structures: they _should_ be passed in float registers
for n32 & n64.  But this is really just a special case of the general
"double chunks are passed in FPRs" rule.  They should be passed in
general registers for o32 & o64.


Anyway, I think that this patch fixes the structure passing problems.
See below for testing.  But we still don't return structures correctly
for n32 & n64.  I'll try to get that done before stage 2 closes.


Patch boostrapped & regression tested on mips-sgi-irix6.5,
mips-sgi-irix6.5o32, mips64-linux-gnu and mips64el-linux-gnu.
All targets are now free of compat/struct and compat/scalar failures.

Also tested on mipsisa64-elf and mips64vrel-elf.  No regressions,
although there are still some compat failures for little-endian EABI32.

I also used the compat tests to check for compatibility with MIPSpro.
First of all, I had to remove two GNUisms (zero-sized structures and
complex integers) since MIPSpro didn't support them.  I also had to
remove complex doubles and complex floats since they caused some
sort of ICE with our copy of MIPSpro.  Results as follows:

  - MIPSpro compiling all code:

      - o32: all tests pass

      - n32 & n64: struct-by-value-10 and struct-return-10 fail
           due to a miscompilation of checkSdl on the x side and
           checkgSdl on the y side.

  - GCC compiling the x side, MIPSpro the y side:

      - o32: scalar-by-value-2 fails due an unrelated ABI incompatiblity.
           All other tests pass.

      - n32 & n64: struct-by-value-10 and struct-return-10 fail for the
           reason above.  The other struct-by-return tests fail because
           of the lingering structure return incompatibility.

  - GCC compiling the y side, MIPSpro the x side:

       Same as above.

OK to install?  If so, I'll update the 3.4 changes.html entry.

Richard


	* calls.c (initialize_argument_information): If an argument has no
	stack space associated with it, and BLOCK_REG_PADDING is defined,
	use it to decide at which end the argument should be padded.
	* function.c (assign_parms): Allocate BLKmode stack slots.
	* config/mips/mips-protos.h (mips_pad_arg_upward): Declare.
	(mips_pad_reg_upward): Declare.
	* config/mips/mips.h (PAD_VARARGS_DOWN): Use FUNCTION_ARG_PADDING.
	(CUMULATIVE_ARGS): Remove num_adjusts and adjusts.
	(FUNCTION_ARG_PADDING): Use mips_pad_arg_upward.
	(BLOCK_REG_PADDING): Use mips_pad_reg_upward.
	* config/mips/mips.c (struct mips_arg_info): Remove struct_p.
	(mips_expand_call): Remove code for generating structure shifts.
	(mips_arg_info): Don't set struct_p.  Don't set fpr_p for non-float
	types unless using the EABI.
	(function_arg_advance): Don't generate shift instructions.
	(function_arg): Don't return them.  Don't short-circuit the
	check for double structure chunks for DFmode arguments.
	(mips_pad_arg_upward, mips_pad_reg_upward): New functions.
	(mips_expand_prologue): Remove code to emit structure shifts.
	* config/mips/irix6-libc-compat.c: Remove workarounds for buggy
	structure passing (inet_ntoa, inet_lnaof, inet_netof).  Update
	comments to say that only structure returns are a problem.

Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.293
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.293 calls.c
*** calls.c	20 Aug 2003 21:46:48 -0000	1.293
--- calls.c	25 Aug 2003 08:28:02 -0000
*************** initialize_argument_information (int num
*** 1238,1243 ****
--- 1238,1251 ----
  #endif
  			     args[i].pass_on_stack ? 0 : args[i].partial,
  			     fndecl, args_size, &args[i].locate);
+ #ifdef BLOCK_REG_PADDING
+       else
+ 	/* The argument is passed entirely in registers.  See at which
+ 	   end it should be padded.  */
+ 	args[i].locate.where_pad =
+ 	  BLOCK_REG_PADDING (mode, type,
+ 			     int_size_in_bytes (type) <= UNITS_PER_WORD);
+ #endif
  
        /* Update ARGS_SIZE, the total stack space for args so far.  */
  
Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.450
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.450 function.c
*** function.c	19 Aug 2003 20:29:00 -0000	1.450
--- function.c	25 Aug 2003 08:28:03 -0000
*************** assign_parms (tree fndecl)
*** 4674,4682 ****
  
  	      if (stack_parm == 0)
  		{
! 		  stack_parm
! 		    = assign_stack_local (GET_MODE (entry_parm),
! 					  size_stored, 0);
  		  set_mem_attributes (stack_parm, parm, 1);
  		}
  
--- 4674,4681 ----
  
  	      if (stack_parm == 0)
  		{
! 		  stack_parm = assign_stack_local (BLKmode, size_stored, 0);
! 		  PUT_MODE (stack_parm, GET_MODE (entry_parm));
  		  set_mem_attributes (stack_parm, parm, 1);
  		}
  
Index: config/mips/mips-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips-protos.h,v
retrieving revision 1.48
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.48 mips-protos.h
*** config/mips/mips-protos.h	12 Aug 2003 20:50:29 -0000	1.48
--- config/mips/mips-protos.h	25 Aug 2003 08:28:03 -0000
*************** extern struct rtx_def *function_arg (con
*** 80,85 ****
--- 80,87 ----
  				     enum machine_mode, tree, int);
  extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *,
  				       enum machine_mode, tree, int);
+ extern bool mips_pad_arg_upward (enum machine_mode, tree);
+ extern bool mips_pad_reg_upward (enum machine_mode, tree);
  extern int mips_setup_incoming_varargs (const CUMULATIVE_ARGS *,
  					enum machine_mode, tree, int);
  extern tree mips_build_va_list (void);
Index: config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.285
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.285 mips.h
*** config/mips/mips.h	21 Aug 2003 11:32:16 -0000	1.285
--- config/mips/mips.h	25 Aug 2003 08:28:04 -0000
*************** #define DATA_ALIGNMENT(TYPE, ALIGN)					
*** 1393,1401 ****
  	|| TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
  
  
! /* Force right-alignment for small varargs in 32 bit little_endian mode */
! 
! #define PAD_VARARGS_DOWN (TARGET_64BIT ? BYTES_BIG_ENDIAN : !BYTES_BIG_ENDIAN)
  
  /* Arguments declared as 'char' or 'short' in a prototype should be
     passed as 'int's.  */
--- 1393,1400 ----
  	|| TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
  
  
! #define PAD_VARARGS_DOWN \
!   (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
  
  /* Arguments declared as 'char' or 'short' in a prototype should be
     passed as 'int's.  */
*************** typedef struct mips_args {
*** 2289,2303 ****
  
    /* True if the function has a prototype.  */
    int prototype;
- 
-   /* When a structure does not take up a full register, the argument
-      should sometimes be shifted left so that it occupies the high part
-      of the register.  These two fields describe an array of ashl
-      patterns for doing this.  See function_arg_advance, which creates
-      the shift patterns, and function_arg, which returns them when given
-      a VOIDmode argument.  */
-   unsigned int num_adjusts;
-   rtx adjust[BIGGEST_MAX_ARGS_IN_REGISTERS];
  } CUMULATIVE_ARGS;
  
  /* Initialize a variable CUM of type CUMULATIVE_ARGS
--- 2288,2293 ----
*************** #define FUNCTION_ARG_BOUNDARY(MODE, TYPE
*** 2355,2372 ****
  #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED)		\
    function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED)
  
! #define FUNCTION_ARG_PADDING(MODE, TYPE)				\
!   (! BYTES_BIG_ENDIAN							\
!    ? upward								\
!    : (((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			\
! 	  && (mips_abi == ABI_32					\
! 	      || mips_abi == ABI_O64					\
! 	      || mips_abi == ABI_EABI					\
! 	      || GET_MODE_CLASS (MODE) == MODE_INT)))			\
!       ? downward : upward))
  
  #define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED)		\
    (mips_abi == ABI_EABI && (NAMED)					\
--- 2345,2355 ----
  #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED)		\
    function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED)
  
! #define FUNCTION_ARG_PADDING(MODE, TYPE)		\
!   (mips_pad_arg_upward (MODE, TYPE) ? upward : downward)
! 
! #define BLOCK_REG_PADDING(MODE, TYPE, FIRST)		\
!   (mips_pad_reg_upward (MODE, TYPE) ? upward : downward)
  
  #define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED)		\
    (mips_abi == ABI_EABI && (NAMED)					\
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.304
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.304 mips.c
*** config/mips/mips.c	21 Aug 2003 11:32:16 -0000	1.304
--- config/mips/mips.c	25 Aug 2003 08:28:05 -0000
*************** struct machine_function GTY(()) {
*** 317,325 ****
  /* Information about a single argument.  */
  struct mips_arg_info
  {
-   /* True if the argument is a record or union type.  */
-   bool struct_p;
- 
    /* True if the argument is passed in a floating-point register, or
       would have been if we hadn't run out of registers.  */
    bool fpr_p;
--- 317,322 ----
*************** mips_gen_conditional_trap (rtx *operands
*** 3208,3215 ****
  void
  mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p)
  {
-   int i;
- 
    if (!call_insn_operand (addr, VOIDmode))
      {
        /* When generating PIC, try to allow global functions to be
--- 3205,3210 ----
*************** mips_expand_call (rtx result, rtx addr, 
*** 3226,3241 ****
        addr = force_reg (Pmode, addr);
      }
  
-   /* In order to pass small structures by value in registers
-      compatibly with the MIPS compiler, we need to shift the value
-      into the high part of the register.  Function_arg has encoded
-      a PARALLEL rtx, holding a vector of adjustments to be made
-      as the next_arg_reg variable, so we split up the insns,
-      and emit them separately.  */
-   if (aux != 0 && GET_CODE (aux) == PARALLEL)
-     for (i = 0; i < XVECLEN (aux, 0); i++)
-       emit_insn (XVECEXP (aux, 0, i));
- 
    if (TARGET_MIPS16
        && mips16_hard_float
        && build_mips16_call_stub (result, addr, args_size,
--- 3221,3226 ----
*************** mips_arg_info (const CUMULATIVE_ARGS *cu
*** 3557,3590 ****
    bool even_reg_p;
    unsigned int num_words, max_regs;
  
-   info->struct_p = (type != 0
- 		    && (TREE_CODE (type) == RECORD_TYPE
- 			|| TREE_CODE (type) == UNION_TYPE
- 			|| TREE_CODE (type) == QUAL_UNION_TYPE));
- 
    /* Decide whether this argument should go in a floating-point register,
       assuming one is free.  Later code checks for availability.  */
  
!   info->fpr_p = false;
!   if (GET_MODE_CLASS (mode) == MODE_FLOAT
!       && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE)
!     {
!       switch (mips_abi)
! 	{
! 	case ABI_32:
! 	case ABI_O64:
! 	  info->fpr_p = (!cum->gp_reg_found && cum->arg_number < 2);
! 	  break;
  
! 	case ABI_EABI:
! 	  info->fpr_p = true;
! 	  break;
  
! 	default:
! 	  info->fpr_p = named;
! 	  break;
! 	}
!     }
  
    /* Now decide whether the argument must go in an even-numbered register.  */
  
--- 3542,3568 ----
    bool even_reg_p;
    unsigned int num_words, max_regs;
  
    /* Decide whether this argument should go in a floating-point register,
       assuming one is free.  Later code checks for availability.  */
  
!   info->fpr_p = (GET_MODE_CLASS (mode) == MODE_FLOAT
! 		 && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE);
  
!   if (info->fpr_p)
!     switch (mips_abi)
!       {
!       case ABI_32:
!       case ABI_O64:
! 	info->fpr_p = (!cum->gp_reg_found
! 		       && cum->arg_number < 2
! 		       && (type == 0 || FLOAT_TYPE_P (type)));
! 	break;
  
!       case ABI_N32:
!       case ABI_64:
! 	info->fpr_p = (named && (type == 0 || FLOAT_TYPE_P (type)));
! 	break;
!       }
  
    /* Now decide whether the argument must go in an even-numbered register.  */
  
*************** function_arg_advance (CUMULATIVE_ARGS *c
*** 3648,3683 ****
  
    mips_arg_info (cum, mode, type, named, &info);
  
-   /* The following is a hack in order to pass 1 byte structures
-      the same way that the MIPS compiler does (namely by passing
-      the structure in the high byte or half word of the register).
-      This also makes varargs work.  If we have such a structure,
-      we save the adjustment RTL, and the call define expands will
-      emit them.  For the VOIDmode argument (argument after the
-      last real argument), pass back a parallel vector holding each
-      of the adjustments.  */
- 
-   /* ??? This scheme requires everything smaller than the word size to
-      shifted to the left, but when TARGET_64BIT and ! TARGET_INT64,
-      that would mean every int needs to be shifted left, which is very
-      inefficient.  Let's not carry this compatibility to the 64 bit
-      calling convention for now.  */
- 
-   if (info.struct_p
-       && info.reg_words == 1
-       && info.num_bytes < UNITS_PER_WORD
-       && !TARGET_64BIT
-       && mips_abi != ABI_EABI)
-     {
-       rtx amount = GEN_INT (BITS_PER_WORD - info.num_bytes * BITS_PER_UNIT);
-       rtx reg = gen_rtx_REG (word_mode, GP_ARG_FIRST + info.reg_offset);
- 
-       if (TARGET_64BIT)
- 	cum->adjust[cum->num_adjusts++] = PATTERN (gen_ashldi3 (reg, reg, amount));
-       else
- 	cum->adjust[cum->num_adjusts++] = PATTERN (gen_ashlsi3 (reg, reg, amount));
-     }
- 
    if (!info.fpr_p)
      cum->gp_reg_found = true;
  
--- 3626,3631 ----
*************** function_arg (const CUMULATIVE_ARGS *cum
*** 3708,3725 ****
  
    /* We will be called with a mode of VOIDmode after the last argument
       has been seen.  Whatever we return will be passed to the call
!      insn.  If we need any shifts for small structures, return them in
!      a PARALLEL; in that case, stuff the mips16 fp_code in as the
!      mode.  Otherwise, if we need a mips16 fp_code, return a REG
!      with the code stored as the mode.  */
    if (mode == VOIDmode)
      {
!       if (cum->num_adjusts > 0)
! 	return gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code,
! 				 gen_rtvec_v (cum->num_adjusts,
! 					      (rtx *) cum->adjust));
! 
!       else if (TARGET_MIPS16 && cum->fp_code != 0)
  	return gen_rtx_REG ((enum machine_mode) cum->fp_code, 0);
  
        else
--- 3656,3666 ----
  
    /* We will be called with a mode of VOIDmode after the last argument
       has been seen.  Whatever we return will be passed to the call
!      insn.  If we need a mips16 fp_code, return a REG with the code
!      stored as the mode.  */
    if (mode == VOIDmode)
      {
!       if (TARGET_MIPS16 && cum->fp_code != 0)
  	return gen_rtx_REG ((enum machine_mode) cum->fp_code, 0);
  
        else
*************** function_arg (const CUMULATIVE_ARGS *cum
*** 3737,3744 ****
        && (mips_abi == ABI_N32 || mips_abi == ABI_64)
        && TYPE_SIZE_UNIT (type)
        && host_integerp (TYPE_SIZE_UNIT (type), 1)
!       && named
!       && mode != DFmode)
      {
        /* The Irix 6 n32/n64 ABIs say that if any 64 bit chunk of the
  	 structure contains a double in its entirety, then that 64 bit
--- 3678,3684 ----
        && (mips_abi == ABI_N32 || mips_abi == ABI_64)
        && TYPE_SIZE_UNIT (type)
        && host_integerp (TYPE_SIZE_UNIT (type), 1)
!       && named)
      {
        /* The Irix 6 n32/n64 ABIs say that if any 64 bit chunk of the
  	 structure contains a double in its entirety, then that 64 bit
*************** function_arg_partial_nregs (const CUMULA
*** 3815,3820 ****
--- 3755,3809 ----
    mips_arg_info (cum, mode, type, named, &info);
    return info.stack_words > 0 ? info.reg_words : 0;
  }
+ 
+ 
+ /* Return true if FUNCTION_ARG_PADDING (MODE, TYPE) should return
+    upward rather than downward.  In other words, return true if the
+    first byte of the stack slot has useful data, false if the last
+    byte does.  */
+ 
+ bool
+ mips_pad_arg_upward (enum machine_mode mode, tree type)
+ {
+   /* On little-endian targets, the first byte of every stack argument
+      is passed in the first byte of the stack slot.  */
+   if (!BYTES_BIG_ENDIAN)
+     return true;
+ 
+   /* Otherwise, integral types are padded downward: the last byte of a
+      stack argument is passed in the last byte of the stack slot.  */
+   if (type != 0
+       ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
+       : GET_MODE_CLASS (mode) == MODE_INT)
+     return false;
+ 
+   /* Other types are padded upward for o32, o64, n32 and n64.  */
+   if (mips_abi != ABI_EABI)
+     return true;
+ 
+   /* Arguments smaller than a stack slot are padded downward.  */
+   if (mode != BLKmode)
+     return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY);
+   else
+     return (int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT));
+ }
+ 
+ 
+ /* Likewise BLOCK_REG_PADDING (MODE, TYPE, ...).  Return !BYTES_BIG_ENDIAN
+    if the least significant byte of the register has useful data.  Return
+    the opposite if the most significant byte does.  */
+ 
+ bool
+ mips_pad_reg_upward (enum machine_mode mode, tree type)
+ {
+   /* No shifting is required for floating-point arguments.  */
+   if (type != 0 ? FLOAT_TYPE_P (type) : GET_MODE_CLASS (mode) == MODE_FLOAT)
+     return !BYTES_BIG_ENDIAN;
+ 
+   /* Otherwise, apply the same padding to register arguments as we do
+      to stack arguments.  */
+   return mips_pad_arg_upward (mode, type);
+ }
  
  int
  mips_setup_incoming_varargs (const CUMULATIVE_ARGS *cum,
*************** mips_expand_prologue (void)
*** 6711,6718 ****
    tree fndecl = current_function_decl;
    tree fntype = TREE_TYPE (fndecl);
    tree fnargs = DECL_ARGUMENTS (fndecl);
-   rtx next_arg_reg;
-   int i;
    tree next_arg;
    tree cur_arg;
    CUMULATIVE_ARGS args_so_far;
--- 6700,6705 ----
*************** mips_expand_prologue (void)
*** 6800,6838 ****
  	{
  	  regno = GP_ARG_LAST+1;
  	  break;
- 	}
-     }
- 
-   /* In order to pass small structures by value in registers compatibly with
-      the MIPS compiler, we need to shift the value into the high part of the
-      register.  Function_arg has encoded a PARALLEL rtx, holding a vector of
-      adjustments to be made as the next_arg_reg variable, so we split up the
-      insns, and emit them separately.  */
- 
-   next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
-   if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
-     {
-       rtvec adjust = XVEC (next_arg_reg, 0);
-       int num = GET_NUM_ELEM (adjust);
- 
-       for (i = 0; i < num; i++)
- 	{
- 	  rtx insn, pattern;
- 
- 	  pattern = RTVEC_ELT (adjust, i);
- 	  if (GET_CODE (pattern) != SET
- 	      || GET_CODE (SET_SRC (pattern)) != ASHIFT)
- 	    fatal_insn ("insn is not a shift", pattern);
- 	  PUT_CODE (SET_SRC (pattern), ASHIFTRT);
- 
- 	  insn = emit_insn (pattern);
- 
- 	  /* Global life information isn't valid at this point, so we
- 	     can't check whether these shifts are actually used.  Mark
- 	     them MAYBE_DEAD so that flow2 will remove them, and not
- 	     complain about dead code in the prologue.  */
- 	  REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
- 					       REG_NOTES (insn));
  	}
      }
  
--- 6787,6792 ----
Index: config/mips/irix6-libc-compat.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/irix6-libc-compat.c,v
retrieving revision 1.5
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.5 irix6-libc-compat.c
*** config/mips/irix6-libc-compat.c	12 Aug 2003 20:50:29 -0000	1.5
--- config/mips/irix6-libc-compat.c	25 Aug 2003 08:28:05 -0000
***************
*** 1,4 ****
! /* Compensate for inconsistent structure passing conventions on IRIX 6.  */
  /* Compile this one with gcc.  */
  /* Copyright (C) 2001  Free Software Foundation, Inc.
  
--- 1,4 ----
! /* Compensate for inconsistent structure return conventions on IRIX 6.  */
  /* Compile this one with gcc.  */
  /* Copyright (C) 2001  Free Software Foundation, Inc.
  
*************** along with GNU CC; see the file COPYING.
*** 28,34 ****
  the Free Software Foundation, 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.  */
  
! /* GCC doesn't correctly implement the structure and union passing and return
     conventions of the N32 and N64 ABIs on IRIX 6, as described in the
     MIPSpro N32 ABI Handbook, ch. 2, Calling Convention Implementations, p.7.
     The ABI requires that structures (or trailing parts of structures) smaller
--- 28,34 ----
  the Free Software Foundation, 59 Temple Place - Suite 330,
  Boston, MA 02111-1307, USA.  */
  
! /* GCC doesn't correctly implement the structure and union return
     conventions of the N32 and N64 ABIs on IRIX 6, as described in the
     MIPSpro N32 ABI Handbook, ch. 2, Calling Convention Implementations, p.7.
     The ABI requires that structures (or trailing parts of structures) smaller
*************** Boston, MA 02111-1307, USA.  */
*** 38,54 ****
     While GCC is internally consistent, calling routines compiled with a
     compiler that does implement the documented ABI (like SGIs MIPSpro C
     compiler) doesn't work.  This is primarily an issue for system libraries
!    like libc.  Fortunately, there exist only very few routines that take
!    structure value arguments or return structures by value, so until the
!    underlying bug is fixed, it is possible to work around it by providing
!    wrapper functions for the few affected routines that compensate for the
!    inconsistent alignment.
  
     These wrappers rely on the fact that e.g. libc contains weak versions of
     those routines, and the real implementation is provided by _-prefixed
     variants.  So we can provide our own versions, which will only be linked
     if the application uses any of the affected functions, calling the private
!    variants after shifting the arguments or results as required.
  
     This is a rewrite of code created by Andy Polyakov.  */
  
--- 38,52 ----
     While GCC is internally consistent, calling routines compiled with a
     compiler that does implement the documented ABI (like SGIs MIPSpro C
     compiler) doesn't work.  This is primarily an issue for system libraries
!    like libc.  Fortunately, there exist only very few routines that return
!    structures by value, so until the underlying bug is fixed, it is possible
!    to work around it by providing wrappers for the few affected routines.
  
     These wrappers rely on the fact that e.g. libc contains weak versions of
     those routines, and the real implementation is provided by _-prefixed
     variants.  So we can provide our own versions, which will only be linked
     if the application uses any of the affected functions, calling the private
!    variants and then shifting the result as required.
  
     This is a rewrite of code created by Andy Polyakov.  */
  
*************** Boston, MA 02111-1307, USA.  */
*** 61,122 ****
  
  #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
  
! /* The affected arguments need to be shifted by
  
! 	BITS_PER_WORD - (sizeof (arg) * BITS_PER_UNIT).
  
!    Since only 32-bit args and results are involved, the shift count is
!    always 32.  */
  #define SHIFT_BITS	32
  
- extern machreg_t inet_ntoa (machreg_t);
- extern machreg_t inet_lnaof (machreg_t);
- extern machreg_t inet_netof (machreg_t);
- extern machreg_t inet_makeaddr (machreg_t, machreg_t);
- 
- extern machreg_t _inet_ntoa (machreg_t);
- extern machreg_t _inet_lnaof (machreg_t);
- extern machreg_t _inet_netof (machreg_t);
  extern machreg_t _inet_makeaddr (machreg_t, machreg_t);
  
  /* <arpa/inet.h> has
  
- 	char *inet_ntoa (struct in_addr);
- 
-    on both IRIX 6.2 and 6.5, with struct in_addr containing a 32-bit int.  */
- 
- machreg_t
- inet_ntoa (machreg_t in)
- {
-   return _inet_ntoa (in << SHIFT_BITS);
- }
- 
- /* <arpa/inet.h> has
- 
- 	unsigned long inet_lnaof (struct in_addr);		(IRIX 6.2)
- 	in_addr_t inet_lnaof (struct in_addr);			(IRIX 6.5)
- 
-    in_addr_t is a 32-bit int.  */
- 
- machreg_t
- inet_lnaof (machreg_t in)
- {
-   return _inet_lnaof (in << SHIFT_BITS);
- }
- 
- /* <arpa/inet.h> has
- 
- 	unsigned long inet_netof (struct in_addr);		(IRIX 6.2)
- 	in_addr_t inet_netof (struct in_addr);			(IRIX 6.5)  */
- 
- machreg_t
- inet_netof (machreg_t in)
- {
-   return _inet_netof (in << SHIFT_BITS);
- }
- 
- /* <arpa/inet.h> has
- 
  	struct in_addr inet_makeaddr (int, int);		(IRIX 6.2)
  	struct in_addr inet_makeaddr (in_addr_t, in_addr_t);	(IRIX 6.5)  */
  
--- 59,75 ----
  
  #if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
  
! /* The affected return values need to be shifted by
  
! 	BITS_PER_WORD - (sizeof (value) * BITS_PER_UNIT).
  
!    Since only 32-bit results are involved, the shift count is always 32.  */
  #define SHIFT_BITS	32
  
  extern machreg_t _inet_makeaddr (machreg_t, machreg_t);
  
  /* <arpa/inet.h> has
  
  	struct in_addr inet_makeaddr (int, int);		(IRIX 6.2)
  	struct in_addr inet_makeaddr (in_addr_t, in_addr_t);	(IRIX 6.5)  */
  
*************** inet_makeaddr (machreg_t net, machreg_t 
*** 125,148 ****
  {
    return _inet_makeaddr (net, lna) >> SHIFT_BITS;
  }
- 
- #if _MIPS_SIM == _ABIN32
- extern machreg_t semctl (machreg_t, machreg_t, machreg_t, machreg_t);
- extern machreg_t _semctl (machreg_t, machreg_t, machreg_t, machreg_t);
- 
- /* <sys/sem.h> has
- 
- 	int semctl (int, int, int, ...);
- 
-    where the variadic argument is union semun if used.  union semun contains
-    an int and two pointers, so the union is already 64 bits wide under the
-    N64 ABI and alignment is not an issue.  */
- 
- machreg_t
- semctl (machreg_t semid, machreg_t semnum, machreg_t cmd, machreg_t arg)
- {
-   return _semctl(semid, semnum, cmd, arg << SHIFT_BITS);
- }
- #endif /* _ABIN32 */
  
  #endif /* _ABIN32 || _ABI64 */
--- 78,82 ----



More information about the Gcc-patches mailing list