sparc.c (sparc_gimplify_va_arg): New fn.
* config/sparc/sparc.c (sparc_gimplify_va_arg): New fn. (TARGET_GIMPLIFY_VA_ARG_EXPR): Define. From-SVN: r82963
This commit is contained in:
parent
b092552d60
commit
5f393b252e
|
@ -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>
|
2004-06-11 Jerry Quinn <jlquinn@optonline.net>
|
||||||
|
|
||||||
* typeclass.h: Add GPL plus exception license. Add include
|
* typeclass.h: Add GPL plus exception license. Add include
|
||||||
|
|
|
@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA. */
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "target-def.h"
|
#include "target-def.h"
|
||||||
#include "cfglayout.h"
|
#include "cfglayout.h"
|
||||||
|
#include "tree-gimple.h"
|
||||||
|
|
||||||
/* Global variables for machine-dependent things. */
|
/* 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 rtx sparc_struct_value_rtx (tree, int);
|
||||||
static bool sparc_return_in_memory (tree, tree);
|
static bool sparc_return_in_memory (tree, tree);
|
||||||
static bool sparc_strict_argument_naming (CUMULATIVE_ARGS *);
|
static bool sparc_strict_argument_naming (CUMULATIVE_ARGS *);
|
||||||
|
static tree sparc_gimplify_va_arg (tree, tree, tree *, tree *);
|
||||||
|
|
||||||
/* Option handling. */
|
/* Option handling. */
|
||||||
|
|
||||||
|
@ -289,6 +291,9 @@ enum processor_type sparc_cpu;
|
||||||
#undef TARGET_STRICT_ARGUMENT_NAMING
|
#undef TARGET_STRICT_ARGUMENT_NAMING
|
||||||
#define TARGET_STRICT_ARGUMENT_NAMING sparc_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;
|
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||||
|
|
||||||
/* Validate and override various options, and do some machine dependent
|
/* Validate and override various options, and do some machine dependent
|
||||||
|
@ -6041,6 +6046,96 @@ sparc_va_arg (tree valist, tree type)
|
||||||
|
|
||||||
return addr_rtx;
|
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
|
/* Return the string to output a conditional branch to LABEL, which is
|
||||||
the operand number of the label. OP is the conditional expression.
|
the operand number of the label. OP is the conditional expression.
|
||||||
|
|
Loading…
Reference in New Issue