diff options
author | dj <dj@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-09-04 03:18:05 +0000 |
---|---|---|
committer | dj <dj@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-09-04 03:18:05 +0000 |
commit | 455507905e358525176b45e9c2c49e0d35e79927 (patch) | |
tree | 99ad51d803293a4cc8d3ad48596aa725cf1cc596 /gcc/config | |
parent | 9d344979cab6242e4366ca8d9c5d924daa9112f5 (diff) |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@71048 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/alpha/alpha.c | 2 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 4 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 6 | ||||
-rw-r--r-- | gcc/config/i960/i960.c | 2 | ||||
-rw-r--r-- | gcc/config/m68hc11/m68hc11.c | 2 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 6 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 2 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 2 | ||||
-rw-r--r-- | gcc/config/sh/sh-protos.h | 7 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 436 | ||||
-rw-r--r-- | gcc/config/sh/sh.h | 255 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 3 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.c | 2 | ||||
-rw-r--r-- | gcc/config/stormy16/stormy16.c | 2 |
14 files changed, 468 insertions, 263 deletions
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 92fe830b2d1..72d01af2f15 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -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); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 747b93115df..5e92b28b79b 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -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; diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 4984fc4f9cf..bccbae9bb3c 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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)); diff --git a/gcc/config/i960/i960.c b/gcc/config/i960/i960.c index cb44ee3efe7..26443223ddc 100644 --- a/gcc/config/i960/i960.c +++ b/gcc/config/i960/i960.c @@ -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; diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c index 38690ee7319..2787ce11649 100644 --- a/gcc/config/m68hc11/m68hc11.c +++ b/gcc/config/m68hc11/m68hc11.c @@ -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; diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 74539249fab..7fa4ad80ebd 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -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; diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 6807511c3c8..378170ca79d 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 4bdb40584ac..7086d5b6932 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -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); diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index e046206dc39..b87aecd0181 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -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 */ diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 15d1d1a57dd..a266471b063 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -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 *)); + /* 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; /* 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)); } /* @@ -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)); diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 3ab2120e9a5..a3aa1dd29ae 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -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) -/* Generate necessary RTL for __builtin_saveregs(). */ -#define EXPAND_BUILTIN_SAVEREGS() sh_builtin_saveregs () - /* Addressing modes, and classification of registers for them. */ #define HAVE_POST_INCREMENT TARGET_SH1 #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 diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index bd341a0b2df..c5c55c76bf2 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -5869,7 +5869,10 @@ 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; diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index b095a007bb8..84d27d26a34 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -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); diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c index 8ce526f90d2..d493b7ce797 100644 --- a/gcc/config/stormy16/stormy16.c +++ b/gcc/config/stormy16/stormy16.c @@ -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); |