targhooks.c: New file.
authorDJ Delorie <dj@redhat.com>
Thu, 4 Sep 2003 03:18:05 +0000 (23:18 -0400)
committerDJ Delorie <dj@gcc.gnu.org>
Thu, 4 Sep 2003 03:18:05 +0000 (23:18 -0400)
* 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.
(expand_function_start): Likewise.  Convert to
calls.struct_value_rtx hook.
(expand_function_end): Convert to calls.promote_function_return hook.
(allocate_struct_function): Pass fndecl to aggregate_value_p.
* 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.
* target-def.h: Add 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.

* 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.
* objc/objc-act.c (generate_struct_by_value_array): Pass NULL 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_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_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.  * config/sh/sh.md (call): Set
call cookie to indicate renesas calls.

* decl.c (finish_function): Pass fndecl to aggregate_value_p.

* misc.c (default_pass_by_ref): Convert to calls.return_in_memory
hook.

From-SVN: r71048

43 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/ada/ChangeLog
gcc/ada/misc.c
gcc/builtins.c
gcc/c-decl.c
gcc/c-typeck.c
gcc/calls.c
gcc/combine.c
gcc/config/alpha/alpha.c
gcc/config/arm/arm.c
gcc/config/i386/i386.c
gcc/config/i960/i960.c
gcc/config/m68hc11/m68hc11.c
gcc/config/mips/mips.c
gcc/config/rs6000/rs6000.c
gcc/config/s390/s390.c
gcc/config/sh/sh-protos.h
gcc/config/sh/sh.c
gcc/config/sh/sh.h
gcc/config/sh/sh.md
gcc/config/sparc/sparc.c
gcc/config/stormy16/stormy16.c
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/doc/tm.texi
gcc/emit-rtl.c
gcc/expr.c
gcc/expr.h
gcc/final.c
gcc/function.c
gcc/hard-reg-set.h
gcc/integrate.c
gcc/objc/objc-act.c
gcc/reg-stack.c
gcc/rtl.h
gcc/stmt.c
gcc/stor-layout.c
gcc/target-def.h
gcc/target.h
gcc/targhooks.c [new file with mode: 0644]
gcc/targhooks.h [new file with mode: 0644]
gcc/tree.h

index bd7880186cf21b989c6bbf63103a6f35a3c372d6..62e9d65b6ced50c309a623d3c832858aa49fffab 100644 (file)
@@ -1,3 +1,135 @@
+2003-09-03  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.
+       (expand_function_start): Likewise.  Convert to
+       calls.struct_value_rtx hook.
+       (expand_function_end): Convert to calls.promote_function_return hook.
+       (allocate_struct_function): Pass fndecl to aggregate_value_p.
+       * 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.
+       * target-def.h: Add 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.
+       
+       * 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.
+       * objc/objc-act.c (generate_struct_by_value_array): Pass NULL 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_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_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.  * config/sh/sh.md (call): Set
+       call cookie to indicate renesas calls.
+       
 2003-09-03  Mostafa Hagog  <mustafa@il.ibm.com>
 
        * gcse.c (replace_one_set): New function.
index b6dd4eedf2e6ea9e078c2e9c8c76264c8dac52cf..672e09ac0f056d754892c448a95a9850d0e7a444 100644 (file)
@@ -844,7 +844,7 @@ OBJS-common = \
  reload.o reload1.o reorg.o resource.o rtl.o rtlanal.o rtl-error.o        \
  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 \
+ 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) 
 
@@ -1488,6 +1488,9 @@ diagnostic.o : diagnostic.c $(DIAGNOSTIC_H) real.h \
 opts.o : opts.c opts.h options.h toplev.h $(CONFIG_H) $(SYSTEM_H) \
        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) \
    debug.h insn-config.h intl.h $(RECOG_H) Makefile toplev.h \
@@ -1526,11 +1529,11 @@ varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_
 function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
    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
+   $(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)
+   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 \
    insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
@@ -1696,7 +1699,7 @@ dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
 et-forest.o : et-forest.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) et-forest.h alloc-pool.h
 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)
