Commit 0310e537 by Richard Henderson Committed by Richard Sandiford

mips-protos.h (mips_va_arg): Delete.

	* config/mips/mips-protos.h (mips_va_arg): Delete.
	* config/mips/mips.h (EXPAND_BUILTIN_VA_ARG): Delete.
	* config/mips/mips.c: Include tree-gimple.h.
	(TARGET_GIMPLIFY_VA_ARG_EXPR): Define.
	(mips_arg_info): Remove special handling of must_pass_in_stck args.
	(mips_gimplify_va_arg_expr): Rewritten from mips_va_arg.
	(function_arg_pass_by_reference): Return true if must_pass_in_stack.

Co-Authored-By: Richard Sandiford <rsandifo@redhat.com>

From-SVN: r84671
parent 1cb6d0da
2004-07-14 Richard Henderson <rth@redhat.com>
Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips-protos.h (mips_va_arg): Delete.
* config/mips/mips.h (EXPAND_BUILTIN_VA_ARG): Delete.
* config/mips/mips.c: Include tree-gimple.h.
(TARGET_GIMPLIFY_VA_ARG_EXPR): Define.
(mips_arg_info): Remove special handling of must_pass_in_stck args.
(mips_gimplify_va_arg_expr): Rewritten from mips_va_arg.
(function_arg_pass_by_reference): Return true if must_pass_in_stack.
2004-07-13 Bob Wilson <bob.wilson@acm.org> 2004-07-13 Bob Wilson <bob.wilson@acm.org>
* config/xtensa/xtensa.c (xtensa_gimplify_va_arg_expr): Swap * config/xtensa/xtensa.c (xtensa_gimplify_va_arg_expr): Swap
......
...@@ -143,7 +143,6 @@ extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *, ...@@ -143,7 +143,6 @@ extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *,
extern bool mips_pad_arg_upward (enum machine_mode, tree); extern bool mips_pad_arg_upward (enum machine_mode, tree);
extern bool mips_pad_reg_upward (enum machine_mode, tree); extern bool mips_pad_reg_upward (enum machine_mode, tree);
extern void mips_va_start (tree, rtx); extern void mips_va_start (tree, rtx);
extern struct rtx_def *mips_va_arg (tree, tree);
extern bool mips_expand_unaligned_load (rtx, rtx, unsigned int, int); extern bool mips_expand_unaligned_load (rtx, rtx, unsigned int, int);
extern bool mips_expand_unaligned_store (rtx, rtx, unsigned int, int); extern bool mips_expand_unaligned_store (rtx, rtx, unsigned int, int);
......
...@@ -55,6 +55,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -55,6 +55,7 @@ Boston, MA 02111-1307, USA. */
#include "langhooks.h" #include "langhooks.h"
#include "cfglayout.h" #include "cfglayout.h"
#include "sched-int.h" #include "sched-int.h"
#include "tree-gimple.h"
/* Enumeration for all of the relational tests, so that we can build /* Enumeration for all of the relational tests, so that we can build
arrays indexed by the test type, and not worry about the order arrays indexed by the test type, and not worry about the order
...@@ -288,6 +289,7 @@ static void mips_init_libfuncs (void); ...@@ -288,6 +289,7 @@ static void mips_init_libfuncs (void);
static void mips_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, static void mips_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
tree, int *, int); tree, int *, int);
static tree mips_build_builtin_va_list (void); static tree mips_build_builtin_va_list (void);
static tree mips_gimplify_va_arg_expr (tree, tree, tree *, tree *);
#if TARGET_IRIX #if TARGET_IRIX
static void irix_asm_named_section_1 (const char *, unsigned int, static void irix_asm_named_section_1 (const char *, unsigned int,
...@@ -716,6 +718,8 @@ const struct mips_cpu_info mips_cpu_info_table[] = { ...@@ -716,6 +718,8 @@ const struct mips_cpu_info mips_cpu_info_table[] = {
#undef TARGET_BUILD_BUILTIN_VA_LIST #undef TARGET_BUILD_BUILTIN_VA_LIST
#define TARGET_BUILD_BUILTIN_VA_LIST mips_build_builtin_va_list #define TARGET_BUILD_BUILTIN_VA_LIST mips_build_builtin_va_list
#undef TARGET_GIMPLIFY_VA_ARG_EXPR
#define TARGET_GIMPLIFY_VA_ARG_EXPR mips_gimplify_va_arg_expr
#undef TARGET_PROMOTE_FUNCTION_ARGS #undef TARGET_PROMOTE_FUNCTION_ARGS
#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
...@@ -3554,12 +3558,6 @@ mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode, ...@@ -3554,12 +3558,6 @@ mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
even_reg_p = true; even_reg_p = true;
} }
if (mips_abi != ABI_EABI && targetm.calls.must_pass_in_stack (mode, type))
/* This argument must be passed on the stack. Eat up all the
remaining registers. */
info->reg_offset = MAX_ARGS_IN_REGISTERS;
else
{
/* Set REG_OFFSET to the register count we're interested in. /* Set REG_OFFSET to the register count we're interested in.
The EABI allocates the floating-point registers separately, The EABI allocates the floating-point registers separately,
but the other ABIs allocate them like integer registers. */ but the other ABIs allocate them like integer registers. */
...@@ -3569,7 +3567,6 @@ mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode, ...@@ -3569,7 +3567,6 @@ mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (even_reg_p) if (even_reg_p)
info->reg_offset += info->reg_offset & 1; info->reg_offset += info->reg_offset & 1;
}
/* The alignment applied to registers is also applied to stack arguments. */ /* The alignment applied to registers is also applied to stack arguments. */
info->stack_offset = cum->stack_words; info->stack_offset = cum->stack_words;
...@@ -4041,72 +4038,32 @@ mips_va_start (tree valist, rtx nextarg) ...@@ -4041,72 +4038,32 @@ mips_va_start (tree valist, rtx nextarg)
/* Implement va_arg. */ /* Implement va_arg. */
rtx static tree
mips_va_arg (tree valist, tree type) mips_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
{ {
HOST_WIDE_INT size, rsize; HOST_WIDE_INT size, rsize;
rtx addr_rtx; tree addr;
tree t;
size = int_size_in_bytes (type);
rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
if (mips_abi == ABI_EABI)
{
bool indirect; bool indirect;
rtx r;
indirect indirect
= function_arg_pass_by_reference (NULL, TYPE_MODE (type), type, 0); = function_arg_pass_by_reference (NULL, TYPE_MODE (type), type, 0);
if (indirect) if (indirect)
{ type = build_pointer_type (type);
size = POINTER_SIZE / BITS_PER_UNIT;
rsize = UNITS_PER_WORD;
}
if (!EABI_FLOAT_VARARGS_P) size = int_size_in_bytes (type);
{ rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
/* Case of all args in a merged stack. No need to check bounds,
just advance valist along the stack. */
tree gpr = valist;
if (!indirect
&& !TARGET_64BIT
&& TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD)
{
/* Align the pointer using: ap = (ap + align - 1) & -align,
where align is 2 * UNITS_PER_WORD. */
t = build (PLUS_EXPR, TREE_TYPE (gpr), gpr,
build_int_2 (2 * UNITS_PER_WORD - 1, 0));
t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
build_int_2 (-2 * UNITS_PER_WORD, -1));
t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
/* Emit code to set addr_rtx to the valist, and postincrement
the valist by the size of the argument, rounded up to the
next word. Account for padding on big-endian targets. */
t = build (POSTINCREMENT_EXPR, TREE_TYPE (gpr), gpr,
size_int (rsize));
addr_rtx = expand_expr (t, 0, Pmode, EXPAND_NORMAL);
if (BYTES_BIG_ENDIAN)
addr_rtx = plus_constant (addr_rtx, rsize - size);
/* Flush the POSTINCREMENT. */ if (mips_abi != ABI_EABI || !EABI_FLOAT_VARARGS_P)
emit_queue(); addr = std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
}
else else
{ {
/* Not a simple merged stack. */ /* Not a simple merged stack. */
tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff; tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
tree ovfl, top, off; tree ovfl, top, off, align;
rtx lab_over = NULL_RTX, lab_false;
HOST_WIDE_INT osize; HOST_WIDE_INT osize;
tree t, u;
addr_rtx = gen_reg_rtx (Pmode);
f_ovfl = TYPE_FIELDS (va_list_type_node); f_ovfl = TYPE_FIELDS (va_list_type_node);
f_gtop = TREE_CHAIN (f_ovfl); f_gtop = TREE_CHAIN (f_ovfl);
...@@ -4144,11 +4101,9 @@ mips_va_arg (tree valist, tree type) ...@@ -4144,11 +4101,9 @@ mips_va_arg (tree valist, tree type)
[1] and [9] can sometimes be optimized away. */ [1] and [9] can sometimes be optimized away. */
lab_false = gen_label_rtx ();
lab_over = gen_label_rtx ();
ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
NULL_TREE); NULL_TREE);
if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT
&& GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE) && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE)
{ {
...@@ -4193,120 +4148,69 @@ mips_va_arg (tree valist, tree type) ...@@ -4193,120 +4148,69 @@ mips_va_arg (tree valist, tree type)
t = build (BIT_AND_EXPR, TREE_TYPE (off), off, t = build (BIT_AND_EXPR, TREE_TYPE (off), off,
build_int_2 (-rsize, -1)); build_int_2 (-rsize, -1));
t = build (MODIFY_EXPR, TREE_TYPE (off), off, t); t = build (MODIFY_EXPR, TREE_TYPE (off), off, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); gimplify_and_add (t, pre_p);
} }
osize = rsize; osize = rsize;
} }
/* [2] Emit code to branch if off == 0. */ /* [2] Emit code to branch if off == 0. */
r = expand_expr (off, NULL_RTX, TYPE_MODE (TREE_TYPE (off)), t = lang_hooks.truthvalue_conversion (off);
EXPAND_NORMAL); addr = build (COND_EXPR, ptr_type_node, t, NULL, NULL);
emit_cmp_and_jump_insns (r, const0_rtx, EQ, const1_rtx, GET_MODE (r),
1, lab_false); /* [5] Emit code for: off -= rsize. We do this as a form of
post-increment not available to C. Also widen for the
coming pointer arithmetic. */
t = fold_convert (TREE_TYPE (off), build_int_2 (rsize, 0));
t = build (POSTDECREMENT_EXPR, TREE_TYPE (off), off, t);
t = fold_convert (sizetype, t);
t = fold_convert (TREE_TYPE (top), t);
/* [4] Emit code for: addr_rtx = top - off. On big endian machines, /* [4] Emit code for: addr_rtx = top - off. On big endian machines,
the argument has RSIZE - SIZE bytes of leading padding. */ the argument has RSIZE - SIZE bytes of leading padding. */
t = build (MINUS_EXPR, TREE_TYPE (top), top, off); t = build (MINUS_EXPR, TREE_TYPE (top), top, t);
if (BYTES_BIG_ENDIAN && rsize > size) if (BYTES_BIG_ENDIAN && rsize > size)
t = build (PLUS_EXPR, TREE_TYPE (t), t, {
build_int_2 (rsize - size, 0)); u = fold_convert (TREE_TYPE (t), build_int_2 (rsize - size, 0));
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL); t = build (PLUS_EXPR, TREE_TYPE (t), t, u);
if (r != addr_rtx) }
emit_move_insn (addr_rtx, r); COND_EXPR_THEN (addr) = t;
/* [5] Emit code for: off -= rsize. */
t = build (MINUS_EXPR, TREE_TYPE (off), off, build_int_2 (rsize, 0));
t = build (MODIFY_EXPR, TREE_TYPE (off), off, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
/* [7] Emit code to jump over the else clause, then the label
that starts it. */
emit_queue();
emit_jump (lab_over);
emit_barrier ();
emit_label (lab_false);
if (osize > UNITS_PER_WORD) if (osize > UNITS_PER_WORD)
{ {
/* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize. */ /* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize. */
t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, u = fold_convert (TREE_TYPE (ovfl), build_int_2 (osize - 1, 0));
build_int_2 (osize - 1, 0)); t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, u);
t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), t, u = fold_convert (TREE_TYPE (ovfl), build_int_2 (-osize, -1));
build_int_2 (-osize, -1)); t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), t, u);
t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t); align = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
} }
else
align = NULL;
/* [10, 11]. Emit code to store ovfl in addr_rtx, then /* [10, 11]. Emit code to store ovfl in addr_rtx, then
post-increment ovfl by osize. On big-endian machines, post-increment ovfl by osize. On big-endian machines,
the argument has OSIZE - SIZE bytes of leading padding. */ the argument has OSIZE - SIZE bytes of leading padding. */
t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u = fold_convert (TREE_TYPE (ovfl), build_int_2 (osize, 0));
size_int (osize)); t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u);
if (BYTES_BIG_ENDIAN && osize > size) if (BYTES_BIG_ENDIAN && osize > size)
t = build (PLUS_EXPR, TREE_TYPE (t), t,
build_int_2 (osize - size, 0));
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx)
emit_move_insn (addr_rtx, r);
emit_queue();
emit_label (lab_over);
}
if (indirect)
{ {
addr_rtx = force_reg (Pmode, addr_rtx); u = fold_convert (TREE_TYPE (t), build_int_2 (osize - size, 0));
r = gen_rtx_MEM (Pmode, addr_rtx); t = build (PLUS_EXPR, TREE_TYPE (t), t, u);
set_mem_alias_set (r, get_varargs_alias_set ());
emit_move_insn (addr_rtx, r);
}
return addr_rtx;
} }
else
{
/* Not EABI. */
int align;
HOST_WIDE_INT min_offset;
/* ??? The original va-mips.h did always align, despite the fact
that alignments <= UNITS_PER_WORD are preserved by the va_arg
increment mechanism. */
if (TARGET_NEWABI && TYPE_ALIGN (type) > 64)
align = 16;
else if (TARGET_64BIT)
align = 8;
else if (TYPE_ALIGN (type) > 32)
align = 8;
else
align = 4;
t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
build_int_2 (align - 1, 0));
t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
/* If arguments of type TYPE must be passed on the stack,
set MIN_OFFSET to the offset of the first stack parameter. */
if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))
min_offset = 0;
else if (TARGET_NEWABI)
min_offset = current_function_pretend_args_size;
else
min_offset = REG_PARM_STACK_SPACE (current_function_decl);
/* Make sure the new address is at least MIN_OFFSET bytes from
the incoming argument pointer. */
if (min_offset > 0)
t = build (MAX_EXPR, TREE_TYPE (valist), t,
make_tree (TREE_TYPE (valist),
plus_constant (virtual_incoming_args_rtx,
min_offset)));
t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
/* Everything past the alignment is standard. */ /* String [9] and [10,11] together. */
return std_expand_builtin_va_arg (valist, type); if (align)
t = build (COMPOUND_EXPR, TREE_TYPE (t), align, t);
COND_EXPR_ELSE (addr) = t;
addr = fold_convert (build_pointer_type (type), addr);
addr = build_fold_indirect_ref (addr);
} }
if (indirect)
addr = build_fold_indirect_ref (addr);
return addr;
} }
/* Return true if it is possible to use left/right accesses for a /* Return true if it is possible to use left/right accesses for a
...@@ -7425,18 +7329,22 @@ function_arg_pass_by_reference (const CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, ...@@ -7425,18 +7329,22 @@ function_arg_pass_by_reference (const CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
enum machine_mode mode, tree type, enum machine_mode mode, tree type,
int named ATTRIBUTE_UNUSED) int named ATTRIBUTE_UNUSED)
{ {
if (mips_abi == ABI_EABI)
{
int size; int size;
/* The EABI is the only one to pass args by reference. */
if (mips_abi != ABI_EABI)
return 0;
/* ??? How should SCmode be handled? */ /* ??? How should SCmode be handled? */
if (type == NULL_TREE || mode == DImode || mode == DFmode) if (type == NULL_TREE || mode == DImode || mode == DFmode)
return 0; return 0;
size = int_size_in_bytes (type); size = int_size_in_bytes (type);
return size == -1 || size > UNITS_PER_WORD; return size == -1 || size > UNITS_PER_WORD;
}
else
{
/* If we have a variable-sized parameter, we have no choice. */
return targetm.calls.must_pass_in_stack (mode, type);
}
} }
/* Return the class of registers for which a mode change from FROM to TO /* Return the class of registers for which a mode change from FROM to TO
......
...@@ -2388,10 +2388,6 @@ typedef struct mips_args { ...@@ -2388,10 +2388,6 @@ typedef struct mips_args {
#define EXPAND_BUILTIN_VA_START(valist, nextarg) \ #define EXPAND_BUILTIN_VA_START(valist, nextarg) \
mips_va_start (valist, nextarg) mips_va_start (valist, nextarg)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
mips_va_arg (valist, type)
/* Output assembler code to FILE to increment profiler label # LABELNO /* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */ for profiling a function entry. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment