diff options
author | aldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-06-03 11:14:07 +0000 |
---|---|---|
committer | aldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-06-03 11:14:07 +0000 |
commit | 915e81b8b3ab82d559c65434587a01ae746d9035 (patch) | |
tree | 20dae8c49de7b0cfdf57e381abee0961ed2ef0d6 /gcc/function.c | |
parent | c3ce66b01e47e99e429d17fb6df311852d2d5fc5 (diff) | |
download | gcc-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.c | 67 |
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 |