+   $(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 \
    real.h toplev.h function.h output.h $(GGC_H) $(TM_P_H) $(EXPR_H) $(TIMEVAR_H)
index 9efeeb85ffbe0531a76143cb738475378d8305ff..ae7a1de3aeaddbc0a7aef2def3e254602586a2b2 100644 (file)
@@ -1,3 +1,8 @@
+2003-09-03  DJ Delorie  <dj@redhat.com>
+
+       * misc.c (default_pass_by_ref): Convert to calls.return_in_memory
+       hook.
+
 2003-08-30  Zack Weinberg  <zack@codesourcery.com>
 
        * Makefile.in: Update substitutions to match changes to
index 60232bf59970f3b9d1b5ad6e27ba30e75ab040f5..f4407e5a35de75e7294775ef04797800ac65566f 100644 (file)
@@ -7,7 +7,7 @@
  *                           C Implementation File                          *
  *                                                                          *
  *                                                                          *
- *          Copyright (C) 1992-2002 Free Software Foundation, Inc.          *
+ *          Copyright (C) 1992-2003 Free Software Foundation, Inc.          *
  *                                                                          *
  * GNAT is free software;  you can  redistribute it  and/or modify it under *
  * terms of the  GNU General Public License as published  by the Free Soft- *
@@ -796,7 +796,7 @@ default_pass_by_ref (gnu_type)
          || FUNCTION_ARG_PASS_BY_REFERENCE (cum, TYPE_MODE (gnu_type),
                                             gnu_type, 1)
 #endif
-         || RETURN_IN_MEMORY (gnu_type)
+         || targetm.calls.return_in_memory (gnu_type, NULL_TREE)
          || (AGGREGATE_TYPE_P (gnu_type)
              && (! host_integerp (TYPE_SIZE (gnu_type), 1)
                  || 0 < compare_tree_int (TYPE_SIZE (gnu_type),
index c63d812d90fa3e53c2fd79cc40f6cd33435dc67d..6fa03503a9e9013dcd7f6faeeda1fd1e114dc454 100644 (file)
@@ -941,7 +941,7 @@ apply_args_size (void)
 
       /* The second value is the structure value address unless this is
         passed as an "invisible" first argument.  */
-      if (struct_value_rtx)
+      if (targetm.calls.struct_value_rtx (TREE_TYPE (cfun->decl), 0))
        size += GET_MODE_SIZE (Pmode);
 
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
@@ -1116,6 +1116,7 @@ expand_builtin_apply_args_1 (void)
   rtx registers;
   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,
      and argument registers can be saved.  */
@@ -1123,7 +1124,7 @@ expand_builtin_apply_args_1 (void)
 
   /* Walk past the arg-pointer and structure value address.  */
   size = GET_MODE_SIZE (Pmode);
-  if (struct_value_rtx)
+  if (targetm.calls.struct_value_rtx (TREE_TYPE (cfun->decl), 0))
     size += GET_MODE_SIZE (Pmode);
 
   /* Save each register used in calling a function to the block.  */
@@ -1149,10 +1150,10 @@ expand_builtin_apply_args_1 (void)
 
   /* Save the structure value address unless this is passed as an
      "invisible" first argument.  */
-  if (struct_value_incoming_rtx)
+  if (struct_incoming_value)
     {
       emit_move_insn (adjust_address (registers, Pmode, size),
-                     copy_to_reg (struct_value_incoming_rtx));
+                     copy_to_reg (struct_incoming_value));
       size += GET_MODE_SIZE (Pmode);
     }
 
@@ -1210,6 +1211,7 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
   rtx incoming_args, result, reg, dest, src, call_insn;
   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
   if (GET_MODE (arguments) != Pmode)
@@ -1263,7 +1265,7 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
 
   /* Walk past the arg-pointer and structure value address.  */
   size = GET_MODE_SIZE (Pmode);
-  if (struct_value_rtx)
+  if (struct_value)
     size += GET_MODE_SIZE (Pmode);
 
   /* Restore each of the registers previously saved.  Make USE insns
@@ -1283,13 +1285,13 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
   /* Restore the structure value address unless this is passed as an
      "invisible" first argument.  */
   size = GET_MODE_SIZE (Pmode);
-  if (struct_value_rtx)
+  if (struct_value)
     {
       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);
+      emit_move_insn (struct_value, value);
+      if (GET_CODE (struct_value) == REG)
+       use_reg (&call_fusage, struct_value);
       size += GET_MODE_SIZE (Pmode);
     }
 
@@ -3728,21 +3730,8 @@ expand_builtin_saveregs (void)
 
   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
+  val = targetm.calls.expand_builtin_saveregs ();
 
   seq = get_insns ();
   end_sequence ();
index 31212ff42c5bc2226669974f14b82dc021a0e1af..f16fe7cd2f606351f8da520ff17b92017184e2f3 100644 (file)
@@ -2672,6 +2672,26 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
   decl_attributes (&decl, attributes, 0);
 
+  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)
@@ -4574,10 +4594,6 @@ get_parm_info (int void_at_end)
         declared types.  The back end may override this.  */
       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.  */
       if (VOID_TYPE_P (type) && !DECL_NAME (decl) && !gave_void_only_once_err)
@@ -5899,7 +5915,7 @@ store_parm_decls_oldstyle (void)
                     useful for argument types like uid_t.  */
                  DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
 
-                 if (PROMOTE_PROTOTYPES
+                 if (targetm.calls.promote_prototypes (TREE_TYPE (current_function_decl))
                      && INTEGRAL_TYPE_P (TREE_TYPE (parm))
                      && TYPE_PRECISION (TREE_TYPE (parm))
                      < TYPE_PRECISION (integer_type_node))
@@ -6051,6 +6067,19 @@ finish_function ()
       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;
+       }
+    }
+
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
 
   /* Must mark the RESULT_DECL as being in this function.  */
index 1d5823c131fc1996f73ffdd4aa8679c5babeae2b..23e73e8798253fbc51a3f163d9bb5aa47bb5044c 100644 (file)
@@ -1866,7 +1866,7 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
                                                (char *) 0, /* arg passing  */
                                                fundecl, name, parmnum + 1);
 
