[patch] convert some call ABI macros to hooks, apply to sh, add bitfield swapper

DJ Delorie dj@redhat.com
Thu Aug 14 01:32:00 GMT 2003


This patch is bigger than I expected, but it accomplishes a single
goal - it improves the Renesas ABI support in the sh backend,
including the ability to link gcc and shc objects together.

It includes a bunch of macro->hook conversions, mostly because the
hooks need an additional parameter (the function) to detect which ones
are Renesas ABI and which are GCC ABI.  The underlying structure of
the new hooks matches the design we discussed a few weeks ago, so no
other backends needed to be converted (yet).

It includes a hook to reverse the way bitfields are laid out, as SHC
lays them out in an endian-neutral way and we had no other way to
specify that.

Some of the HUGE macros in sh.h I had to move to functions in sh.c
just because I couldn't follow them otherwise.

It also includes a patch to support -mrenesas as an alias for
-mhitachi.  A similar patch was approved long ago but never applied.

Tested on sh-elf, x86-linux, and (mostly) xstormy16-elf (no sid, I
need to restart the tests, but the build and compile tests worked).

2003-08-13  DJ Delorie  <dj@redhat.com>

	* targhooks.c: New file.
	* targhooks.h: New file.
	* Makefile.in: Add targhooks.o support.
	(function.o): Depend on$(TARGET_H).
	(stmt.o): Likewise.
	(combine.o): Depend on $(TREE_H) and $(TARGET_H).
	* builtins.c (apply_args_size, expand_builtin_apply_args_1,
	expand_builtin_apply): Convert to calls.struct_value_rtx hook.
	(expand_builtin_saveregs): Convert to
	calls.expand_builtin_saveregs hook.
	* c-decl.c (start_decl): Handle new calls.promote_prototypes hook
	here, instead of ...
	(get_parm_info) ... here.
	(store_parm_decls_oldstyle): Convert to calls.promote_prototypes
	hook.
	(finish_function): Handle calls.promote_prototypes hook here too.
	* c-typeck.c (convert_arguments): Convert to
	calls.promote_prototypes hook.
	(c_convert_parm_for_inlining): Likewise.
	* calls.c (initialize_argument_information): Convert to
	calls.promote_function_args hook.
	(expand_call): Convert to calls.struct_value_rtx,
	calls.strict_argument_naming,
	calls.pretend_outgoing_varargs_named, and
	calls.promote_function_return hooks.  Pass fndecl to
	aggregate_value_p.  Initialize CUMULATIVE_ARGS before calling
	hooks, so they can use that.
	(emit_library_call_value_1): Likewise.
	* combine.c (setup_incoming_promotions): Convert to
	calls.promote_function_args hook.
	* emit-rtl.c: Convert to calls.struct_value_rtx hook.
	* expr.c (expand_assignment): Pass call to aggregate_value_p.
	(expand_expr): Likewise.
	* expr.h: Remove support for SETUP_INCOMING_VARARGS,
	STRICT_ARGUMENT_NAMING, PRETEND_OUTGOING_VARARGS_NAMED,
	RETURN_IN_MEMORY macro defaults.
	* final.c (profile_function): Convert to calls.struct_value_rtx
	hook.
	* function.c (aggregate_value_p): Accept function type tree as
	second parameter; try to deduce fntype from it.  Convert to
	calls.return_in_memory hook.
	(assign_parms): Convert to calls.setup_incoming_varargs,
	calls.strict_argument_naming, calls.promote_function_args,
	calls.pretend_outgoing_varargs_named hooks.  Pass fndecl to
	aggregate_value_p.
	(init_function_start): Pass subr to aggregate_value_p.
	(expand_function_start): Likewise.  Convert to
	calls.struct_value_rtx hook.
	(expand_function_end): Convert to calls.promote_function_return hook.
	* hard-reg-set.h: Update comments to new hook names.
	* integrate.c (expand_inline_function): Pass fndecl to aggregate_value_p.
	* reg-stack.c (stack_result): Likewise.
	* rtl.h (struct_value_rtx, struct_value_incoming_rtx): Delete.
	* stmt.c (expand_value_return): Convert to
	calls.promote_function_return hook.
	* stor-layout.c (reverse_bitfield_layout): New.
	(finish_record_layout): Call it when appropriate.
	* target-def.h: Add TARGET_REVERSE_BITFIELD_LAYOUT_P,
	TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN,
	TARGET_PROMOTE_PROTOTYPES, TARGET_STRUCT_VALUE_RTX,
	TARGET_RETURN_IN_MEMORY, TARGET_EXPAND_BUILTIN_SAVEREGS,
	TARGET_SETUP_INCOMING_VARARGS, TARGET_STRICT_ARGUMENT_NAMING,
	TARGET_PRETEND_OUTGOING_VARARGS_NAMED, and TARGET_CALLS.
	* target.h: Likewise.
	* tree.h (aggregate_value_p): Also takes a tree to deduce function
	attributes from (for target hooks).
	* doc/tm.texi (PROMOTE_FUNCTION_ARGS, PROMOTE_FUNCTION_RETURN,
	PROMOTE_PROTOTYPES, RETURN_IN_MEMORY, STRUCT_VALUE_REGNUM,
	STRUCT_VALUE, STRUCT_VALUE_INCOMING_REGNUM, STRUCT_VALUE_INCOMING,
	EXPAND_BUILTIN_SAVEREGS, SETUP_INCOMING_VARARGS,
	STRICT_ARGUMENT_NAMING, PRETEND_OUTGOING_VARARGS_NAMED): Convert
	to hooks.
	(TARGET_REVERSE_BITFIELD_LAYOUT_P): New.
	
	* config/alpha/alpha.c (alpha_output_mi_thunk_osf): Pass function
	to aggregate_value_p.
	* config/arm/arm.c (arm_init_cumulative_args,
	arm_output_mi_thunk): Likewise.
	* config/i386/i386.c (ix86_return_pops_args, x86_this_parameter):
	Likewise.
	* config/mips/mips.c (mips_save_reg_p, mips_expand_prologue,
	mips_can_use_return_insn): Likewise.
	* config/rs6000/rs6000.c (rs6000_output_mi_thunk): Likewise.
	* config/s390/s390.c (s390_output_mi_thunk): Likewise.
	* config/sparc/sparc.c (sparc_output_mi_thunk): Pass function to
	aggregate_value_p.
	* config/story16/stormy16.c (xstormy16_asm_output_mi_thunk): Pass
	function to aggregate_value_p.
	
	* config/sh/sh-protos.h (sh_builtin_saveregs): Remove.
	(sh_attr_renesas_p, sh_cfun_attr_renesas_p, sh_function_arg,
	sh_function_arg_advance, sh_pass_in_reg_p): New.
	* config/sh/sh.c (sh_handle_renesas_attribute,
	sh_reverse_bitfield_layout_p, sh_promote_prototypes,
	sh_struct_value_rtx, sh_return_in_memory, sh_builtin_saveregs,
	sh_setup_incoming_varargs, sh_strict_argument_naming,
	sh_pretend_outgoing_varargs_named): New decls.
	(targetm): Add new hooks.
	(calc_live_regs): Save MACL and MACH if the function has the
	renesas attribute.
	(sh_expand_prologue): Support renesas attribute.
	(sh_builtin_saveregs): Make static.
	(sh_build_va_list): Support renesas attribute.
	(sh_va_start): Likewise.
	(sh_va_arg): Likewise.
	(sh_promote_prototypes): New.
	(sh_function_arg): New, moved from sh.h.  Support renesas
	attribute.
	(sh_function_arg_advance): Likewise.
	(sh_return_in_memory): Likewise.
	(sh_strict_argument_naming): Likewise.
	(sh_pretend_outgoing_varargs_named): Likewise.
	(sh_struct_value_rtx): New.
	(sh_attribute): Add renesas attribute.
	(sh_handle_renesas_attribute): New.
	(sh_attr_renesas_p, sh_cfun_attr_renesas_p): New.
	(sh_ms_bitfield_layout_p): Support renesas attribute also.
	(sh_reverse_bitfield_layout_p): New.
	(sh_output_mi_thunk): Pass function to aggregate_value_p.
	* config/sh/sh.h (TARGET_SWITCHES): Add -mrenesas as an alias for
	-mhitachi.
	(STRUCT_VALUE_REGNUM, STRUCT_VALUE, RETURN_IN_MEMORY): Moved to
	target hooks.
	(sh_args): Add renesas_abi flag.
	(INIT_CUMULATIVE_ARGS): Set it.  Pass fndecl to aggregate_value_p.
	(FUNCTION_ARG_ADVANCE, FUNCTION_ARG): Move to sh.c.
	(PASS_IN_REG_P): Support renesas attribute.  Pass DF and TF on the
	stack for the renesas abi.
	(STRICT_ARGUMENT_NAMING, PRETEND_OUTGOING_VARARGS_NAMED,
	SETUP_INCOMING_VARARGS, EXPAND_BUILTIN_SAVEREGS,
	PROMOTE_PROTOTYPES): Moved to sh.c.

? targhooks.h
? targhooks.c
[appended at the end]
	
Index: Makefile.in
===================================================================
RCS file: /cvs/uberbaum/gcc/Makefile.in,v
retrieving revision 1.1138
diff -p -2 -r1.1138  Makefile.in
*** Makefile.in	12 Aug 2003 01:14:58 -0000	1.1138
--- Makefile.in	14 Aug 2003 00:39:12 -0000
*************** OBJS-common = \
*** 828,832 ****
   sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o	   \
   sibcall.o simplify-rtx.o sreal.o ssa.o ssa-ccp.o ssa-dce.o stmt.o	   \
!  stor-layout.o stringpool.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
   unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o		   \
   alloc-pool.o et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) 
--- 828,832 ----
   sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o	   \
   sibcall.o simplify-rtx.o sreal.o ssa.o ssa-ccp.o ssa-dce.o stmt.o	   \
!  stor-layout.o stringpool.o targhooks.o timevar.o toplev.o tracer.o tree.o tree-dump.o \
   unroll.o varasm.o varray.o version.o vmsdbgout.o xcoffout.o		   \
   alloc-pool.o et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) 
*************** opts.o : opts.c opts.h options.h toplev.
*** 1490,1493 ****
--- 1490,1496 ----
  	coretypes.h $(TREE_H) $(TM_H) $(LANGHOOKS_H) $(GGC_H) $(RTL_H) \
  	output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h
+ targhooks.o : targhooks.c targhooks.h $(CONFIG_H) $(SYSTEM_H) \
+ 	coretypes.h $(TREE_H) $(TM_H) $(RTL_H) $(TM_P_H) function.h toplev.h
+ 
  toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
     function.h flags.h xcoffout.h input.h $(INSN_ATTR_H) output.h $(DIAGNOSTIC_H) \
*************** function.o : function.c $(CONFIG_H) $(SY
*** 1528,1536 ****
     flags.h function.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h \
     insn-config.h $(RECOG_H) output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) \
!    $(TM_P_H) langhooks.h gt-function.h
  stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \
     function.h insn-config.h hard-reg-set.h $(EXPR_H) libfuncs.h except.h \
     $(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H) \
!    langhooks.h $(PREDICT_H) gt-stmt.h $(OPTABS_H)
  except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
     flags.h except.h function.h $(EXPR_H) libfuncs.h $(INTEGRATE_H) langhooks.h \
--- 1531,1539 ----
     flags.h function.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h \
     insn-config.h $(RECOG_H) output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) \
!    $(TM_P_H) langhooks.h gt-function.h $(TARGET_H)
  stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \
     function.h insn-config.h hard-reg-set.h $(EXPR_H) libfuncs.h except.h \
     $(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H) \
!    langhooks.h $(PREDICT_H) gt-stmt.h $(OPTABS_H) $(TARGET_H)
  except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
     flags.h except.h function.h $(EXPR_H) libfuncs.h $(INTEGRATE_H) langhooks.h \
