summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2004-06-11 06:08:09 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2004-06-11 06:08:09 +0000
commit86747063f2160145960e695ead7ed7c9db72a904 (patch)
tree12957ed1ea43ada7073244def69f5ac23d486637 /gcc
parentb40a8f897bc0d4a113dc2f0244f92bb48f94f5de (diff)
downloadgcc-86747063f2160145960e695ead7ed7c9db72a904.tar.gz
* config/sparc/sparc.c (sparc_gimplify_va_arg): New fn.
(TARGET_GIMPLIFY_VA_ARG_EXPR): Define. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@82963 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/sparc/sparc.c95
2 files changed, 100 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f9b6182eccd..00d09a0ba1e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2004-06-11 Jason Merrill <jason@redhat.com>
+
+ * config/sparc/sparc.c (sparc_gimplify_va_arg): New fn.
+ (TARGET_GIMPLIFY_VA_ARG_EXPR): Define.
+
2004-06-11 Jerry Quinn <jlquinn@optonline.net>
* typeclass.h: Add GPL plus exception license. Add include
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 0d197271456..5be84c886e0 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA. */
#include "target.h"
#include "target-def.h"
#include "cfglayout.h"
+#include "tree-gimple.h"
/* Global variables for machine-dependent things. */
@@ -181,6 +182,7 @@ static bool sparc_promote_prototypes (tree);
static rtx sparc_struct_value_rtx (tree, int);
static bool sparc_return_in_memory (tree, tree);
static bool sparc_strict_argument_naming (CUMULATIVE_ARGS *);
+static tree sparc_gimplify_va_arg (tree, tree, tree *, tree *);
/* Option handling. */
@@ -289,6 +291,9 @@ enum processor_type sparc_cpu;
#undef TARGET_STRICT_ARGUMENT_NAMING
#define TARGET_STRICT_ARGUMENT_NAMING sparc_strict_argument_naming
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR sparc_gimplify_va_arg
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Validate and override various options, and do some machine dependent
@@ -6041,6 +6046,96 @@ sparc_va_arg (tree valist, tree type)
return addr_rtx;
}
+
+tree
+sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
+{
+ HOST_WIDE_INT size, rsize, align;
+ tree addr, incr;
+ bool indirect;
+ tree ptrtype = build_pointer_type (type);
+
+ if (function_arg_pass_by_reference (0, TYPE_MODE (type), type, 0))
+ {
+ indirect = true;
+ size = rsize = UNITS_PER_WORD;
+ align = 0;
+ }
+ else
+ {
+ indirect = false;
+ size = int_size_in_bytes (type);
+ rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
+ align = 0;
+
+ if (TARGET_ARCH64)
+ {
+ /* For SPARC64, objects requiring 16-byte alignment get it. */
+ if (TYPE_ALIGN (type) >= 2 * (unsigned) BITS_PER_WORD)
+ align = 2 * UNITS_PER_WORD;
+
+ /* SPARC-V9 ABI states that structures up to 16 bytes in size
+ are given whole slots as needed. */
+ if (AGGREGATE_TYPE_P (type))
+ {
+ if (size == 0)
+ size = rsize = UNITS_PER_WORD;
+ else
+ size = rsize;
+ }
+ }
+ }
+
+ incr = valist;
+ if (align)
+ {
+ incr = fold (build2 (PLUS_EXPR, ptr_type_node, incr,
+ ssize_int (align - 1)));
+ incr = fold (build2 (BIT_AND_EXPR, ptr_type_node, incr,
+ ssize_int (-align)));
+ }
+
+ gimplify_expr (&incr, pre_p, post_p, is_gimple_val, fb_rvalue);
+ addr = incr;
+
+ if (BYTES_BIG_ENDIAN && size < rsize)
+ addr = fold (build2 (PLUS_EXPR, ptr_type_node, incr,
+ ssize_int (rsize - size)));
+
+ if (indirect)
+ {
+ addr = fold_convert (build_pointer_type (ptrtype), addr);
+ addr = build_fold_indirect_ref (addr);
+ }
+ /* If the address isn't aligned properly for the type,
+ we may need to copy to a temporary.
+ FIXME: This is inefficient. Usually we can do this
+ in registers. */
+ else if (align == 0
+ && TYPE_ALIGN (type) > BITS_PER_WORD)
+ {
+ tree tmp = create_tmp_var (type, "va_arg_tmp");
+ tree dest_addr = build_fold_addr_expr (tmp);
+
+ tree copy = build_function_call_expr
+ (implicit_built_in_decls[BUILT_IN_MEMCPY],
+ tree_cons (NULL_TREE, dest_addr,
+ tree_cons (NULL_TREE, addr,
+ tree_cons (NULL_TREE, size_int (rsize),
+ NULL_TREE))));
+
+ gimplify_and_add (copy, pre_p);
+ addr = dest_addr;
+ }
+ else
+ addr = fold_convert (ptrtype, addr);
+
+ incr = fold (build2 (PLUS_EXPR, ptr_type_node, incr, ssize_int (rsize)));
+ incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr);
+ gimplify_and_add (incr, post_p);
+
+ return build_fold_indirect_ref (addr);
+}
/* Return the string to output a conditional branch to LABEL, which is
the operand number of the label. OP is the conditional expression.