-             if (PROMOTE_PROTOTYPES
+             if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
                  && INTEGRAL_TYPE_P (type)
                  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
                parmval = default_conversion (parmval);
@@ -3615,7 +3615,7 @@ c_convert_parm_for_inlining (tree parm, tree value, tree fn)
   ret = convert_for_assignment (type, value,
                                (char *) 0 /* arg passing  */, fn,
                                DECL_NAME (fn), 0);
-  if (PROMOTE_PROTOTYPES
+  if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
       && INTEGRAL_TYPE_P (type)
       && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
     ret = default_conversion (ret);
index 50fa592972a55bfd5ccdad2056b37a00e04b7a0b..dc3da0a91749720823b3b7d21a066118f6dd027e 100644 (file)
@@ -1,5 +1,5 @@
 /* Convert function calls to rtl insns, for GNU C compiler.
-   Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
+   Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -1177,9 +1177,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
       mode = TYPE_MODE (type);
       unsignedp = TREE_UNSIGNED (type);
 
-#ifdef PROMOTE_FUNCTION_ARGS
-      mode = promote_mode (type, mode, &unsignedp, 1);
-#endif
+      if (targetm.calls.promote_function_args (fndecl ? TREE_TYPE (fndecl) : 0))
+       mode = promote_mode (type, mode, &unsignedp, 1);
 
       args[i].unsignedp = unsignedp;
       args[i].mode = mode;
@@ -2060,6 +2059,7 @@ expand_call (tree exp, rtx target, int ignore)
   /* Nonzero if called function returns an aggregate in memory PCC style,
      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.  */
   int num_actuals;
@@ -2175,6 +2175,8 @@ expand_call (tree exp, rtx target, int ignore)
   else
     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.  */
   if (warn_aggregate_return && AGGREGATE_TYPE_P (TREE_TYPE (exp)))
@@ -2222,7 +2224,7 @@ expand_call (tree exp, rtx target, int ignore)
   /* Set up a place to return a structure.  */
 
   /* Cater to broken compilers.  */
-  if (aggregate_value_p (exp))
+  if (aggregate_value_p (exp, fndecl))
     {
       /* This call returns a big structure.  */
       flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
@@ -2316,7 +2318,7 @@ expand_call (tree exp, rtx target, int ignore)
 
   /* 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 && struct_value == 0)
     {
       /* If structure_value_addr is a REG other than
         virtual_outgoing_args_rtx, we can use always use it.  If it
@@ -2342,6 +2344,14 @@ expand_call (tree exp, rtx target, int ignore)
   for (p = actparms, num_actuals = 0; p; p = TREE_CHAIN (p))
     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.
      We do include the last named arg if STRICT_ARGUMENT_NAMING is nonzero.
@@ -2358,27 +2368,19 @@ expand_call (tree exp, rtx target, int ignore)
      reliable way to pass unnamed args in registers, so we must force
      them into memory.  */
 
-  if ((STRICT_ARGUMENT_NAMING
-       || ! PRETEND_OUTGOING_VARARGS_NAMED)
+  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.  */
-        - (STRICT_ARGUMENT_NAMING ? 0 : 1)
+        - (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);
   else
     /* If we know nothing, treat all args as named.  */
     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));
   memset (args, 0, num_actuals * sizeof (struct arg_data));
@@ -3016,13 +3018,13 @@ expand_call (tree exp, rtx target, int ignore)
            structure_value_addr = convert_memory_address
                                        (Pmode, structure_value_addr);
 #endif
-         emit_move_insn (struct_value_rtx,
+         emit_move_insn (struct_value,
                          force_reg (Pmode,
                                     force_operand (structure_value_addr,
                                                    NULL_RTX)));
 
-         if (GET_CODE (struct_value_rtx) == REG)
-           use_reg (&call_fusage, struct_value_rtx);
+         if (GET_CODE (struct_value) == REG)
+           use_reg (&call_fusage, struct_value);
        }
 
       funexp = prepare_call_address (funexp, fndecl, &call_fusage,
@@ -3246,7 +3248,8 @@ expand_call (tree exp, rtx target, int ignore)
       else
        target = copy_to_reg (valreg);
 
-#ifdef PROMOTE_FUNCTION_RETURN
+      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.  */
       if (GET_CODE (target) == REG
@@ -3277,7 +3280,7 @@ expand_call (tree exp, rtx target, int ignore)
          SUBREG_PROMOTED_VAR_P (target) = 1;
          SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
        }
-#endif
+       }
 
       /* If size of args is variable or this was a constructor call for a stack
         argument, restore saved stack-pointer value.  */
@@ -3586,6 +3589,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
   int initial_highest_arg_in_use = highest_outgoing_arg_in_use;
   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
   reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
@@ -3638,7 +3643,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
   if (outmode != VOIDmode)
     {
       tfom = (*lang_hooks.types.type_for_mode) (outmode, 0);
-      if (aggregate_value_p (tfom))
+      if (aggregate_value_p (tfom, 0))
        {
 #ifdef PCC_STATIC_STRUCT_RETURN
          rtx pointer_reg
@@ -3693,7 +3698,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 
   /* 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)
+  if (mem_value && struct_value == 0 && ! pcc_struct_value)
     {
       rtx addr = XEXP (mem_value, 0);
       nargs++;
@@ -4068,14 +4073,14 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
     }
 
   /* Pass the function the address in which to return a structure value.  */
-  if (mem_value != 0 && struct_value_rtx != 0 && ! pcc_struct_value)
+  if (mem_value != 0 && struct_value != 0 && ! pcc_struct_value)
     {
-      emit_move_insn (struct_value_rtx,
+      emit_move_insn (struct_value,
                      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);
+      if (GET_CODE (struct_value) == REG)
+       use_reg (&call_fusage, struct_value);
     }
 
   /* Don't allow popping to be deferred, since then
index cc7c7de156e2dad313220e871bbb808fd174334a..26cdf49dc78483ca1fc2498e2677f7b167f16883 100644 (file)
@@ -75,6 +75,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "coretypes.h"
 #include "tm.h"
 #include "rtl.h"
+#include "tree.h"
 #include "tm_p.h"
 #include "flags.h"
 #include "regs.h"
@@ -88,6 +89,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "recog.h"
 #include "real.h"
 #include "toplev.h"
+#include "target.h"
 
 /* It is not safe to use ordinary gen_lowpart in combine.
    Use gen_lowpart_for_combine instead.  See comments there.  */
@@ -799,30 +801,31 @@ init_reg_last_arrays (void)
 static void
 setup_incoming_promotions (void)
 {
-#ifdef PROMOTE_FUNCTION_ARGS
   unsigned int regno;
   rtx reg;
   enum machine_mode mode;
   int unsignedp;
   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)));
-      }
-#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)));
+         }
+    }
 }
 \f
 /* Called via note_stores.  If X is a pseudo that is narrower than
index 92fe830b2d18282df6646cca4fa28e2d1acc3fb6..72d01af2f153595d10c2a053274000f5cf4b1a09 100644 (file)
@@ -7799,7 +7799,7 @@ alpha_output_mi_thunk_osf (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
 
   /* 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))))
+  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
     this = gen_rtx_REG (Pmode, 17);
   else
     this = gen_rtx_REG (Pmode, 16);
index 747b93115dfc6a9f87afaf0f40e15a2a7e3e7280..5e92b28b79b566a8359bc08639a025edc9ca8ecf 100644 (file)
@@ -1968,7 +1968,7 @@ arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
                          tree fndecl ATTRIBUTE_UNUSED)
 {
   /* On the ARM, the offset starts at 0.  */
-  pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype))) ? 1 : 0);
+  pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype), fntype)) ? 1 : 0);
   pcum->iwmmxt_nregs = 0;
   
   pcum->call_cookie = CALL_NORMAL;
@@ -12962,7 +12962,7 @@ arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
   int mi_delta = delta;
   const char *const mi_op = mi_delta < 0 ? "sub" : "add";
   int shift = 0;
-  int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)))
+  int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)
                     ? 1 : 0);
   if (mi_delta < 0)
     mi_delta = - mi_delta;
index 4984fc4f9cf15339b019414e03b1c0cce6dce837..bccbae9bb3c490f6249fd0cfa072e71181b49765 100644 (file)
@@ -1748,7 +1748,7 @@ ix86_return_pops_args (tree fundecl, tree funtype, int size)
   }
 
   /* Lose any fake structure return argument if it is passed on the stack.  */
-  if (aggregate_value_p (TREE_TYPE (funtype))
+  if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
       && !TARGET_64BIT)
     {
       int nregs = ix86_function_regparm (funtype, fundecl);
@@ -15150,7 +15150,7 @@ x86_this_parameter (tree function)
 
   if (TARGET_64BIT)
     {
-      int n = aggregate_value_p (TREE_TYPE (type)) != 0;
+      int n = aggregate_value_p (TREE_TYPE (type), type) != 0;
       return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
     }
 
@@ -15174,7 +15174,7 @@ x86_this_parameter (tree function)
        }
     }
 
-  if (aggregate_value_p (TREE_TYPE (type)))
+  if (aggregate_value_p (TREE_TYPE (type), type))
     return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
   else
     return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
index cb44ee3efe79da09ed4371e0a75605b747d22a48..26443223ddc68e386e13e2ccab048bade023113c 100644 (file)
@@ -1086,7 +1086,7 @@ i960_function_name_declare (file, name, fndecl)
       
   /* See if caller passes in an address to return value.  */
 