*************** et-forest.o : et-forest.c $(CONFIG_H) $(
*** 1698,1702 ****
  combine.o : combine.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
     function.h insn-config.h $(INSN_ATTR_H) $(REGS_H) $(EXPR_H) \
!    $(BASIC_BLOCK_H) $(RECOG_H) real.h hard-reg-set.h toplev.h $(TM_P_H)
  regclass.o : regclass.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     hard-reg-set.h flags.h $(BASIC_BLOCK_H) $(REGS_H) insn-config.h $(RECOG_H) reload.h \
--- 1701,1705 ----
  combine.o : combine.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \
     function.h insn-config.h $(INSN_ATTR_H) $(REGS_H) $(EXPR_H) \
!    $(BASIC_BLOCK_H) $(RECOG_H) real.h hard-reg-set.h toplev.h $(TM_P_H) $(TREE_H) $(TARGET_H)
  regclass.o : regclass.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     hard-reg-set.h flags.h $(BASIC_BLOCK_H) $(REGS_H) insn-config.h $(RECOG_H) reload.h \
Index: builtins.c
===================================================================
RCS file: /cvs/uberbaum/gcc/builtins.c,v
retrieving revision 1.237
diff -p -2 -r1.237  builtins.c
*** builtins.c	11 Aug 2003 03:15:14 -0000	1.237
--- builtins.c	14 Aug 2003 00:39:13 -0000
*************** apply_args_size (void)
*** 940,944 ****
        /* The second value is the structure value address unless this is
  	 passed as an "invisible" first argument.  */
!       if (struct_value_rtx)
  	size += GET_MODE_SIZE (Pmode);
  
--- 940,944 ----
        /* The second value is the structure value address unless this is
  	 passed as an "invisible" first argument.  */
!       if (targetm.calls.struct_value_rtx (TREE_TYPE (cfun->decl), 0))
  	size += GET_MODE_SIZE (Pmode);
  
*************** expand_builtin_apply_args_1 (void)
*** 1115,1118 ****
--- 1115,1119 ----
    int size, align, regno;
    enum machine_mode mode;
+   rtx struct_incoming_value = targetm.calls.struct_value_rtx (TREE_TYPE (cfun->decl), 1);
  
    /* Create a block where the arg-pointer, structure value address,
*************** expand_builtin_apply_args_1 (void)
*** 1122,1126 ****
    /* Walk past the arg-pointer and structure value address.  */
    size = GET_MODE_SIZE (Pmode);
!   if (struct_value_rtx)
      size += GET_MODE_SIZE (Pmode);
  
--- 1123,1127 ----
    /* Walk past the arg-pointer and structure value address.  */
    size = GET_MODE_SIZE (Pmode);
!   if (targetm.calls.struct_value_rtx (TREE_TYPE (cfun->decl), 0))
      size += GET_MODE_SIZE (Pmode);
  
*************** expand_builtin_apply_args_1 (void)
*** 1148,1155 ****
    /* Save the structure value address unless this is passed as an
       "invisible" first argument.  */
!   if (struct_value_incoming_rtx)
      {
        emit_move_insn (adjust_address (registers, Pmode, size),
! 		      copy_to_reg (struct_value_incoming_rtx));
        size += GET_MODE_SIZE (Pmode);
      }
--- 1149,1156 ----
    /* Save the structure value address unless this is passed as an
       "invisible" first argument.  */
!   if (struct_incoming_value)
      {
        emit_move_insn (adjust_address (registers, Pmode, size),
! 		      copy_to_reg (struct_incoming_value));
        size += GET_MODE_SIZE (Pmode);
      }
*************** expand_builtin_apply (rtx function, rtx 
*** 1209,1212 ****
--- 1210,1214 ----
    rtx old_stack_level = 0;
    rtx call_fusage = 0;
+   rtx struct_value = targetm.calls.struct_value_rtx (TREE_TYPE (cfun->decl), 0);
  
  #ifdef POINTERS_EXTEND_UNSIGNED
*************** expand_builtin_apply (rtx function, rtx 
*** 1262,1266 ****
    /* Walk past the arg-pointer and structure value address.  */
    size = GET_MODE_SIZE (Pmode);
!   if (struct_value_rtx)
      size += GET_MODE_SIZE (Pmode);
  
--- 1264,1268 ----
    /* Walk past the arg-pointer and structure value address.  */
    size = GET_MODE_SIZE (Pmode);
!   if (struct_value)
      size += GET_MODE_SIZE (Pmode);
  
*************** expand_builtin_apply (rtx function, rtx 
*** 1282,1292 ****
       "invisible" first argument.  */
    size = GET_MODE_SIZE (Pmode);
!   if (struct_value_rtx)
      {
        rtx value = gen_reg_rtx (Pmode);
        emit_move_insn (value, adjust_address (arguments, Pmode, size));
!       emit_move_insn (struct_value_rtx, value);
!       if (GET_CODE (struct_value_rtx) == REG)
! 	use_reg (&call_fusage, struct_value_rtx);
        size += GET_MODE_SIZE (Pmode);
      }
--- 1284,1294 ----
       "invisible" first argument.  */
    size = GET_MODE_SIZE (Pmode);
!   if (struct_value)
      {
        rtx value = gen_reg_rtx (Pmode);
        emit_move_insn (value, adjust_address (arguments, Pmode, size));
!       emit_move_insn (struct_value, value);
!       if (GET_CODE (struct_value) == REG)
! 	use_reg (&call_fusage, struct_value);
        size += GET_MODE_SIZE (Pmode);
      }
*************** expand_builtin_saveregs (void)
*** 3779,3797 ****
    start_sequence ();
  
- #ifdef EXPAND_BUILTIN_SAVEREGS
    /* Do whatever the machine needs done in this case.  */
!   val = EXPAND_BUILTIN_SAVEREGS ();
! #else
!   /* ??? We used to try and build up a call to the out of line function,
!      guessing about what registers needed saving etc.  This became much
!      harder with __builtin_va_start, since we don't have a tree for a
!      call to __builtin_saveregs to fall back on.  There was exactly one
!      port (i860) that used this code, and I'm unconvinced it could actually
!      handle the general case.  So we no longer try to handle anything
!      weird and make the backend absorb the evil.  */
! 
!   error ("__builtin_saveregs not supported by this target");
!   val = const0_rtx;
! #endif
  
    seq = get_insns ();
--- 3781,3786 ----
    start_sequence ();
  
    /* Do whatever the machine needs done in this case.  */
!   val = targetm.calls.expand_builtin_saveregs ();
  
    seq = get_insns ();
Index: c-decl.c
===================================================================
RCS file: /cvs/uberbaum/gcc/c-decl.c,v
retrieving revision 1.430
diff -p -2 -r1.430  c-decl.c
*** c-decl.c	9 Aug 2003 21:59:01 -0000	1.430
--- c-decl.c	14 Aug 2003 00:39:13 -0000
*************** start_decl (tree declarator, tree declsp
*** 2672,2675 ****
--- 2672,2695 ----
  
    if (TREE_CODE (decl) == FUNCTION_DECL
+       && targetm.calls.promote_prototypes (TREE_TYPE (decl)))
+     {
+       tree ce = declarator;
+ 
+       if (TREE_CODE (ce) == INDIRECT_REF)
+ 	ce = TREE_OPERAND (declarator, 0);
+       if (TREE_CODE (ce) == CALL_EXPR)
+ 	{
+ 	  tree args = TREE_PURPOSE (TREE_OPERAND (ce, 1));
+ 	  for (; args; args = TREE_CHAIN (args))
+ 	    {
+ 	      tree type = TREE_TYPE (args);
+ 	      if (INTEGRAL_TYPE_P (type)
+ 		  && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ 		DECL_ARG_TYPE (args) = integer_type_node;
+ 	    }
+ 	}
+     }
+ 
+   if (TREE_CODE (decl) == FUNCTION_DECL
        && DECL_DECLARED_INLINE_P (decl)
        && DECL_UNINLINABLE (decl)
*************** get_parm_info (int void_at_end)
*** 4573,4580 ****
        type = TREE_TYPE (decl);
        DECL_ARG_TYPE (decl) = type;
-       if (PROMOTE_PROTOTYPES
- 	  && INTEGRAL_TYPE_P (type)
- 	  && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
- 	DECL_ARG_TYPE (decl) = integer_type_node;
  
        /* Check for (..., void, ...) and issue an error.  */
--- 4593,4596 ----
*************** store_parm_decls_oldstyle (void)
*** 5932,5936 ****
  		  DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
  
! 		  if (PROMOTE_PROTOTYPES
  		      && INTEGRAL_TYPE_P (TREE_TYPE (parm))
  		      && TYPE_PRECISION (TREE_TYPE (parm))
--- 5948,5952 ----
  		  DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
  
! 		  if (targetm.calls.promote_prototypes (TREE_TYPE (current_function_decl))
  		      && INTEGRAL_TYPE_P (TREE_TYPE (parm))
  		      && TYPE_PRECISION (TREE_TYPE (parm))
*************** finish_function (int nested, int can_def
*** 6085,6088 ****
--- 6101,6117 ----
        pushlevel (0);
        poplevel (0, 0, 0);
+     }
+ 
+   if (TREE_CODE (fndecl) == FUNCTION_DECL
+       && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
+     {
+       tree args = DECL_ARGUMENTS (fndecl);
+       for (; args; args = TREE_CHAIN (args))
+  	{
+  	  tree type = TREE_TYPE (args);
+  	  if (INTEGRAL_TYPE_P (type)
+  	      && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+  	    DECL_ARG_TYPE (args) = integer_type_node;
+  	}
      }
  
Index: c-typeck.c
===================================================================
RCS file: /cvs/uberbaum/gcc/c-typeck.c,v
retrieving revision 1.252
diff -p -2 -r1.252  c-typeck.c
*** c-typeck.c	12 Aug 2003 01:45:23 -0000	1.252
--- c-typeck.c	14 Aug 2003 00:39:13 -0000
*************** convert_arguments (tree typelist, tree v
*** 1838,1842 ****
  						fundecl, name, parmnum + 1);
  
! 	      if (PROMOTE_PROTOTYPES
  		  && INTEGRAL_TYPE_P (type)
  		  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
--- 1838,1842 ----
  						fundecl, name, parmnum + 1);
  
! 	      if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
  		  && INTEGRAL_TYPE_P (type)
  		  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
*************** c_convert_parm_for_inlining (tree parm, 
*** 3587,3591 ****
  				(char *) 0 /* arg passing  */, fn,
  				DECL_NAME (fn), 0);
!   if (PROMOTE_PROTOTYPES
        && INTEGRAL_TYPE_P (type)
        && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
--- 3587,3591 ----
  				(char *) 0 /* arg passing  */, fn,
  				DECL_NAME (fn), 0);
!   if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
        && INTEGRAL_TYPE_P (type)
        && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
Index: calls.c
===================================================================
RCS file: /cvs/uberbaum/gcc/calls.c,v
retrieving revision 1.292
diff -p -2 -r1.292  calls.c
*** calls.c	6 Aug 2003 03:26:17 -0000	1.292
--- calls.c	14 Aug 2003 00:39:14 -0000
***************
*** 1,4 ****
  /* Convert function calls to rtl insns, for GNU C compiler.
!    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
     1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
  
--- 1,4 ----
  /* Convert function calls to rtl insns, for GNU C compiler.
!    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003
     1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
  
*************** initialize_argument_information (int num
*** 1178,1184 ****
        unsignedp = TREE_UNSIGNED (type);
  
! #ifdef PROMOTE_FUNCTION_ARGS
!       mode = promote_mode (type, mode, &unsignedp, 1);
! #endif
  
        args[i].unsignedp = unsignedp;
--- 1178,1183 ----
        unsignedp = TREE_UNSIGNED (type);
  
!       if (targetm.calls.promote_function_args (fndecl ? TREE_TYPE (fndecl) : 0))
! 	mode = promote_mode (type, mode, &unsignedp, 1);
  
        args[i].unsignedp = unsignedp;
*************** expand_call (tree exp, rtx target, int i
*** 2053,2056 ****
--- 2052,2056 ----
       by returning the address of where to find it.  */
    int pcc_struct_value = 0;
+   rtx struct_value = 0;
  
    /* Number of actual parameters in this call, including struct value addr.  */
*************** expand_call (tree exp, rtx target, int i
*** 2168,2171 ****
--- 2168,2173 ----
      flags |= flags_from_decl_or_type (TREE_TYPE (TREE_TYPE (p)));
  
+   struct_value = targetm.calls.struct_value_rtx (fndecl ? TREE_TYPE (fndecl) : 0, 0);
+ 
    /* Warn if this value is an aggregate type,
       regardless of which calling convention we are using for it.  */
*************** expand_call (tree exp, rtx target, int i
*** 2215,2219 ****
  
    /* Cater to broken compilers.  */
!   if (aggregate_value_p (exp))
      {
        /* This call returns a big structure.  */
--- 2217,2221 ----
  
    /* Cater to broken compilers.  */
!   if (aggregate_value_p (exp, fndecl))
      {
        /* This call returns a big structure.  */
*************** expand_call (tree exp, rtx target, int i
*** 2309,2313 ****
    /* If struct_value_rtx is 0, it means pass the address
       as if it were an extra parameter.  */
!   if (structure_value_addr && struct_value_rtx == 0)
      {
        /* If structure_value_addr is a REG other than
--- 2311,2315 ----
    /* If struct_value_rtx is 0, it means pass the address
       as if it were an extra parameter.  */
!   if (structure_value_addr && struct_value == 0)
      {
        /* If structure_value_addr is a REG other than
*************** expand_call (tree exp, rtx target, int i
*** 2335,2338 ****
--- 2337,2348 ----
      num_actuals++;
  
+   /* Start updating where the next arg would go.
+ 
+      On some machines (such as the PA) indirect calls have a difuferent
+      calling convention than normal calls.  The last argument in
+      INIT_CUMULATIVE_ARGS tells the backend if this is an indirect call
+      or not.  */
+   INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX, fndecl);
+ 
    /* Compute number of named args.
       Normally, don't include the last named arg if anonymous args follow.
*************** expand_call (tree exp, rtx target, int i
*** 2351,2361 ****
       them into memory.  */
  
!   if ((STRICT_ARGUMENT_NAMING
!        || ! PRETEND_OUTGOING_VARARGS_NAMED)
        && type_arg_types != 0)
      n_named_args
        = (list_length (type_arg_types)
  	 /* Don't include the last named arg.  */
! 	 - (STRICT_ARGUMENT_NAMING ? 0 : 1)
  	 /* Count the struct value address, if it is passed as a parm.  */
  	 + structure_value_addr_parm);
--- 2361,2371 ----
       them into memory.  */
  
!   if ((targetm.calls.strict_argument_naming (&args_so_far)
!        || ! targetm.calls.pretend_outgoing_varargs_named (&args_so_far))
        && type_arg_types != 0)
      n_named_args
        = (list_length (type_arg_types)
  	 /* Don't include the last named arg.  */
! 	 - (targetm.calls.strict_argument_naming (&args_so_far) ? 0 : 1)
  	 /* Count the struct value address, if it is passed as a parm.  */
  	 + structure_value_addr_parm);
*************** expand_call (tree exp, rtx target, int i
*** 2364,2375 ****
      n_named_args = num_actuals;
  
-   /* Start updating where the next arg would go.
- 
-      On some machines (such as the PA) indirect calls have a different
-      calling convention than normal calls.  The last argument in
-      INIT_CUMULATIVE_ARGS tells the backend if this is an indirect call
-      or not.  */
-   INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX, fndecl);
- 
    /* Make a vector to hold all the information about each arg.  */
    args = alloca (num_actuals * sizeof (struct arg_data));
--- 2374,2377 ----
*************** expand_call (tree exp, rtx target, int i
*** 3009,3019 ****
  					(Pmode, structure_value_addr);
  #endif
! 	  emit_move_insn (struct_value_rtx,
  			  force_reg (Pmode,
  				     force_operand (structure_value_addr,
  						    NULL_RTX)));
  
! 	  if (GET_CODE (struct_value_rtx) == REG)
! 	    use_reg (&call_fusage, struct_value_rtx);
  	}
  
--- 3011,3021 ----
  					(Pmode, structure_value_addr);
  #endif
! 	  emit_move_insn (struct_value,
  			  force_reg (Pmode,
  				     force_operand (structure_value_addr,
  						    NULL_RTX)));
  
! 	  if (GET_CODE (struct_value) == REG)
! 	    use_reg (&call_fusage, struct_value);
  	}
  
*************** expand_call (tree exp, rtx target, int i
*** 3239,3243 ****
  	target = copy_to_reg (valreg);
  
! #ifdef PROMOTE_FUNCTION_RETURN
        /* If we promoted this return value, make the proper SUBREG.  TARGET
  	 might be const0_rtx here, so be careful.  */
--- 3241,3246 ----
  	target = copy_to_reg (valreg);
  
!       if (targetm.calls.promote_function_return(funtype))
! 	{
        /* If we promoted this return value, make the proper SUBREG.  TARGET
  	 might be const0_rtx here, so be careful.  */
*************** expand_call (tree exp, rtx target, int i
*** 3270,3274 ****
  	  SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
  	}
! #endif
  
        /* If size of args is variable or this was a constructor call for a stack
--- 3273,3277 ----
  	  SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
  	}
! 	}
  
        /* If size of args is variable or this was a constructor call for a stack
*************** emit_library_call_value_1 (int retval, r
*** 3579,3582 ****
--- 3582,3587 ----
    char *initial_stack_usage_map = stack_usage_map;
  
+   rtx struct_value = targetm.calls.struct_value_rtx (0, 0);
+ 
  #ifdef REG_PARM_STACK_SPACE
  #ifdef MAYBE_REG_PARM_STACK_SPACE
*************** emit_library_call_value_1 (int retval, r
*** 3631,3635 ****
      {
        tfom = (*lang_hooks.types.type_for_mode) (outmode, 0);
!       if (aggregate_value_p (tfom))
  	{
  #ifdef PCC_STATIC_STRUCT_RETURN
--- 3636,3640 ----
      {
        tfom = (*lang_hooks.types.type_for_mode) (outmode, 0);
!       if (aggregate_value_p (tfom, 0))
  	{
  #ifdef PCC_STATIC_STRUCT_RETURN
*************** emit_library_call_value_1 (int retval, r
*** 3686,3690 ****
    /* If there's a structure value address to be passed,
       either pass it in the special place, or pass it as an extra argument.  */
!   if (mem_value && struct_value_rtx == 0 && ! pcc_struct_value)
      {
        rtx addr = XEXP (mem_value, 0);
--- 3691,3695 ----
    /* If there's a structure value address to be passed,
       either pass it in the special place, or pass it as an extra argument.  */
!   if (mem_value && struct_value == 0 && ! pcc_struct_value)
      {
        rtx addr = XEXP (mem_value, 0);
*************** emit_library_call_value_1 (int retval, r
*** 4068,4079 ****
  
    /* Pass the function the address in which to return a structure value.  */
!   if (mem_value != 0 && struct_value_rtx != 0 && ! pcc_struct_value)
      {
!       emit_move_insn (struct_value_rtx,
  		      force_reg (Pmode,
  				 force_operand (XEXP (mem_value, 0),
  						NULL_RTX)));
!       if (GET_CODE (struct_value_rtx) == REG)
! 	use_reg (&call_fusage, struct_value_rtx);
      }
  
--- 4073,4084 ----
  
    /* Pass the function the address in which to return a structure value.  */
!   if (mem_value != 0 && struct_value != 0 && ! pcc_struct_value)
      {
!       emit_move_insn (struct_value,
  		      force_reg (Pmode,
  				 force_operand (XEXP (mem_value, 0),
  						NULL_RTX)));
!       if (GET_CODE (struct_value) == REG)
! 	use_reg (&call_fusage, struct_value);
      }
  
Index: combine.c
===================================================================
RCS file: /cvs/uberbaum/gcc/combine.c,v
retrieving revision 1.377
diff -p -2 -r1.377  combine.c
*** combine.c	31 Jul 2003 18:37:23 -0000	1.377
--- combine.c	14 Aug 2003 00:39:15 -0000
*************** Software Foundation, 59 Temple Place - S
*** 76,79 ****
--- 76,80 ----
  #include "tm.h"
  #include "rtl.h"
+ #include "tree.h"
  #include "tm_p.h"
  #include "flags.h"
*************** Software Foundation, 59 Temple Place - S
*** 89,92 ****
--- 90,94 ----
  #include "real.h"
  #include "toplev.h"
+ #include "target.h"
  
  /* It is not safe to use ordinary gen_lowpart in combine.
*************** static void
*** 800,804 ****
  setup_incoming_promotions (void)
  {
- #ifdef PROMOTE_FUNCTION_ARGS
    unsigned int regno;
    rtx reg;
--- 802,805 ----
*************** setup_incoming_promotions (void)
*** 807,827 ****
    rtx first = get_insns ();
  
  #ifndef OUTGOING_REGNO
  #define OUTGOING_REGNO(N) N
  #endif
!   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
!     /* Check whether this register can hold an incoming pointer
!        argument.  FUNCTION_ARG_REGNO_P tests outgoing register
!        numbers, so translate if necessary due to register windows.  */
!     if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (regno))
! 	&& (reg = promoted_input_arg (regno, &mode, &unsignedp)) != 0)
!       {
! 	record_value_for_reg
! 	  (reg, first, gen_rtx_fmt_e ((unsignedp ? ZERO_EXTEND
! 				       : SIGN_EXTEND),
! 				      GET_MODE (reg),
! 				      gen_rtx_CLOBBER (mode, const0_rtx)));
!       }
! #endif
  }
  
--- 808,830 ----
    rtx first = get_insns ();
  
+   if (targetm.calls.promote_function_args (TREE_TYPE (cfun->decl)))
+     {
  #ifndef OUTGOING_REGNO
  #define OUTGOING_REGNO(N) N
  #endif
!       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
! 	/* Check whether this register can hold an incoming pointer
! 	   argument.  FUNCTION_ARG_REGNO_P tests outgoing register
! 	   numbers, so translate if necessary due to register windows.  */
! 	if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (regno))
! 	    && (reg = promoted_input_arg (regno, &mode, &unsignedp)) != 0)
! 	  {
! 	    record_value_for_reg
! 	      (reg, first, gen_rtx_fmt_e ((unsignedp ? ZERO_EXTEND
! 					   : SIGN_EXTEND),
! 					  GET_MODE (reg),
! 					  gen_rtx_CLOBBER (mode, const0_rtx)));
! 	  }
!     }
  }
  
Index: emit-rtl.c
===================================================================
RCS file: /cvs/uberbaum/gcc/emit-rtl.c,v
retrieving revision 1.344
diff -p -2 -r1.344  emit-rtl.c
*** emit-rtl.c	19 Jul 2003 14:47:02 -0000	1.344
--- emit-rtl.c	14 Aug 2003 00:39:15 -0000
*************** REAL_VALUE_TYPE dconsthalf;
*** 133,138 ****
     In an inline procedure, the stack and frame pointer rtxs may not be
     used for anything else.  */
- rtx struct_value_rtx;		/* (REG:Pmode STRUCT_VALUE_REGNUM) */
- rtx struct_value_incoming_rtx;	/* (REG:Pmode STRUCT_VALUE_INCOMING_REGNUM) */
  rtx static_chain_rtx;		/* (REG:Pmode STATIC_CHAIN_REGNUM) */
  rtx static_chain_incoming_rtx;	/* (REG:Pmode STATIC_CHAIN_INCOMING_REGNUM) */
--- 133,136 ----
*************** init_emit_once (int line_numbers)
*** 5463,5483 ****
    return_address_pointer_rtx
      = gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);
- #endif
- 
- #ifdef STRUCT_VALUE
-   struct_value_rtx = STRUCT_VALUE;
- #else
-   struct_value_rtx = gen_rtx_REG (Pmode, STRUCT_VALUE_REGNUM);
- #endif
- 
- #ifdef STRUCT_VALUE_INCOMING
-   struct_value_incoming_rtx = STRUCT_VALUE_INCOMING;
- #else
- #ifdef STRUCT_VALUE_INCOMING_REGNUM
-   struct_value_incoming_rtx
-     = gen_rtx_REG (Pmode, STRUCT_VALUE_INCOMING_REGNUM);
- #else
-   struct_value_incoming_rtx = struct_value_rtx;
- #endif
  #endif
  
--- 5461,5464 ----
Index: expr.c
===================================================================
RCS file: /cvs/uberbaum/gcc/expr.c,v
retrieving revision 1.576
diff -p -2 -r1.576  expr.c
*** expr.c	12 Aug 2003 01:45:22 -0000	1.576
--- expr.c	14 Aug 2003 00:39:16 -0000
*************** expand_assignment (tree to, tree from, i
*** 4275,4279 ****
       needs to be done.  Handling this in the normal way is safe because no
       computation is done before the call.  */
!   if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from)
        && TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST
        && ! ((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL)
--- 4275,4279 ----
       needs to be done.  Handling this in the normal way is safe because no
       computation is done before the call.  */
!   if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from, from)
        && TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST
        && ! ((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL)
*************** expand_expr (tree exp, rtx target, enum 
*** 6706,6710 ****
        && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER)
        && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
!       && ! (code == CALL_EXPR && aggregate_value_p (exp)))
      target = 0;
  
--- 6706,6710 ----
        && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER)
        && ! (code == CONSTRUCTOR && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
!       && ! (code == CALL_EXPR && aggregate_value_p (exp, exp)))
      target = 0;
  
Index: expr.h
===================================================================
RCS file: /cvs/uberbaum/gcc/expr.h,v
retrieving revision 1.145
diff -p -2 -r1.145  expr.h
*** expr.h	15 Jul 2003 05:31:44 -0000	1.145
--- expr.h	14 Aug 2003 00:39:16 -0000
*************** tree split_complex_types (tree);
*** 170,200 ****
  tree split_complex_values (tree);
  
- /* Provide a default value for STRICT_ARGUMENT_NAMING.  */
- #ifndef STRICT_ARGUMENT_NAMING
- #define STRICT_ARGUMENT_NAMING 0
- #endif
- 
- /* Provide a default value for PRETEND_OUTGOING_VARARGS_NAMED.  */
- #ifdef SETUP_INCOMING_VARARGS
- #ifndef PRETEND_OUTGOING_VARARGS_NAMED
- #define PRETEND_OUTGOING_VARARGS_NAMED 1
- #endif
- #else
- /* It is an error to define PRETEND_OUTGOING_VARARGS_NAMED without
-    defining SETUP_INCOMING_VARARGS.  */
- #define PRETEND_OUTGOING_VARARGS_NAMED 0
- #endif
- 
  /* Nonzero if we do not know how to pass TYPE solely in registers.  */
  extern bool default_must_pass_in_stack (enum machine_mode, tree);
  #ifndef MUST_PASS_IN_STACK
  #define MUST_PASS_IN_STACK(MODE,TYPE) default_must_pass_in_stack(MODE, TYPE)
- #endif
- 
- /* Nonzero if type TYPE should be returned in memory.
-    Most machines can use the following default definition.  */
- 
- #ifndef RETURN_IN_MEMORY
- #define RETURN_IN_MEMORY(TYPE) (TYPE_MODE (TYPE) == BLKmode)
  #endif
  
--- 170,177 ----
Index: final.c
===================================================================
RCS file: /cvs/uberbaum/gcc/final.c,v
retrieving revision 1.289
diff -p -2 -r1.289  final.c
*** final.c	30 Jul 2003 17:27:06 -0000	1.289
--- final.c	14 Aug 2003 00:39:16 -0000
*************** profile_function (FILE *file ATTRIBUTE_U
*** 1419,1425 ****
  #endif
  #if defined(ASM_OUTPUT_REG_PUSH)
- #if defined(STRUCT_VALUE_INCOMING_REGNUM) || defined(STRUCT_VALUE_REGNUM)
    int sval = current_function_returns_struct;
! #endif
  #if defined(STATIC_CHAIN_INCOMING_REGNUM) || defined(STATIC_CHAIN_REGNUM)
    int cxt = current_function_needs_context;
--- 1419,1424 ----
  #endif
  #if defined(ASM_OUTPUT_REG_PUSH)
    int sval = current_function_returns_struct;
!   rtx svrtx = targetm.calls.struct_value_rtx (TREE_TYPE (current_function_decl), 1);
  #if defined(STATIC_CHAIN_INCOMING_REGNUM) || defined(STATIC_CHAIN_REGNUM)
    int cxt = current_function_needs_context;
*************** profile_function (FILE *file ATTRIBUTE_U
*** 1438,1451 ****
    function_section (current_function_decl);
  
! #if defined(STRUCT_VALUE_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
!   if (sval)
!     ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM);
! #else
! #if defined(STRUCT_VALUE_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
!   if (sval)
!     {
!       ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM);
!     }
! #endif
  #endif
  
--- 1437,1443 ----
    function_section (current_function_decl);
  
! #if defined(ASM_OUTPUT_REG_PUSH)
!   if (sval && GET_CODE (svrtx) == REG)
!     ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx));
  #endif
  
*************** profile_function (FILE *file ATTRIBUTE_U
*** 1476,1489 ****
  #endif
  
! #if defined(STRUCT_VALUE_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
!   if (sval)
!     ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM);
! #else
! #if defined(STRUCT_VALUE_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
!   if (sval)
!     {
!       ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM);
!     }
! #endif
  #endif
  }
--- 1468,1474 ----
  #endif
  
! #if defined(ASM_OUTPUT_REG_PUSH)
!   if (sval && GET_CODE (svrtx) == REG)
!     ASM_OUTPUT_REG_POP (file, REGNO (svrtx));
  #endif
  }
Index: function.c
===================================================================
RCS file: /cvs/uberbaum/gcc/function.c,v
retrieving revision 1.449
diff -p -2 -r1.449  function.c
*** function.c	25 Jul 2003 09:52:25 -0000	1.449
--- function.c	14 Aug 2003 00:39:16 -0000
*************** Software Foundation, 59 Temple Place - S
*** 63,66 ****
--- 63,67 ----
  #include "integrate.h"
  #include "langhooks.h"
+ #include "target.h"
  
  #ifndef TRAMPOLINE_ALIGNMENT
*************** get_first_nonparm_insn (void)
*** 4178,4182 ****
  
  int
! aggregate_value_p (tree exp)
  {
    int i, regno, nregs;
--- 4179,4183 ----
  
  int
! aggregate_value_p (tree exp, tree fntype)
  {
    int i, regno, nregs;
*************** aggregate_value_p (tree exp)
*** 4185,4191 ****
    tree type = (TYPE_P (exp)) ? exp : TREE_TYPE (exp);
  
    if (TREE_CODE (type) == VOID_TYPE)
      return 0;
!   if (RETURN_IN_MEMORY (type))
      return 1;
    /* Types that are TREE_ADDRESSABLE must be constructed in memory,
--- 4186,4210 ----
    tree type = (TYPE_P (exp)) ? exp : TREE_TYPE (exp);
  
+   if (fntype)
+     switch (TREE_CODE (fntype))
+       {
+       case CALL_EXPR:
+ 	fntype = get_callee_fndecl (fntype);
+ 	fntype = fntype ? TREE_TYPE (fntype) : 0;
+ 	break;
+       case FUNCTION_DECL:
+ 	fntype = TREE_TYPE (fntype);
+ 	break;
+       case FUNCTION_TYPE:
+         break;
+       default:
+ 	fprintf(stderr, "\n-- aggregate_value_p --\n");
+ 	debug_tree (fntype);
+ 	break;
+       }
+ 
    if (TREE_CODE (type) == VOID_TYPE)
      return 0;
!   if (targetm.calls.return_in_memory (type, fntype))
      return 1;
    /* Types that are TREE_ADDRESSABLE must be constructed in memory,
*************** assign_parms (tree fndecl)
*** 4231,4237 ****
       the function returns a structure.  */
    tree function_result_decl = 0;
- #ifdef SETUP_INCOMING_VARARGS
    int varargs_setup = 0;
- #endif
    int reg_parm_stack_space = 0;
    rtx conversion_insns = 0;
--- 4250,4254 ----
*************** assign_parms (tree fndecl)
*** 4266,4272 ****
  
    /* If struct value address is treated as the first argument, make it so.  */
!   if (aggregate_value_p (DECL_RESULT (fndecl))
        && ! current_function_returns_pcc_struct
!       && struct_value_incoming_rtx == 0)
      {
        tree type = build_pointer_type (TREE_TYPE (fntype));
--- 4283,4289 ----
  
    /* If struct value address is treated as the first argument, make it so.  */
!   if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
        && ! current_function_returns_pcc_struct
!       && targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
      {
        tree type = build_pointer_type (TREE_TYPE (fntype));
*************** assign_parms (tree fndecl)
*** 4337,4341 ****
  	 most machines, if this is a varargs/stdarg function, then we treat
  	 the last named arg as if it were anonymous too.  */
!       named_arg = STRICT_ARGUMENT_NAMING ? 1 : ! last_named;
  
        if (TREE_TYPE (parm) == error_mark_node
--- 4354,4358 ----
  	 most machines, if this is a varargs/stdarg function, then we treat
  	 the last named arg as if it were anonymous too.  */
!       named_arg = targetm.calls.strict_argument_naming (&args_so_far) ? 1 : ! last_named;
  
        if (TREE_TYPE (parm) == error_mark_node
*************** assign_parms (tree fndecl)
*** 4402,4410 ****
        promoted_mode = passed_mode;
  
! #ifdef PROMOTE_FUNCTION_ARGS
!       /* Compute the mode in which the arg is actually extended to.  */
!       unsignedp = TREE_UNSIGNED (passed_type);
!       promoted_mode = promote_mode (passed_type, promoted_mode, &unsignedp, 1);
! #endif
  
        /* Let machine desc say which reg (if any) the parm arrives in.
--- 4419,4428 ----
        promoted_mode = passed_mode;
  
!       if (targetm.calls.promote_function_args (TREE_TYPE (fndecl)))
! 	{
! 	  /* Compute the mode in which the arg is actually extended to.  */
! 	  unsignedp = TREE_UNSIGNED (passed_type);
! 	  promoted_mode = promote_mode (passed_type, promoted_mode, &unsignedp, 1);
! 	}
  
        /* Let machine desc say which reg (if any) the parm arrives in.
*************** assign_parms (tree fndecl)
*** 4421,4425 ****
  	promoted_mode = passed_mode;
  
- #ifdef SETUP_INCOMING_VARARGS
        /* If this is the last named parameter, do any required setup for
  	 varargs or stdargs.  We need to know about the case of this being an
--- 4439,4442 ----
*************** assign_parms (tree fndecl)
*** 4434,4442 ****
        if (last_named && !varargs_setup)
  	{
! 	  SETUP_INCOMING_VARARGS (args_so_far, promoted_mode, passed_type,
! 				  current_function_pretend_args_size, 0);
  	  varargs_setup = 1;
  	}
- #endif
  
        /* Determine parm's home in the stack,
--- 4451,4459 ----
        if (last_named && !varargs_setup)
  	{
! 	  targetm.calls.setup_incoming_varargs (&args_so_far, promoted_mode,
! 						  passed_type,
! 						  &current_function_pretend_args_size, 0);
  	  varargs_setup = 1;
  	}
  
        /* Determine parm's home in the stack,
*************** assign_parms (tree fndecl)
*** 4458,4462 ****
        if (!in_regs && !named_arg)
  	{
! 	  int pretend_named = PRETEND_OUTGOING_VARARGS_NAMED;
  	  if (pretend_named)
  	    {
--- 4475,4480 ----
        if (!in_regs && !named_arg)
  	{
! 	  int pretend_named =
! 	    targetm.calls.pretend_outgoing_varargs_named (&args_so_far);
  	  if (pretend_named)
  	    {
*************** split_complex_args (tree args)
*** 5277,5282 ****
     unsigned.  */
  
- #ifdef PROMOTE_FUNCTION_ARGS
- 
  rtx
  promoted_input_arg (unsigned int regno, enum machine_mode *pmode, int *punsignedp)
--- 5295,5298 ----
*************** promoted_input_arg (unsigned int regno, 
*** 5306,5310 ****
  }
  
- #endif
  
  /* Compute the size and offset from the start of the stacked arguments for a
--- 5322,5325 ----
*************** init_function_start (tree subr)
*** 6424,6428 ****
  
    /* Set flags used by final.c.  */
!   if (aggregate_value_p (DECL_RESULT (subr)))
      {
  #ifdef PCC_STATIC_STRUCT_RETURN
--- 6439,6443 ----
  
    /* Set flags used by final.c.  */
!   if (aggregate_value_p (DECL_RESULT (subr), subr))
      {
  #ifdef PCC_STATIC_STRUCT_RETURN
*************** expand_function_start (tree subr, int pa
*** 6585,6589 ****
  
    /* Decide whether to return the value in memory or in a register.  */
!   if (aggregate_value_p (DECL_RESULT (subr)))
      {
        /* Returning something that won't go in a register.  */
--- 6600,6604 ----
  
    /* Decide whether to return the value in memory or in a register.  */
!   if (aggregate_value_p (DECL_RESULT (subr), subr))
      {
        /* Returning something that won't go in a register.  */
*************** expand_function_start (tree subr, int pa
*** 6599,6609 ****
  #endif
  	{
  	  /* Expect to be passed the address of a place to store the value.
  	     If it is passed as an argument, assign_parms will take care of
  	     it.  */
! 	  if (struct_value_incoming_rtx)
  	    {
  	      value_address = gen_reg_rtx (Pmode);
! 	      emit_move_insn (value_address, struct_value_incoming_rtx);
  	    }
  	}
--- 6614,6625 ----
  #endif
  	{
+ 	  rtx sv = targetm.calls.struct_value_rtx (TREE_TYPE (subr), 1);
  	  /* Expect to be passed the address of a place to store the value.
  	     If it is passed as an argument, assign_parms will take care of
  	     it.  */
! 	  if (sv)
  	    {
  	      value_address = gen_reg_rtx (Pmode);
! 	      emit_move_insn (value_address, sv);
  	    }
  	}
*************** expand_function_end (void)
*** 7043,7050 ****
  	      int unsignedp = TREE_UNSIGNED (TREE_TYPE (decl_result));
  
! #ifdef PROMOTE_FUNCTION_RETURN
! 	      promote_mode (TREE_TYPE (decl_result), GET_MODE (decl_rtl),
! 			    &unsignedp, 1);
! #endif
  
  	      convert_move (real_decl_rtl, decl_rtl, unsignedp);
--- 7059,7065 ----
  	      int unsignedp = TREE_UNSIGNED (TREE_TYPE (decl_result));
  
! 	      if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl)))
! 		promote_mode (TREE_TYPE (decl_result), GET_MODE (decl_rtl),
! 			      &unsignedp, 1);
  
  	      convert_move (real_decl_rtl, decl_rtl, unsignedp);
Index: hard-reg-set.h
===================================================================
RCS file: /cvs/uberbaum/gcc/hard-reg-set.h,v
retrieving revision 1.19
diff -p -2 -r1.19  hard-reg-set.h
*** hard-reg-set.h	31 Jan 2003 23:34:13 -0000	1.19
--- hard-reg-set.h	14 Aug 2003 00:39:16 -0000
***************
*** 1,4 ****
  /* Sets (bit vectors) of hard registers, and operations on them.
!    Copyright (C) 1987, 1992, 1994, 2000 Free Software Foundation, Inc.
  
  This file is part of GCC
--- 1,4 ----
  /* Sets (bit vectors) of hard registers, and operations on them.
!    Copyright (C) 1987, 1992, 1994, 2000, 2003 Free Software Foundation, Inc.
  
  This file is part of GCC
*************** extern HARD_REG_SET losing_caller_save_r
*** 419,423 ****
  /* Indexed by hard register number, contains 1 for registers that are
     fixed use -- i.e. in fixed_regs -- or a function value return register
!    or STRUCT_VALUE_REGNUM or STATIC_CHAIN_REGNUM.  These are the
     registers that cannot hold quantities across calls even if we are
     willing to save and restore them.  */
--- 419,423 ----
  /* Indexed by hard register number, contains 1 for registers that are
     fixed use -- i.e. in fixed_regs -- or a function value return register
!    or TARGET_STRUCT_VALUE_RTX or STATIC_CHAIN_REGNUM.  These are the
     registers that cannot hold quantities across calls even if we are
     willing to save and restore them.  */
Index: integrate.c
===================================================================
RCS file: /cvs/uberbaum/gcc/integrate.c,v
retrieving revision 1.232
diff -p -2 -r1.232  integrate.c
*** integrate.c	19 Jul 2003 14:47:07 -0000	1.232
--- integrate.c	14 Aug 2003 00:39:16 -0000
*************** expand_inline_function (tree fndecl, tre
*** 1029,1033 ****
  	{
  	  if (! structure_value_addr
! 	      || ! aggregate_value_p (DECL_RESULT (fndecl)))
  	    abort ();
  
--- 1029,1033 ----
  	{
  	  if (! structure_value_addr
! 	      || ! aggregate_value_p (DECL_RESULT (fndecl), fndecl))
  	    abort ();
  
*************** expand_inline_function (tree fndecl, tre
*** 1284,1288 ****
    if (target
        && TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == BLKmode
!       && ! aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
      target = copy_blkmode_from_reg (0, target, TREE_TYPE (TREE_TYPE (fndecl)));
  
--- 1284,1288 ----
    if (target
        && TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == BLKmode
!       && ! aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)), fndecl))
      target = copy_blkmode_from_reg (0, target, TREE_TYPE (TREE_TYPE (fndecl)));
  
Index: reg-stack.c
===================================================================
RCS file: /cvs/uberbaum/gcc/reg-stack.c,v
retrieving revision 1.131
diff -p -2 -r1.131  reg-stack.c
*** reg-stack.c	19 Jul 2003 14:47:12 -0000	1.131
--- reg-stack.c	14 Aug 2003 00:39:17 -0000
*************** stack_result (tree decl)
*** 803,807 ****
    /* If the value is supposed to be returned in memory, then clearly
       it is not returned in a stack register.  */
!   if (aggregate_value_p (DECL_RESULT (decl)))
      return 0;
  
--- 803,807 ----
    /* If the value is supposed to be returned in memory, then clearly
       it is not returned in a stack register.  */
!   if (aggregate_value_p (DECL_RESULT (decl), decl))
      return 0;
  
Index: rtl.h
===================================================================
RCS file: /cvs/uberbaum/gcc/rtl.h,v
retrieving revision 1.432
diff -p -2 -r1.432  rtl.h
*** rtl.h	1 Aug 2003 21:51:13 -0000	1.432
--- rtl.h	14 Aug 2003 00:39:17 -0000
*************** extern GTY(()) rtx global_rtl[GR_MAX];
*** 1817,1822 ****
  
  extern GTY(()) rtx pic_offset_table_rtx;
- extern GTY(()) rtx struct_value_rtx;
- extern GTY(()) rtx struct_value_incoming_rtx;
  extern GTY(()) rtx static_chain_rtx;
  extern GTY(()) rtx static_chain_incoming_rtx;
--- 1817,1820 ----
Index: stmt.c
===================================================================
RCS file: /cvs/uberbaum/gcc/stmt.c,v
retrieving revision 1.324
diff -p -2 -r1.324  stmt.c
*** stmt.c	1 Aug 2003 00:37:39 -0000	1.324
--- stmt.c	14 Aug 2003 00:39:17 -0000
*************** Software Foundation, 59 Temple Place - S
*** 58,61 ****
--- 58,62 ----
  #include "predict.h"
  #include "optabs.h"
+ #include "target.h"
  
  /* Assume that case vectors are not pc-relative.  */
*************** expand_value_return (rtx val)
*** 2960,2973 ****
      {
        tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
! #ifdef PROMOTE_FUNCTION_RETURN
!       int unsignedp = TREE_UNSIGNED (type);
!       enum machine_mode old_mode
! 	= DECL_MODE (DECL_RESULT (current_function_decl));
!       enum machine_mode mode
! 	= promote_mode (type, old_mode, &unsignedp, 1);
  
!       if (mode != old_mode)
! 	val = convert_modes (mode, old_mode, val, unsignedp);
! #endif
        if (GET_CODE (return_reg) == PARALLEL)
  	emit_group_load (return_reg, val, type, int_size_in_bytes (type));
--- 2961,2975 ----
      {
        tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
!       if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl)))
!       {
! 	int unsignedp = TREE_UNSIGNED (type);
! 	enum machine_mode old_mode
! 	  = DECL_MODE (DECL_RESULT (current_function_decl));
! 	enum machine_mode mode
! 	  = promote_mode (type, old_mode, &unsignedp, 1);
  
! 	if (mode != old_mode)
! 	  val = convert_modes (mode, old_mode, val, unsignedp);
!       }
        if (GET_CODE (return_reg) == PARALLEL)
  	emit_group_load (return_reg, val, type, int_size_in_bytes (type));
Index: stor-layout.c
===================================================================
RCS file: /cvs/uberbaum/gcc/stor-layout.c,v
retrieving revision 1.165
diff -p -2 -r1.165  stor-layout.c
*** stor-layout.c	29 Jul 2003 01:14:19 -0000	1.165
--- stor-layout.c	14 Aug 2003 00:39:17 -0000
*************** finalize_type_size (tree type)
*** 1439,1442 ****
--- 1439,1463 ----
  }
  
+ static void
+ reverse_bitfield_layout (record_layout_info rli)
+ {
+   tree field, oldtype;
+   for (field = TYPE_FIELDS (rli->t); field; field = TREE_CHAIN (field))
+     {
+       tree type = TREE_TYPE (field);
+       if (TREE_CODE (field) != FIELD_DECL)
+ 	continue;
+       if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
+ 	return;
+       oldtype = TREE_TYPE (DECL_FIELD_BIT_OFFSET (field));
+       DECL_FIELD_BIT_OFFSET (field)
+ 	= size_binop (MINUS_EXPR,
+ 		      size_binop (MINUS_EXPR, TYPE_SIZE (type),
+ 				  DECL_SIZE (field)),
+ 		      DECL_FIELD_BIT_OFFSET (field));
+       TREE_TYPE (DECL_FIELD_BIT_OFFSET (field)) = oldtype;
+     }
+ }
+ 
  /* Do all of the work required to layout the type indicated by RLI,
     once the fields have been laid out.  This function will call `free'
*************** void
*** 1448,1451 ****
--- 1469,1477 ----
  finish_record_layout (record_layout_info rli, int free_p)
  {
+   if ((* targetm.ms_bitfield_layout_p) (rli->t)
+       && (* targetm.reverse_bitfield_layout_p) (rli->t)
+       && ! TYPE_PACKED (rli->t))
+       reverse_bitfield_layout (rli);
+ 
    /* Compute the final size.  */
    finalize_record_size (rli);
Index: target-def.h
===================================================================
RCS file: /cvs/uberbaum/gcc/target-def.h,v
retrieving revision 1.54
diff -p -2 -r1.54  target-def.h
*** target-def.h	29 Jun 2003 18:34:34 -0000	1.54
--- target-def.h	14 Aug 2003 00:39:17 -0000
*************** Foundation, 59 Temple Place - Suite 330,
*** 294,297 ****
--- 294,298 ----
  #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P hook_bool_tree_false
  #define TARGET_MS_BITFIELD_LAYOUT_P hook_bool_tree_false
+ #define TARGET_REVERSE_BITFIELD_LAYOUT_P hook_bool_tree_false
  #define TARGET_RTX_COSTS hook_bool_rtx_int_int_intp_false
  
*************** Foundation, 59 Temple Place - Suite 330,
*** 306,309 ****
--- 307,334 ----
  #define TARGET_MACHINE_DEPENDENT_REORG 0
  
+ #define TARGET_PROMOTE_FUNCTION_ARGS default_promote_function_args
+ #define TARGET_PROMOTE_FUNCTION_RETURN default_promote_function_return
+ #define TARGET_PROMOTE_PROTOTYPES default_promote_prototypes
+ 
+ #define TARGET_STRUCT_VALUE_RTX default_struct_value_rtx
+ #define TARGET_RETURN_IN_MEMORY default_return_in_memory
+ 
+ #define TARGET_EXPAND_BUILTIN_SAVEREGS default_expand_builtin_saveregs
+ #define TARGET_SETUP_INCOMING_VARARGS default_setup_incoming_varargs
+ #define TARGET_STRICT_ARGUMENT_NAMING default_strict_argument_naming
+ #define TARGET_PRETEND_OUTGOING_VARARGS_NAMED default_pretend_outgoing_varargs_named
+ 
+ #define TARGET_CALLS {						\
+    TARGET_PROMOTE_FUNCTION_ARGS,				\
+    TARGET_PROMOTE_FUNCTION_RETURN,				\
+    TARGET_PROMOTE_PROTOTYPES,					\
+    TARGET_STRUCT_VALUE_RTX,					\
+    TARGET_RETURN_IN_MEMORY,					\
+    TARGET_EXPAND_BUILTIN_SAVEREGS,				\
+    TARGET_SETUP_INCOMING_VARARGS,				\
+    TARGET_STRICT_ARGUMENT_NAMING,				\
+    TARGET_PRETEND_OUTGOING_VARARGS_NAMED,			\
+    }
+ 
  /* The whole shebang.  */
  #define TARGET_INITIALIZER			\
*************** Foundation, 59 Temple Place - Suite 330,
*** 319,322 ****
--- 344,348 ----
    TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P,	\
    TARGET_MS_BITFIELD_LAYOUT_P,			\
+   TARGET_REVERSE_BITFIELD_LAYOUT_P,		\
    TARGET_INIT_BUILTINS,				\
    TARGET_EXPAND_BUILTIN,			\
*************** Foundation, 59 Temple Place - Suite 330,
*** 346,350 ****
--- 372,378 ----
    TARGET_ASM_FILE_START_APP_OFF,		\
    TARGET_ASM_FILE_START_FILE_DIRECTIVE,		\
+   TARGET_CALLS,					\
  }
  
  #include "hooks.h"
+ #include "targhooks.h"
Index: target.h
===================================================================
RCS file: /cvs/uberbaum/gcc/target.h,v
retrieving revision 1.61
diff -p -2 -r1.61  target.h
*** target.h	6 Jul 2003 12:35:55 -0000	1.61
--- target.h	14 Aug 2003 00:39:17 -0000
*************** struct gcc_target
*** 279,282 ****
--- 279,286 ----
    bool (* ms_bitfield_layout_p) (tree record_type);
  
+   /* Return true if bitfields in RECORD_TYPE should be allocated
+      within their base type's bytes starting at the opposite end.  */
+   bool (* reverse_bitfield_layout_p) (tree record_type);
+ 
    /* Set up target-specific built-in functions.  */
    void (* init_builtins) (void);
*************** struct gcc_target
*** 387,390 ****
--- 391,411 ----
       at the beginning of assembly output.  */
    bool file_start_file_directive;
+ 
+   /* Functions relating to calls - argument passing, returns, etc.  */
+   struct calls {
+     bool (*promote_function_args) (tree fntype);
+     bool (*promote_function_return) (tree fntype);
+     bool (*promote_prototypes) (tree fntype);
+     rtx (*struct_value_rtx) (tree fndecl, int incoming);
+     bool (*return_in_memory) (tree type, tree fndecl);
+     rtx (*expand_builtin_saveregs) (void);
+     /* Returns pretend_argument_size.  */
+     void (*setup_incoming_varargs) (CUMULATIVE_ARGS *ca, enum machine_mode mode,
+ 				    tree type, int *pretend_arg_size, int second_time);
+     bool (*strict_argument_naming) (CUMULATIVE_ARGS *ca);
+     /* Returns true if we should use SETUP_INCOMING_VARARGS and/or
+        STRICT_ARGUMENT_NAMING. */
+     bool (*pretend_outgoing_varargs_named) (CUMULATIVE_ARGS *ca);
+   } calls;
  };
  
Index: tree.h
===================================================================
RCS file: /cvs/uberbaum/gcc/tree.h,v
retrieving revision 1.434
diff -p -2 -r1.434  tree.h
*** tree.h	8 Aug 2003 20:23:05 -0000	1.434
--- tree.h	14 Aug 2003 00:39:18 -0000
*************** extern void push_temp_slots (void);
*** 2846,2850 ****
  extern void preserve_temp_slots (rtx);
  extern void preserve_rtl_expr_temps (tree);
! extern int aggregate_value_p (tree);
  extern void free_temps_for_rtl_expr (tree);
  extern void instantiate_virtual_regs (tree, rtx);
--- 2846,2850 ----
  extern void preserve_temp_slots (rtx);
  extern void preserve_rtl_expr_temps (tree);
! extern int aggregate_value_p (tree, tree);
  extern void free_temps_for_rtl_expr (tree);
  extern void instantiate_virtual_regs (tree, rtx);
Index: ada/ChangeLog
===================================================================
RCS file: /cvs/uberbaum/gcc/ada/ChangeLog,v
retrieving revision 1.339
diff -p -2 -r1.339  ada/ChangeLog
*** ada/ChangeLog	18 Jul 2003 05:32:39 -0000	1.339
--- ada/ChangeLog	14 Aug 2003 00:39:19 -0000
***************
*** 1,2 ****
--- 1,7 ----
+ 2003-08-13  DJ Delorie  <dj@redhat.com>
+ 
+ 	* misc.c (default_pass_by_ref): Convert to calls.return_in_memory
+ 	hook.
+ 
  2003-07-18  Neil Booth  <neil@daikokuya.co.uk>
  
Index: ada/misc.c
===================================================================
RCS file: /cvs/uberbaum/gcc/ada/misc.c,v
retrieving revision 1.63
diff -p -2 -r1.63  ada/misc.c
*** ada/misc.c	6 Jul 2003 19:01:18 -0000	1.63
--- ada/misc.c	14 Aug 2003 00:39:19 -0000
***************
*** 8,12 ****
   *                                                                          *
   *                                                                          *
!  *          Copyright (C) 1992-2002 Free Software Foundation, Inc.          *
   *                                                                          *
   * GNAT is free software;  you can  redistribute it  and/or modify it under *
--- 8,12 ----
   *                                                                          *
   *                                                                          *
!  *          Copyright (C) 1992-2003 Free Software Foundation, Inc.          *
   *                                                                          *
   * GNAT is free software;  you can  redistribute it  and/or modify it under *
*************** default_pass_by_ref (gnu_type)
*** 797,801 ****
  					     gnu_type, 1)
  #endif
! 	  || RETURN_IN_MEMORY (gnu_type)
  	  || (AGGREGATE_TYPE_P (gnu_type)
  	      && (! host_integerp (TYPE_SIZE (gnu_type), 1)
--- 797,801 ----
  					     gnu_type, 1)
  #endif
! 	  || targetm.calls.return_in_memory (gnu_type, NULL_TREE)
  	  || (AGGREGATE_TYPE_P (gnu_type)
  	      && (! host_integerp (TYPE_SIZE (gnu_type), 1)
Index: config/alpha/alpha.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/alpha/alpha.c,v
retrieving revision 1.323
diff -p -2 -r1.323  config/alpha/alpha.c
*** config/alpha/alpha.c	12 Jul 2003 23:02:21 -0000	1.323
--- config/alpha/alpha.c	14 Aug 2003 00:39:21 -0000
*************** alpha_output_mi_thunk_osf (FILE *file, t
*** 7800,7804 ****
    /* Find the "this" pointer.  If the function returns a structure,
       the structure return pointer is in $16.  */
!   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
      this = gen_rtx_REG (Pmode, 17);
    else
--- 7800,7804 ----
    /* Find the "this" pointer.  If the function returns a structure,
       the structure return pointer is in $16.  */
!   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
      this = gen_rtx_REG (Pmode, 17);
    else
Index: config/arm/arm.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/arm/arm.c,v
retrieving revision 1.290
diff -p -2 -r1.290  config/arm/arm.c
*** config/arm/arm.c	12 Jul 2003 23:02:22 -0000	1.290
--- config/arm/arm.c	14 Aug 2003 00:39:23 -0000
*************** arm_init_cumulative_args (CUMULATIVE_ARG
*** 1969,1973 ****
  {
    /* On the ARM, the offset starts at 0.  */
!   pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype))) ? 1 : 0);
    pcum->iwmmxt_nregs = 0;
    
--- 1969,1973 ----
  {
    /* On the ARM, the offset starts at 0.  */
!   pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype), fntype)) ? 1 : 0);
    pcum->iwmmxt_nregs = 0;
    
*************** arm_output_mi_thunk (FILE *file, tree th
*** 12963,12967 ****
    const char *const mi_op = mi_delta < 0 ? "sub" : "add";
    int shift = 0;
!   int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)))
                      ? 1 : 0);
    if (mi_delta < 0)
--- 12963,12967 ----
    const char *const mi_op = mi_delta < 0 ? "sub" : "add";
    int shift = 0;
!   int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)
                      ? 1 : 0);
    if (mi_delta < 0)
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/i386/i386.c,v
retrieving revision 1.592
diff -p -2 -r1.592  config/i386/i386.c
*** config/i386/i386.c	31 Jul 2003 22:54:30 -0000	1.592
--- config/i386/i386.c	14 Aug 2003 00:39:24 -0000
*************** ix86_return_pops_args (tree fundecl, tre
*** 1723,1727 ****
  
    /* Lose any fake structure return argument if it is passed on the stack.  */
!   if (aggregate_value_p (TREE_TYPE (funtype))
        && !TARGET_64BIT)
      {
--- 1723,1727 ----
  
    /* Lose any fake structure return argument if it is passed on the stack.  */
!   if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
        && !TARGET_64BIT)
      {
*************** x86_this_parameter (tree function)
*** 15084,15088 ****
    if (TARGET_64BIT)
      {
!       int n = aggregate_value_p (TREE_TYPE (type)) != 0;
        return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
      }
--- 15084,15088 ----
    if (TARGET_64BIT)
      {
!       int n = aggregate_value_p (TREE_TYPE (type), type) != 0;
        return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
      }
*************** x86_this_parameter (tree function)
*** 15103,15107 ****
      }
  
!   if (aggregate_value_p (TREE_TYPE (type)))
      return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
    else
--- 15103,15107 ----
      }
  
!   if (aggregate_value_p (TREE_TYPE (type), type))
      return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
    else
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mips/mips.c,v
retrieving revision 1.301
diff -p -2 -r1.301  config/mips/mips.c
*** config/mips/mips.c	12 Aug 2003 20:50:29 -0000	1.301
--- config/mips/mips.c	14 Aug 2003 00:39:25 -0000
*************** mips_save_reg_p (unsigned int regno)
*** 5942,5946 ****
  	  && mips16_hard_float
  	  && !mips_entry
! 	  && !aggregate_value_p (return_type)
  	  && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
  	  && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
--- 5942,5946 ----
  	  && mips16_hard_float
  	  && !mips_entry
! 	  && !aggregate_value_p (return_type, current_function_decl)
  	  && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
  	  && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
*************** mips_expand_prologue (void)
*** 6728,6732 ****
  
    /* If struct value address is treated as the first argument, make it so.  */
!   if (aggregate_value_p (DECL_RESULT (fndecl))
        && ! current_function_returns_pcc_struct
        && struct_value_incoming_rtx == 0)
--- 6728,6732 ----
  
    /* If struct value address is treated as the first argument, make it so.  */
!   if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
        && ! current_function_returns_pcc_struct
        && struct_value_incoming_rtx == 0)
*************** mips_can_use_return_insn (void)
*** 7298,7302 ****
    if (TARGET_MIPS16
        && mips16_hard_float
!       && ! aggregate_value_p (return_type)
        && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
        && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
--- 7298,7302 ----
    if (TARGET_MIPS16
        && mips16_hard_float
!       && ! aggregate_value_p (return_type, current_function_decl)
        && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
        && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.511
diff -p -2 -r1.511  config/rs6000/rs6000.c
*** config/rs6000/rs6000.c	11 Aug 2003 15:24:47 -0000	1.511
--- config/rs6000/rs6000.c	14 Aug 2003 00:39:26 -0000
*************** rs6000_output_mi_thunk (file, thunk_fnde
*** 12431,12435 ****
    /* Find the "this" pointer.  If the function returns a structure,
       the structure return pointer is in r3.  */
!   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
      this = gen_rtx_REG (Pmode, 4);
    else
--- 12431,12435 ----
    /* Find the "this" pointer.  If the function returns a structure,
       the structure return pointer is in r3.  */
!   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
      this = gen_rtx_REG (Pmode, 4);
    else
Index: config/s390/s390.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/s390/s390.c,v
retrieving revision 1.106
diff -p -2 -r1.106  config/s390/s390.c
*** config/s390/s390.c	1 Aug 2003 15:41:55 -0000	1.106
--- config/s390/s390.c	14 Aug 2003 00:39:27 -0000
*************** s390_output_mi_thunk (file, thunk, delta
*** 6725,6729 ****
  
    /* Operand 1 is the 'this' pointer.  */
!   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
      op[1] = gen_rtx_REG (Pmode, 3);
    else
--- 6725,6729 ----
  
    /* Operand 1 is the 'this' pointer.  */
!   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
      op[1] = gen_rtx_REG (Pmode, 3);
    else
Index: config/sh/sh-protos.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/sh/sh-protos.h,v
retrieving revision 1.45
diff -p -2 -r1.45  config/sh/sh-protos.h
*** config/sh/sh-protos.h	16 Jul 2003 21:41:20 -0000	1.45
--- config/sh/sh-protos.h	14 Aug 2003 00:39:27 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 26,30 ****
  
  #ifdef RTX_CODE
- extern struct rtx_def *sh_builtin_saveregs PARAMS ((void));
  extern struct rtx_def *prepare_scc_operands PARAMS ((enum rtx_code));
  
--- 26,29 ----
*************** extern int sh_pr_n_sets PARAMS ((void));
*** 122,125 ****
--- 121,126 ----
  extern int sh_hard_regno_rename_ok PARAMS ((unsigned int, unsigned int));
  extern int sh_cfun_interrupt_handler_p PARAMS ((void));
+ extern int sh_attr_renesas_p PARAMS ((tree));
+ extern int sh_cfun_attr_renesas_p PARAMS ((void));
  extern void sh_initialize_trampoline PARAMS ((rtx, rtx, rtx));
  extern bool sh_cannot_change_mode_class
*************** extern void sh_pr_nosave_low_regs PARAMS
*** 138,141 ****
--- 139,146 ----
  extern rtx function_symbol (const char *);
  extern rtx sh_get_pr_initial_val (void);
+ 
+ extern rtx sh_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+ extern void sh_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+ extern int sh_pass_in_reg_p (CUMULATIVE_ARGS *, enum machine_mode, tree);
  
  #endif /* ! GCC_SH_PROTOS_H */
Index: config/sh/sh.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/sh/sh.c,v
retrieving revision 1.234
diff -p -2 -r1.234  config/sh/sh.c
*** config/sh/sh.c	13 Aug 2003 19:20:16 -0000	1.234
--- config/sh/sh.c	14 Aug 2003 00:39:27 -0000
***************
*** 1,4 ****
  /* Output routines for GCC for Renesas / SuperH SH.
!    Copyright (C) 1993, 1994, 1995, 1997, 1997, 1998, 1999, 2000, 2001, 2002,
     2003 Free Software Foundation, Inc.
     Contributed by Steve Chamberlain (sac@cygnus.com).
--- 1,4 ----
  /* Output routines for GCC for Renesas / SuperH SH.
!    Copyright (C) 1993, 1994, 1995, 1997, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
     2003 Free Software Foundation, Inc.
     Contributed by Steve Chamberlain (sac@cygnus.com).
*************** static tree sh_handle_interrupt_handler_
*** 204,207 ****
--- 204,208 ----
  static tree sh_handle_sp_switch_attribute PARAMS ((tree *, tree, tree, int, bool *));
  static tree sh_handle_trap_exit_attribute PARAMS ((tree *, tree, tree, int, bool *));
+ static tree sh_handle_renesas_attribute PARAMS ((tree *, tree, tree, int, bool *));
  static void sh_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
  static void sh_insert_attributes PARAMS ((tree, tree *));
*************** static int sh_target_reg_class (void);
*** 215,218 ****
--- 216,220 ----
  static bool sh_optimize_target_register_callee_saved (bool);
  static bool sh_ms_bitfield_layout_p PARAMS ((tree));
+ static bool sh_reverse_bitfield_layout_p PARAMS ((tree));
  
  static void sh_init_builtins PARAMS ((void));
*************** struct save_schedule_s;
*** 239,242 ****
--- 241,253 ----
  static struct save_entry_s *sh5_schedule_saves (HARD_REG_SET *,
  						struct save_schedule_s *, int);
+ 
+ static bool sh_promote_prototypes PARAMS ((tree));
+ static rtx sh_struct_value_rtx PARAMS ((tree, int));
+ static bool sh_return_in_memory PARAMS ((tree, tree));
+ static rtx sh_builtin_saveregs PARAMS ((void));
+ static void sh_setup_incoming_varargs PARAMS ((CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int));
+ static bool sh_strict_argument_naming PARAMS ((CUMULATIVE_ARGS *));
+ static bool sh_pretend_outgoing_varargs_named PARAMS ((CUMULATIVE_ARGS *));
+ 
  
  /* Initialize the GCC target structure.  */
*************** static struct save_entry_s *sh5_schedule
*** 292,295 ****
--- 303,308 ----
  #undef TARGET_MS_BITFIELD_LAYOUT_P
  #define TARGET_MS_BITFIELD_LAYOUT_P sh_ms_bitfield_layout_p
+ #undef TARGET_REVERSE_BITFIELD_LAYOUT_P
+ #define TARGET_REVERSE_BITFIELD_LAYOUT_P sh_reverse_bitfield_layout_p
  
  #undef TARGET_INIT_BUILTINS
*************** static struct save_entry_s *sh5_schedule
*** 316,319 ****
--- 329,353 ----
  #endif
  
+ #undef TARGET_PROMOTE_PROTOTYPES
+ #define TARGET_PROMOTE_PROTOTYPES sh_promote_prototypes
+ #undef TARGET_PROMOTE_FUNCTION_ARGS
+ #define TARGET_PROMOTE_FUNCTION_ARGS sh_promote_prototypes
+ #undef TARGET_PROMOTE_FUNCTION_RETURN
+ #define TARGET_PROMOTE_FUNCTION_RETURN sh_promote_prototypes
+ 
+ #undef TARGET_STRUCT_VALUE_RTX
+ #define TARGET_STRUCT_VALUE_RTX sh_struct_value_rtx
+ #undef TARGET_RETURN_IN_MEMORY
+ #define TARGET_RETURN_IN_MEMORY sh_return_in_memory
+ 
+ #undef TARGET_EXPAND_BUILTIN_SAVEREGS
+ #define TARGET_EXPAND_BUILTIN_SAVEREGS sh_builtin_saveregs
+ #undef TARGET_SETUP_INCOMING_VARARGS
+ #define TARGET_SETUP_INCOMING_VARARGS sh_setup_incoming_varargs
+ #undef TARGET_STRICT_ARGUMENT_NAMING
+ #define TARGET_STRICT_ARGUMENT_NAMING sh_strict_argument_naming
+ #undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED
+ #define TARGET_PRETEND_OUTGOING_VARARGS_NAMED sh_pretend_outgoing_varargs_named
+ 
  struct gcc_target targetm = TARGET_INITIALIZER;
  
*************** calc_live_regs (live_regs_mask)
*** 4899,4903 ****
  		     || reg == (int) EH_RETURN_DATA_REGNO (1)
  		     || reg == (int) EH_RETURN_DATA_REGNO (2)
! 		     || reg == (int) EH_RETURN_DATA_REGNO (3)))))
  	{
  	  SET_HARD_REG_BIT (*live_regs_mask, reg);
--- 4933,4941 ----
  		     || reg == (int) EH_RETURN_DATA_REGNO (1)
  		     || reg == (int) EH_RETURN_DATA_REGNO (2)
! 		     || reg == (int) EH_RETURN_DATA_REGNO (3)))
! 	     || ((reg == MACL_REG || reg == MACH_REG)
! 		 && regs_ever_live[reg]
! 		 && sh_cfun_attr_renesas_p ())
! 	     ))
  	{
  	  SET_HARD_REG_BIT (*live_regs_mask, reg);
*************** sh_expand_prologue ()
*** 5191,5195 ****
      {
        /* This is not used by the SH2E calling convention  */
!       if (TARGET_SH1 && ! TARGET_SH2E && ! TARGET_SH5 && ! TARGET_HITACHI)
  	{
  	  /* Push arg regs as if they'd been provided by caller in stack.  */
--- 5229,5234 ----
      {
        /* This is not used by the SH2E calling convention  */
!       if (TARGET_SH1 && ! TARGET_SH2E && ! TARGET_SH5
! 	  && ! (TARGET_HITACHI || sh_cfun_attr_renesas_p ()))
  	{
  	  /* Push arg regs as if they'd been provided by caller in stack.  */
*************** sh_output_function_epilogue (file, size)
*** 5823,5827 ****
  }
  
! rtx
  sh_builtin_saveregs ()
  {
--- 5862,5866 ----
  }
  
! static rtx
  sh_builtin_saveregs ()
  {
*************** sh_build_va_list ()
*** 5973,5977 ****
    tree record;
  
!   if (TARGET_SH5 || (! TARGET_SH2E && ! TARGET_SH4) || TARGET_HITACHI)
      return ptr_type_node;
  
--- 6012,6017 ----
    tree record;
  
!   if (TARGET_SH5 || (! TARGET_SH2E && ! TARGET_SH4) || TARGET_HITACHI
!       || sh_cfun_attr_renesas_p ())
      return ptr_type_node;
  
*************** sh_va_start (valist, nextarg)
*** 6027,6031 ****
      }
  
!   if ((! TARGET_SH2E && ! TARGET_SH4) || TARGET_HITACHI)
      {
        std_expand_builtin_va_start (valist, nextarg);
--- 6067,6072 ----
      }
  
!   if ((! TARGET_SH2E && ! TARGET_SH4) || TARGET_HITACHI
!       || sh_cfun_attr_renesas_p ())
      {
        std_expand_builtin_va_start (valist, nextarg);
*************** sh_va_arg (valist, type)
*** 6106,6110 ****
      type = build_pointer_type (type);
  
!   if (! TARGET_SH5 && (TARGET_SH2E || TARGET_SH4) && ! TARGET_HITACHI)
      {
        tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
--- 6147,6152 ----
      type = build_pointer_type (type);
  
!   if (! TARGET_SH5 && (TARGET_SH2E || TARGET_SH4)
!       && ! (TARGET_HITACHI || sh_cfun_attr_renesas_p ()))
      {
        tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
*************** sh_va_arg (valist, type)
*** 6290,6293 ****
--- 6332,6662 ----
  }
  
+ static bool
+ sh_promote_prototypes (type)
+      tree type;
+ {
+   if (TARGET_HITACHI)
+     return 0;
+   if (!type)
+     return 1;
+   return ! sh_attr_renesas_p (type);
+ }
+ 
+ /* Define where to put the arguments to a function.
+    Value is zero to push the argument on the stack,
+    or a hard register in which to store the argument.
+ 
+    MODE is the argument's machine mode.
+    TYPE is the data type of the argument (as a tree).
+     This is null for libcalls where that information may
+     not be available.
+    CUM is a variable of type CUMULATIVE_ARGS which gives info about
+     the preceding args and about the function being called.
+    NAMED is nonzero if this argument is a named parameter
+     (otherwise it is an extra parameter matching an ellipsis).
+ 
+    On SH the first args are normally in registers
+    and the rest are pushed.  Any arg that starts within the first
+    NPARM_REGS words is at least partially passed in a register unless
+    its data type forbids.  */
+ 
+ 
+ rtx
+ sh_function_arg (ca, mode, type, named)
+      CUMULATIVE_ARGS *ca;
+      enum machine_mode mode;
+      tree type;
+      int named;
+ {
+   if (! TARGET_SH5
+       && PASS_IN_REG_P ((*ca), (mode), (type))
+       && ((named) || !(TARGET_HITACHI || (*ca).renesas_abi)))
+     {
+       int regno;
+ 
+       if ((mode) == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN
+ 	  && (! FUNCTION_ARG_SCmode_WART || (ROUND_REG ((*ca), (mode)) & 1)))
+ 	{
+ 	  rtx r1 = gen_rtx_EXPR_LIST (VOIDmode,
+ 				      gen_rtx_REG (SFmode,
+ 						   BASE_ARG_REG (mode)
+ 						   + (ROUND_REG ((*ca), (mode)) ^ 1)),
+ 				      const0_rtx);
+ 	  rtx r2 = gen_rtx_EXPR_LIST(VOIDmode,
+ 				     gen_rtx_REG (SFmode,
+ 						  BASE_ARG_REG (mode)
+ 						  + ((ROUND_REG ((*ca), (mode)) + 1) ^ 1)),
+ 				     GEN_INT (4));
+ 	  return gen_rtx_PARALLEL(SCmode, gen_rtvec(2, r1, r2));
+ 	}
+ 
+       if ((TARGET_HITACHI || ca->renesas_abi)
+ 	  && ca->free_single_fp_reg
+ 	  && mode == SFmode)
+ 	return gen_rtx_REG (mode, ca->free_single_fp_reg);
+ 
+       regno = (BASE_ARG_REG (mode) + ROUND_REG ((*ca), (mode)))
+ 	       ^ ((mode) == SFmode && TARGET_SH4
+ 		  && TARGET_LITTLE_ENDIAN != 0
+ 		  && !TARGET_HITACHI && !(*ca).renesas_abi);
+       return gen_rtx_REG (mode, regno);
+ 
+     }
+   
+   if (TARGET_SH5)
+     {
+       if ((mode) == VOIDmode && TARGET_SHCOMPACT)
+ 	return GEN_INT ((*ca).call_cookie);
+ 
+       /* The following test assumes unnamed arguments are promoted to
+ 	 DFmode.  */
+       if ((mode) == SFmode && (*ca).free_single_fp_reg)
+ 	return SH5_PROTOTYPED_FLOAT_ARG ((*ca), (mode), (*ca).free_single_fp_reg);
+ 
+       if ((GET_SH_ARG_CLASS (mode) == SH_ARG_FLOAT)
+ 	  && ((named) || ! (*ca).prototype_p)
+ 	  && (*ca).arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (SFmode))
+ 	{
+ 	  if (! (*ca).prototype_p && TARGET_SHMEDIA)
+ 	    return SH5_PROTOTYPELESS_FLOAT_ARG ((*ca), (mode));
+ 
+ 	  return SH5_PROTOTYPED_FLOAT_ARG ((*ca), (mode),
+ 					   FIRST_FP_PARM_REG
+ 					   + (*ca).arg_count[(int) SH_ARG_FLOAT]);
+ 	}
+ 
+       if ((*ca).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)
+ 	  && (! TARGET_SHCOMPACT
+ 	      || (! SHCOMPACT_FORCE_ON_STACK ((mode), (type))
+ 		  && ! SH5_WOULD_BE_PARTIAL_NREGS ((*ca), (mode),
+ 						   (type), (named)))))
+ 	{
+ 	  return gen_rtx_REG ((mode), (FIRST_PARM_REG
+ 				       + (*ca).arg_count[(int) SH_ARG_INT]));
+ 	}
+ 
+       return 0;
+     }
+ 
+   return 0;
+ }
+  
+ /* Update the data in CUM to advance over an argument
+    of mode MODE and data type TYPE.
+    (TYPE is null for libcalls where that information may not be
+    available.)  */
+ 
+ void
+ sh_function_arg_advance (ca, mode, type, named)
+      CUMULATIVE_ARGS *ca;
+      enum machine_mode mode;
+      tree type;
+      int named;
+ {
+   /*  dump_ca (ca, __LINE__, "in sh_function_arg_advance");*/
+  if ((*ca).force_mem)
+    (*ca).force_mem = 0;
+  else if (TARGET_SH5)
+    {
+      tree TYPE_ = ((*ca).byref && (type)
+ 		   ? TREE_TYPE (type)
+  		   : (type));
+      enum machine_mode MODE_ = ((*ca).byref && (type)
+ 				? TYPE_MODE (TYPE_)
+ 				: (mode));
+      int dwords = (((*ca).byref
+ 		    ? (*ca).byref
+ 		    : (MODE_) == BLKmode
+ 		    ? int_size_in_bytes (TYPE_)
+ 		    : GET_MODE_SIZE (MODE_)) + 7) / 8;
+      int numregs = MIN (dwords, NPARM_REGS (SImode)
+ 			- (*ca).arg_count[(int) SH_ARG_INT]);
+ 
+      if (numregs)
+        {
+ 	 (*ca).arg_count[(int) SH_ARG_INT] += numregs;
+ 	 if (TARGET_SHCOMPACT
+ 	     && SHCOMPACT_FORCE_ON_STACK (MODE_, TYPE_))
+ 	   {
+ 	     (*ca).call_cookie
+ 	       |= CALL_COOKIE_INT_REG (((*ca).arg_count[(int) SH_ARG_INT]
+ 					- numregs), 1);
+ 	     /* N.B. We want this also for outgoing.   */
+ 	     (*ca).stack_regs += numregs;
+ 	   }
+ 	 else if ((*ca).byref)
+ 	   {
+ 	     if (! (*ca).outgoing)
+ 	       (*ca).stack_regs += numregs;
+ 	     (*ca).byref_regs += numregs;
+ 	     (*ca).byref = 0;
+ 	     do
+ 	       (*ca).call_cookie
+ 		 |= CALL_COOKIE_INT_REG (((*ca).arg_count[(int) SH_ARG_INT]
+ 					  - numregs), 2);
+ 	     while (--numregs);
+ 	     (*ca).call_cookie
+ 	       |= CALL_COOKIE_INT_REG (((*ca).arg_count[(int) SH_ARG_INT]
+ 				        - 1), 1);
+ 	   }
+ 	 else if (dwords > numregs)
+ 	   {
+ 	     int pushregs = numregs;
+ 
+ 	     if (TARGET_SHCOMPACT)
+ 	       (*ca).stack_regs += numregs;
+ 	     while (pushregs < NPARM_REGS (SImode) - 1
+ 		    && (CALL_COOKIE_INT_REG_GET
+ 			((*ca).call_cookie,
+ 			NPARM_REGS (SImode) - pushregs)
+ 			== 1))
+ 	       {
+ 		 (*ca).call_cookie
+ 		   &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode)
+ 					     - pushregs, 1);
+ 		 pushregs++;
+ 	       }
+ 	     if (numregs == NPARM_REGS (SImode))
+ 	       (*ca).call_cookie
+ 		 |= CALL_COOKIE_INT_REG (0, 1)
+ 		    | CALL_COOKIE_STACKSEQ (numregs - 1);
+ 	     else
+ 	       (*ca).call_cookie
+ 		 |= CALL_COOKIE_STACKSEQ (numregs);
+ 	   }
+        }
+      if (GET_SH_ARG_CLASS (MODE_) == SH_ARG_FLOAT
+ 	 && ((named) || ! (*ca).prototype_p))
+        {
+ 	 if ((MODE_) == SFmode && (*ca).free_single_fp_reg)
+ 	   (*ca).free_single_fp_reg = 0;
+ 	 else if ((*ca).arg_count[(int) SH_ARG_FLOAT]
+  		  < NPARM_REGS (SFmode))
+ 	   {
+ 	     int numfpregs
+ 	       = MIN ((GET_MODE_SIZE (MODE_) + 7) / 8 * 2,
+ 		      NPARM_REGS (SFmode)
+ 		      - (*ca).arg_count[(int) SH_ARG_FLOAT]);
+ 
+ 	     (*ca).arg_count[(int) SH_ARG_FLOAT] += numfpregs;
+ 
+ 	     if (TARGET_SHCOMPACT && ! (*ca).prototype_p)
+ 	       {
+ 		 if ((*ca).outgoing && numregs > 0)
+ 		   do
+ 		     {
+ 		       (*ca).call_cookie
+ 			 |= (CALL_COOKIE_INT_REG
+ 			     ((*ca).arg_count[(int) SH_ARG_INT]
+ 			      - numregs + ((numfpregs - 2) / 2),
+ 			      4 + ((*ca).arg_count[(int) SH_ARG_FLOAT]
+ 				   - numfpregs) / 2));
+ 		     }
+ 		   while (numfpregs -= 2);
+ 	       }
+ 	     else if ((MODE_) == SFmode && (named)
+ 		      && ((*ca).arg_count[(int) SH_ARG_FLOAT]
+ 			  < NPARM_REGS (SFmode)))
+ 	       (*ca).free_single_fp_reg
+ 		 = FIRST_FP_PARM_REG - numfpregs
+ 		 + (*ca).arg_count[(int) SH_ARG_FLOAT] + 1;
+ 	   }
+        }
+      return;
+    }
+ 
+  if ((TARGET_HITACHI || ca->renesas_abi) && TARGET_FPU_DOUBLE)
+    {
+      if ((mode) == SFmode && (*ca).free_single_fp_reg)
+        {
+ 	 (*ca).free_single_fp_reg = 0;
+ 	 return;
+        }
+      if ((mode) == DFmode
+ 	 && ROUND_REG (*ca, DFmode) != ROUND_REG (*ca, SFmode))
+        {
+ 	 (*ca).free_single_fp_reg = (ROUND_REG (*ca, SFmode)
+ 				     + BASE_ARG_REG (mode));
+        }
+    }
+ 
+  if (! (TARGET_SH4 || ca->renesas_abi)
+      || PASS_IN_REG_P ((*ca), (mode), (type)))
+    ((*ca).arg_count[(int) GET_SH_ARG_CLASS (mode)]
+     = (ROUND_REG ((*ca), (mode))
+        + ((mode) == BLKmode
+ 	  ? ROUND_ADVANCE (int_size_in_bytes (type))
+ 	  : ROUND_ADVANCE (GET_MODE_SIZE (mode)))));
+ }
+ 
+ /* If the structure value address is not passed in a register, define
+    `STRUCT_VALUE' as an expression returning an RTX for the place
+    where the address is passed.  If it returns 0, the address is
+    passed as an "invisible" first argument.  */
+ /* The Renesas calling convention doesn't quite fit into this scheme since
+    the address is passed like an invisible argument, but one that is always
+    passed in memory.  */
+ static rtx
+ sh_struct_value_rtx (fndecl, incoming)
+      tree fndecl;
+      int incoming ATTRIBUTE_UNUSED;
+ {
+   if (TARGET_HITACHI || sh_attr_renesas_p (fndecl))
+     return 0;
+   return gen_rtx_REG (Pmode, 2);
+ }
+ 
+ static bool
+ sh_return_in_memory (type, fndecl)
+      tree type;
+      tree fndecl;
+ {
+   if (TARGET_SH5)
+     {
+       if (TYPE_MODE (type) == BLKmode)
+ 	return ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)) > 8;
+       else
+ 	return GET_MODE_SIZE (TYPE_MODE (type)) > 8;
+     }
+   else
+     {
+       return (TYPE_MODE (type) == BLKmode
+ 	      || ((TARGET_HITACHI || sh_attr_renesas_p(fndecl))
+ 		  && TREE_CODE (type) == RECORD_TYPE));
+     }
+ }
+ 
+ /* We actually emit the code in sh_expand_prologue.  We used to use
+    a static variable to flag that we need to emit this code, but that
+    doesn't when inlining, when functions are deferred and then emitted
+    later.  Fortunately, we already have two flags that are part of struct
+    function that tell if a function uses varargs or stdarg.  */
+ static void
+ sh_setup_incoming_varargs (ca, mode, type, pretend_arg_size, second_time)
+      CUMULATIVE_ARGS *ca;
+      enum machine_mode mode;
+      tree type;
+      int *pretend_arg_size;
+      int second_time;
+ {
+   if (! current_function_stdarg)
+     abort ();
+ }
+ 
+ static bool
+ sh_strict_argument_naming (ca)
+      CUMULATIVE_ARGS *ca;
+ {
+   return TARGET_SH5;
+ }
+ 
+ static bool
+ sh_pretend_outgoing_varargs_named (ca)
+      CUMULATIVE_ARGS *ca;
+ {
+   return ! (TARGET_HITACHI || ca->renesas_abi) && ! TARGET_SH5;
+ }
+ 
+ 
  /* Define the offset between two registers, one to be eliminated, and
     the other its replacement, at the start of a routine.  */
*************** sh_insert_attributes (node, attributes)
*** 6425,6429 ****
  
     trap_exit -- use a trapa to exit an interrupt function instead of
!    an rte instruction.  */
  
  const struct attribute_spec sh_attribute_table[] =
--- 6794,6803 ----
  
     trap_exit -- use a trapa to exit an interrupt function instead of
!    an rte instruction.
! 
!    renesas -- use Renesas calling/layout conventions (functions and
!    structures).
! 
! */
  
  const struct attribute_spec sh_attribute_table[] =
*************** const struct attribute_spec sh_attribute
*** 6433,6436 ****
--- 6807,6811 ----
    { "sp_switch",         1, 1, true,  false, false, sh_handle_sp_switch_attribute },
    { "trap_exit",         1, 1, true,  false, false, sh_handle_trap_exit_attribute },
+   { "renesas",           0, 0, false, true, false, sh_handle_renesas_attribute },
    { NULL,                0, 0, false, false, false, NULL }
  };
*************** sh_handle_trap_exit_attribute (node, nam
*** 6538,6541 ****
--- 6913,6949 ----
  }
  
+ static tree
+ sh_handle_renesas_attribute (node, name, args, flags, no_add_attrs)
+      tree *node;
+      tree name;
+      tree args;
+      int flags ATTRIBUTE_UNUSED;
+      bool *no_add_attrs;
+ {
+   return NULL_TREE;
+ }
+ 
+ /* True if __attribute__((renesas)) and not -mrenesas.  */
+ int
+ sh_attr_renesas_p (td)
+      tree td;
+ {
+   if (TARGET_HITACHI)
+     return 1;
+   if (td == 0)
+     return 0;
+   if (DECL_P (td))
+     td = TREE_TYPE (td);
+   return (lookup_attribute ("renesas", TYPE_ATTRIBUTES (td))
+ 	  != NULL_TREE);
+ }
+ 
+ /* True if __attribute__((renesas)) and not -mrenesas.  */
+ int
+ sh_cfun_attr_renesas_p ()
+ {
+   return sh_attr_renesas_p (current_function_decl);
+ }
+ 
  int
  sh_cfun_interrupt_handler_p ()
*************** sh_ms_bitfield_layout_p (record_type)
*** 8001,8005 ****
       tree record_type ATTRIBUTE_UNUSED;
  {
!   return TARGET_SH5;
  }
  
--- 8409,8422 ----
       tree record_type ATTRIBUTE_UNUSED;
  {
!   return (TARGET_SH5 || TARGET_HITACHI || sh_attr_renesas_p (record_type));
! }
! 
! static bool
! sh_reverse_bitfield_layout_p (record_type)
!      tree record_type ATTRIBUTE_UNUSED;
! {
!   if (! TARGET_LITTLE_ENDIAN)
!     return 0;
!   return (TARGET_SH5 || TARGET_HITACHI || sh_attr_renesas_p (record_type));
  }
  
*************** sh_output_mi_thunk (file, thunk_fndecl, 
*** 8684,8691 ****
    INIT_CUMULATIVE_ARGS (cum, funtype, NULL_RTX, 0);
  #ifndef PCC_STATIC_STRUCT_RETURN
!   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
      structure_value_byref = 1;
  #endif /* not PCC_STATIC_STRUCT_RETURN */
!   if (structure_value_byref && struct_value_rtx == 0)
      { 
        tree ptype = build_pointer_type (TREE_TYPE (funtype));
--- 9101,9108 ----
    INIT_CUMULATIVE_ARGS (cum, funtype, NULL_RTX, 0);
  #ifndef PCC_STATIC_STRUCT_RETURN
!   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
      structure_value_byref = 1;
  #endif /* not PCC_STATIC_STRUCT_RETURN */
!   if (structure_value_byref && sh_struct_value_rtx (function, 0) == 0)
      { 
        tree ptype = build_pointer_type (TREE_TYPE (funtype));
Index: config/sh/sh.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/sh/sh.h,v
retrieving revision 1.219
diff -p -2 -r1.219  config/sh/sh.h
*** config/sh/sh.h	7 Aug 2003 19:35:52 -0000	1.219
--- config/sh/sh.h	14 Aug 2003 00:39:27 -0000
***************
*** 1,4 ****
  /* Definitions of target machine for GNU compiler for Renesas / SuperH SH.
!    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
     2003 Free Software Foundation, Inc.
     Contributed by Steve Chamberlain (sac@cygnus.com).
--- 1,4 ----
  /* Definitions of target machine for GNU compiler for Renesas / SuperH SH.
!    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
     2003 Free Software Foundation, Inc.
     Contributed by Steve Chamberlain (sac@cygnus.com).
*************** extern int target_flags;
*** 320,323 ****
--- 320,324 ----
    {"fmovd",  	FMOVD_BIT, "" },		\
    {"hitachi",	HITACHI_BIT, "Follow Renesas (formerly Hitachi) / SuperH calling conventions" },		\
+   {"renesas",	HITACHI_BIT, "Follow Renesas (formerly Hitachi) / SuperH calling conventions" },		\
    {"nomacsave", NOMACSAVE_BIT, "Mark MAC register as call-clobbered" },		\
    {"ieee",  	IEEE_BIT, "Increase the IEEE compliance for floating-point code" },			\
*************** extern char sh_additional_register_names
*** 1127,1153 ****
  #define STATIC_CHAIN_REGNUM	(TARGET_SH5 ? 1 : 3)
  
- /* The register in which a struct value address is passed.  */
- 
- #define STRUCT_VALUE_REGNUM 2
- 
- /* If the structure value address is not passed in a register, define
-    `STRUCT_VALUE' as an expression returning an RTX for the place
-    where the address is passed.  If it returns 0, the address is
-    passed as an "invisible" first argument.  */
- 
- /* The Renesas calling convention doesn't quite fit into this scheme since
-    the address is passed like an invisible argument, but one that is always
-    passed in memory.  */
- #define STRUCT_VALUE \
-   (TARGET_HITACHI ? 0 : gen_rtx_REG (Pmode, STRUCT_VALUE_REGNUM))
- 
- #define RETURN_IN_MEMORY(TYPE) \
-   (TARGET_SH5 \
-    ? ((TYPE_MODE (TYPE) == BLKmode \
-        ? (unsigned HOST_WIDE_INT) int_size_in_bytes (TYPE) \
-        : GET_MODE_SIZE (TYPE_MODE (TYPE))) > 8) \
-    : (TYPE_MODE (TYPE) == BLKmode \
-       || (TARGET_HITACHI && TREE_CODE (TYPE) == RECORD_TYPE)))
- 
  /* Don't default to pcc-struct-return, because we have already specified
     exactly how to return structures in the RETURN_IN_MEMORY macro.  */
--- 1128,1131 ----
*************** struct sh_args {
*** 1798,1801 ****
--- 1776,1783 ----
    (((COOKIE) >> CALL_COOKIE_INT_REG_SHIFT (REG)) & ((REG) < 4 ? 7 : 15))
      long call_cookie;
+ 
+   /* This is set to non-zero when the call in question must use the Renesas ABI,
+      even without the -mrenesas option.  */
+     int renesas_abi;
  };
  
*************** struct sh_args {
*** 1840,1854 ****
     For TARGET_HITACHI, the structure value pointer is passed in memory.  */
  
! #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
    do {								\
      (CUM).arg_count[(int) SH_ARG_INT] = 0;			\
      (CUM).arg_count[(int) SH_ARG_FLOAT] = 0;			\
      (CUM).force_mem						\
!       = (TARGET_HITACHI && FNTYPE				\
! 	 && aggregate_value_p (TREE_TYPE (FNTYPE)));		\
      (CUM).prototype_p = (FNTYPE) && TYPE_ARG_TYPES (FNTYPE);	\
      (CUM).arg_count[(int) SH_ARG_INT]				\
        = (TARGET_SH5 && (FNTYPE)					\
! 	 && aggregate_value_p (TREE_TYPE (FNTYPE)));		\
      (CUM).free_single_fp_reg = 0;				\
      (CUM).outgoing = 1;						\
--- 1822,1837 ----
     For TARGET_HITACHI, the structure value pointer is passed in memory.  */
  
! #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL) \
    do {								\
      (CUM).arg_count[(int) SH_ARG_INT] = 0;			\
      (CUM).arg_count[(int) SH_ARG_FLOAT] = 0;			\
+     (CUM).renesas_abi = sh_attr_renesas_p (FNTYPE) ? 1 : 0;	\
      (CUM).force_mem						\
!       = ((TARGET_HITACHI || (CUM).renesas_abi) && FNTYPE	\
! 	 && aggregate_value_p (TREE_TYPE (FNTYPE), FNDECL));	\
      (CUM).prototype_p = (FNTYPE) && TYPE_ARG_TYPES (FNTYPE);	\
      (CUM).arg_count[(int) SH_ARG_INT]				\
        = (TARGET_SH5 && (FNTYPE)					\
! 	 && aggregate_value_p (TREE_TYPE (FNTYPE), FNDECL));	\
      (CUM).free_single_fp_reg = 0;				\
      (CUM).outgoing = 1;						\
*************** struct sh_args {
*** 1882,2007 ****
      (CUM).outgoing = 0;						\
    } while (0)
-  
- /* Update the data in CUM to advance over an argument
-    of mode MODE and data type TYPE.
-    (TYPE is null for libcalls where that information may not be
-    available.)  */
  
  #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)	\
!  if ((CUM).force_mem)					\
!    (CUM).force_mem = 0;					\
!  else if (TARGET_SH5)					\
!    {							\
!      tree TYPE_ = ((CUM).byref && (TYPE)		\
! 		   ? TREE_TYPE (TYPE)			\
!  		   : (TYPE));				\
!      enum machine_mode MODE_ = ((CUM).byref && (TYPE)	\
! 				? TYPE_MODE (TYPE_)	\
! 				: (MODE));		\
!      int dwords = (((CUM).byref				\
! 		    ? (CUM).byref			\
! 		    : (MODE_) == BLKmode		\
! 		    ? int_size_in_bytes (TYPE_)		\
! 		    : GET_MODE_SIZE (MODE_)) + 7) / 8;	\
!      int numregs = MIN (dwords, NPARM_REGS (SImode)	\
! 			- (CUM).arg_count[(int) SH_ARG_INT]); \
! 							\
!      if (numregs)					\
!        {						\
! 	 (CUM).arg_count[(int) SH_ARG_INT] += numregs;	\
! 	 if (TARGET_SHCOMPACT				\
! 	     && SHCOMPACT_FORCE_ON_STACK (MODE_, TYPE_)) \
! 	   {						\
! 	     (CUM).call_cookie 				\
! 	       |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
! 					- numregs), 1);	\
! 	     /* N.B. We want this also for outgoing.   */\
! 	     (CUM).stack_regs += numregs;		\
! 	   }						\
! 	 else if ((CUM).byref)				\
! 	   {						\
! 	     if (! (CUM).outgoing)			\
! 	       (CUM).stack_regs += numregs;		\
! 	     (CUM).byref_regs += numregs;		\
! 	     (CUM).byref = 0;				\
! 	     do						\
! 	       (CUM).call_cookie			\
! 		 |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
! 					  - numregs), 2); \
! 	     while (--numregs);				\
! 	     (CUM).call_cookie				\
! 	       |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
! 				        - 1), 1); \
! 	   }						\
! 	 else if (dwords > numregs)			\
! 	   {						\
! 	     int pushregs = numregs;			\
! 							\
! 	     if (TARGET_SHCOMPACT)			\
! 	       (CUM).stack_regs += numregs;		\
! 	     while (pushregs < NPARM_REGS (SImode) - 1	\
! 		    && (CALL_COOKIE_INT_REG_GET		\
! 			((CUM).call_cookie,		\
! 			NPARM_REGS (SImode) - pushregs) \
! 			== 1))				\
! 	       {					\
! 		 (CUM).call_cookie			\
! 		   &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode) \
! 					     - pushregs, 1); \
! 		 pushregs++;				\
! 	       }					\
! 	     if (numregs == NPARM_REGS (SImode))	\
! 	       (CUM).call_cookie 			\
! 		 |= CALL_COOKIE_INT_REG (0, 1)		\
! 		    | CALL_COOKIE_STACKSEQ (numregs - 1); \
! 	     else					\
! 	       (CUM).call_cookie			\
! 		 |= CALL_COOKIE_STACKSEQ (numregs);	\
! 	   }						\
!        }						\
!      if (GET_SH_ARG_CLASS (MODE_) == SH_ARG_FLOAT	\
! 	 && ((NAMED) || ! (CUM).prototype_p))		\
!        {						\
! 	 if ((MODE_) == SFmode && (CUM).free_single_fp_reg) \
! 	   (CUM).free_single_fp_reg = 0;		\
! 	 else if ((CUM).arg_count[(int) SH_ARG_FLOAT]	\
!  		  < NPARM_REGS (SFmode))		\
! 	   {					        \
! 	     int numfpregs		 		\
! 	       = MIN ((GET_MODE_SIZE (MODE_) + 7) / 8 * 2, \
! 		      NPARM_REGS (SFmode)		\
! 		      - (CUM).arg_count[(int) SH_ARG_FLOAT]); \
! 		 					\
! 	     (CUM).arg_count[(int) SH_ARG_FLOAT] += numfpregs; \
! 							\
! 	     if (TARGET_SHCOMPACT && ! (CUM).prototype_p) \
! 	       {					\
! 		 if ((CUM).outgoing && numregs > 0)	\
! 		   do					\
! 		     {					\
! 		       (CUM).call_cookie		\
! 			 |= (CALL_COOKIE_INT_REG	\
! 			     ((CUM).arg_count[(int) SH_ARG_INT] \
! 			      - numregs + ((numfpregs - 2) / 2), \
! 			      4 + ((CUM).arg_count[(int) SH_ARG_FLOAT] \
! 				   - numfpregs) / 2));	\
! 		     }					\
! 		   while (numfpregs -= 2);		\
! 	       }					\
! 	     else if ((MODE_) == SFmode && (NAMED)	\
! 		      && ((CUM).arg_count[(int) SH_ARG_FLOAT] \
! 			  < NPARM_REGS (SFmode)))	\
! 	       (CUM).free_single_fp_reg			\
! 		 = FIRST_FP_PARM_REG - numfpregs	\
! 		 + (CUM).arg_count[(int) SH_ARG_FLOAT] + 1; \
! 	   }						\
!        }						\
!    }							\
!  else if (! TARGET_SH4 || PASS_IN_REG_P ((CUM), (MODE), (TYPE))) \
!    ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)]	\
!     = (ROUND_REG ((CUM), (MODE))			\
!        + ((MODE) == BLKmode				\
! 	  ? ROUND_ADVANCE (int_size_in_bytes (TYPE))	\
! 	  : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))))
  
  /* Return boolean indicating arg of mode MODE will be passed in a reg.
--- 1865,1873 ----
      (CUM).outgoing = 0;						\
    } while (0)
  
  #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)	\
! 	sh_function_arg_advance (&(CUM), (MODE), (TYPE), (NAMED))
! #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED)	\
! 	sh_function_arg (&(CUM), (MODE), (TYPE), (NAMED))
  
  /* Return boolean indicating arg of mode MODE will be passed in a reg.
*************** struct sh_args {
*** 2011,2015 ****
    (((TYPE) == 0 \
      || (! TREE_ADDRESSABLE ((tree)(TYPE)) \
! 	&& (! TARGET_HITACHI || ! AGGREGATE_TYPE_P (TYPE)))) \
     && ! (CUM).force_mem \
     && (TARGET_SH2E \
--- 1877,1884 ----
    (((TYPE) == 0 \
      || (! TREE_ADDRESSABLE ((tree)(TYPE)) \
! 	&& (! (TARGET_HITACHI || (CUM).renesas_abi) \
! 	    || ! (AGGREGATE_TYPE_P (TYPE) \
! 		  || (!TARGET_FPU_ANY && ((MODE) == DFmode \
! 				       || (MODE) == TFmode)))))) \
     && ! (CUM).force_mem \
     && (TARGET_SH2E \
*************** struct sh_args {
*** 2041,2113 ****
  #define FUNCTION_ARG_SCmode_WART 1
  
- /* Define where to put the arguments to a function.
-    Value is zero to push the argument on the stack,
-    or a hard register in which to store the argument.
- 
-    MODE is the argument's machine mode.
-    TYPE is the data type of the argument (as a tree).
-     This is null for libcalls where that information may
-     not be available.
-    CUM is a variable of type CUMULATIVE_ARGS which gives info about
-     the preceding args and about the function being called.
-    NAMED is nonzero if this argument is a named parameter
-     (otherwise it is an extra parameter matching an ellipsis).
- 
-    On SH the first args are normally in registers
-    and the rest are pushed.  Any arg that starts within the first
-    NPARM_REGS words is at least partially passed in a register unless
-    its data type forbids.  */
- 
- #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
-   ((! TARGET_SH5 \
-     && PASS_IN_REG_P ((CUM), (MODE), (TYPE))				\
-     && ((NAMED) || !TARGET_HITACHI))					\
-    ? (((MODE) == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN		\
-        && (! FUNCTION_ARG_SCmode_WART || (ROUND_REG ((CUM), (MODE)) & 1)))\
-       ? (gen_rtx_PARALLEL						\
- 	 (SCmode,							\
- 	  (gen_rtvec							\
- 	   (2, 								\
- 	    (gen_rtx_EXPR_LIST						\
- 	     (VOIDmode,							\
- 	      gen_rtx_REG (SFmode,					\
- 			   BASE_ARG_REG (MODE)				\
- 			   + (ROUND_REG ((CUM), (MODE)) ^ 1)),		\
- 	      const0_rtx)),						\
- 	    (gen_rtx_EXPR_LIST						\
- 	     (VOIDmode,							\
- 	      gen_rtx_REG (SFmode,					\
- 			   BASE_ARG_REG (MODE)				\
- 			   + ((ROUND_REG ((CUM), (MODE)) + 1) ^ 1)),	\
- 	      GEN_INT (4)))))))						\
-       : gen_rtx_REG ((MODE),						\
- 		     ((BASE_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE))) \
- 		      ^ ((MODE) == SFmode && TARGET_SH4			\
- 			 && TARGET_LITTLE_ENDIAN != 0))))		\
-    : TARGET_SH5								\
-    ? ((MODE) == VOIDmode && TARGET_SHCOMPACT				\
-       ? GEN_INT ((CUM).call_cookie)					\
-       /* The following test assumes unnamed arguments are promoted to	\
- 	 DFmode.  */							\
-       : (MODE) == SFmode && (CUM).free_single_fp_reg			\
-       ? SH5_PROTOTYPED_FLOAT_ARG ((CUM), (MODE), (CUM).free_single_fp_reg) \
-       : (GET_SH_ARG_CLASS (MODE) == SH_ARG_FLOAT			\
-          && ((NAMED) || ! (CUM).prototype_p)				\
-          && (CUM).arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (SFmode))	\
-       ? ((! (CUM).prototype_p && TARGET_SHMEDIA)			\
- 	 ? SH5_PROTOTYPELESS_FLOAT_ARG ((CUM), (MODE))			\
- 	 : SH5_PROTOTYPED_FLOAT_ARG ((CUM), (MODE),			\
- 				     FIRST_FP_PARM_REG			\
- 				     + (CUM).arg_count[(int) SH_ARG_FLOAT])) \
-       : ((CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)	\
- 	 && (! TARGET_SHCOMPACT						\
- 	     || (! SHCOMPACT_FORCE_ON_STACK ((MODE), (TYPE))		\
- 	         && ! SH5_WOULD_BE_PARTIAL_NREGS ((CUM), (MODE),	\
- 						  (TYPE), (NAMED)))))	\
-       ? gen_rtx_REG ((MODE), (FIRST_PARM_REG				\
-  			      + (CUM).arg_count[(int) SH_ARG_INT]))	\
-       : 0)								\
-    : 0)
- 
  /* Whether an argument must be passed by reference.  On SHcompact, we
     pretend arguments wider than 32-bits that would have been passed in
--- 1910,1913 ----
*************** struct sh_args {
*** 2204,2211 ****
  				   const0_rtx))))
  
- #define STRICT_ARGUMENT_NAMING TARGET_SH5
- 
- #define PRETEND_OUTGOING_VARARGS_NAMED (! TARGET_HITACHI && ! TARGET_SH5)
- 
  /* For an arg passed partly in registers and partly in memory,
     this is the number of registers used.
--- 2004,2007 ----
*************** struct sh_args {
*** 2239,2252 ****
     variable number of arguments.  */
  
