aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c96
1 files changed, 42 insertions, 54 deletions
diff --git a/gcc/function.c b/gcc/function.c
index ac5ba94..6314ae0 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2082,25 +2082,13 @@ assign_parms_initialize_all (struct assign_parm_data_all *all)
entries of the component type. Return a new list of substitutions are
needed, else the old list. */
-static tree
-split_complex_args (tree args)
+static void
+split_complex_args (VEC(tree, heap) **args)
{
+ unsigned i;
tree p;
- /* Before allocating memory, check for the common case of no complex. */
- for (p = args; p; p = TREE_CHAIN (p))
- {
- tree type = TREE_TYPE (p);
- if (TREE_CODE (type) == COMPLEX_TYPE
- && targetm.calls.split_complex_arg (type))
- goto found;
- }
- return args;
-
- found:
- args = copy_list (args);
-
- for (p = args; p; p = TREE_CHAIN (p))
+ for (i = 0; VEC_iterate (tree, *args, i, p); ++i)
{
tree type = TREE_TYPE (p);
if (TREE_CODE (type) == COMPLEX_TYPE
@@ -2111,6 +2099,7 @@ split_complex_args (tree args)
bool addressable = TREE_ADDRESSABLE (p);
/* Rewrite the PARM_DECL's type with its component. */
+ p = copy_node (p);
TREE_TYPE (p) = subtype;
DECL_ARG_TYPE (p) = TREE_TYPE (DECL_ARG_TYPE (p));
DECL_MODE (p) = VOIDmode;
@@ -2124,6 +2113,7 @@ split_complex_args (tree args)
DECL_IGNORED_P (p) = addressable;
TREE_ADDRESSABLE (p) = 0;
layout_decl (p, 0);
+ VEC_replace (tree, *args, i, p);
/* Build a second synthetic decl. */
decl = build_decl (EXPR_LOCATION (p),
@@ -2132,27 +2122,27 @@ split_complex_args (tree args)
DECL_ARTIFICIAL (decl) = addressable;
DECL_IGNORED_P (decl) = addressable;
layout_decl (decl, 0);
-
- /* Splice it in; skip the new decl. */
- TREE_CHAIN (decl) = TREE_CHAIN (p);
- TREE_CHAIN (p) = decl;
- p = decl;
+ VEC_safe_insert (tree, heap, *args, ++i, decl);
}
}
-
- return args;
}
/* A subroutine of assign_parms. Adjust the parameter list to incorporate
the hidden struct return argument, and (abi willing) complex args.
Return the new parameter list. */
-static tree
+static VEC(tree, heap) *
assign_parms_augmented_arg_list (struct assign_parm_data_all *all)
{
tree fndecl = current_function_decl;
tree fntype = TREE_TYPE (fndecl);
- tree fnargs = DECL_ARGUMENTS (fndecl);
+ VEC(tree, heap) *fnargs = NULL;
+ tree arg;
+
+ for (arg = DECL_ARGUMENTS (fndecl); arg; arg = TREE_CHAIN (arg))
+ VEC_safe_push (tree, heap, fnargs, arg);
+
+ all->orig_fnargs = DECL_ARGUMENTS (fndecl);
/* If struct value address is treated as the first argument, make it so. */
if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
@@ -2168,16 +2158,16 @@ assign_parms_augmented_arg_list (struct assign_parm_data_all *all)
DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 1;
- TREE_CHAIN (decl) = fnargs;
- fnargs = decl;
+ TREE_CHAIN (decl) = all->orig_fnargs;
+ all->orig_fnargs = decl;
+ VEC_safe_insert (tree, heap, fnargs, 0, decl);
+
all->function_result_decl = decl;
}
- all->orig_fnargs = fnargs;
-
/* If the target wants to split complex arguments into scalars, do so. */
if (targetm.calls.split_complex_arg)
- fnargs = split_complex_args (fnargs);
+ split_complex_args (&fnargs);
return fnargs;
}
@@ -3065,12 +3055,14 @@ assign_parm_setup_stack (struct assign_parm_data_all *all, tree parm,
undo the frobbing that we did in assign_parms_augmented_arg_list. */
static void
-assign_parms_unsplit_complex (struct assign_parm_data_all *all, tree fnargs)
+assign_parms_unsplit_complex (struct assign_parm_data_all *all,
+ VEC(tree, heap) *fnargs)
{
tree parm;
tree orig_fnargs = all->orig_fnargs;
+ unsigned i = 0;
- for (parm = orig_fnargs; parm; parm = TREE_CHAIN (parm))
+ for (parm = orig_fnargs; parm; parm = TREE_CHAIN (parm), ++i)
{
if (TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE
&& targetm.calls.split_complex_arg (TREE_TYPE (parm)))
@@ -3078,8 +3070,8 @@ assign_parms_unsplit_complex (struct assign_parm_data_all *all, tree fnargs)
rtx tmp, real, imag;
enum machine_mode inner = GET_MODE_INNER (DECL_MODE (parm));
- real = DECL_RTL (fnargs);
- imag = DECL_RTL (TREE_CHAIN (fnargs));
+ real = DECL_RTL (VEC_index (tree, fnargs, i));
+ imag = DECL_RTL (VEC_index (tree, fnargs, i + 1));
if (inner != GET_MODE (real))
{
real = gen_lowpart_SUBREG (inner, real);
@@ -3112,8 +3104,8 @@ assign_parms_unsplit_complex (struct assign_parm_data_all *all, tree fnargs)
tmp = gen_rtx_CONCAT (DECL_MODE (parm), real, imag);
SET_DECL_RTL (parm, tmp);
- real = DECL_INCOMING_RTL (fnargs);
- imag = DECL_INCOMING_RTL (TREE_CHAIN (fnargs));
+ real = DECL_INCOMING_RTL (VEC_index (tree, fnargs, i));
+ imag = DECL_INCOMING_RTL (VEC_index (tree, fnargs, i + 1));
if (inner != GET_MODE (real))
{
real = gen_lowpart_SUBREG (inner, real);
@@ -3121,20 +3113,8 @@ assign_parms_unsplit_complex (struct assign_parm_data_all *all, tree fnargs)
}
tmp = gen_rtx_CONCAT (DECL_MODE (parm), real, imag);
set_decl_incoming_rtl (parm, tmp, false);
- fnargs = TREE_CHAIN (fnargs);
- }
- else
- {
- SET_DECL_RTL (parm, DECL_RTL (fnargs));
- set_decl_incoming_rtl (parm, DECL_INCOMING_RTL (fnargs), false);
-
- /* Set MEM_EXPR to the original decl, i.e. to PARM,
- instead of the copy of decl, i.e. FNARGS. */
- if (DECL_INCOMING_RTL (parm) && MEM_P (DECL_INCOMING_RTL (parm)))
- set_mem_expr (DECL_INCOMING_RTL (parm), parm);
+ i++;
}
-
- fnargs = TREE_CHAIN (fnargs);
}
}
@@ -3145,7 +3125,9 @@ static void
assign_parms (tree fndecl)
{
struct assign_parm_data_all all;
- tree fnargs, parm;
+ tree parm;
+ VEC(tree, heap) *fnargs;
+ unsigned i;
crtl->args.internal_arg_pointer
= targetm.calls.internal_arg_pointer ();
@@ -3153,7 +3135,7 @@ assign_parms (tree fndecl)
assign_parms_initialize_all (&all);
fnargs = assign_parms_augmented_arg_list (&all);
- for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
+ for (i = 0; VEC_iterate (tree, fnargs, i, parm); ++i)
{
struct assign_parm_data_one data;
@@ -3216,9 +3198,11 @@ assign_parms (tree fndecl)
assign_parm_setup_stack (&all, parm, &data);
}
- if (targetm.calls.split_complex_arg && fnargs != all.orig_fnargs)
+ if (targetm.calls.split_complex_arg)
assign_parms_unsplit_complex (&all, fnargs);
+ VEC_free (tree, heap, fnargs);
+
/* Output all parameter conversion instructions (possibly including calls)
now that all parameters have been copied out of hard registers. */
emit_insn (all.first_conversion_insn);
@@ -3370,13 +3354,15 @@ gimple_seq
gimplify_parameters (void)
{
struct assign_parm_data_all all;
- tree fnargs, parm;
+ tree parm;
gimple_seq stmts = NULL;
+ VEC(tree, heap) *fnargs;
+ unsigned i;
assign_parms_initialize_all (&all);
fnargs = assign_parms_augmented_arg_list (&all);
- for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
+ for (i = 0; VEC_iterate (tree, fnargs, i, parm); ++i)
{
struct assign_parm_data_one data;
@@ -3454,6 +3440,8 @@ gimplify_parameters (void)
}
}
+ VEC_free (tree, heap, fnargs);
+
return stmts;
}