-  if (aggregate_value_p (DECL_RESULT (fndecl)))
+  if (aggregate_value_p (DECL_RESULT (fndecl), fndecl))
     {
       tail_call_ok = 0;
       leaf_proc_ok = 0;
index 38690ee7319335e63b3a2a2117ef3cda5656ffd4..2787ce11649c6e46c453b6b32688671aecccc76a 100644 (file)
@@ -1490,7 +1490,7 @@ m68hc11_init_cumulative_args (cum, fntype, libname)
 
   ret_type = TREE_TYPE (fntype);
 
-  if (ret_type && aggregate_value_p (ret_type))
+  if (ret_type && aggregate_value_p (ret_type, fntype))
     {
       cum->words = 1;
       cum->nregs = 1;
index 74539249fab515bf3da3c52778922f1fd0fe7a11..7fa4ad80ebdcdd6083d5eb12be491bfb59999930 100644 (file)
@@ -5933,7 +5933,7 @@ mips_save_reg_p (unsigned int regno)
       if (regno == GP_REG_FIRST + 31
          && mips16_hard_float
          && !mips_entry
-         && !aggregate_value_p (return_type)
+         && !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)
        return true;
@@ -6712,7 +6712,7 @@ mips_expand_prologue (void)
     REGNO (pic_offset_table_rtx) = cfun->machine->global_pointer;
 
   /* If struct value address is treated as the first argument, make it so.  */
-  if (aggregate_value_p (DECL_RESULT (fndecl))
+  if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
       && ! current_function_returns_pcc_struct
       && struct_value_incoming_rtx == 0)
     {
@@ -7179,7 +7179,7 @@ mips_can_use_return_insn (void)
      registers.  */
   if (TARGET_MIPS16
       && mips16_hard_float
-      && ! aggregate_value_p (return_type)
+      && ! 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)
     return 0;
index 6807511c3c8173bfca219b4a1d617e9d2fb590ef..378170ca79d2a9e8a9b69d3444cbd098923bcda7 100644 (file)
@@ -12430,7 +12430,7 @@ rs6000_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
 
   /* 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))))
+  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
     this = gen_rtx_REG (Pmode, 4);
   else
     this = gen_rtx_REG (Pmode, 3);
index 4bdb40584acce2ce52961786e1ccfc8ae33c828c..7086d5b69325acc6b0be8c39f281520b47f52a51 100644 (file)
@@ -6629,7 +6629,7 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
     }
 
   /* Operand 1 is the 'this' pointer.  */
-  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
     op[1] = gen_rtx_REG (Pmode, 3);
   else
     op[1] = gen_rtx_REG (Pmode, 2);
index e046206dc393d045c2e95a8997e06634e1588d8d..b87aecd0181b489632102c95f414ff07bcb9a164 100644 (file)
@@ -25,7 +25,6 @@ Boston, MA 02111-1307, USA.  */
 #define GCC_SH_PROTOS_H
 
 #ifdef RTX_CODE
-extern struct rtx_def *sh_builtin_saveregs PARAMS ((void));
 extern struct rtx_def *prepare_scc_operands PARAMS ((enum rtx_code));
 
 /* Declare functions defined in sh.c and used in templates.  */
@@ -121,6 +120,8 @@ extern int fldi_ok PARAMS ((void));
 extern int sh_pr_n_sets PARAMS ((void));
 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
              PARAMS ((enum machine_mode, enum machine_mode, enum reg_class));
@@ -138,4 +139,8 @@ extern void sh_pr_nosave_low_regs PARAMS ((struct cpp_reader *));
 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 15d1d1a57dd5905270e1d946a2546c0cec1725c4..a266471b063a6ce4cee638876fd75e2bdc1aef93 100644 (file)
@@ -203,6 +203,7 @@ const struct attribute_spec sh_attribute_table[];
 static tree sh_handle_interrupt_handler_attribute PARAMS ((tree *, tree, tree, int, bool *));
 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_adjust_cost PARAMS ((rtx, rtx, rtx, int));
@@ -238,6 +239,15 @@ static int scavenge_reg (HARD_REG_SET *s);
 struct save_schedule_s;
 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 *));
+
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ATTRIBUTE_TABLE
@@ -315,6 +325,27 @@ static struct save_entry_s *sh5_schedule_saves (HARD_REG_SET *,
 #define TARGET_HAVE_TLS true
 #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;
 \f
 /* Print the operand address in x to the stream.  */
@@ -4898,7 +4929,11 @@ calc_live_regs (live_regs_mask)
                 && (reg == (int) EH_RETURN_DATA_REGNO (0)
                     || reg == (int) EH_RETURN_DATA_REGNO (1)
                     || reg == (int) EH_RETURN_DATA_REGNO (2)
-                    || reg == (int) EH_RETURN_DATA_REGNO (3)))))
+                    || 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);
          count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
@@ -5190,7 +5225,8 @@ sh_expand_prologue ()
   if (current_function_stdarg)
     {
       /* This is not used by the SH2E calling convention  */
-      if (TARGET_SH1 && ! TARGET_SH2E && ! TARGET_SH5 && ! TARGET_HITACHI)
+      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.  */
          for (i = 0; i < NPARM_REGS(SImode); i++)
@@ -5822,7 +5858,7 @@ sh_output_function_epilogue (file, size)
   sp_switch = NULL_RTX;
 }
 
-rtx
+static rtx
 sh_builtin_saveregs ()
 {
   /* First unnamed integer register.  */
@@ -5972,7 +6008,8 @@ sh_build_va_list ()
   tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
   tree record;
 
-  if (TARGET_SH5 || (! TARGET_SH2E && ! TARGET_SH4) || TARGET_HITACHI)
+  if (TARGET_SH5 || (! TARGET_SH2E && ! TARGET_SH4)
+      || TARGET_HITACHI || sh_cfun_attr_renesas_p ())
     return ptr_type_node;
 
   record = make_node (RECORD_TYPE);
@@ -6026,7 +6063,8 @@ sh_va_start (valist, nextarg)
       return;
     }
 
-  if ((! TARGET_SH2E && ! TARGET_SH4) || TARGET_HITACHI)
+  if ((! TARGET_SH2E && ! TARGET_SH4)
+      || TARGET_HITACHI || sh_cfun_attr_renesas_p ())
     {
       std_expand_builtin_va_start (valist, nextarg);
       return;
@@ -6105,7 +6143,8 @@ sh_va_arg (valist, type)
   if (pass_by_ref)
     type = build_pointer_type (type);
 
-  if (! TARGET_SH5 && (TARGET_SH2E || TARGET_SH4) && ! TARGET_HITACHI)
+  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;
       tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
@@ -6289,6 +6328,343 @@ sh_va_arg (valist, type)
   return result;
 }
 
