* Re: gimple va_arg for xtensa
2004-07-09 10:49 gimple va_arg for xtensa Richard Henderson
@ 2004-07-09 12:08 ` Richard Henderson
2004-07-14 7:05 ` Bob Wilson
0 siblings, 1 reply; 3+ messages in thread
From: Richard Henderson @ 2004-07-09 12:08 UTC (permalink / raw)
To: gcc-patches
On Fri, Jul 09, 2004 at 03:13:46AM -0700, Richard Henderson wrote:
> * 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.
Grr, right patch file this time.
r~
Index: config/xtensa/xtensa-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa-protos.h,v
retrieving revision 1.16
diff -u -p -c -r1.16 xtensa-protos.h
*** config/xtensa/xtensa-protos.h 10 Feb 2004 01:35:52 -0000 1.16
--- config/xtensa/xtensa-protos.h 9 Jul 2004 09:54:10 -0000
*************** extern char *xtensa_emit_call (int, rtx
*** 77,83 ****
#ifdef TREE_CODE
extern void init_cumulative_args (CUMULATIVE_ARGS *, int);
extern void xtensa_va_start (tree, rtx);
- extern rtx xtensa_va_arg (tree, tree);
#endif /* TREE_CODE */
extern void print_operand (FILE *, rtx, int);
--- 77,82 ----
Index: config/xtensa/xtensa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa.c,v
retrieving revision 1.60
diff -u -p -c -r1.60 xtensa.c
*** config/xtensa/xtensa.c 7 Jul 2004 19:24:54 -0000 1.60
--- config/xtensa/xtensa.c 9 Jul 2004 09:54:11 -0000
*************** Software Foundation, 59 Temple Place - S
*** 48,53 ****
--- 48,55 ----
#include "target.h"
#include "target-def.h"
#include "langhooks.h"
+ #include "tree-gimple.h"
+
/* Enumeration for all of the relational tests, so that we can build
arrays indexed by the test type, and not worry about the order
*************** static void xtensa_select_rtx_section (e
*** 211,216 ****
--- 213,219 ----
static bool xtensa_rtx_costs (rtx, int, int, int *);
static tree xtensa_build_builtin_va_list (void);
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] =
REG_ALLOC_ORDER;
*************** static const int reg_nonleaf_alloc_order
*** 255,260 ****
--- 258,265 ----
#undef TARGET_EXPAND_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
#define TARGET_RETURN_IN_MSB xtensa_return_in_msb
*************** xtensa_va_start (tree valist, rtx nextar
*** 2461,2493 ****
/* Implement `va_arg'. */
! rtx
! xtensa_va_arg (tree valist, tree type)
{
tree f_stk, stk;
tree f_reg, reg;
tree f_ndx, ndx;
! tree tmp, addr_tree, type_size;
! rtx array, orig_ndx, r, addr, size, va_size;
! rtx lab_false, lab_over, lab_false2;
/* Handle complex values as separate real and imaginary parts. */
if (TREE_CODE (type) == COMPLEX_TYPE)
{
! rtx real_part, imag_part, concat_val, local_copy;
! real_part = xtensa_va_arg (valist, TREE_TYPE (type));
! imag_part = xtensa_va_arg (valist, TREE_TYPE (type));
! /* Make a copy of the value in case the parts are not contiguous. */
! real_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), real_part);
! imag_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), imag_part);
! concat_val = gen_rtx_CONCAT (TYPE_MODE (type), real_part, imag_part);
! local_copy = assign_temp (type, 0, 1, 0);
! emit_move_insn (local_copy, concat_val);
!
! return XEXP (local_copy, 0);
}
f_stk = TYPE_FIELDS (va_list_type_node);
--- 2466,2495 ----
/* Implement `va_arg'. */
! static tree
! xtensa_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
! tree *post_p ATTRIBUTE_UNUSED)
{
tree f_stk, stk;
tree f_reg, reg;
tree f_ndx, ndx;
! tree type_size, array, orig_ndx, addr, size, va_size, t;
! tree lab_false, lab_over, lab_false2;
/* Handle complex values as separate real and imaginary parts. */
if (TREE_CODE (type) == COMPLEX_TYPE)
{
! tree real_part, imag_part;
! real_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
! pre_p, NULL);
! real_part = get_initialized_tmp_var (real_part, pre_p, NULL);
! imag_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
! pre_p, NULL);
! imag_part = get_initialized_tmp_var (imag_part, pre_p, NULL);
! return build (COMPLEX_EXPR, type, real_part, imag_part);
}
f_stk = TYPE_FIELDS (va_list_type_node);
*************** xtensa_va_arg (tree valist, tree type)
*** 2498,2552 ****
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);
! 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 if necessary for this arg:
if (__alignof__ (TYPE) > 4 )
! (AP).__va_ndx = (((AP).__va_ndx + __alignof__ (TYPE) - 1)
& -__alignof__ (TYPE)); */
if (TYPE_ALIGN (type) > BITS_PER_WORD)
{
int align = TYPE_ALIGN (type) / BITS_PER_UNIT;
! tmp = build (PLUS_EXPR, integer_type_node, ndx,
! build_int_2 (align - 1, 0));
! tmp = build (BIT_AND_EXPR, integer_type_node, tmp,
! build_int_2 (-align, -1));
! tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp);
! TREE_SIDE_EFFECTS (tmp) = 1;
! expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
/* Increment __va_ndx to point past the argument:
! orig_ndx = (AP).__va_ndx;
! (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,
! make_tree (intSI_type_node, va_size));
! tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp);
! TREE_SIDE_EFFECTS (tmp) = 1;
! expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
/* Check if the argument is in registers:
--- 2500,2540 ----
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);
! type_size = size_in_bytes (type);
! va_size = round_up (type_size, UNITS_PER_WORD);
! gimplify_expr (&va_size, pre_p, NULL, is_gimple_val, fb_rvalue);
/* First align __va_ndx if necessary for this arg:
+ orig_ndx = (AP).__va_ndx;
if (__alignof__ (TYPE) > 4 )
! orig_ndx = ((orig_ndx + __alignof__ (TYPE) - 1)
& -__alignof__ (TYPE)); */
+ orig_ndx = get_initialized_tmp_var (ndx, pre_p, NULL);
+
if (TYPE_ALIGN (type) > BITS_PER_WORD)
{
int align = TYPE_ALIGN (type) / BITS_PER_UNIT;
!
! t = build (PLUS_EXPR, integer_type_node, orig_ndx,
! build_int_2 (align - 1, 0));
! t = build (BIT_AND_EXPR, integer_type_node, t,
! build_int_2 (-align, -1));
! t = build (MODIFY_EXPR, integer_type_node, orig_ndx, t);
! gimplify_and_add (t, pre_p);
}
/* Increment __va_ndx to point past the argument:
! (AP).__va_ndx = orig_ndx + __va_size (TYPE); */
! t = fold_convert (integer_type_node, va_size);
! t = build (PLUS_EXPR, integer_type_node, orig_ndx, t);
! t = build (MODIFY_EXPR, integer_type_node, ndx, t);
! gimplify_and_add (t, pre_p);
/* Check if the argument is in registers:
*************** xtensa_va_arg (tree valist, tree type)
*** 2555,2583 ****
&& !MUST_PASS_IN_STACK (type))
__array = (AP).__va_reg; */
! array = gen_reg_rtx (Pmode);
! lab_over = NULL_RTX;
if (!MUST_PASS_IN_STACK (VOIDmode, type))
{
! lab_false = gen_label_rtx ();
! lab_over = gen_label_rtx ();
! emit_cmp_and_jump_insns (expand_expr (ndx, NULL_RTX, SImode,
! EXPAND_NORMAL),
! GEN_INT (MAX_ARGS_IN_REGISTERS
! * UNITS_PER_WORD),
! GT, const1_rtx, SImode, 0, lab_false);
!
! r = expand_expr (reg, array, Pmode, EXPAND_NORMAL);
! if (r != array)
! emit_move_insn (array, r);
!
! emit_jump_insn (gen_jump (lab_over));
! emit_barrier ();
! emit_label (lab_false);
}
/* ...otherwise, the argument is on the stack (never split between
registers and the stack -- change __va_ndx if necessary):
--- 2543,2574 ----
&& !MUST_PASS_IN_STACK (type))
__array = (AP).__va_reg; */
! array = create_tmp_var (ptr_type_node, NULL);
! lab_over = NULL;
if (!MUST_PASS_IN_STACK (VOIDmode, type))
{
! lab_false = create_artificial_label ();
! lab_over = create_artificial_label ();
!
! t = build_int_2 (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, 0);
! t = build (GT_EXPR, boolean_type_node, ndx, t);
! t = build (COND_EXPR, void_type_node, t,
! build (GOTO_EXPR, void_type_node, lab_false),
! NULL);
! gimplify_and_add (t, pre_p);
! t = build (MODIFY_EXPR, void_type_node, array, reg);
! gimplify_and_add (t, pre_p);
!
! t = build (GOTO_EXPR, void_type_node, lab_over);
! gimplify_and_add (t, pre_p);
!
! 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
registers and the stack -- change __va_ndx if necessary):
*************** xtensa_va_arg (tree valist, tree type)
*** 2588,2612 ****
__array = (AP).__va_stk;
} */
! lab_false2 = gen_label_rtx ();
! 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),
! build_int_2 (32, 0));
! tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp);
! TREE_SIDE_EFFECTS (tmp) = 1;
! expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
!
! emit_label (lab_false2);
!
! r = expand_expr (stk, array, Pmode, EXPAND_NORMAL);
! if (r != array)
! emit_move_insn (array, r);
! if (lab_over != NULL_RTX)
! emit_label (lab_over);
/* Given the base array pointer (__array) and index to the subsequent
--- 2579,2609 ----
__array = (AP).__va_stk;
} */
! lab_false2 = create_artificial_label ();
!
! t = build_int_2 (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, 0);
! t = build (GT_EXPR, boolean_type_node, orig_ndx, t);
! t = build (COND_EXPR, void_type_node, t,
! build (GOTO_EXPR, void_type_node, lab_false2),
! NULL);
! gimplify_and_add (t, pre_p);
!
! 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);
!
! t = build (LABEL_EXPR, void_type_node, lab_false2);
! gimplify_and_add (t, pre_p);
!
! t = build (MODIFY_EXPR, void_type_node, array, stk);
! 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
*************** xtensa_va_arg (tree valist, tree type)
*** 2619,2651 ****
The results are endian-dependent because values smaller than one word
are aligned differently. */
- 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,
! make_tree (ptr_type_node, array),
! 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;
}
--- 2616,2639 ----
The results are endian-dependent because values smaller than one word
are aligned differently. */
if (BYTES_BIG_ENDIAN)
{
! t = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
! t = fold (build (GE_EXPR, boolean_type_node, type_size, t));
! t = fold (build (COND_EXPR, sizetype, t, type_size, va_size));
! size = t;
! }
! 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 = fold_convert (build_pointer_type (type), addr);
! return build_fold_indirect_ref (addr);
}
Index: config/xtensa/xtensa.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa.h,v
retrieving revision 1.56
diff -u -p -c -r1.56 xtensa.h
*** config/xtensa/xtensa.h 21 May 2004 01:03:20 -0000 1.56
--- config/xtensa/xtensa.h 9 Jul 2004 09:54:11 -0000
*************** typedef struct xtensa_args
*** 901,910 ****
#define EXPAND_BUILTIN_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
to setup the stack so that arbitrary frames can be accessed.
--- 901,906 ----
^ permalink raw reply [flat|nested] 3+ messages in thread