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/calls.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/calls.c')
-rw-r--r-- | gcc/calls.c | 91 |
1 files changed, 89 insertions, 2 deletions
diff --git a/gcc/calls.c b/gcc/calls.c index 9d7899c8bce..4e95735376c 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -2071,6 +2071,7 @@ expand_call (exp, target, ignore) rtx tail_call_insns = NULL_RTX; /* Data type of the function. */ tree funtype; + tree type_arg_types; /* Declaration of the function being called, or 0 if the function is computed (not known by name). */ tree fndecl = 0; @@ -2306,6 +2307,16 @@ expand_call (exp, target, ignore) abort (); funtype = TREE_TYPE (funtype); + /* Munge the tree to split complex arguments into their imaginary + and real parts. */ + if (SPLIT_COMPLEX_ARGS) + { + type_arg_types = split_complex_types (TYPE_ARG_TYPES (funtype)); + actparms = split_complex_values (actparms); + } + else + type_arg_types = TYPE_ARG_TYPES (funtype); + /* See if this is a call to a function that can return more than once or a call to longjmp or malloc. */ flags |= special_function_p (fndecl, flags); @@ -2359,9 +2370,9 @@ expand_call (exp, target, ignore) if ((STRICT_ARGUMENT_NAMING || ! PRETEND_OUTGOING_VARARGS_NAMED) - && TYPE_ARG_TYPES (funtype) != 0) + && type_arg_types != 0) n_named_args - = (list_length (TYPE_ARG_TYPES (funtype)) + = (list_length (type_arg_types) /* Don't include the last named arg. */ - (STRICT_ARGUMENT_NAMING ? 0 : 1) /* Count the struct value address, if it is passed as a parm. */ @@ -3447,6 +3458,82 @@ expand_call (exp, target, ignore) return target; } + +/* Traverse an argument list in VALUES and expand all complex + arguments into their components. */ +tree +split_complex_values (tree values) +{ + tree p; + + values = copy_list (values); + + for (p = values; p; p = TREE_CHAIN (p)) + { + tree complex_value = TREE_VALUE (p); + tree complex_type; + + complex_type = TREE_TYPE (complex_value); + if (!complex_type) + continue; + + if (TREE_CODE (complex_type) == COMPLEX_TYPE) + { + tree subtype; + tree real, imag, next; + + subtype = TREE_TYPE (complex_type); + complex_value = save_expr (complex_value); + real = build1 (REALPART_EXPR, subtype, complex_value); + imag = build1 (IMAGPART_EXPR, subtype, complex_value); + + TREE_VALUE (p) = real; + next = TREE_CHAIN (p); + imag = build_tree_list (NULL_TREE, imag); + TREE_CHAIN (p) = imag; + TREE_CHAIN (imag) = next; + + /* Skip the newly created node. */ + p = TREE_CHAIN (p); + } + } + + return values; +} + +/* Traverse a list of TYPES and expand all complex types into their + components. */ +tree +split_complex_types (tree types) +{ + tree p; + + types = copy_list (types); + + for (p = types; p; p = TREE_CHAIN (p)) + { + tree complex_type = TREE_VALUE (p); + + if (TREE_CODE (complex_type) == COMPLEX_TYPE) + { + tree next, imag; + + /* Rewrite complex type with component type. */ + TREE_VALUE (p) = TREE_TYPE (complex_type); + next = TREE_CHAIN (p); + + /* Add another component type for the imaginary part. */ + imag = build_tree_list (NULL_TREE, TREE_VALUE (p)); + TREE_CHAIN (p) = imag; + TREE_CHAIN (imag) = next; + + /* Skip the newly created node. */ + p = TREE_CHAIN (p); + } + } + + return types; +} /* Output a library call to function FUN (a SYMBOL_REF rtx). The RETVAL parameter specifies whether return value needs to be saved, other |