+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 && mode == VOIDmode)
+    return GEN_INT (ca->renesas_abi ? 1 : 0);
+
+  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 the alignment of a DF value causes an SF register to be
+       skipped, we will use that skipped register for the next SF
+       value.  */
+      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;
+{
+ if (ca->force_mem)
+   ca->force_mem = 0;
+ else if (TARGET_SH5)
+   {
+     tree type2 = (ca->byref && type
+                  ? TREE_TYPE (type)
+                  : type);
+     enum machine_mode mode2 = (ca->byref && type
+                               ? TYPE_MODE (type2)
+                               : mode);
+     int dwords = ((ca->byref
+                   ? ca->byref
+                   : mode2 == BLKmode
+                   ? int_size_in_bytes (type2)
+                   : GET_MODE_SIZE (mode2)) + 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 (mode2, type2))
+          {
+            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 (mode2) == SH_ARG_FLOAT
+        && (named || ! ca->prototype_p))
+       {
+        if (mode2 == 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 (mode2) + 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 (mode2 == 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)
+   {
+     /* Note that we've used the skipped register.  */
+     if (mode == SFmode && ca->free_single_fp_reg)
+       {
+        ca->free_single_fp_reg = 0;
+        return;
+       }
+     /* When we have a DF after an SF, there's an SF register that get
+       skipped in order to align the DF value.  We note this skipped
+       register, because the next SF value will use it, and not the
+       SF that follows the DF.  */
+     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 ATTRIBUTE_UNUSED;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+     tree type ATTRIBUTE_UNUSED;
+     int *pretend_arg_size ATTRIBUTE_UNUSED;
+     int second_time ATTRIBUTE_UNUSED;
+{
+  if (! current_function_stdarg)
+    abort ();
+}
+
+static bool
+sh_strict_argument_naming (ca)
+     CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED;
+{
+  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.  */
 
@@ -6424,7 +6800,12 @@ sh_insert_attributes (node, attributes)
    to run on.
 
    trap_exit -- use a trapa to exit an interrupt function instead of
-   an rte instruction.  */
+   an rte instruction.
+
+   renesas -- use Renesas calling/layout conventions (functions and
+   structures).
+
+*/
 
 const struct attribute_spec sh_attribute_table[] =
 {
@@ -6432,6 +6813,7 @@ const struct attribute_spec sh_attribute_table[] =
   { "interrupt_handler", 0, 0, true,  false, false, sh_handle_interrupt_handler_attribute },
   { "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 }
 };
 
@@ -6537,6 +6919,40 @@ sh_handle_trap_exit_attribute (node, name, args, flags, no_add_attrs)
   return NULL_TREE;
 }
 
+static tree
+sh_handle_renesas_attribute (node, name, args, flags, no_add_attrs)
+     tree *node ATTRIBUTE_UNUSED;
+     tree name ATTRIBUTE_UNUSED;
+     tree args ATTRIBUTE_UNUSED;
+     int flags ATTRIBUTE_UNUSED;
+     bool *no_add_attrs ATTRIBUTE_UNUSED;
+{
+  return NULL_TREE;
+}
+
+/* True if __attribute__((renesas)) or -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)) or -mrenesas, for the current
+   function.  */
+int
+sh_cfun_attr_renesas_p ()
+{
+  return sh_attr_renesas_p (current_function_decl);
+}
+
 int
 sh_cfun_interrupt_handler_p ()
 {
@@ -8000,7 +8416,7 @@ static bool
 sh_ms_bitfield_layout_p (record_type)
      tree record_type ATTRIBUTE_UNUSED;
 {
-  return TARGET_SH5;
+  return (TARGET_SH5 || TARGET_HITACHI || sh_attr_renesas_p (record_type));
 }
 \f
 /* 
@@ -8683,10 +9099,10 @@ sh_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
      comes first, in which case "this" comes second.  */
   INIT_CUMULATIVE_ARGS (cum, funtype, NULL_RTX, 0);
 #ifndef PCC_STATIC_STRUCT_RETURN
-  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
     structure_value_byref = 1;
 #endif /* not PCC_STATIC_STRUCT_RETURN */
-  if (structure_value_byref && struct_value_rtx == 0)
+  if (structure_value_byref && sh_struct_value_rtx (function, 0) == 0)
     { 
       tree ptype = build_pointer_type (TREE_TYPE (funtype));
 
index 3ab2120e9a51a7da56f664716e70ed1e2bca429b..a3aa1dd29ae06aff67653e3b9873472f7d3d1ec7 100644 (file)
@@ -319,6 +319,7 @@ extern int target_flags;
   {"dalign",   DALIGN_BIT, "Aligns doubles at 64-bit boundaries" },            \
   {"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" },                     \
   {"isize",    ISIZE_BIT, "" },                \
@@ -1126,29 +1127,6 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 /* Register in which the static-chain is passed to a function.  */
 #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.  */
 
@@ -1797,6 +1775,10 @@ struct sh_args {
 #define CALL_COOKIE_INT_REG_GET(COOKIE, REG) \
   (((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;
 };
 
 #define CUMULATIVE_ARGS  struct sh_args
@@ -1839,17 +1821,18 @@ struct sh_args {
 
    For TARGET_HITACHI, the structure value pointer is passed in memory.  */
 
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
+#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 && FNTYPE                              \
-        && aggregate_value_p (TREE_TYPE (FNTYPE)));            \
+      = ((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)));            \
+        && aggregate_value_p (TREE_TYPE (FNTYPE), (FNDECL)));  \
     (CUM).free_single_fp_reg = 0;                              \
     (CUM).outgoing = 1;                                                \
     (CUM).stack_regs = 0;                                      \
@@ -1881,128 +1864,11 @@ struct sh_args {
     INIT_CUMULATIVE_ARGS ((CUM), (FNTYPE), (LIBNAME), 0);      \
     (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)))))
+       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.
    This macro is only used in this file.  */
@@ -2010,7 +1876,11 @@ struct sh_args {
 #define PASS_IN_REG_P(CUM, MODE, TYPE) \
   (((TYPE) == 0 \
     || (! TREE_ADDRESSABLE ((tree)(TYPE)) \
-       && (! TARGET_HITACHI || ! AGGREGATE_TYPE_P (TYPE)))) \
+       && (! (TARGET_HITACHI || (CUM).renesas_abi) \
+           || ! (AGGREGATE_TYPE_P (TYPE) \
+                 || (!TARGET_FPU_ANY \
+                     && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+                         && GET_MODE_SIZE (MODE) > GET_MODE_SIZE (SFmode))))))) \
    && ! (CUM).force_mem \
    && (TARGET_SH2E \
        ? ((MODE) == BLKmode \
@@ -2040,75 +1910,6 @@ struct sh_args {
    foo (float a, __complex float b); a: fr5 b.real: fr4 b.imag: fr7  */
 #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
    registers are passed by reference, so that an SHmedia trampoline
@@ -2203,10 +2004,6 @@ struct sh_args {
                                                          (REG)),       \
                                   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.
    For args passed entirely in registers or entirely in memory, zero.
@@ -2238,16 +2035,6 @@ struct sh_args {
 /* Perform any needed actions needed for a function that is receiving a
    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) \
   (VALIST) = sh_build_va_list ()
@@ -2336,9 +2123,6 @@ while (0)
 #define INCOMING_RETURN_ADDR_RTX \
   gen_rtx_REG (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG)
 \f
-/* Generate necessary RTL for __builtin_saveregs().  */
-#define EXPAND_BUILTIN_SAVEREGS() sh_builtin_saveregs ()
-\f
 /* Addressing modes, and classification of registers for them.  */
 #define HAVE_POST_INCREMENT  TARGET_SH1
 #define HAVE_PRE_DECREMENT   TARGET_SH1
@@ -2919,9 +2703,6 @@ while (0)
    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.  */
 #define Pmode  (TARGET_SHMEDIA64 ? DImode : SImode)
 #define FUNCTION_MODE  Pmode
index bd341a0b2df0b1a8bafdda45d932454e965fdd31..c5c55c76bf2a7978718956abfd15740812171eda 100644 (file)
       DONE;
     }
   else
+  {
     operands[0] = force_reg (SImode, XEXP (operands[0], 0));
+    operands[1] = operands[2];
+  }
 
   emit_call_insn (gen_calli (operands[0], operands[1]));
   DONE;
index b095a007bb889cb683da350a54f248fc1cffd329..84d27d26a34d97db62d514ad8fb8c6e379382a08 100644 (file)
@@ -8301,7 +8301,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
 
   /* 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))))
+  if (TARGET_ARCH64 && aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
     this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST + 1);
   else
     this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST);
index 8ce526f90d22defbaecac1a333071472afbd5d1b..d493b7ce79767168e73dc878b74cf476ecae6c98 100644 (file)
@@ -1562,7 +1562,7 @@ xstormy16_asm_output_mi_thunk (file, thunk_fndecl, delta,
   int regnum = FIRST_ARGUMENT_REGISTER;
   
   /* There might be a hidden first argument for a returned structure.  */
-  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
     regnum += 1;
   
   fprintf (file, "\tadd %s,#0x%x\n", reg_names[regnum], (int) delta & 0xFFFF);
index b64cf992998e73a3fdd2d8751f3a09c780cbc99f..dafa9c545a2cdd00fcab4e2c55f75609d4ce6493 100644 (file)
@@ -1,3 +1,7 @@
+2003-09-03  DJ Delorie  <dj@redhat.com>
+
+       * decl.c (finish_function): Pass fndecl to aggregate_value_p.
+
 2003-09-03  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/12053
index 4c287ea7158be7e5405be9ba17df18344d89d97c..1575ec4dbf110625e37abe5a7e08b2c6604e351b 100644 (file)
@@ -14118,7 +14118,7 @@ finish_function (int flags)
       if (r != error_mark_node
          /* This is only worth doing for fns that return in memory--and
             simpler, since we don't have to worry about promoted modes.  */
-         && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)))
+         && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)), fndecl)
          /* Only allow this for variables declared in the outer scope of
             the function so we know that their lifetime always ends with a
             return; see g++.dg/opt/nrv6.C.  We could be more flexible if
index c501aacdbe7c4ea4a1bb7a564afffffcb97be458..ef49a688033453a2127fb1db01db11feae4fdc2c 100644 (file)
@@ -1058,24 +1058,25 @@ sign-extend the result to 64 bits.  On such machines, set
 Do not define this macro if it would never modify @var{m}.
 @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
+@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
 
-@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.
+@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 macro is defined, @code{FUNCTION_VALUE} must perform the same
-promotions done by @code{PROMOTE_MODE}.
-@end defmac
+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{PROMOTE_FUNCTION_ARGS}
-and @code{PROMOTE_FUNCTION_RETURN}, respectively.
+function return values, as specified by @code{TARGET_PROMOTE_FUNCTION_ARGS}
+and @code{TARGET_PROMOTE_FUNCTION_RETURN}, respectively.
 @end defmac
 
 @defmac PARM_BOUNDARY
@@ -3353,14 +3354,13 @@ The macros in this section control how arguments are passed
 on the stack.  See the following section for other macros that
 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
+@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
 A C expression.  If nonzero, push insns will be used to pass
@@ -3819,7 +3819,7 @@ register where the return value is stored.  The value can also be a
 @code{parallel} RTX, if the return value is in multiple places.  See
 @code{FUNCTION_ARG} for an explanation of the @code{parallel} form.
 
-If @code{PROMOTE_FUNCTION_RETURN} is defined, you must apply the same
+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.
 
@@ -3910,24 +3910,24 @@ is called the @dfn{structure value address}.
 This section describes how to control returning structure values in
 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.
+@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 macro.  Also, the option @option{-fpcc-struct-return}
+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 macro undefined; this causes a default
+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 macro to indicate that structures and unions should always
+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 defmac
+@end deftypefn
 
 @defmac DEFAULT_PCC_STRUCT_RETURN
 Define this macro to be 1 if all structure and union return values must be
@@ -3939,36 +3939,23 @@ and union return values are decided by the @code{RETURN_IN_MEMORY} macro.
 If not defined, this defaults to the value 1.
 @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
+@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.
 
-@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.
+@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 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
+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
 Define this macro if the usual system convention on the target machine
@@ -4428,70 +4415,71 @@ interpret the values of @code{__builtin_classify_type}.
 
 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
+@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
 
-@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.
+@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} is the @code{CUMULATIVE_ARGS} data
+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 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.
+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{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.
+@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 macro @code{SETUP_INCOMING_VARARGS} should
+end of the source file.  The hook @code{TARGET_SETUP_INCOMING_VARARGS} should
 not generate any instructions in this case.
-@end defmac
+@end deftypefn
 
-@defmac STRICT_ARGUMENT_NAMING
-Define this macro to be a nonzero value if the location where a function
+@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 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.
+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 macro if it always returns zero.
-@end defmac
+You need not define this hook if it always returns zero.
+@end deftypefn
 
-@defmac PRETEND_OUTGOING_VARARGS_NAMED
+@deftypefn {Target Hook} bool TARGET_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
+@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
 @section Trampolines for Nested Functions
index 4140abc15d0c2832cb44746e7f4631e67a07f375..0668cfb20e4e39663fd4028d7a66b63f2cb76227 100644 (file)
@@ -132,8 +132,6 @@ REAL_VALUE_TYPE dconsthalf;
 
    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) */
 rtx pic_offset_table_rtx;      /* (REG:Pmode PIC_OFFSET_TABLE_REGNUM) */
@@ -5467,23 +5465,6 @@ init_emit_once (int line_numbers)
     = 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
-
 #ifdef STATIC_CHAIN_REGNUM
   static_chain_rtx = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
 
index 489aba4b496b47a65b2f5712d156791d4efe871d..eb25fed8a4a5ed8b2412b547ca239f11fa91123b 100644 (file)
@@ -4273,7 +4273,7 @@ expand_assignment (tree to, tree from, int want_value)
      since it might be a promoted variable where the zero- or sign- extension
      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)
+  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)
            && GET_CODE (DECL_RTL (to)) == REG))