- /* We actually emit the code in sh_expand_prologue.  We used to use
-    a static variable to flag that we need to emit this code, but that
-    doesn't when inlining, when functions are deferred and then emitted
-    later.  Fortunately, we already have two flags that are part of struct
-    function that tell if a function uses varargs or stdarg.  */
- #define SETUP_INCOMING_VARARGS(ASF, MODE, TYPE, PAS, ST)  do \
-   if (! current_function_stdarg) \
-     abort (); \
- while (0)
- 
  /* Define the `__builtin_va_list' type for the ABI.  */
  #define BUILD_VA_LIST_TYPE(VALIST) \
--- 2035,2038 ----
*************** while (0)
*** 2337,2343 ****
    gen_rtx_REG (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG)
  
- /* Generate necessary RTL for __builtin_saveregs().  */
- #define EXPAND_BUILTIN_SAVEREGS() sh_builtin_saveregs ()
- 
  /* Addressing modes, and classification of registers for them.  */
  #define HAVE_POST_INCREMENT  TARGET_SH1
--- 2123,2126 ----
*************** while (0)
*** 2919,2925 ****
     but a CALL with constant address is cheap.  */
  /*#define NO_FUNCTION_CSE 1*/
- 
- /* Chars and shorts should be passed as ints.  */
- #define PROMOTE_PROTOTYPES 1
  
  /* The machine modes of pointers and functions.  */
