targhooks.c: New file.

* 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
This commit is contained in:
DJ Delorie 2003-09-03 23:18:05 -04:00 committed by DJ Delorie
parent b885908b11
commit 61f71b3447
43 changed files with 1111 additions and 554 deletions

View 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.

View 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)

View 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

View 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),

View 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 ();

View 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. */

View 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);

View 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

View 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)));
}
}
}
/* Called via note_stores. If X is a pseudo that is narrower than

View 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);

View 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;

View 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));

View 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;

View 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;

View 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;

View 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);

View 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);

View 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 */

View 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 *));
/* 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));

View 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)
/* 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

View File

@ -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;

View 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);

View 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);

View 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

View 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

View 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
@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
If the structure value address is not passed in a register, define
@code{STRUCT_VALUE} as an expression returning an RTX for the place
where the address is passed. If it returns 0, the address is passed as
an ``invisible'' first argument.
@end defmac
@defmac STRUCT_VALUE_INCOMING_REGNUM
On some architectures the place where the structure value address
is found by the called function is not the same place that the
caller put it. This can be due to register windows, or it could
be because the function prologue moves it to a different place.
@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

View 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);

View 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)

View 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. */

View 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
}

View 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
/* 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);
}

View 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. */

View 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)

View 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;
}

View 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));

View File

@ -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;

View 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 (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);
#endif
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

View 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);
}

View 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"

View 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;

158
gcc/targhooks.c Normal file
View File

@ -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
}

31
gcc/targhooks.h Normal file
View File

@ -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 *);

View 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);