@@ -6704,7 +6704,7 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier
   if (! cse_not_expected && mode != BLKmode && target
       && (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)))
+      && ! (code == CALL_EXPR && aggregate_value_p (exp, exp)))
     target = 0;
 
   switch (code)
index 9abea77872b90ceed289632a20c1b63efe7f445f..aa9936e1555fc80e5a29fb9d59b05e73c33d757c 100644 (file)
@@ -169,35 +169,12 @@ do {                                                      \
 tree split_complex_types (tree);
 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
-
 /* Supply a default definition of STACK_SAVEAREA_MODE for emit_stack_save.
    Normally move_insn, so Pmode stack pointer.  */
 
index f43f9d92b6e186c6ec57f8773fd33c09f518bd71..6ee13a604f8e67f3037343fc5c4be267f2ceb814 100644 (file)
@@ -1418,9 +1418,8 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
 # define NO_PROFILE_COUNTERS   0
 #endif
 #if defined(ASM_OUTPUT_REG_PUSH)
-#if defined(STRUCT_VALUE_INCOMING_REGNUM) || defined(STRUCT_VALUE_REGNUM)
   int sval = current_function_returns_struct;
-#endif
+  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;
 #endif
@@ -1437,16 +1436,9 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
 
   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
+#if defined(ASM_OUTPUT_REG_PUSH)
+  if (sval && GET_CODE (svrtx) == REG)
+    ASM_OUTPUT_REG_PUSH (file, REGNO (svrtx));
 #endif
 
 #if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
@@ -1475,16 +1467,9 @@ profile_function (FILE *file ATTRIBUTE_UNUSED)
 #endif
 #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
+#if defined(ASM_OUTPUT_REG_PUSH)
+  if (sval && GET_CODE (svrtx) == REG)
+    ASM_OUTPUT_REG_POP (file, REGNO (svrtx));
 #endif
 }
 
