[PATCH] hookize FUNCTION_{INCOMING_,}ARG and FUNCTION_ARG_ADVANCE
Nathan Froyd
froydnj@codesourcery.com
Mon May 31 07:13:00 GMT 2010
The patch below hookizes FUNCTION_{INCOMING_,}ARG and
FUNCTION_ARG_ADVANCE. The patch does introduce a small amount of
inefficiency in the default hook for TARGET_FUNCTION_ARG_ADVANCE; I have
patches for all primary and secondary targets (and several of the
tertiary ones...) that will remove that inefficiency by the time 4.6 is
released.
Tested on i686-pc-linux-gnu. OK to commit? (And are the similar
modifications for other back-ends pre-approved, subject to appropriate
testing and perhaps a waiting period for commits?)
-Nathan
* calls.c, dse.c, expr.c, function.c: Call targetm.calls.function_arg,
targetm.calls.function_incoming_arg, and
targetm.calls.function_arg_advance instead of FUNCTION_ARG,
FUNCTION_INCOMING_ARG, and FUNCTION_ARG_ADVANCE, respectively.
* target.h (struct gcc_target): Add function_arg_advance,
function_arg, and function_incoming_arg fields.
* target-def.h (TARGET_FUNCTION_ARG_ADVANCE, TARGET_FUNCTION_ARG):
(TARGET_FUNCTION_INCOMING_ARG): Define.
(TARGET_CALLS): Add TARGET_FUNCTION_ARG_ADVANCE, TARGET_FUNCTION_ARG,
and TARGET_FUNCTION_INCOMING_ARG.
* targhooks.h (default_function_arg_advance): Declare.
(default_function_arg, default_function_incoming_arg): Declare.
* targhooks.c (default_function_arg_advance): New function.
(default_function_arg, default_function_incoming_arg): New function.
* config/i386/i386.c (function_arg_advance): Rename to...
(ix86_function_arg_advance): ...this. Make static.
(function_arg): Rename to...
(ix86_function_arg): ...this. Make static.
(TARGET_FUNCTION_ARG_ADVANCE): Define.
(TARGET_FUNCTION_ARG): Define.
* config/i386/i386.h (FUNCTION_ARG_ADVANCE): Delete.
(FUNCTION_ARG): Delete.
* config/i386/i386-protos.h (function_arg_advance): Delete prototype.
(function_arg): Delete prototype.
diff --git a/gcc/calls.c b/gcc/calls.c
index 9c51f1a..13df566 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -226,7 +226,7 @@ prepare_call_address (tree fndecl, rtx funexp, rtx static_chain_value,
It is zero if this call doesn't want a structure value.
NEXT_ARG_REG is the rtx that results from executing
- FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1)
+ targetm.calls.function_arg (&args_so_far, VOIDmode, void_type_node, true)
just after all the args have had their registers assigned.
This could be whatever you like, but normally it is the first
arg-register beyond those used for args in this call,
@@ -1124,17 +1124,18 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
args[i].unsignedp = unsignedp;
args[i].mode = mode;
- args[i].reg = FUNCTION_ARG (*args_so_far, mode, type,
- argpos < n_named_args);
-#ifdef FUNCTION_INCOMING_ARG
+ args[i].reg = targetm.calls.function_arg (args_so_far, mode, type,
+ argpos < n_named_args);
+
/* If this is a sibling call and the machine has register windows, the
register window has to be unwinded before calling the routine, so
arguments have to go into the incoming registers. */
- args[i].tail_call_reg = FUNCTION_INCOMING_ARG (*args_so_far, mode, type,
- argpos < n_named_args);
-#else
- args[i].tail_call_reg = args[i].reg;
-#endif
+ if (targetm.calls.function_incoming_arg != targetm.calls.function_arg)
+ args[i].tail_call_reg
+ = targetm.calls.function_incoming_arg (args_so_far, mode, type,
+ argpos < n_named_args);
+ else
+ args[i].tail_call_reg = args[i].reg;
if (args[i].reg)
args[i].partial
@@ -1189,8 +1190,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
/* Increment ARGS_SO_FAR, which has info about which arg-registers
have been used, etc. */
- FUNCTION_ARG_ADVANCE (*args_so_far, TYPE_MODE (type), type,
- argpos < n_named_args);
+ targetm.calls.function_arg_advance (args_so_far, TYPE_MODE (type),
+ type, argpos < n_named_args);
}
}
@@ -2825,14 +2826,15 @@ expand_call (tree exp, rtx target, int ignore)
/* Set up next argument register. For sibling calls on machines
with register windows this should be the incoming register. */
-#ifdef FUNCTION_INCOMING_ARG
if (pass == 0)
- next_arg_reg = FUNCTION_INCOMING_ARG (args_so_far, VOIDmode,
- void_type_node, 1);
+ next_arg_reg = targetm.calls.function_incoming_arg (&args_so_far,
+ VOIDmode,
+ void_type_node,
+ true);
else
-#endif
- next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode,
- void_type_node, 1);
+ next_arg_reg = targetm.calls.function_arg (&args_so_far,
+ VOIDmode, void_type_node,
+ true);
/* All arguments and registers used for the call must be set up by
now! */
@@ -3419,7 +3421,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
argvec[count].mode = Pmode;
argvec[count].partial = 0;
- argvec[count].reg = FUNCTION_ARG (args_so_far, Pmode, NULL_TREE, 1);
+ argvec[count].reg = targetm.calls.function_arg (&args_so_far,
+ Pmode, NULL_TREE, true);
gcc_assert (targetm.calls.arg_partial_bytes (&args_so_far, Pmode,
NULL_TREE, 1) == 0);
@@ -3435,7 +3438,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
|| reg_parm_stack_space > 0)
args_size.constant += argvec[count].locate.size.constant;
- FUNCTION_ARG_ADVANCE (args_so_far, Pmode, (tree) 0, 1);
+ targetm.calls.function_arg_advance (&args_so_far, Pmode, (tree) 0, true);
count++;
}
@@ -3494,7 +3497,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
argvec[count].value = val;
argvec[count].mode = mode;
- argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
+ argvec[count].reg = targetm.calls.function_arg (&args_so_far, mode,
+ NULL_TREE, true);
argvec[count].partial
= targetm.calls.arg_partial_bytes (&args_so_far, mode, NULL_TREE, 1);
@@ -3514,7 +3518,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
|| reg_parm_stack_space > 0)
args_size.constant += argvec[count].locate.size.constant;
- FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1);
+ targetm.calls.function_arg_advance (&args_so_far, mode, (tree) 0, true);
}
/* If this machine requires an external definition for library
@@ -3823,7 +3827,8 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
build_function_type (tfom, NULL_TREE),
original_args_size.constant, args_size.constant,
struct_value_size,
- FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
+ targetm.calls.function_arg (&args_so_far,
+ VOIDmode, void_type_node, true),
valreg,
old_inhibit_defer_pop + 1, call_fusage, flags, & args_so_far);
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index eaff7ab..77cd7f4 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -184,9 +184,6 @@ extern void ix86_expand_truncdf_32 (rtx, rtx);
#ifdef TREE_CODE
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
-extern rtx function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
-extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
- tree, int);
#endif /* TREE_CODE */
#endif /* RTX_CODE */
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index de291c7..9a938e4 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -6029,9 +6029,13 @@ function_arg_advance_ms_64 (CUMULATIVE_ARGS *cum, HOST_WIDE_INT bytes,
}
}
-void
-function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, int named)
+/* 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.) */
+
+static void
+ix86_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ const_tree type, int named)
{
HOST_WIDE_INT bytes, words;
@@ -6266,9 +6270,19 @@ function_arg_ms_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
return gen_reg_or_parallel (mode, orig_mode, regno);
}
-rtx
-function_arg (CUMULATIVE_ARGS *cum, enum machine_mode omode,
- tree type, int named)
+/* Return where to put the arguments to a function.
+ Return 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. It is null for libcalls where that information may not be
+ available. CUM gives information 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). */
+
+static rtx
+ix86_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode omode,
+ const_tree type, int named)
{
enum machine_mode mode = omode;
HOST_WIDE_INT bytes, words;
@@ -30767,6 +30781,10 @@ ix86_enum_va_list (int idx, const char **pname, tree *ptree)
#define TARGET_SETUP_INCOMING_VARARGS ix86_setup_incoming_varargs
#undef TARGET_MUST_PASS_IN_STACK
#define TARGET_MUST_PASS_IN_STACK ix86_must_pass_in_stack
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE ix86_function_arg_advance
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG ix86_function_arg
#undef TARGET_PASS_BY_REFERENCE
#define TARGET_PASS_BY_REFERENCE ix86_pass_by_reference
#undef TARGET_INTERNAL_ARG_POINTER
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 005664c..ff449cb 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1611,29 +1611,6 @@ typedef struct ix86_args {
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME), (FNDECL))
-/* 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) \
- function_arg_advance (&(CUM), (MODE), (TYPE), (NAMED))
-
-/* 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). */
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- function_arg (&(CUM), (MODE), (TYPE), (NAMED))
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
diff --git a/gcc/dse.c b/gcc/dse.c
index 2be8a94..140c3f8 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -2326,7 +2326,8 @@ get_call_args (rtx call_insn, tree fn, rtx *args, int nargs)
arg = TREE_CHAIN (arg), idx++)
{
enum machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
- rtx reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1), link, tmp;
+ rtx reg, link, tmp;
+ reg = targetm.calls.function_arg (&args_so_far, mode, NULL_TREE, true);
if (!reg || !REG_P (reg) || GET_MODE (reg) != mode
|| GET_MODE_CLASS (mode) != MODE_INT)
return false;
@@ -2360,7 +2361,7 @@ get_call_args (rtx call_insn, tree fn, rtx *args, int nargs)
if (tmp)
args[idx] = tmp;
- FUNCTION_ARG_ADVANCE (args_so_far, mode, NULL_TREE, 1);
+ targetm.calls.function_arg_advance (&args_so_far, mode, NULL_TREE, true);
}
if (arg != void_list_node || idx != nargs)
return false;
diff --git a/gcc/expr.c b/gcc/expr.c
index 82c0371..182b30c 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -1276,12 +1276,14 @@ block_move_libcall_safe_for_call_parm (void)
for ( ; arg != void_list_node ; arg = TREE_CHAIN (arg))
{
enum machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
- rtx tmp = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
+ rtx tmp = targetm.calls.function_arg (&args_so_far, mode,
+ NULL_TREE, true);
if (!tmp || !REG_P (tmp))
return false;
if (targetm.calls.arg_partial_bytes (&args_so_far, mode, NULL, 1))
return false;
- FUNCTION_ARG_ADVANCE (args_so_far, mode, NULL_TREE, 1);
+ targetm.calls.function_arg_advance (&args_so_far, mode,
+ NULL_TREE, true);
}
}
return true;
diff --git a/gcc/function.c b/gcc/function.c
index 7715529..fcf1b97 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2374,13 +2374,10 @@ assign_parm_find_entry_rtl (struct assign_parm_data_all *all,
return;
}
-#ifdef FUNCTION_INCOMING_ARG
- entry_parm = FUNCTION_INCOMING_ARG (all->args_so_far, data->promoted_mode,
- data->passed_type, data->named_arg);
-#else
- entry_parm = FUNCTION_ARG (all->args_so_far, data->promoted_mode,
- data->passed_type, data->named_arg);
-#endif
+ entry_parm = targetm.calls.function_incoming_arg (&all->args_so_far,
+ data->promoted_mode,
+ data->passed_type,
+ data->named_arg);
if (entry_parm == 0)
data->promoted_mode = data->passed_mode;
@@ -2404,13 +2401,9 @@ assign_parm_find_entry_rtl (struct assign_parm_data_all *all,
if (targetm.calls.pretend_outgoing_varargs_named (&all->args_so_far))
{
rtx tem;
-#ifdef FUNCTION_INCOMING_ARG
- tem = FUNCTION_INCOMING_ARG (all->args_so_far, data->promoted_mode,
- data->passed_type, true);
-#else
- tem = FUNCTION_ARG (all->args_so_far, data->promoted_mode,
- data->passed_type, true);
-#endif
+ tem = targetm.calls.function_incoming_arg (&all->args_so_far,
+ data->promoted_mode,
+ data->passed_type, true);
in_regs = tem != NULL;
}
}
@@ -3275,8 +3268,8 @@ assign_parms (tree fndecl)
set_decl_incoming_rtl (parm, data.entry_parm, data.passed_pointer);
/* Update info on where next arg arrives in registers. */
- FUNCTION_ARG_ADVANCE (all.args_so_far, data.promoted_mode,
- data.passed_type, data.named_arg);
+ targetm.calls.function_arg_advance (&all.args_so_far, data.promoted_mode,
+ data.passed_type, data.named_arg);
assign_parm_adjust_stack_rtl (&data);
@@ -3464,8 +3457,8 @@ gimplify_parameters (void)
continue;
/* Update info on where next arg arrives in registers. */
- FUNCTION_ARG_ADVANCE (all.args_so_far, data.promoted_mode,
- data.passed_type, data.named_arg);
+ targetm.calls.function_arg_advance (&all.args_so_far, data.promoted_mode,
+ data.passed_type, data.named_arg);
/* ??? Once upon a time variable_size stuffed parameter list
SAVE_EXPRs (amongst others) onto a pending sizes list. This
diff --git a/gcc/target-def.h b/gcc/target-def.h
index 1097723..0b6cdd2 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -683,6 +683,22 @@
#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false
#define TARGET_ARG_PARTIAL_BYTES hook_int_CUMULATIVE_ARGS_mode_tree_bool_0
+#ifndef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE default_function_arg_advance
+#endif
+
+#ifndef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG default_function_arg
+#endif
+
+#ifndef TARGET_FUNCTION_INCOMING_ARG
+#ifndef FUNCTION_INCOMING_ARG
+#define TARGET_FUNCTION_INCOMING_ARG TARGET_FUNCTION_ARG
+#else
+#define TARGET_FUNCTION_INCOMING_ARG default_function_incoming_arg
+#endif
+#endif
+
#define TARGET_FUNCTION_VALUE default_function_value
#define TARGET_LIBCALL_VALUE default_libcall_value
#define TARGET_FUNCTION_VALUE_REGNO_P default_function_value_regno_p
@@ -709,6 +725,9 @@
TARGET_MUST_PASS_IN_STACK, \
TARGET_CALLEE_COPIES, \
TARGET_ARG_PARTIAL_BYTES, \
+ TARGET_FUNCTION_ARG_ADVANCE, \
+ TARGET_FUNCTION_ARG, \
+ TARGET_FUNCTION_INCOMING_ARG, \
TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN, \
TARGET_FUNCTION_VALUE, \
TARGET_LIBCALL_VALUE, \
diff --git a/gcc/target.h b/gcc/target.h
index e17cc21..94d27c2 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -981,6 +981,26 @@ struct gcc_target
int (* arg_partial_bytes) (CUMULATIVE_ARGS *ca, enum machine_mode mode,
tree type, bool named);
+ /* Update the state in CA to advance past an argument in the
+ argument list. The values MODE, TYPE, and NAMED describe that
+ argument. */
+ void (*function_arg_advance) (CUMULATIVE_ARGS *ca,
+ enum machine_mode mode, const_tree type,
+ bool named);
+
+ /* Return zero if the argument described by the state of CA should
+ be placed on a stack, or a hard register in which to store the
+ argument. The values MODE, TYPE, and NAMED describe that
+ argument. */
+ rtx (*function_arg) (const CUMULATIVE_ARGS *ca,
+ enum machine_mode mode, const_tree type, bool named);
+
+ /* Likewise, but for machines with register windows. Return the
+ location where the argument will appear to the callee. */
+ rtx (*function_incoming_arg) (const CUMULATIVE_ARGS *ca,
+ enum machine_mode mode,
+ const_tree type, bool named);
+
/* Return the diagnostic message string if function without a prototype
is not allowed for this 'val' argument; NULL otherwise. */
const char *(*invalid_arg_for_unprototyped_fn) (const_tree typelist,
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index da84019..4b42a60 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -474,6 +474,49 @@ hook_int_CUMULATIVE_ARGS_mode_tree_bool_0 (
}
void
+default_function_arg_advance (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ const_tree type ATTRIBUTE_UNUSED,
+ bool named ATTRIBUTE_UNUSED)
+{
+#ifdef FUNCTION_ARG_ADVANCE
+ CUMULATIVE_ARGS args = *ca;
+ FUNCTION_ARG_ADVANCE (args, mode, CONST_CAST_TREE (type), named);
+ *ca = args;
+#else
+ gcc_unreachable ();
+#endif
+}
+
+rtx
+default_function_arg (const CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ const_tree type ATTRIBUTE_UNUSED,
+ bool named ATTRIBUTE_UNUSED)
+{
+#ifdef FUNCTION_ARG
+ return FUNCTION_ARG (*(CONST_CAST (CUMULATIVE_ARGS *, ca)), mode,
+ CONST_CAST_TREE (type), named);
+#else
+ gcc_unreachable ();
+#endif
+}
+
+rtx
+default_function_incoming_arg (const CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ const_tree type ATTRIBUTE_UNUSED,
+ bool named ATTRIBUTE_UNUSED)
+{
+#ifdef FUNCTION_INCOMING_ARG
+ return FUNCTION_INCOMING_ARG (*(CONST_CAST (CUMULATIVE_ARGS *, ca)), mode,
+ CONST_CAST_TREE (type), named);
+#else
+ gcc_unreachable ();
+#endif
+}
+
+void
hook_void_bitmap (bitmap regs ATTRIBUTE_UNUSED)
{
}
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index be167e5..d5ff4b3 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -96,6 +96,12 @@ extern int hook_int_CUMULATIVE_ARGS_mode_tree_bool_0
(CUMULATIVE_ARGS *, enum machine_mode, tree, bool);
extern const char *hook_invalid_arg_for_unprototyped_fn
(const_tree, const_tree, const_tree);
+extern void default_function_arg_advance
+ (CUMULATIVE_ARGS *, enum machine_mode, const_tree, bool);
+extern rtx default_function_arg
+ (const CUMULATIVE_ARGS *, enum machine_mode, const_tree, bool);
+extern rtx default_function_incoming_arg
+ (const CUMULATIVE_ARGS *, enum machine_mode, const_tree, bool);
extern bool hook_bool_const_rtx_commutative_p (const_rtx, int);
extern rtx default_function_value (const_tree, const_tree, bool);
extern rtx default_libcall_value (enum machine_mode, const_rtx);
More information about the Gcc-patches
mailing list