Commit 85d53c1d by Richard Henderson Committed by Richard Henderson

xtensa-protos.h (xtensa_va_arg): Remove.

        * config/xtensa/xtensa-protos.h (xtensa_va_arg): Remove.
        * config/xtensa/xtensa.c (TARGET_GIMPLIFY_VA_ARG_EXPR): New.
        (xtensa_gimplify_va_arg_expr): Rewrite from xtensa_va_arg.
        * config/xtensa/xtensa.h (EXPAND_BUILTIN_VA_ARG): Remove.

From-SVN: r84360
parent a900345f
2004-07-09 Richard Henderson <rth@redhat.com> 2004-07-09 Richard Henderson <rth@redhat.com>
* config/xtensa/xtensa-protos.h (xtensa_va_arg): Remove.
* config/xtensa/xtensa.c (TARGET_GIMPLIFY_VA_ARG_EXPR): New.
(xtensa_gimplify_va_arg_expr): Rewrite from xtensa_va_arg.
* config/xtensa/xtensa.h (EXPAND_BUILTIN_VA_ARG): Remove.
* config/v850/v850-protos.h (v850_va_arg): Remove. * config/v850/v850-protos.h (v850_va_arg): Remove.
* config/v850/v850.c (TARGET_GIMPLIFY_VA_ARG_EXPR): New. * config/v850/v850.c (TARGET_GIMPLIFY_VA_ARG_EXPR): New.
(v850_gimplify_va_arg_expr): Rewrite from v850_va_arg. (v850_gimplify_va_arg_expr): Rewrite from v850_va_arg.
......
...@@ -77,7 +77,6 @@ extern char *xtensa_emit_call (int, rtx *); ...@@ -77,7 +77,6 @@ extern char *xtensa_emit_call (int, rtx *);
#ifdef TREE_CODE #ifdef TREE_CODE
extern void init_cumulative_args (CUMULATIVE_ARGS *, int); extern void init_cumulative_args (CUMULATIVE_ARGS *, int);
extern void xtensa_va_start (tree, rtx); extern void xtensa_va_start (tree, rtx);
extern rtx xtensa_va_arg (tree, tree);
#endif /* TREE_CODE */ #endif /* TREE_CODE */
extern void print_operand (FILE *, rtx, int); extern void print_operand (FILE *, rtx, int);
......
...@@ -48,6 +48,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -48,6 +48,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "target.h" #include "target.h"
#include "target-def.h" #include "target-def.h"
#include "langhooks.h" #include "langhooks.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
...@@ -211,6 +213,7 @@ static void xtensa_select_rtx_section (enum machine_mode, rtx, ...@@ -211,6 +213,7 @@ static void xtensa_select_rtx_section (enum machine_mode, rtx,
static bool xtensa_rtx_costs (rtx, int, int, int *); static bool xtensa_rtx_costs (rtx, int, int, int *);
static tree xtensa_build_builtin_va_list (void); static tree xtensa_build_builtin_va_list (void);
static bool xtensa_return_in_memory (tree, tree); static bool xtensa_return_in_memory (tree, tree);
static tree xtensa_gimplify_va_arg_expr (tree, tree, tree *, tree *);
static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
REG_ALLOC_ORDER; REG_ALLOC_ORDER;
...@@ -255,6 +258,8 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = ...@@ -255,6 +258,8 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
#undef TARGET_EXPAND_BUILTIN_SAVEREGS #undef TARGET_EXPAND_BUILTIN_SAVEREGS
#define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs #define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs
#undef TARGET_GIMPLIFY_VA_ARG_EXPR
#define TARGET_GIMPLIFY_VA_ARG_EXPR xtensa_gimplify_va_arg_expr
#undef TARGET_RETURN_IN_MSB #undef TARGET_RETURN_IN_MSB
#define TARGET_RETURN_IN_MSB xtensa_return_in_msb #define TARGET_RETURN_IN_MSB xtensa_return_in_msb
...@@ -2461,33 +2466,30 @@ xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) ...@@ -2461,33 +2466,30 @@ xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
/* Implement `va_arg'. */ /* Implement `va_arg'. */
rtx static tree
xtensa_va_arg (tree valist, tree type) xtensa_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
tree *post_p ATTRIBUTE_UNUSED)
{ {
tree f_stk, stk; tree f_stk, stk;
tree f_reg, reg; tree f_reg, reg;
tree f_ndx, ndx; tree f_ndx, ndx;
tree tmp, addr_tree, type_size; tree type_size, array, orig_ndx, addr, size, va_size, t;
rtx array, orig_ndx, r, addr, size, va_size; tree lab_false, lab_over, lab_false2;
rtx lab_false, lab_over, lab_false2;
/* Handle complex values as separate real and imaginary parts. */ /* Handle complex values as separate real and imaginary parts. */
if (TREE_CODE (type) == COMPLEX_TYPE) if (TREE_CODE (type) == COMPLEX_TYPE)
{ {
rtx real_part, imag_part, concat_val, local_copy; tree real_part, imag_part;
real_part = xtensa_va_arg (valist, TREE_TYPE (type)); real_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
imag_part = xtensa_va_arg (valist, TREE_TYPE (type)); pre_p, NULL);
real_part = get_initialized_tmp_var (real_part, pre_p, NULL);
/* Make a copy of the value in case the parts are not contiguous. */ imag_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
real_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), real_part); pre_p, NULL);
imag_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), imag_part); imag_part = get_initialized_tmp_var (imag_part, pre_p, NULL);
concat_val = gen_rtx_CONCAT (TYPE_MODE (type), real_part, imag_part);
local_copy = assign_temp (type, 0, 1, 0); return build (COMPLEX_EXPR, type, real_part, imag_part);
emit_move_insn (local_copy, concat_val);
return XEXP (local_copy, 0);
} }
f_stk = TYPE_FIELDS (va_list_type_node); f_stk = TYPE_FIELDS (va_list_type_node);
...@@ -2498,55 +2500,41 @@ xtensa_va_arg (tree valist, tree type) ...@@ -2498,55 +2500,41 @@ xtensa_va_arg (tree valist, tree type)
reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE); reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE);
ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE); ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE);
type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type)); type_size = size_in_bytes (type);
va_size = round_up (type_size, UNITS_PER_WORD);
va_size = gen_reg_rtx (SImode); gimplify_expr (&va_size, pre_p, NULL, is_gimple_val, fb_rvalue);
tmp = fold (build (MULT_EXPR, sizetype,
fold (build (TRUNC_DIV_EXPR, sizetype,
fold (build (PLUS_EXPR, sizetype,
type_size,
size_int (UNITS_PER_WORD - 1))),
size_int (UNITS_PER_WORD))),
size_int (UNITS_PER_WORD)));
r = expand_expr (tmp, va_size, SImode, EXPAND_NORMAL);
if (r != va_size)
emit_move_insn (va_size, r);
/* First align __va_ndx if necessary for this arg: /* First align __va_ndx if necessary for this arg:
orig_ndx = (AP).__va_ndx;
if (__alignof__ (TYPE) > 4 ) if (__alignof__ (TYPE) > 4 )
(AP).__va_ndx = (((AP).__va_ndx + __alignof__ (TYPE) - 1) orig_ndx = ((orig_ndx + __alignof__ (TYPE) - 1)
& -__alignof__ (TYPE)); */ & -__alignof__ (TYPE)); */
orig_ndx = get_initialized_tmp_var (ndx, pre_p, NULL);
if (TYPE_ALIGN (type) > BITS_PER_WORD) if (TYPE_ALIGN (type) > BITS_PER_WORD)
{ {
int align = TYPE_ALIGN (type) / BITS_PER_UNIT; int align = TYPE_ALIGN (type) / BITS_PER_UNIT;
tmp = build (PLUS_EXPR, integer_type_node, ndx,
build_int_2 (align - 1, 0)); t = build (PLUS_EXPR, integer_type_node, orig_ndx,
tmp = build (BIT_AND_EXPR, integer_type_node, tmp, build_int_2 (align - 1, 0));
build_int_2 (-align, -1)); t = build (BIT_AND_EXPR, integer_type_node, t,
tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp); build_int_2 (-align, -1));
TREE_SIDE_EFFECTS (tmp) = 1; t = build (MODIFY_EXPR, integer_type_node, orig_ndx, t);
expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL); gimplify_and_add (t, pre_p);
} }
/* Increment __va_ndx to point past the argument: /* Increment __va_ndx to point past the argument:
orig_ndx = (AP).__va_ndx; (AP).__va_ndx = orig_ndx + __va_size (TYPE); */
(AP).__va_ndx += __va_size (TYPE); */
orig_ndx = gen_reg_rtx (SImode);
r = expand_expr (ndx, orig_ndx, SImode, EXPAND_NORMAL);
if (r != orig_ndx)
emit_move_insn (orig_ndx, r);
tmp = build (PLUS_EXPR, integer_type_node, ndx, t = fold_convert (integer_type_node, va_size);
make_tree (intSI_type_node, va_size)); t = build (PLUS_EXPR, integer_type_node, orig_ndx, t);
tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp); t = build (MODIFY_EXPR, integer_type_node, ndx, t);
TREE_SIDE_EFFECTS (tmp) = 1; gimplify_and_add (t, pre_p);
expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
/* Check if the argument is in registers: /* Check if the argument is in registers:
...@@ -2555,29 +2543,32 @@ xtensa_va_arg (tree valist, tree type) ...@@ -2555,29 +2543,32 @@ xtensa_va_arg (tree valist, tree type)
&& !MUST_PASS_IN_STACK (type)) && !MUST_PASS_IN_STACK (type))
__array = (AP).__va_reg; */ __array = (AP).__va_reg; */
array = gen_reg_rtx (Pmode); array = create_tmp_var (ptr_type_node, NULL);
lab_over = NULL_RTX; lab_over = NULL;
if (!MUST_PASS_IN_STACK (VOIDmode, type)) if (!MUST_PASS_IN_STACK (VOIDmode, type))
{ {
lab_false = gen_label_rtx (); lab_false = create_artificial_label ();
lab_over = gen_label_rtx (); lab_over = create_artificial_label ();
emit_cmp_and_jump_insns (expand_expr (ndx, NULL_RTX, SImode, t = build_int_2 (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, 0);
EXPAND_NORMAL), t = build (GT_EXPR, boolean_type_node, ndx, t);
GEN_INT (MAX_ARGS_IN_REGISTERS t = build (COND_EXPR, void_type_node, t,
* UNITS_PER_WORD), build (GOTO_EXPR, void_type_node, lab_false),
GT, const1_rtx, SImode, 0, lab_false); NULL);
gimplify_and_add (t, pre_p);
r = expand_expr (reg, array, Pmode, EXPAND_NORMAL);
if (r != array) t = build (MODIFY_EXPR, void_type_node, array, reg);
emit_move_insn (array, r); gimplify_and_add (t, pre_p);
emit_jump_insn (gen_jump (lab_over)); t = build (GOTO_EXPR, void_type_node, lab_over);
emit_barrier (); gimplify_and_add (t, pre_p);
emit_label (lab_false);
t = build (LABEL_EXPR, void_type_node, lab_false);
gimplify_and_add (t, pre_p);
} }
/* ...otherwise, the argument is on the stack (never split between /* ...otherwise, the argument is on the stack (never split between
registers and the stack -- change __va_ndx if necessary): registers and the stack -- change __va_ndx if necessary):
...@@ -2588,25 +2579,31 @@ xtensa_va_arg (tree valist, tree type) ...@@ -2588,25 +2579,31 @@ xtensa_va_arg (tree valist, tree type)
__array = (AP).__va_stk; __array = (AP).__va_stk;
} */ } */
lab_false2 = gen_label_rtx (); lab_false2 = create_artificial_label ();
emit_cmp_and_jump_insns (orig_ndx,
GEN_INT (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD),
GT, const1_rtx, SImode, 0, lab_false2);
tmp = build (PLUS_EXPR, sizetype, make_tree (intSI_type_node, va_size), t = build_int_2 (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, 0);
build_int_2 (32, 0)); t = build (GT_EXPR, boolean_type_node, orig_ndx, t);
tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp); t = build (COND_EXPR, void_type_node, t,
TREE_SIDE_EFFECTS (tmp) = 1; build (GOTO_EXPR, void_type_node, lab_false2),
expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL); NULL);
gimplify_and_add (t, pre_p);
emit_label (lab_false2); t = size_binop (PLUS_EXPR, va_size, size_int (32));
t = fold_convert (integer_type_node, t);
t = build (MODIFY_EXPR, integer_type_node, ndx, t);
gimplify_and_add (t, pre_p);
r = expand_expr (stk, array, Pmode, EXPAND_NORMAL); t = build (LABEL_EXPR, void_type_node, lab_false2);
if (r != array) gimplify_and_add (t, pre_p);
emit_move_insn (array, r);
if (lab_over != NULL_RTX) t = build (MODIFY_EXPR, void_type_node, array, stk);
emit_label (lab_over); gimplify_and_add (t, pre_p);
if (lab_over)
{
t = build (LABEL_EXPR, void_type_node, lab_over);
gimplify_and_add (t, pre_p);
}
/* Given the base array pointer (__array) and index to the subsequent /* Given the base array pointer (__array) and index to the subsequent
...@@ -2619,33 +2616,24 @@ xtensa_va_arg (tree valist, tree type) ...@@ -2619,33 +2616,24 @@ xtensa_va_arg (tree valist, tree type)
The results are endian-dependent because values smaller than one word The results are endian-dependent because values smaller than one word
are aligned differently. */ are aligned differently. */
size = gen_reg_rtx (SImode);
emit_move_insn (size, va_size);
if (BYTES_BIG_ENDIAN) if (BYTES_BIG_ENDIAN)
{ {
rtx lab_use_va_size = gen_label_rtx (); t = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
t = fold (build (GE_EXPR, boolean_type_node, type_size, t));
emit_cmp_and_jump_insns (expand_expr (type_size, NULL_RTX, SImode, t = fold (build (COND_EXPR, sizetype, t, type_size, va_size));
EXPAND_NORMAL), size = t;
GEN_INT (PARM_BOUNDARY / BITS_PER_UNIT),
GE, const1_rtx, SImode, 0, lab_use_va_size);
r = expand_expr (type_size, size, SImode, EXPAND_NORMAL);
if (r != size)
emit_move_insn (size, r);
emit_label (lab_use_va_size);
} }
else
size = va_size;
t = fold_convert (ptr_type_node, ndx);
addr = build (PLUS_EXPR, ptr_type_node, array, t);
t = fold_convert (ptr_type_node, size);
addr = build (MINUS_EXPR, ptr_type_node, addr, t);
addr_tree = build (PLUS_EXPR, ptr_type_node, addr = fold_convert (build_pointer_type (type), addr);
make_tree (ptr_type_node, array), return build_fold_indirect_ref (addr);
ndx);
addr_tree = build (MINUS_EXPR, ptr_type_node, addr_tree,
make_tree (intSI_type_node, size));
addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
addr = copy_to_reg (addr);
return addr;
} }
......
...@@ -901,10 +901,6 @@ typedef struct xtensa_args ...@@ -901,10 +901,6 @@ typedef struct xtensa_args
#define EXPAND_BUILTIN_VA_START(valist, nextarg) \ #define EXPAND_BUILTIN_VA_START(valist, nextarg) \
xtensa_va_start (valist, nextarg) xtensa_va_start (valist, nextarg)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
xtensa_va_arg (valist, type)
/* If defined, a C expression that produces the machine-specific code /* If defined, a C expression that produces the machine-specific code
to setup the stack so that arbitrary frames can be accessed. to setup the stack so that arbitrary frames can be accessed.
......
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