index 6decfdf232ddb6e9545623ed64b9ec6262e39a38..8227139d256a480cbc2b778f8a5411051ddd0c87 100644 (file)
@@ -62,6 +62,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tm_p.h"
 #include "integrate.h"
 #include "langhooks.h"
+#include "target.h"
 
 #ifndef TRAMPOLINE_ALIGNMENT
 #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
@@ -4177,16 +4178,37 @@ get_first_nonparm_insn (void)
    EXP may be a type node or an expression (whose type is tested).  */
 
 int
-aggregate_value_p (tree exp)
+aggregate_value_p (tree exp, tree fntype)
 {
   int i, regno, nregs;
   rtx reg;
 
   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:
+      case METHOD_TYPE:
+        break;
+      case IDENTIFIER_NODE:
+       fntype = 0;
+       break;
+      default:
+       /* We don't expect other rtl types here.  */
+       abort();
+      }
+
   if (TREE_CODE (type) == VOID_TYPE)
     return 0;
-  if (RETURN_IN_MEMORY (type))
+  if (targetm.calls.return_in_memory (type, fntype))
     return 1;
   /* Types that are TREE_ADDRESSABLE must be constructed in memory,
      and thus can't be returned in registers.  */
@@ -4230,9 +4252,7 @@ assign_parms (tree fndecl)
   /* This is a dummy PARM_DECL that we used for the function result if
      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;
 
@@ -4265,9 +4285,9 @@ assign_parms (tree fndecl)
   stack_args_size.var = 0;
 
   /* If struct value address is treated as the first argument, make it so.  */
