aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Edelsohn <edelsohn@gnu.org>2003-01-29 17:37:25 +0000
committerDavid Edelsohn <dje@gcc.gnu.org>2003-01-29 12:37:25 -0500
commitc8c99a68775bacea4b8986024cca0d2b0e62b451 (patch)
tree61f6e6fb66454a09fc43b654799025f56490d708 /gcc
parentccf4d5128446c504efe2133f907f8b13181b0f3c (diff)
downloadgcc-c8c99a68775bacea4b8986024cca0d2b0e62b451.zip
gcc-c8c99a68775bacea4b8986024cca0d2b0e62b451.tar.gz
gcc-c8c99a68775bacea4b8986024cca0d2b0e62b451.tar.bz2
rs6000.c (function_arg_pass_by_reference): Return true for variable sized types.
* config/rs6000/rs6000.c (function_arg_pass_by_reference): Return true for variable sized types. (rs6000_va_arg): Handle variable sized types passed by reference on non-SVR4 ABI. From-SVN: r62095
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/rs6000/rs6000.c31
2 files changed, 34 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 744f126..8d908ff 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2003-01-29 David Edelsohn <edelsohn@gnu.org>
+
+ * config/rs6000/rs6000.c (function_arg_pass_by_reference):
+ Return true for variable sized types.
+ (rs6000_va_arg): Handle variable sized types passed by reference
+ on non-SVR4 ABI.
+
2003-01-29 Richard Earnshaw <rearnsha@arm.com>
* arm.c (arm_legtimize_address): New function.
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 31eb55e..41284e8 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -3314,7 +3314,10 @@ function_arg_partial_nregs (cum, mode, type, named)
the argument itself. The pointer is passed in whatever way is
appropriate for passing a pointer to that type.
- Under V.4, structures and unions are passed by reference. */
+ Under V.4, structures and unions are passed by reference.
+
+ As an extension to all ABIs, variable sized types are passed by
+ reference. */
int
function_arg_pass_by_reference (cum, mode, type, named)
@@ -3332,8 +3335,7 @@ function_arg_pass_by_reference (cum, mode, type, named)
return 1;
}
-
- return 0;
+ return type && int_size_in_bytes (type) <= 0;
}
/* Perform any needed actions needed for a function that is receiving a
@@ -3569,7 +3571,28 @@ rs6000_va_arg (valist, type)
rtx lab_false, lab_over, addr_rtx, r;
if (DEFAULT_ABI != ABI_V4)
- return std_expand_builtin_va_arg (valist, type);
+ {
+ /* Variable sized types are passed by reference. */
+ if (int_size_in_bytes (type) <= 0)
+ {
+ u = build_pointer_type (type);
+
+ /* Args grow upward. */
+ t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist,
+ build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
+ TREE_SIDE_EFFECTS (t) = 1;
+
+ t = build1 (NOP_EXPR, build_pointer_type (u), t);
+ TREE_SIDE_EFFECTS (t) = 1;
+
+ t = build1 (INDIRECT_REF, u, t);
+ TREE_SIDE_EFFECTS (t) = 1;
+
+ return expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
+ }
+ else
+ return std_expand_builtin_va_arg (valist, type);
+ }
f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
f_fpr = TREE_CHAIN (f_gpr);