#include "target.h"
#include "target-def.h"
#include "langhooks.h"
+#include "tree-gimple.h"
static rtx find_addr_reg (rtx);
/* Update the VALIST structure as necessary for an
argument of the given TYPE, and return the argument. */
-rtx
-i860_va_arg (tree valist, tree type)
+static tree
+i860_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
{
tree f_gpr, f_fpr, f_mem, f_sav;
- tree gpr, fpr, mem, sav, reg, t, u;
- int size, n_reg, sav_ofs, sav_scale, max_reg;
- rtx lab_false, lab_over, addr_rtx, r;
+ tree gpr, fpr, mem, sav;
+ tree size, t, u, addr, type_ptr;
+ tree reg, n_reg, sav_ofs, lim_reg;
+ HOST_WIDE_INT isize;
#ifdef I860_SVR4_VA_LIST
f_gpr = TYPE_FIELDS (va_list_type_node);
mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem, NULL_TREE);
sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
- size = int_size_in_bytes (type);
+ size = size_in_bytes (type);
+ type_ptr = build_pointer_type (type);
if (AGGREGATE_TYPE_P (type))
{
align = BITS_PER_WORD;
align /= BITS_PER_UNIT;
- addr_rtx = gen_reg_rtx (Pmode);
- t = build (PLUS_EXPR, ptr_type_node, mem, build_int_2 (align - 1, 0));
- t = build (BIT_AND_EXPR, ptr_type_node, t, build_int_2 (-align, -1));
- r = expand_expr (t, addr_rtx, VOIDmode /* Pmode */, EXPAND_NORMAL);
- if (r != addr_rtx)
- emit_move_insn (addr_rtx, r);
+ u = fold_convert (ptr_type_node, size_int (align - 1));
+ t = build (PLUS_EXPR, ptr_type_node, mem, u);
+ u = fold (build (BIT_NOT_EXPR, ptr_type_node, u));
+ t = build (BIT_AND_EXPR, ptr_type_node, t, u);
+ addr = get_initialized_tmp_var (t, pre_p, post_p);
- t = fold (build (PLUS_EXPR, ptr_type_node,
- make_tree (ptr_type_node, addr_rtx),
- build_int_2 (size, 0)));
+ u = fold_convert (ptr_type_node, size);
+ t = build (PLUS_EXPR, ptr_type_node, addr, size);
t = build (MODIFY_EXPR, ptr_type_node, mem, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- return addr_rtx;
- }
- else if (FLOAT_TYPE_P (type) || (INTEGRAL_TYPE_P (type) && size == 8))
- {
- /* Floats and long longs are passed in the floating-point registers. */
- reg = fpr;
- n_reg = size / UNITS_PER_WORD;
- sav_ofs = FREG_OFFSET;
- sav_scale = UNITS_PER_WORD;
- max_reg = NUM_PARM_FREGS;
+ gimplify_and_add (t, pre_p);
}
else
{
- /* Everything else is passed in general registers. */
- reg = gpr;
- n_reg = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
- sav_ofs = IREG_OFFSET;
- sav_scale = UNITS_PER_WORD;
- max_reg = NUM_PARM_IREGS;
- if (n_reg > 1)
- abort ();
- }
-
- /* The value was passed in a register, so read it from the register
- save area initialized by __builtin_saveregs. */
-
- lab_false = gen_label_rtx ();
- lab_over = gen_label_rtx ();
- addr_rtx = gen_reg_rtx (Pmode);
-
- emit_cmp_and_jump_insns (expand_expr (reg, NULL_RTX, Pmode, EXPAND_NORMAL),
- GEN_INT (max_reg - n_reg),
- GT, const1_rtx, Pmode, 0, lab_false);
-
- if (sav_ofs)
- t = build (PLUS_EXPR, ptr_type_node, sav, build_int_2 (sav_ofs, 0));
- else
- t = sav;
+ isize = tree_low_cst (size, 0);
- u = build (MULT_EXPR, long_integer_type_node,
- reg, build_int_2 (sav_scale, 0));
- TREE_SIDE_EFFECTS (u) = 1;
-
- t = build (PLUS_EXPR, ptr_type_node, t, u);
- TREE_SIDE_EFFECTS (t) = 1;
+ if (FLOAT_TYPE_P (type) || (INTEGRAL_TYPE_P (type) && isize == 8))
+ {
+ /* Floats and long longs are passed in the fp registers. */
+ reg = fpr;
+ n_reg = size_int (isize / UNITS_PER_WORD);
+ n_reg = fold_convert (unsigned_type_node, n_reg);
+ lim_reg = size_int (NUM_PARM_FREGS - (isize / UNITS_PER_WORD));
+ lim_reg = fold_convert (unsigned_type_node, lim_reg);
+ sav_ofs = size_int (FREG_OFFSET);
+ }
+ else
+ {
+ /* Everything else is passed in general registers. */
+ reg = gpr;
+ if ((isize + UNITS_PER_WORD - 1) / UNITS_PER_WORD > 1)
+ abort ();
+ n_reg = fold_convert (unsigned_type_node, integer_one_node);
+ lim_reg = size_int (NUM_PARM_IREGS - 1);
+ lim_reg = fold_convert (unsigned_type_node, lim_reg);
+ sav_ofs = size_int (IREG_OFFSET);
+ }
- r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
- if (r != addr_rtx)
- emit_move_insn (addr_rtx, r);
+ u = build (LE_EXPR, boolean_type_node, reg, lim_reg);
+ addr = build (COND_EXPR, ptr_type_node, u, NULL, NULL);
- emit_jump_insn (gen_jump (lab_over));
- emit_barrier ();
- emit_label (lab_false);
+ /* The value was passed in a register, so read it from the register
+ save area initialized by __builtin_saveregs. */
- /* The value was passed in memory, so read it from the overflow area. */
+ sav_ofs = fold_convert (ptr_type_node, sav_ofs);
+ sav_ofs = fold (build (PLUS_EXPR, ptr_type_node, sav, sav_ofs));
- t = save_expr (mem);
- r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
- if (r != addr_rtx)
- emit_move_insn (addr_rtx, r);
+ u = fold_convert (unsigned_type_node, size_int (UNITS_PER_WORD));
+ u = build (MULT_EXPR, unsigned_type_node, reg, u);
+ u = fold_convert (ptr_type_node, u);
+ u = build (PLUS_EXPR, ptr_type_node, sav_ofs, u);
+ COND_EXPR_THEN (addr) = u;
- t = build (PLUS_EXPR, TREE_TYPE (t), t, build_int_2 (size, 0));
- t = build (MODIFY_EXPR, TREE_TYPE (mem), mem, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ /* The value was passed in memory, so read it from the overflow area. */
- emit_label (lab_over);
+ t = fold_convert (ptr_type_node, size);
+ u = build (POSTINCREMENT_EXPR, ptr_type_node, mem, t);
+ COND_EXPR_ELSE (addr) = u;
- /* Increment either the ireg_used or freg_used field. */
+ /* Increment either the ireg_used or freg_used field. */
- u = build (PREINCREMENT_EXPR, TREE_TYPE (reg), reg, build_int_2 (n_reg, 0));
- TREE_SIDE_EFFECTS (u) = 1;
- expand_expr (u, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ t = build (PLUS_EXPR, unsigned_type_node, reg, n_reg);
+ t = build (MODIFY_EXPR, unsigned_type_node, reg, t);
+ gimplify_and_add (t, post_p);
+ }
- return addr_rtx;
+ addr = fold_convert (type_ptr, addr);
+ return build_fold_indirect_ref (addr);
}
/* Compute a (partial) cost for rtx X. Return true if the complete
#undef TARGET_BUILD_BUILTIN_VA_LIST
#define TARGET_BUILD_BUILTIN_VA_LIST i860_build_builtin_va_list
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR i860_gimplify_va_arg_expr
#undef TARGET_STRUCT_VALUE_RTX
#define TARGET_STRUCT_VALUE_RTX i860_struct_value_rtx