summaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
authoraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>2003-06-03 11:14:07 +0000
committeraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>2003-06-03 11:14:07 +0000
commit915e81b8b3ab82d559c65434587a01ae746d9035 (patch)
tree20dae8c49de7b0cfdf57e381abee0961ed2ef0d6 /gcc/function.c
parentc3ce66b01e47e99e429d17fb6df311852d2d5fc5 (diff)
downloadgcc-915e81b8b3ab82d559c65434587a01ae746d9035.tar.gz
2003-06-03 Aldy Hernandez <aldyh@redhat.com>
* function.c (assign_parms): Split complex arguments. * doc/tm.texi (SPLIT_COMPLEX_ARGS): Document. * expr.h (SPLIT_COMPLEX_ARGS): Define. (split_complex_types): Protoize. (split_complex_values): Protoize. * calls.c (expand_call): Split complex arguments on architectures that require it. (split_complex_values): New. (split_complex_types): New. * config/rs6000/rs6000.c (rs6000_libcall_value): New. (rs6000_function_value): Handle complex values on AIX. (rs6000_complex_function_value): New. * config/rs6000/rs6000-protos.h (rs6000_libcall_value): Protoize. * config/rs6000/rs6000.h (LIBCALL_VALUE): Call function. (SPLIT_COMPLEX_ARGS): New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@67367 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c67
1 files changed, 66 insertions, 1 deletions
diff --git a/gcc/function.c b/gcc/function.c
index 76184b9b659..c090d4aa869 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -296,6 +296,7 @@ static void prepare_function_start PARAMS ((void));
static void do_clobber_return_reg PARAMS ((rtx, void *));
static void do_use_return_reg PARAMS ((rtx, void *));
static void instantiate_virtual_regs_lossage PARAMS ((rtx));
+static tree split_complex_args (tree);
/* Pointer to chain of `struct function' for containing functions. */
static GTY(()) struct function *outer_function_chain;
@@ -4346,7 +4347,7 @@ assign_parms (fndecl)
given as a constant and a tree-expression. */
struct args_size stack_args_size;
tree fntype = TREE_TYPE (fndecl);
- tree fnargs = DECL_ARGUMENTS (fndecl);
+ tree fnargs = DECL_ARGUMENTS (fndecl), orig_fnargs;
/* This is used for the arg pointer when referring to stack args. */
rtx internal_arg_pointer;
/* This is a dummy PARM_DECL that we used for the function result if
@@ -4400,9 +4401,14 @@ assign_parms (fndecl)
fnargs = function_result_decl;
}
+ orig_fnargs = fnargs;
+
max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
parm_reg_stack_loc = (rtx *) ggc_alloc_cleared (max_parm_reg * sizeof (rtx));
+ if (SPLIT_COMPLEX_ARGS)
+ fnargs = split_complex_args (fnargs);
+
#ifdef REG_PARM_STACK_SPACE
#ifdef MAYBE_REG_PARM_STACK_SPACE
reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
@@ -5189,6 +5195,35 @@ assign_parms (fndecl)
}
}
+ if (SPLIT_COMPLEX_ARGS)
+ {
+ parm = orig_fnargs;
+
+ for (; parm; parm = TREE_CHAIN (parm))
+ {
+ tree type = TREE_TYPE (parm);
+
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ SET_DECL_RTL (parm,
+ gen_rtx_CONCAT (DECL_MODE (parm),
+ DECL_RTL (fnargs),
+ DECL_RTL (TREE_CHAIN (fnargs))));
+ DECL_INCOMING_RTL (parm)
+ = gen_rtx_CONCAT (DECL_MODE (parm),
+ DECL_INCOMING_RTL (fnargs),
+ DECL_INCOMING_RTL (TREE_CHAIN (fnargs)));
+ fnargs = TREE_CHAIN (fnargs);
+ }
+ else
+ {
+ SET_DECL_RTL (parm, DECL_RTL (fnargs));
+ DECL_INCOMING_RTL (parm) = DECL_INCOMING_RTL (fnargs);
+ }
+ fnargs = TREE_CHAIN (fnargs);
+ }
+ }
+
/* Output all parameter conversion instructions (possibly including calls)
now that all parameters have been copied out of hard registers. */
emit_insn (conversion_insns);
@@ -5292,6 +5327,36 @@ assign_parms (fndecl)
}
}
}
+
+static tree
+split_complex_args (tree args)
+{
+ tree p;
+
+ args = copy_list (args);
+
+ for (p = args; p; p = TREE_CHAIN (p))
+ {
+ tree complex_type = TREE_TYPE (p);
+
+ if (TREE_CODE (complex_type) == COMPLEX_TYPE)
+ {
+ tree decl;
+ tree subtype = TREE_TYPE (complex_type);
+
+ /* Rewrite the PARM_DECL's type with its component. */
+ TREE_TYPE (p) = subtype;
+ DECL_ARG_TYPE (p) = TREE_TYPE (DECL_ARG_TYPE (p));
+
+ decl = build_decl (PARM_DECL, NULL_TREE, subtype);
+ DECL_ARG_TYPE (decl) = DECL_ARG_TYPE (p);
+ TREE_CHAIN (decl) = TREE_CHAIN (p);
+ TREE_CHAIN (p) = decl;
+ }
+ }
+
+ return args;
+}
/* Indicate whether REGNO is an incoming argument to the current function
that was promoted to a wider mode. If so, return the RTX for the