Fix for GCC/G++ 1.37 -fpcc-struct-return under SCO UNIX

Chip Salzenberg chip at tct.uucp
Thu Jan 3 06:26:48 AEST 1991


This file is a shar archive containing patches for GCC 1.37 and
G++ 1.37.1 to generate correct code for -fpcc-struct-return under
SCO UNIX/386 and possibly other 386 operating systems.

As distributed, GCC -fpcc-struct-return assumes that a function that
returns a structure will pop the return-area pointer from the stack
using the "ret 4" instruction, thus leaving only the normal function
parameters on the stack to be removed by the caller.

At least under SCO UNIX, the system C compiler doesn't work that way.
Instead, the function returning the structure is expected to return
normally using a simple "ret" instruction, and both the return-area
pointer and the normal arguments must be removed from the stack by the
caller.

With these patches GCC and G++ with -fpcc-struct-return let the caller
remove all function arguments, including the return-area pointer, and
make the function returning the structure finish with a simple "ret".
This change allows GCC and G++ to work with standard SCO library
functions that return structures, such as div(), ldiv(), and the dbm
library.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  GCC.struct G++.struct
# Wrapped by chip at tct on Wed Jan  2 14:10:43 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'GCC.struct' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'GCC.struct'\"
else
echo shar: Extracting \"'GCC.struct'\" \(5012 characters\)
sed "s/^X//" >'GCC.struct' <<'END_OF_FILE'
XIndex: expr.c
X***************
X*** 4010,4016 ****
X    funtype = TREE_TYPE (funtype);
X  
X!   /* If struct_value_rtx is 0, it means pass the address
X!      as if it were an extra parameter.  */
X!   if (structure_value_addr && struct_value_rtx == 0)
X      {
X        rtx tem;
X--- 4010,4018 ----
X    funtype = TREE_TYPE (funtype);
X  
X!   /* If structure_value_addr is set, it means pass the address
X!      as if it were an extra parameter.  But this is only done in
X!      the normal, straightforward way if we're using the old PCC
X!      structure return convention.  */
X!   if (structure_value_addr && flag_pcc_struct_return)
X      {
X        rtx tem;
X***************
X*** 4027,4032 ****
X  				       force_reg (Pmode, structure_value_addr)),
X  				actparms);
X- 	  structure_value_addr_parm = 1;
X  	}
X      }
X  
X--- 4029,4034 ----
X  				       force_reg (Pmode, structure_value_addr)),
X  				actparms);
X  	}
X+       structure_value_addr_parm = 1;
X      }
X  
X***************
X*** 4439,4443 ****
X      adjust_stack (protected_stack);
X  
X!   /* Pass the function the address in which to return a structure value.  */
X    if (structure_value_addr && ! structure_value_addr_parm)
X      emit_move_insn (struct_value_rtx,
X--- 4441,4448 ----
X      adjust_stack (protected_stack);
X  
X!   /* If the function will be returning a structure, and if the address in
X!      which to return the value isn't being passed as a parameter, pass it
X!      now.  This may result in a register move or in a push; if it's a push,
X!      we count on the called routine to pop it.  */
X    if (structure_value_addr && ! structure_value_addr_parm)
X      emit_move_insn (struct_value_rtx,
X***************
X*** 4482,4494 ****
X  
X    /* Figure out the register where the value, if any, will come back.  */
X!   valreg = 0;
X!   if (TYPE_MODE (TREE_TYPE (exp)) != VOIDmode
X!       && ! structure_value_addr)
X!     {
X!       if (pcc_struct_value)
X! 	valreg = hard_libcall_value (Pmode);
X!       else
X! 	valreg = hard_function_value (TREE_TYPE (exp), fndecl);
X!     }
X  
X    /* Generate the actual call instruction.  */
X--- 4487,4497 ----
X  
X    /* Figure out the register where the value, if any, will come back.  */
X!   if (pcc_struct_value)
X!     valreg = hard_libcall_value (Pmode);
X!   else if (TYPE_MODE (TREE_TYPE (exp)) != VOIDmode
X! 	   && ! structure_value_addr)
X!     valreg = hard_function_value (TREE_TYPE (exp), fndecl);
X!   else
X!     valreg = 0;
X  
X    /* Generate the actual call instruction.  */
X***************
X*** 4542,4555 ****
X        target = const0_rtx;
X      }
X-   else if (structure_value_addr)
X-     {
X-       if (target == 0 || GET_CODE (target) != MEM)
X- 	target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
X- 			  memory_address (BLKmode, structure_value_addr));
X-     }
X    else if (pcc_struct_value)
X      {
X-       valreg = hard_function_value (build_pointer_type (TREE_TYPE (exp)),
X- 				    fndecl);
X        if (target == 0)
X  	target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
X--- 4545,4550 ----
X***************
X*** 4562,4565 ****
X--- 4557,4566 ----
X  			 expr_size (exp),
X  			 TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
X+     }
X+   else if (structure_value_addr)
X+     {
X+       if (target == 0 || GET_CODE (target) != MEM)
X+ 	target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
X+ 			  memory_address (BLKmode, structure_value_addr));
X      }
X    else if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)))
X
XIndex: config/out-i386.c
X***************
X*** 801,810 ****
X    register int nregs, limit;
X    int assure_sp_pos;
X    extern int frame_pointer_needed;
X    extern int current_function_pops_args;
X    extern int current_function_args_size;
X    limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
X    nregs = 0;
X! 
X  
X    for (regno = (limit -1); regno >= 0; regno--)
X--- 801,814 ----
X    register int nregs, limit;
X    int assure_sp_pos;
X+   int return_struct_adjust;
X    extern int frame_pointer_needed;
X    extern int current_function_pops_args;
X    extern int current_function_args_size;
X+   extern int flag_pcc_struct_return;
X+ 
X    limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
X    nregs = 0;
X!   return_struct_adjust = (current_function_returns_struct
X! 			  && !flag_pcc_struct_return) ? 4 : 0;
X  
X    for (regno = (limit -1); regno >= 0; regno--)
X***************
X*** 836,843 ****
X    if (current_function_pops_args && current_function_args_size)
X      fprintf (file, "\tret %s%d\n", IP,
X! 	     (current_function_args_size
X! 	      + (current_function_returns_struct ? 4 : 0)));
X!   else if (current_function_returns_struct)
X!     fprintf (file, "\tret %s4\n", IP);
X    else
X      fprintf (file, "\tret\n");
X--- 840,846 ----
X    if (current_function_pops_args && current_function_args_size)
X      fprintf (file, "\tret %s%d\n", IP,
X! 	     (current_function_args_size + return_struct_adjust));
X!   else if (return_struct_adjust)
X!     fprintf (file, "\tret %s%d\n", IP, return_struct_adjust);
X    else
X      fprintf (file, "\tret\n");
END_OF_FILE
if test 5012 -ne `wc -c <'GCC.struct'`; then
    echo shar: \"'GCC.struct'\" unpacked with wrong size!