--- 2702,2705 ----
Index: config/sparc/sparc.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/sparc/sparc.c,v
retrieving revision 1.254
diff -p -2 -r1.254  config/sparc/sparc.c
*** config/sparc/sparc.c	16 Jul 2003 08:36:27 -0000	1.254
--- config/sparc/sparc.c	14 Aug 2003 00:39:28 -0000
*************** sparc_output_mi_thunk (file, thunk_fndec
*** 8606,8610 ****
    /* Find the "this" pointer.  Normally in %o0, but in ARCH64 if the function
       returns a structure, the structure return pointer is there instead.  */
!   if (TARGET_ARCH64 && aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
      this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST + 1);
    else
--- 8606,8610 ----
    /* Find the "this" pointer.  Normally in %o0, but in ARCH64 if the function
       returns a structure, the structure return pointer is there instead.  */
!   if (TARGET_ARCH64 && aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
      this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST + 1);
    else
Index: config/stormy16/stormy16.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/stormy16/stormy16.c,v
retrieving revision 1.48
diff -p -2 -r1.48  config/stormy16/stormy16.c
*** config/stormy16/stormy16.c	3 Jul 2003 16:25:52 -0000	1.48
--- config/stormy16/stormy16.c	14 Aug 2003 00:39:28 -0000
*************** xstormy16_asm_output_mi_thunk (file, thu
*** 1563,1567 ****
    
    /* There might be a hidden first argument for a returned structure.  */
!   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
      regnum += 1;
    
--- 1563,1567 ----
    
    /* There might be a hidden first argument for a returned structure.  */
!   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
      regnum += 1;
    
Index: doc/tm.texi
===================================================================
RCS file: /cvs/uberbaum/gcc/doc/tm.texi,v
retrieving revision 1.252
diff -p -2 -r1.252  doc/tm.texi
*** doc/tm.texi	1 Aug 2003 21:53:22 -0000	1.252
--- doc/tm.texi	14 Aug 2003 00:39:33 -0000
*************** Do not define this macro if it would nev
*** 1057,1078 ****
  @end defmac
  
! @defmac PROMOTE_FUNCTION_ARGS
! Define this macro if the promotion described by @code{PROMOTE_MODE}
! should also be done for outgoing function arguments.
! @end defmac
  
! @defmac PROMOTE_FUNCTION_RETURN
! Define this macro if the promotion described by @code{PROMOTE_MODE}
! should also be done for the return value of functions.
  
! If this macro is defined, @code{FUNCTION_VALUE} must perform the same
! promotions done by @code{PROMOTE_MODE}.
! @end defmac
  
  @defmac PROMOTE_FOR_CALL_ONLY
  Define this macro if the promotion described by @code{PROMOTE_MODE}
  should @emph{only} be performed for outgoing function arguments or
! function return values, as specified by @code{PROMOTE_FUNCTION_ARGS}
! and @code{PROMOTE_FUNCTION_RETURN}, respectively.
  @end defmac
  
--- 1057,1079 ----
  @end defmac
  
! @deftypefn {Target Hook} bool TARGET_PROMOTE_FUNCTION_ARGS (tree @var{fntype})
! This target hook should return @code{true} if the promotion described by
! @code{PROMOTE_MODE} should also be done for outgoing function arguments.
! @end deftypefn
  
! @deftypefn {Target Hook} bool TARGET_PROMOTE_FUNCTION_RETURN (tree @var{fntype})
! This target hook should return @code{true} if the promotion described by
! @code{PROMOTE_MODE} should also be done for the return value of
! functions.
  
! If this target hook returns @code{true}, @code{FUNCTION_VALUE} must
! perform the same promotions done by @code{PROMOTE_MODE}.
! @end deftypefn
  
  @defmac PROMOTE_FOR_CALL_ONLY
  Define this macro if the promotion described by @code{PROMOTE_MODE}
  should @emph{only} be performed for outgoing function arguments or
! function return values, as specified by @code{TARGET_PROMOTE_FUNCTION_ARGS}
! and @code{TARGET_PROMOTE_FUNCTION_RETURN}, respectively.
  @end defmac
  
*************** may affect its placement.
*** 1499,1502 ****
--- 1500,1514 ----
  @end deftypefn
  
+ @deftypefn {Target Hook} bool TARGET_REVERSE_BITFIELD_LAYOUT_P (tree @var{record_type})
+ This target hook returns @code{true} if space for bit-fields should be
+ allocated from the "other end" of the space their base type takes up in
+ the structure.  For example, normally on a big-endian target, the first
+ bitfield will show up in the MSB of the underlying type, but this hook
+ makes it show up in the LSB.  Note that because of the way GCC normally
+ fills structs, this option is only available when each base type is kept
+ separate - in other words, the @code{TARGET_MS_BITFIELD_LAYOUT_P} hook
+ must also return @code{true} for the given structure.
+ @end deftypefn
+ 
  @node Type Layout
  @section Layout of Source Language Data Types
*************** on the stack.  See the following section
*** 3352,3363 ****
  control passing certain arguments in registers.
  
! @defmac PROMOTE_PROTOTYPES
! A C expression whose value is nonzero if an argument declared in
! a prototype as an integral type smaller than @code{int} should
! actually be passed as an @code{int}.  In addition to avoiding
! errors in certain cases of mismatch, it also makes for better
! code on certain machines.  If the macro is not defined in target
! header files, it defaults to 0.
! @end defmac
  
  @defmac PUSH_ARGS
--- 3364,3374 ----
  control passing certain arguments in registers.
  
! @deftypefn {Target Hook} bool TARGET_PROMOTE_PROTOTYPES (tree @var{fntype})
! This target hook returns @code{true} if an argument declared in a
! prototype as an integral type smaller than @code{int} should actually be
! passed as an @code{int}.  In addition to avoiding errors in certain
! cases of mismatch, it also makes for better code on certain machines.
! The default is to not promote prototypes.
! @end deftypefn
  
  @defmac PUSH_ARGS
*************** register where the return value is store
*** 3818,3822 ****
  @code{FUNCTION_ARG} for an explanation of the @code{parallel} form.
  
! If @code{PROMOTE_FUNCTION_RETURN} is defined, you must apply the same
  promotion rules specified in @code{PROMOTE_MODE} if @var{valtype} is a
  scalar type.
--- 3829,3833 ----
  @code{FUNCTION_ARG} for an explanation of the @code{parallel} form.
  
! If @code{TARGET_PROMOTE_FUNCTION_RETURN} is defined, you must apply the same
  promotion rules specified in @code{PROMOTE_MODE} if @var{valtype} is a
  scalar type.
*************** This section describes how to control re
*** 3909,3930 ****
  memory.
  
! @defmac RETURN_IN_MEMORY (@var{type})
! A C expression which can inhibit the returning of certain function
! values in registers, based on the type of value.  A nonzero value says
! to return the function value in memory, just as large structures are
! always returned.  Here @var{type} will be a C expression of type
! @code{tree}, representing the data type of the value.
  
  Note that values of mode @code{BLKmode} must be explicitly handled
! by this macro.  Also, the option @option{-fpcc-struct-return}
  takes effect regardless of this macro.  On most systems, it is
! possible to leave the macro undefined; this causes a default
  definition to be used, whose value is the constant 1 for @code{BLKmode}
  values, and 0 otherwise.
  
! Do not use this macro to indicate that structures and unions should always
  be returned in memory.  You should instead use @code{DEFAULT_PCC_STRUCT_RETURN}
  to indicate this.
! @end defmac
  
  @defmac DEFAULT_PCC_STRUCT_RETURN
--- 3920,3941 ----
  memory.
  
! @deftypefn {Target Hook} bool RETURN_IN_MEMORY (tree @var{type}, tree @var{fntype})
! This target hook should return a nonzero value to say to return the
! function value in memory, just as large structures are always returned.
! Here @var{type} will be the data type of the value, and @var{fntype}
! will be the type of the function doing the returning, or @code{NULL} for
! libcalls.
  
  Note that values of mode @code{BLKmode} must be explicitly handled
! by this function.  Also, the option @option{-fpcc-struct-return}
  takes effect regardless of this macro.  On most systems, it is
! possible to leave the hook undefined; this causes a default
  definition to be used, whose value is the constant 1 for @code{BLKmode}
  values, and 0 otherwise.
  
! Do not use this hook to indicate that structures and unions should always
  be returned in memory.  You should instead use @code{DEFAULT_PCC_STRUCT_RETURN}
  to indicate this.
! @end deftypefn
  
  @defmac DEFAULT_PCC_STRUCT_RETURN
*************** If not defined, this defaults to the val
*** 3938,3971 ****
  @end defmac
  
! @defmac STRUCT_VALUE_REGNUM
! If the structure value address is passed in a register, then
! @code{STRUCT_VALUE_REGNUM} should be the number of that register.
! @end defmac
! 
! @defmac STRUCT_VALUE
! If the structure value address is not passed in a register, define
! @code{STRUCT_VALUE} as an expression returning an RTX for the place
! where the address is passed.  If it returns 0, the address is passed as
! an ``invisible'' first argument.
! @end defmac
  
- @defmac STRUCT_VALUE_INCOMING_REGNUM
  On some architectures the place where the structure value address
  is found by the called function is not the same place that the
  caller put it.  This can be due to register windows, or it could
  be because the function prologue moves it to a different place.
  
! If the incoming location of the structure value address is in a
! register, define this macro as the register number.
! @end defmac
! 
! @defmac STRUCT_VALUE_INCOMING
! If the incoming location is not a register, then you should define
! @code{STRUCT_VALUE_INCOMING} as an expression for an RTX for where the
! called function should find the value.  If it should find the value on
! the stack, define this to create a @code{mem} which refers to the frame
! pointer.  A definition of 0 means that the address is passed as an
! ``invisible'' first argument.
! @end defmac
  
  @defmac PCC_STATIC_STRUCT_RETURN
--- 3949,3969 ----
  @end defmac
  
! @deftypefn {Target Hook} rtx TARGET_STRUCT_VALUE_RTX (tree @var{fndecl}, int @var{incoming})
! This target hook should return the location of the structure value
! address (normally a @code{mem} or @code{reg}), or 0 if the address is
! passed as an ``invisible'' first argument.  Note that @var{fndecl} may
! be @code{NULL}, for libcalls.
  
  On some architectures the place where the structure value address
  is found by the called function is not the same place that the
  caller put it.  This can be due to register windows, or it could
  be because the function prologue moves it to a different place.
+ @var{incoming} is @code{true} when the location is needed in
+ the context of the called function, and @code{false} in the context of
+ the caller.
  
! If @var{incoming} is @code{true} and the address is to be found on the
! stack, return a @code{mem} which refers to the frame pointer.
! @end deftypefn
  
  @defmac PCC_STATIC_STRUCT_RETURN
*************** interpret the values of @code{__builtin_
*** 4427,4494 ****
  These machine description macros help implement varargs:
  
! @defmac EXPAND_BUILTIN_SAVEREGS ()
! If defined, is a C expression that produces the machine-specific code
! for a call to @code{__builtin_saveregs}.  This code will be moved to the
! very beginning of the function, before any parameter access are made.
! The return value of this function should be an RTX that contains the
! value to use as the return of @code{__builtin_saveregs}.
! @end defmac
! 
! @defmac SETUP_INCOMING_VARARGS (@var{args_so_far}, @var{mode}, @var{type}, @var{pretend_args_size}, @var{second_time})
! This macro offers an alternative to using @code{__builtin_saveregs} and
! defining the macro @code{EXPAND_BUILTIN_SAVEREGS}.  Use it to store the
! anonymous register arguments into the stack so that all the arguments
! appear to have been passed consecutively on the stack.  Once this is
! done, you can use the standard implementation of varargs that works for
! machines that pass all their arguments on the stack.
  
! The argument @var{args_so_far} is the @code{CUMULATIVE_ARGS} data
  structure, containing the values that are obtained after processing the
  named arguments.  The arguments @var{mode} and @var{type} describe the
  last named argument---its machine mode and its data type as a tree node.
  
! The macro implementation should do two things: first, push onto the
! stack all the argument registers @emph{not} used for the named
! arguments, and second, store the size of the data thus pushed into the
! @code{int}-valued variable whose name is supplied as the argument
! @var{pretend_args_size}.  The value that you store here will serve as
! additional offset for setting up the stack frame.
  
  Because you must generate code to push the anonymous arguments at
  compile time without knowing their data types,
! @code{SETUP_INCOMING_VARARGS} is only useful on machines that have just
! a single category of argument register and use it uniformly for all data
! types.
  
  If the argument @var{second_time} is nonzero, it means that the
  arguments of the function are being analyzed for the second time.  This
  happens for an inline function, which is not actually compiled until the
! end of the source file.  The macro @code{SETUP_INCOMING_VARARGS} should
  not generate any instructions in this case.
! @end defmac
  
! @defmac STRICT_ARGUMENT_NAMING
! Define this macro to be a nonzero value if the location where a function
  argument is passed depends on whether or not it is a named argument.
  
! This macro controls how the @var{named} argument to @code{FUNCTION_ARG}
! is set for varargs and stdarg functions.  If this macro returns a
! nonzero value, the @var{named} argument is always true for named
! arguments, and false for unnamed arguments.  If it returns a value of
! zero, but @code{SETUP_INCOMING_VARARGS} is defined, then all arguments
! are treated as named.  Otherwise, all named arguments except the last
! are treated as named.
  
! You need not define this macro if it always returns zero.
! @end defmac
  
! @defmac PRETEND_OUTGOING_VARARGS_NAMED
  If you need to conditionally change ABIs so that one works with
! @code{SETUP_INCOMING_VARARGS}, but the other works like neither
! @code{SETUP_INCOMING_VARARGS} nor @code{STRICT_ARGUMENT_NAMING} was
! defined, then define this macro to return nonzero if
! @code{SETUP_INCOMING_VARARGS} is used, zero otherwise.
! Otherwise, you should not define this macro.
! @end defmac
  
  @node Trampolines
--- 4425,4493 ----
  These machine description macros help implement varargs:
  
! @deftypefn {Target Hook} rtx TARGET_EXPAND_BUILTIN_SAVEREGS (void)
! If defined, this hook produces the machine-specific code for a call to
! @code{__builtin_saveregs}.  This code will be moved to the very
! beginning of the function, before any parameter access are made.  The
! return value of this function should be an RTX that contains the value
! to use as the return of @code{__builtin_saveregs}.
! @end deftypefn
! 
! @deftypefn {Target Hook} void TARGET_SETUP_INCOMING_VARARGS (CUMULATIVE_ARGS *@var{args_so_far}, enum machine_mode @var{mode}, tree @var{type}, int *@var{pretend_args_size}, int @var{second_time})
! This target hook offers an alternative to using
! @code{__builtin_saveregs} and defining the hook
! @code{TARGET_EXPAND_BUILTIN_SAVEREGS}.  Use it to store the anonymous
! register arguments into the stack so that all the arguments appear to
! have been passed consecutively on the stack.  Once this is done, you can
! use the standard implementation of varargs that works for machines that
! pass all their arguments on the stack.
  
! The argument @var{args_so_far} points to the @code{CUMULATIVE_ARGS} data
  structure, containing the values that are obtained after processing the
  named arguments.  The arguments @var{mode} and @var{type} describe the
  last named argument---its machine mode and its data type as a tree node.
  
! The target hook should do two things: first, push onto the stack all the
! argument registers @emph{not} used for the named arguments, and second,
! store the size of the data thus pushed into the @code{int}-valued
! variable pointed to by @var{pretend_args_size}.  The value that you
! store here will serve as additional offset for setting up the stack
! frame.
  
  Because you must generate code to push the anonymous arguments at
  compile time without knowing their data types,
! @code{TARGET_SETUP_INCOMING_VARARGS} is only useful on machines that
! have just a single category of argument register and use it uniformly
! for all data types.
  
  If the argument @var{second_time} is nonzero, it means that the
  arguments of the function are being analyzed for the second time.  This
  happens for an inline function, which is not actually compiled until the
! end of the source file.  The hook @code{TARGET_SETUP_INCOMING_VARARGS} should
  not generate any instructions in this case.
! @end deftypefn
  
! @deftypefn {Target Hook} bool TARGET_STRICT_ARGUMENT_NAMING (CUMULATIVE_ARGS *@var{ca})
! Define this hook to return @code{true} if the location where a function
  argument is passed depends on whether or not it is a named argument.
  
! This hook controls how the @var{named} argument to @code{FUNCTION_ARG}
! is set for varargs and stdarg functions.  If this hook returns
! @code{true}, the @var{named} argument is always true for named
! arguments, and false for unnamed arguments.  If it returns @code{false},
! but @code{TARGET_PRETEND_OUTOGOING_VARARGS_NAMED} returns @code{true},
! then all arguments are treated as named.  Otherwise, all named arguments
! except the last are treated as named.
  
! You need not define this hook if it always returns zero.
! @end deftypefn
  
! @deftypefn {Target Hook} bool TARGET_PRETEND_OUTGOING_VARARGS_NAMED
  If you need to conditionally change ABIs so that one works with
! @code{TARGET_SETUP_INCOMING_VARARGS}, but the other works like neither
! @code{TARGET_SETUP_INCOMING_VARARGS} nor @code{TARGET_STRICT_ARGUMENT_NAMING} was
! defined, then define this hook to return @code{true} if
! @code{SETUP_INCOMING_VARARGS} is used, @code{false} otherwise.
! Otherwise, you should not define this hook.
! @end deftypefn
  
  @node Trampolines

---------------------------------------- targhooks.h
/* Default target hook functions.
   Copyright (C) 2003 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */

extern bool default_promote_function_args (tree);
extern bool default_promote_function_return (tree);
extern bool default_promote_prototypes (tree);

extern rtx default_struct_value_rtx (tree, int);
extern bool default_return_in_memory (tree, tree);

extern rtx default_expand_builtin_saveregs (void);
extern void default_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int);
extern bool default_strict_argument_naming (CUMULATIVE_ARGS *);
extern bool default_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *);

---------------------------------------- targhooks.c
/* Default target hook functions.
   Copyright (C) 2003 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "machmode.h"
#include "rtl.h"
#include "tree.h"
#include "expr.h"
#include "toplev.h"
#include "function.h"
#include "target.h"
#include "tm_p.h"
#include "target-def.h"

bool
default_promote_function_args (fntype)
     tree fntype ATTRIBUTE_UNUSED;
{
#ifdef PROMOTE_FUNCTION_ARGS
  return true;
#else
  return false;
#endif
}

bool
default_promote_function_return (fntype)
     tree fntype ATTRIBUTE_UNUSED;
{
#ifdef PROMOTE_FUNCTION_RETURN
  return true;
#else
  return false;
#endif
}

bool
default_promote_prototypes (fntype)
     tree fntype ATTRIBUTE_UNUSED;
{
  if (PROMOTE_PROTOTYPES)
    return true;
  else
    return false;
}

rtx
default_struct_value_rtx (tree fntype, int incoming)
{
  rtx rv = 0;
  if (incoming)
    {
#ifdef STRUCT_VALUE_INCOMING
      rv = STRUCT_VALUE_INCOMING;
#else
#ifdef STRUCT_VALUE_INCOMING_REGNUM
      rv = gen_rtx_REG (Pmode, STRUCT_VALUE_INCOMING_REGNUM);
#else
#ifdef STRUCT_VALUE
      rv = STRUCT_VALUE;
#else
#ifndef STRUCT_VALUE_REGNUM
      abort();
#else
      rv = gen_rtx_REG (Pmode, STRUCT_VALUE_REGNUM);
#endif
#endif
#endif
#endif
    }
  else
    {
#ifdef STRUCT_VALUE
      rv = STRUCT_VALUE;
#else
#ifndef STRUCT_VALUE_REGNUM
      abort();
#else
      rv = gen_rtx_REG (Pmode, STRUCT_VALUE_REGNUM);
#endif
#endif
    }
  return rv;
}

bool
default_return_in_memory (tree type,
			  tree fntype ATTRIBUTE_UNUSED)
{
  return RETURN_IN_MEMORY (type);
}

rtx
default_expand_builtin_saveregs (void)
{
#ifdef EXPAND_BUILTIN_SAVEREGS
  return EXPAND_BUILTIN_SAVEREGS ();
#else
  error ("__builtin_saveregs not supported by this target");
  return const0_rtx;
#endif
}

void
default_setup_incoming_varargs (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
				enum machine_mode mode ATTRIBUTE_UNUSED,
				tree type ATTRIBUTE_UNUSED,
				int *pretend_arg_size ATTRIBUTE_UNUSED,
				int second_time ATTRIBUTE_UNUSED)
{
#ifdef SETUP_INCOMING_VARARGS
  SETUP_INCOMING_VARARGS ((*ca), mode, type, (*pretend_arg_size), second_time);
#endif
}

bool
default_strict_argument_naming (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
{
#ifdef STRICT_ARGUMENT_NAMING
  return STRICT_ARGUMENT_NAMING;
#else
  return 0;
#endif
}

bool
default_pretend_outgoing_varargs_named(CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
{
#ifdef PRETEND_OUTGOING_VARARGS_NAMED
  return PRETEND_OUTGOING_VARARGS_NAMED;
#else
#ifdef SETUP_INCOMING_VARARGS
  return 1;
#else
  return (targetm.calls.setup_incoming_varargs != default_setup_incoming_varargs);
#endif
#endif
}



More information about the Gcc-patches mailing list