-  if (aggregate_value_p (DECL_RESULT (fndecl))
+  if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
       && ! current_function_returns_pcc_struct
-      && struct_value_incoming_rtx == 0)
+      && targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
     {
       tree type = build_pointer_type (TREE_TYPE (fntype));
 
@@ -4336,7 +4356,7 @@ assign_parms (tree fndecl)
       /* Set NAMED_ARG if this arg should be treated as a named arg.  For
         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;
+      named_arg = targetm.calls.strict_argument_naming (&args_so_far) ? 1 : ! last_named;
 
       if (TREE_TYPE (parm) == error_mark_node
          /* This can happen after weird syntax errors
@@ -4401,11 +4421,12 @@ assign_parms (tree fndecl)
 
       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
+      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.
         0 means it arrives on the stack.  */
@@ -4420,7 +4441,6 @@ assign_parms (tree fndecl)
       if (entry_parm == 0)
        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
         addressable type, in which case we skip the registers it
@@ -4433,11 +4453,11 @@ assign_parms (tree fndecl)
         Also, indicate when RTL generation is to be suppressed.  */
       if (last_named && !varargs_setup)
        {
-         SETUP_INCOMING_VARARGS (args_so_far, promoted_mode, passed_type,
-                                 current_function_pretend_args_size, 0);
+         targetm.calls.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,
         in case it arrives in the stack or we should pretend it did.
@@ -4457,7 +4477,8 @@ assign_parms (tree fndecl)
 #endif
       if (!in_regs && !named_arg)
        {
-         int pretend_named = PRETEND_OUTGOING_VARARGS_NAMED;
+         int pretend_named =
+           targetm.calls.pretend_outgoing_varargs_named (&args_so_far);
          if (pretend_named)
            {
 #ifdef FUNCTION_INCOMING_ARG
@@ -5275,8 +5296,6 @@ split_complex_args (tree args)
    that REGNO is promoted from and whether the promotion was signed or
    unsigned.  */
 
-#ifdef PROMOTE_FUNCTION_ARGS
-
 rtx
 promoted_input_arg (unsigned int regno, enum machine_mode *pmode, int *punsignedp)
 {
@@ -5304,7 +5323,6 @@ promoted_input_arg (unsigned int regno, enum machine_mode *pmode, int *punsigned
   return 0;
 }
 
-#endif
 \f
 /* Compute the size and offset from the start of the stacked arguments for a
    parm passed in mode PASSED_MODE and with type TYPE.
@@ -6284,7 +6302,7 @@ allocate_struct_function (tree fndecl)
   current_function_name = (*lang_hooks.decl_printable_name) (fndecl, 2);
 
   result = DECL_RESULT (fndecl);
-  if (aggregate_value_p (result))
+  if (aggregate_value_p (result, fndecl))
     {
 #ifdef PCC_STATIC_STRUCT_RETURN
       current_function_returns_pcc_struct = 1;
@@ -6515,7 +6533,7 @@ expand_function_start (tree subr, int parms_have_cleanups)
      before any library calls that assign parms might generate.  */
 
   /* Decide whether to return the value in memory or in a register.  */
-  if (aggregate_value_p (DECL_RESULT (subr)))
+  if (aggregate_value_p (DECL_RESULT (subr), subr))
     {
       /* Returning something that won't go in a register.  */
       rtx value_address = 0;
@@ -6529,13 +6547,14 @@ expand_function_start (tree subr, int parms_have_cleanups)
       else
 #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 (struct_value_incoming_rtx)
+         if (sv)
            {
              value_address = gen_reg_rtx (Pmode);
-             emit_move_insn (value_address, struct_value_incoming_rtx);
+             emit_move_insn (value_address, sv);
            }
        }
       if (value_address)
@@ -6973,10 +6992,9 @@ expand_function_end (void)
            {
              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
+             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 53330cf28b7675f3bc85954852e8e85f6ee357a2..a770180e3868c7320c6c850ee1920083af8ba1fb 100644 (file)
@@ -1,5 +1,5 @@
 /* Sets (bit vectors) of hard registers, and operations on them.
-   Copyright (C) 1987, 1992, 1994, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1992, 1994, 2000, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC
 
@@ -418,7 +418,7 @@ extern HARD_REG_SET losing_caller_save_reg_set;
 
 /* 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
+   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 15474ba3f248eae0cf2438ffe14cd750610c216d..f0abe89f3e24c35ec6e196ac7982da6ad80e94f2 100644 (file)
@@ -1028,7 +1028,7 @@ expand_inline_function (tree fndecl, tree parms, rtx target, int ignore,
       else
        {
          if (! structure_value_addr
-             || ! aggregate_value_p (DECL_RESULT (fndecl)))
+             || ! aggregate_value_p (DECL_RESULT (fndecl), fndecl))
            abort ();
 
          /* Pass the function the address in which to return a structure
@@ -1283,7 +1283,7 @@ expand_inline_function (tree fndecl, tree parms, rtx target, int ignore,
      out of the temp register into a BLKmode memory object.  */
   if (target
       && TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == BLKmode
-      && ! aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
+      && ! aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)), fndecl))
     target = copy_blkmode_from_reg (0, target, TREE_TYPE (TREE_TYPE (fndecl)));
 
   if (structure_value_addr)
index 8350cb9e9867cc5bfc1601aec799e13b179fba40..10cc88912fca972e10e7ca2c8b7eb8e2993d1438 100644 (file)
@@ -406,7 +406,7 @@ generate_struct_by_value_array ()
        }
       finish_struct (type, field_decl_chain, NULL_TREE);
  
-      aggregate_in_mem[i] = aggregate_value_p (type);
+      aggregate_in_mem[i] = aggregate_value_p (type, 0);
       if (!aggregate_in_mem[i])
        found = 1;
     }
index 016c5c7c2c66087bb50a3930d35591d9218b4318..fd707e21e8305c48330542ea8f8c86e2221334fd 100644 (file)
@@ -802,7 +802,7 @@ stack_result (tree decl)
 
   /* 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)))
+  if (aggregate_value_p (DECL_RESULT (decl), decl))
     return 0;
 
   result = DECL_RTL_IF_SET (DECL_RESULT (decl));
index 82dddc74fa004739256f0a19d89c0eda29e5117b..b7db32adeede874492eaeda0e0734918674b08b7 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1816,8 +1816,6 @@ extern GTY(()) rtx global_rtl[GR_MAX];
 #define arg_pointer_rtx                (global_rtl[GR_ARG_POINTER])
 
 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;
 extern GTY(()) rtx return_address_pointer_rtx;
index 9a8c0bc6cb95a86b88ce3be599c4172af958d960..b62f83eccb36b2de1848de5b94c0d55807ac2528 100644 (file)
@@ -57,6 +57,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "langhooks.h"
 #include "predict.h"
 #include "optabs.h"
+#include "target.h"
 
 /* Assume that case vectors are not pc-relative.  */
 #ifndef CASE_VECTOR_PC_RELATIVE
@@ -2937,16 +2938,17 @@ expand_value_return (rtx val)
   if (return_reg != val)
     {
       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 (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));
       else
index afd830d20e8b199dd9d2bd8647e37c15224d3d2b..d1a856983a54fc4f878137162cea7e2363c0154e 100644 (file)
@@ -1093,6 +1093,7 @@ place_field (record_layout_info rli, tree field)
                rli->prev_field = NULL;
            }
 
+         rli->offset_align = tree_low_cst (TYPE_SIZE (type), 0);
          normalize_rli (rli);
         }
 
index e3c4df1d670670274e853e01ac25d2e7e0039c65..da6003eff5c717f7d0024635faf5b757cbca39b0 100644 (file)
@@ -305,6 +305,30 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #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                     \
 {                                              \
@@ -345,6 +369,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   TARGET_TERMINATE_DW2_EH_FRAME_INFO,          \
   TARGET_ASM_FILE_START_APP_OFF,               \
   TARGET_ASM_FILE_START_FILE_DIRECTIVE,                \
+  TARGET_CALLS,                                        \
 }
 
 #include "hooks.h"
+#include "targhooks.h"
index 8acfb7ab26f7ec2a27300fff545fe67977d29246..3a7ea78af38cd25729125c6cec48d7887b1c762b 100644 (file)
@@ -386,6 +386,23 @@ struct gcc_target
   /* True if output_file_directive should be called for main_input_filename
      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;
 };
 
 extern struct gcc_target targetm;
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
new file mode 100644 (file)
index 0000000..943c5bd
--- /dev/null
@@ -0,0 +1,158 @@
+/* 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 ATTRIBUTE_UNUSED, 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
+}
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
new file mode 100644 (file)
index 0000000..335134b
--- /dev/null
@@ -0,0 +1,31 @@
+/* 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 *);
index ec60935542be990f00f10600ca5928e12ca6a5e9..d742bc3d95b3dca2af81e999b62540d306629642 100644 (file)
@@ -2871,7 +2871,7 @@ extern void pop_temp_slots (void);
 extern void push_temp_slots (void);
 extern void preserve_temp_slots (rtx);
 extern void preserve_rtl_expr_temps (tree);
-extern int aggregate_value_p (tree);
+extern int aggregate_value_p (tree, tree);
 extern void free_temps_for_rtl_expr (tree);
 extern void instantiate_virtual_regs (tree, rtx);
 extern void unshare_all_rtl (tree, rtx);