Commit 8be56275 by Bob Wilson Committed by Bob Wilson

* config/xtensa/xtensa.c (xtensa_va_arg): Handle variable-sized types.

From-SVN: r51400
parent c8c21a8c
2002-03-26 Bob Wilson <bob.wilson@acm.org>
* config/xtensa/xtensa.c (xtensa_va_arg): Handle variable-sized types.
2002-03-26 Richard Earnshaw <rearnsha@arm.com> 2002-03-26 Richard Earnshaw <rearnsha@arm.com>
PR target/5621 PR target/5621
......
...@@ -2431,14 +2431,10 @@ xtensa_va_arg (valist, type) ...@@ -2431,14 +2431,10 @@ xtensa_va_arg (valist, type)
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; tree tmp, addr_tree, type_size;
rtx array, orig_ndx, r, addr; rtx array, orig_ndx, r, addr, size, va_size;
HOST_WIDE_INT size, va_size;
rtx lab_false, lab_over, lab_false2; rtx lab_false, lab_over, lab_false2;
size = int_size_in_bytes (type);
va_size = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
f_stk = TYPE_FIELDS (va_list_type_node); f_stk = TYPE_FIELDS (va_list_type_node);
f_reg = TREE_CHAIN (f_stk); f_reg = TREE_CHAIN (f_stk);
f_ndx = TREE_CHAIN (f_reg); f_ndx = TREE_CHAIN (f_reg);
...@@ -2447,6 +2443,20 @@ xtensa_va_arg (valist, type) ...@@ -2447,6 +2443,20 @@ xtensa_va_arg (valist, type)
reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg); reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg);
ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx); ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx);
type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type));
va_size = gen_reg_rtx (SImode);
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 to a double word boundary if necessary for this arg: /* First align __va_ndx to a double word boundary if necessary for this arg:
...@@ -2477,7 +2487,8 @@ xtensa_va_arg (valist, type) ...@@ -2477,7 +2487,8 @@ xtensa_va_arg (valist, type)
if (r != orig_ndx) if (r != orig_ndx)
emit_move_insn (orig_ndx, r); emit_move_insn (orig_ndx, r);
tmp = build (PLUS_EXPR, integer_type_node, ndx, build_int_2 (va_size, 0)); tmp = build (PLUS_EXPR, integer_type_node, ndx,
make_tree (intSI_type_node, va_size));
tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp); tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp);
TREE_SIDE_EFFECTS (tmp) = 1; TREE_SIDE_EFFECTS (tmp) = 1;
expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
...@@ -2522,7 +2533,8 @@ xtensa_va_arg (valist, type) ...@@ -2522,7 +2533,8 @@ xtensa_va_arg (valist, type)
GEN_INT (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD), GEN_INT (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD),
GE, const1_rtx, SImode, 0, lab_false2); GE, const1_rtx, SImode, 0, lab_false2);
tmp = build_int_2 ((MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD) + va_size, 0); tmp = build (PLUS_EXPR, sizetype, make_tree (intSI_type_node, va_size),
build_int_2 (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, 0));
tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp); tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp);
TREE_SIDE_EFFECTS (tmp) = 1; TREE_SIDE_EFFECTS (tmp) = 1;
expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
...@@ -2533,31 +2545,44 @@ xtensa_va_arg (valist, type) ...@@ -2533,31 +2545,44 @@ xtensa_va_arg (valist, type)
if (r != array) if (r != array)
emit_move_insn (array, r); emit_move_insn (array, r);
emit_label (lab_over);
/* Given the base array pointer (__array) and index to the subsequent /* Given the base array pointer (__array) and index to the subsequent
argument (__va_ndx), find the address: argument (__va_ndx), find the address:
Big-endian: __array + (AP).__va_ndx - (BYTES_BIG_ENDIAN && sizeof (TYPE) < 4
__array + (AP).__va_ndx - sizeof (TYPE) ? sizeof (TYPE)
: __va_size (TYPE))
Little-endian:
__array + (AP).__va_ndx - __va_size (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.
*/ */
emit_label (lab_over); size = gen_reg_rtx (SImode);
emit_move_insn (size, va_size);
if (BYTES_BIG_ENDIAN)
{
rtx lab_use_va_size = gen_label_rtx ();
emit_cmp_and_jump_insns (expand_expr (type_size, NULL_RTX, SImode,
EXPAND_NORMAL),
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);
}
addr_tree = build (PLUS_EXPR, ptr_type_node, addr_tree = build (PLUS_EXPR, ptr_type_node,
make_tree (ptr_type_node, array), make_tree (ptr_type_node, array),
ndx); ndx);
addr_tree = build (PLUS_EXPR, ptr_type_node, addr_tree = build (MINUS_EXPR, ptr_type_node, addr_tree,
addr_tree, make_tree (intSI_type_node, size));
build_int_2 (BYTES_BIG_ENDIAN
&& size < (PARM_BOUNDARY / BITS_PER_UNIT)
? -size
: -va_size, -1));
addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL); addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
addr = copy_to_reg (addr); addr = copy_to_reg (addr);
return addr; return addr;
......
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