fi
# end of 'GCC.struct'
fi
if test -f 'G++.struct' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'G++.struct'\"
else
echo shar: Extracting \"'G++.struct'\" \(3391 characters\)
sed "s/^X//" >'G++.struct' <<'END_OF_FILE'
XIndex: expr.c
X***************
X*** 4323,4329 ****
X    funtype = TREE_TYPE (funtype);
X  
X!   /* If struct_value_rtx is 0, it means pass the address
X!      as if it were an extra parameter.  */
X!   if (structure_value_addr && struct_value_rtx == 0)
X      {
X        rtx tem;
X--- 4323,4331 ----
X    funtype = TREE_TYPE (funtype);
X  
X!   /* If structure_value_addr is set, it means pass the address
X!      as if it were an extra parameter.  But this is only done in
X!      the normal, straightforward way if we're using the old PCC
X!      structure return convention.  */
X!   if (structure_value_addr && flag_pcc_struct_return)
X      {
X        rtx tem;
X***************
X*** 4340,4345 ****
X  				       force_reg (Pmode, structure_value_addr)),
X  				actparms);
X- 	  structure_value_addr_parm = 1;
X  	}
X      }
X  
X--- 4342,4347 ----
X  				       force_reg (Pmode, structure_value_addr)),
X  				actparms);
X  	}
X+       structure_value_addr_parm = 1;
X      }
X  
X***************
X*** 4730,4737 ****
X  
X    /* Figure out the register where the value, if any, will come back.  */
X!   valreg = 0;
X!   if (TYPE_MODE (TREE_TYPE (exp)) != VOIDmode
X!       && TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
X      valreg = hard_function_value (TREE_TYPE (exp), fndecl);
X  
X    /* Now compute and store all non-register parms.
X--- 4732,4743 ----
X  
X    /* Figure out the register where the value, if any, will come back.  */
X!   if (pcc_struct_value)
X!     valreg = hard_libcall_value (Pmode);
X!   else if (TYPE_MODE (TREE_TYPE (exp)) != VOIDmode
X! 	   && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
X! 	   && ! structure_value_addr)
X      valreg = hard_function_value (TREE_TYPE (exp), fndecl);
X+   else
X+     valreg = 0;
X  
X    /* Now compute and store all non-register parms.
X***************
X*** 4767,4771 ****
X      adjust_stack (protected_stack);
X  
X!   /* Pass the function the address in which to return a structure value.  */
X    if (structure_value_addr && ! structure_value_addr_parm)
X      emit_move_insn (struct_value_rtx,
X--- 4773,4780 ----
X      adjust_stack (protected_stack);
X  
X!   /* If the function will be returning a structure, and if the address in
X!      which to return the value isn't being passed as a parameter, pass it
X!      now.  This may result in a register move or in a push; if it's a push,
X!      we count on the called routine to pop it.  */
X    if (structure_value_addr && ! structure_value_addr_parm)
X      emit_move_insn (struct_value_rtx,
X***************
X*** 4859,4872 ****
X        target = const0_rtx;
X      }
X-   else if (structure_value_addr)
X-     {
X-       if (target == 0 || GET_CODE (target) != MEM)
X- 	target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
X- 			  memory_address (BLKmode, structure_value_addr));
X-     }
X    else if (pcc_struct_value)
X      {
X-       valreg = hard_function_value (build_pointer_type (TREE_TYPE (exp)),
X- 				    fndecl);
X        if (target == 0)
X  	target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
X--- 4868,4873 ----
X***************
X*** 4879,4882 ****
X--- 4880,4889 ----
X  			 expr_size (exp),
X  			 TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
X+     }
X+   else if (structure_value_addr)
X+     {
X+       if (target == 0 || GET_CODE (target) != MEM)
X+ 	target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
X+ 			  memory_address (BLKmode, structure_value_addr));
X      }
X    else if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)))
END_OF_FILE
if test 3391 -ne `wc -c <'G++.struct'`; then
    echo shar: \"'G++.struct'\" unpacked with wrong size!
fi
# end of 'G++.struct'
fi
echo shar: End of shell archive.
exit 0
-- 
Chip Salzenberg at Teltronics/TCT     <chip at tct.uucp>, <uunet!pdn!tct!chip>
"Please don't send me any more of yer scandalous email, Mr. Salzenberg..."
		-- Bruce Becker



More information about the Comp.unix.sysv386 mailing list