i386.h (EXPAND_BUILTIN_VA_ARG): Just abort.

* config/i386/i386.h (EXPAND_BUILTIN_VA_ARG): Just abort.
        * config/i386/i386.c (ix86_va_arg): Remove.
        * config/rs6000/rs6000.h (EXPAND_BUILTIN_VA_ARG): Just abort.
        * config/rs6000/rs6000.c (rs6000_va_arg): Remove.
        * config/alpha/alpha.h (EXPAND_BUILTIN_VA_ARG): Just abort.
        * config/alpha/alpha.c (alpha_va_arg): Remove.
        * config/sparc/sparc.h (EXPAND_BUILTIN_VA_ARG): Just abort.
        * config/sparc/sparc.c (sparc_va_arg): Remove.

        * tree-ssa-operands.c (get_stmt_operands): Use a V_MAY_DEF if the
        assignment might throw.
        * tree-eh.c (tree_could_throw_p): Support non-call exceptions in
        expressions.

From-SVN: r82992
This commit is contained in:
Jason Merrill 2004-06-11 14:41:47 -04:00 committed by Jason Merrill
parent 67fc0c0f59
commit 67c605a553
14 changed files with 37 additions and 738 deletions

View File

@ -1,3 +1,19 @@
2004-06-11 Jason Merrill <jason@redhat.com>
* config/i386/i386.h (EXPAND_BUILTIN_VA_ARG): Just abort.
* config/i386/i386.c (ix86_va_arg): Remove.
* config/rs6000/rs6000.h (EXPAND_BUILTIN_VA_ARG): Just abort.
* config/rs6000/rs6000.c (rs6000_va_arg): Remove.
* config/alpha/alpha.h (EXPAND_BUILTIN_VA_ARG): Just abort.
* config/alpha/alpha.c (alpha_va_arg): Remove.
* config/sparc/sparc.h (EXPAND_BUILTIN_VA_ARG): Just abort.
* config/sparc/sparc.c (sparc_va_arg): Remove.
* tree-ssa-operands.c (get_stmt_operands): Use a V_MAY_DEF if the
assignment might throw.
* tree-eh.c (tree_could_throw_p): Support non-call exceptions in
expressions.
2004-06-11 J"orn Rennecke <joern.rennecke@superh.com>
PR 15886:

View File

@ -6291,115 +6291,6 @@ alpha_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
}
}
rtx
alpha_va_arg (tree valist, tree type)
{
rtx addr;
tree t, type_size, rounded_size;
tree offset_field, base_field, addr_tree, addend;
tree wide_type, wide_ofs;
int indirect = 0;
if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
return std_expand_builtin_va_arg (valist, type);
if (type == error_mark_node
|| (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
|| TREE_OVERFLOW (type_size))
rounded_size = size_zero_node;
else
rounded_size = fold (build (MULT_EXPR, sizetype,
fold (build (TRUNC_DIV_EXPR, sizetype,
fold (build (PLUS_EXPR, sizetype,
type_size,
size_int (7))),
size_int (8))),
size_int (8)));
base_field = TYPE_FIELDS (TREE_TYPE (valist));
offset_field = TREE_CHAIN (base_field);
base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
valist, base_field);
offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
valist, offset_field);
/* If the type could not be passed in registers, skip the block
reserved for the registers. */
if (MUST_PASS_IN_STACK (TYPE_MODE (type), type))
{
t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field,
build (MAX_EXPR, TREE_TYPE (offset_field),
offset_field, build_int_2 (6*8, 0)));
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
wide_type = make_signed_type (64);
wide_ofs = save_expr (build1 (CONVERT_EXPR, wide_type, offset_field));
addend = wide_ofs;
if (TYPE_MODE (type) == TFmode || TYPE_MODE (type) == TCmode)
{
indirect = 1;
rounded_size = size_int (UNITS_PER_WORD);
}
else if (TREE_CODE (type) == COMPLEX_TYPE)
{
rtx real_part, imag_part, value, tmp;
real_part = alpha_va_arg (valist, TREE_TYPE (type));
imag_part = alpha_va_arg (valist, TREE_TYPE (type));
/* ??? Most irritatingly, we're not returning the value here,
but the address. Since real_part and imag_part are not
necessarily contiguous, we must copy to local storage. */
real_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), real_part);
imag_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), imag_part);
value = gen_rtx_CONCAT (TYPE_MODE (type), real_part, imag_part);
tmp = assign_temp (type, 0, 1, 0);
emit_move_insn (tmp, value);
return XEXP (tmp, 0);
}
else if (TREE_CODE (type) == REAL_TYPE)
{
tree fpaddend, cond;
fpaddend = fold (build (PLUS_EXPR, TREE_TYPE (addend),
addend, build_int_2 (-6*8, 0)));
cond = fold (build (LT_EXPR, integer_type_node,
wide_ofs, build_int_2 (6*8, 0)));
addend = fold (build (COND_EXPR, TREE_TYPE (addend), cond,
fpaddend, addend));
}
addr_tree = build (PLUS_EXPR, TREE_TYPE (base_field),
base_field, addend);
addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
addr = copy_to_reg (addr);
t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field,
build (PLUS_EXPR, TREE_TYPE (offset_field),
offset_field, rounded_size));
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
if (indirect)
{
addr = force_reg (Pmode, addr);
addr = gen_rtx_MEM (Pmode, addr);
}
return addr;
}
static tree
alpha_gimplify_va_arg_1 (tree type, tree base, tree offset,
tree *pre_p, tree *post_p)

View File

@ -1687,8 +1687,7 @@ do { \
alpha_va_start (valist, nextarg)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
alpha_va_arg (valist, type)
#define EXPAND_BUILTIN_VA_ARG(valist, type) (abort (), NULL_RTX)
/* Tell collect that the object format is ECOFF. */
#define OBJECT_FORMAT_COFF

View File

@ -3177,246 +3177,6 @@ ix86_va_start (tree valist, rtx nextarg)
}
/* Implement va_arg. */
rtx
ix86_va_arg (tree valist, tree type)
{
static const int intreg[6] = { 0, 1, 2, 3, 4, 5 };
tree f_gpr, f_fpr, f_ovf, f_sav;
tree gpr, fpr, ovf, sav, t;
int size, rsize;
rtx lab_false, lab_over = NULL_RTX;
rtx addr_rtx, r;
rtx container;
int indirect_p = 0;
/* Only 64bit target needs something special. */
if (!TARGET_64BIT)
{
return std_expand_builtin_va_arg (valist, type);
}
f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
f_fpr = TREE_CHAIN (f_gpr);
f_ovf = TREE_CHAIN (f_fpr);
f_sav = TREE_CHAIN (f_ovf);
valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
size = int_size_in_bytes (type);
if (size == -1)
{
/* Passed by reference. */
indirect_p = 1;
type = build_pointer_type (type);
size = int_size_in_bytes (type);
}
rsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
container = construct_container (TYPE_MODE (type), type, 0,
REGPARM_MAX, SSE_REGPARM_MAX, intreg, 0);
/*
* Pull the value out of the saved registers ...
*/
addr_rtx = gen_reg_rtx (Pmode);
if (container)
{
rtx int_addr_rtx, sse_addr_rtx;
int needed_intregs, needed_sseregs;
int need_temp;
lab_over = gen_label_rtx ();
lab_false = gen_label_rtx ();
examine_argument (TYPE_MODE (type), type, 0,
&needed_intregs, &needed_sseregs);
need_temp = ((needed_intregs && TYPE_ALIGN (type) > 64)
|| TYPE_ALIGN (type) > 128);
/* In case we are passing structure, verify that it is consecutive block
on the register save area. If not we need to do moves. */
if (!need_temp && !REG_P (container))
{
/* Verify that all registers are strictly consecutive */
if (SSE_REGNO_P (REGNO (XEXP (XVECEXP (container, 0, 0), 0))))
{
int i;
for (i = 0; i < XVECLEN (container, 0) && !need_temp; i++)
{
rtx slot = XVECEXP (container, 0, i);
if (REGNO (XEXP (slot, 0)) != FIRST_SSE_REG + (unsigned int) i
|| INTVAL (XEXP (slot, 1)) != i * 16)
need_temp = 1;
}
}
else
{
int i;
for (i = 0; i < XVECLEN (container, 0) && !need_temp; i++)
{
rtx slot = XVECEXP (container, 0, i);
if (REGNO (XEXP (slot, 0)) != (unsigned int) i
|| INTVAL (XEXP (slot, 1)) != i * 8)
need_temp = 1;
}
}
}
if (!need_temp)
{
int_addr_rtx = addr_rtx;
sse_addr_rtx = addr_rtx;
}
else
{
int_addr_rtx = gen_reg_rtx (Pmode);
sse_addr_rtx = gen_reg_rtx (Pmode);
}
/* First ensure that we fit completely in registers. */
if (needed_intregs)
{
emit_cmp_and_jump_insns (expand_expr
(gpr, NULL_RTX, SImode, EXPAND_NORMAL),
GEN_INT ((REGPARM_MAX - needed_intregs +
1) * 8), GE, const1_rtx, SImode,
1, lab_false);
}
if (needed_sseregs)
{
emit_cmp_and_jump_insns (expand_expr
(fpr, NULL_RTX, SImode, EXPAND_NORMAL),
GEN_INT ((SSE_REGPARM_MAX -
needed_sseregs + 1) * 16 +
REGPARM_MAX * 8), GE, const1_rtx,
SImode, 1, lab_false);
}
/* Compute index to start of area used for integer regs. */
if (needed_intregs)
{
t = build (PLUS_EXPR, ptr_type_node, sav, gpr);
r = expand_expr (t, int_addr_rtx, Pmode, EXPAND_NORMAL);
if (r != int_addr_rtx)
emit_move_insn (int_addr_rtx, r);
}
if (needed_sseregs)
{
t = build (PLUS_EXPR, ptr_type_node, sav, fpr);
r = expand_expr (t, sse_addr_rtx, Pmode, EXPAND_NORMAL);
if (r != sse_addr_rtx)
emit_move_insn (sse_addr_rtx, r);
}
if (need_temp)
{
int i;
rtx mem;
rtx x;
/* Never use the memory itself, as it has the alias set. */
x = XEXP (assign_temp (type, 0, 1, 0), 0);
mem = gen_rtx_MEM (BLKmode, x);
force_operand (x, addr_rtx);
set_mem_alias_set (mem, get_varargs_alias_set ());
set_mem_align (mem, BITS_PER_UNIT);
for (i = 0; i < XVECLEN (container, 0); i++)
{
rtx slot = XVECEXP (container, 0, i);
rtx reg = XEXP (slot, 0);
enum machine_mode mode = GET_MODE (reg);
rtx src_addr;
rtx src_mem;
int src_offset;
rtx dest_mem;
if (SSE_REGNO_P (REGNO (reg)))
{
src_addr = sse_addr_rtx;
src_offset = (REGNO (reg) - FIRST_SSE_REG) * 16;
}
else
{
src_addr = int_addr_rtx;
src_offset = REGNO (reg) * 8;
}
src_mem = gen_rtx_MEM (mode, src_addr);
set_mem_alias_set (src_mem, get_varargs_alias_set ());
src_mem = adjust_address (src_mem, mode, src_offset);
dest_mem = adjust_address (mem, mode, INTVAL (XEXP (slot, 1)));
emit_move_insn (dest_mem, src_mem);
}
}
if (needed_intregs)
{
t =
build (PLUS_EXPR, TREE_TYPE (gpr), gpr,
build_int_2 (needed_intregs * 8, 0));
t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
if (needed_sseregs)
{
t =
build (PLUS_EXPR, TREE_TYPE (fpr), fpr,
build_int_2 (needed_sseregs * 16, 0));
t = build (MODIFY_EXPR, TREE_TYPE (fpr), fpr, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
emit_jump_insn (gen_jump (lab_over));
emit_barrier ();
emit_label (lab_false);
}
/* ... otherwise out of the overflow area. */
/* Care for on-stack alignment if needed. */
if (FUNCTION_ARG_BOUNDARY (VOIDmode, type) <= 64)
t = ovf;
else
{
HOST_WIDE_INT align = FUNCTION_ARG_BOUNDARY (VOIDmode, type) / 8;
t = build (PLUS_EXPR, TREE_TYPE (ovf), ovf, build_int_2 (align - 1, 0));
t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
}
t = save_expr (t);
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx)
emit_move_insn (addr_rtx, r);
t =
build (PLUS_EXPR, TREE_TYPE (t), t,
build_int_2 (rsize * UNITS_PER_WORD, 0));
t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
if (container)
emit_label (lab_over);
if (indirect_p)
{
r = gen_rtx_MEM (Pmode, addr_rtx);
set_mem_alias_set (r, get_varargs_alias_set ());
emit_move_insn (addr_rtx, r);
}
return addr_rtx;
}
/* Lower VA_ARG_EXPR at gimplification time. */
tree
ix86_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)

View File

@ -1790,8 +1790,7 @@ typedef struct ix86_args {
ix86_va_start (VALIST, NEXTARG)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(VALIST, TYPE) \
ix86_va_arg ((VALIST), (TYPE))
#define EXPAND_BUILTIN_VA_ARG(VALIST, TYPE) (abort (), NULL_RTX)
#define TARGET_ASM_FILE_END ix86_file_end
#define NEED_INDICATE_EXEC_STACK 0

View File

@ -3958,41 +3958,6 @@ ia64_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
/* Implement va_arg. */
rtx
ia64_va_arg (tree valist, tree type)
{
tree t;
/* Variable sized types are passed by reference. */
if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
rtx addr = force_reg (ptr_mode,
std_expand_builtin_va_arg (valist, build_pointer_type (type)));
#ifdef POINTERS_EXTEND_UNSIGNED
addr = convert_memory_address (Pmode, addr);
#endif
return gen_rtx_MEM (ptr_mode, addr);
}
/* Aggregate arguments with alignment larger than 8 bytes start at
the next even boundary. Integer and floating point arguments
do so if they are larger than 8 bytes, whether or not they are
also aligned larger than 8 bytes. */
if ((TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == INTEGER_TYPE)
? int_size_in_bytes (type) > 8 : TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
{
t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
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 (valist), valist, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
return std_expand_builtin_va_arg (valist, type);
}
static tree
ia64_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
{

View File

@ -1403,8 +1403,7 @@ do { \
|| ((REGNO) >= FR_ARG_FIRST && (REGNO) < (FR_ARG_FIRST + MAX_ARGUMENT_SLOTS)))
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
ia64_va_arg (valist, type)
#define EXPAND_BUILTIN_VA_ARG(valist, type) (abort (), NULL_RTX)
/* How Scalar Function Values are Returned */

View File

@ -5069,229 +5069,6 @@ rs6000_va_start (tree valist, rtx nextarg)
/* Implement va_arg. */
rtx
rs6000_va_arg (tree valist, tree type)
{
tree f_gpr, f_fpr, f_res, f_ovf, f_sav;
tree gpr, fpr, ovf, sav, reg, t, u;
int indirect_p, size, rsize, n_reg, sav_ofs, sav_scale;
rtx lab_false, lab_over, addr_rtx, r;
int align;
if (DEFAULT_ABI != ABI_V4)
{
/* Variable sized types are passed by reference, as are AltiVec
vectors when 32-bit and not using the AltiVec ABI extension. */
if (int_size_in_bytes (type) < 0
|| (TARGET_32BIT
&& !TARGET_ALTIVEC_ABI
&& ALTIVEC_VECTOR_MODE (TYPE_MODE (type))))
{
u = build_pointer_type (type);
/* Args grow upward. */
t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist,
build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
TREE_SIDE_EFFECTS (t) = 1;
t = build1 (NOP_EXPR, build_pointer_type (u), t);
TREE_SIDE_EFFECTS (t) = 1;
t = build1 (INDIRECT_REF, u, t);
TREE_SIDE_EFFECTS (t) = 1;
return expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
}
if (targetm.calls.split_complex_arg
&& TREE_CODE (type) == COMPLEX_TYPE)
{
tree elem_type = TREE_TYPE (type);
enum machine_mode elem_mode = TYPE_MODE (elem_type);
int elem_size = GET_MODE_SIZE (elem_mode);
if (elem_size < UNITS_PER_WORD)
{
rtx real_part, imag_part, dest_real, rr;
real_part = rs6000_va_arg (valist, elem_type);
imag_part = rs6000_va_arg (valist, elem_type);
/* We're not returning the value here, but the address.
real_part and imag_part are not contiguous, and we know
there is space available to pack real_part next to
imag_part. float _Complex is not promoted to
double _Complex by the default promotion rules that
promote float to double. */
if (2 * elem_size > UNITS_PER_WORD)
abort ();
real_part = gen_rtx_MEM (elem_mode, real_part);
imag_part = gen_rtx_MEM (elem_mode, imag_part);
dest_real = adjust_address (imag_part, elem_mode, -elem_size);
rr = gen_reg_rtx (elem_mode);
emit_move_insn (rr, real_part);
emit_move_insn (dest_real, rr);
return XEXP (dest_real, 0);
}
}
return std_expand_builtin_va_arg (valist, type);
}
f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
f_fpr = TREE_CHAIN (f_gpr);
f_res = TREE_CHAIN (f_fpr);
f_ovf = TREE_CHAIN (f_res);
f_sav = TREE_CHAIN (f_ovf);
valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist);
gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr);
ovf = build (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf);
sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
size = int_size_in_bytes (type);
rsize = (size + 3) / 4;
align = 1;
if (AGGREGATE_TYPE_P (type)
|| TYPE_MODE (type) == TFmode
|| (!TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (TYPE_MODE (type))))
{
/* Aggregates, long doubles, and AltiVec vectors are passed by
reference. */
indirect_p = 1;
reg = gpr;
n_reg = 1;
sav_ofs = 0;
sav_scale = 4;
size = 4;
rsize = 1;
}
else if (TARGET_HARD_FLOAT && TARGET_FPRS
&& (TYPE_MODE (type) == SFmode || TYPE_MODE (type) == DFmode))
{
/* FP args go in FP registers, if present. */
indirect_p = 0;
reg = fpr;
n_reg = 1;
sav_ofs = 8*4;
sav_scale = 8;
if (TYPE_MODE (type) == DFmode)
align = 8;
}
else
{
/* Otherwise into GP registers. */
indirect_p = 0;
reg = gpr;
n_reg = rsize;
sav_ofs = 0;
sav_scale = 4;
if (n_reg == 2)
align = 8;
}
/* Pull the value out of the saved registers.... */
lab_over = NULL_RTX;
addr_rtx = gen_reg_rtx (Pmode);
/* AltiVec vectors never go in registers when -mabi=altivec. */
if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (TYPE_MODE (type)))
align = 16;
else
{
lab_false = gen_label_rtx ();
lab_over = gen_label_rtx ();
/* Long long and SPE vectors are aligned in the registers.
As are any other 2 gpr item such as complex int due to a
historical mistake. */
u = reg;
if (n_reg == 2)
{
u = build (BIT_AND_EXPR, TREE_TYPE (reg), reg,
build_int_2 (n_reg - 1, 0));
u = build (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, u);
TREE_SIDE_EFFECTS (u) = 1;
}
emit_cmp_and_jump_insns
(expand_expr (u, NULL_RTX, QImode, EXPAND_NORMAL),
GEN_INT (8 - n_reg + 1), GE, const1_rtx, QImode, 1,
lab_false);
t = sav;
if (sav_ofs)
t = build (PLUS_EXPR, ptr_type_node, sav, build_int_2 (sav_ofs, 0));
u = build (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg,
build_int_2 (n_reg, 0));
TREE_SIDE_EFFECTS (u) = 1;
u = build1 (CONVERT_EXPR, integer_type_node, u);
TREE_SIDE_EFFECTS (u) = 1;
u = build (MULT_EXPR, integer_type_node, u, 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;
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx)
emit_move_insn (addr_rtx, r);
emit_jump_insn (gen_jump (lab_over));
emit_barrier ();
emit_label (lab_false);
if (n_reg > 2)
{
/* Ensure that we don't find any more args in regs.
Alignment has taken care of the n_reg == 2 case. */
t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, build_int_2 (8, 0));
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
}
/* ... otherwise out of the overflow area. */
/* Care for on-stack alignment if needed. */
t = ovf;
if (align != 1)
{
t = build (PLUS_EXPR, TREE_TYPE (t), t, build_int_2 (align - 1, 0));
t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
}
t = save_expr (t);
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx)
emit_move_insn (addr_rtx, r);
t = build (PLUS_EXPR, TREE_TYPE (t), t, build_int_2 (size, 0));
t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
if (lab_over)
emit_label (lab_over);
if (indirect_p)
{
r = gen_rtx_MEM (Pmode, addr_rtx);
set_mem_alias_set (r, get_varargs_alias_set ());
emit_move_insn (addr_rtx, r);
}
return addr_rtx;
}
tree
rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
{

View File

@ -1760,8 +1760,7 @@ typedef struct rs6000_args
rs6000_va_start (valist, nextarg)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
rs6000_va_arg (valist, type)
#define EXPAND_BUILTIN_VA_ARG(valist, type) (abort (), NULL_RTX)
#define PAD_VARARGS_DOWN \
(FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)

View File

@ -5942,111 +5942,6 @@ sparc_va_start (tree valist, rtx nextarg)
/* Implement `va_arg' for stdarg. */
rtx
sparc_va_arg (tree valist, tree type)
{
HOST_WIDE_INT size, rsize, align;
tree addr, incr;
rtx addr_rtx;
bool indirect;
if (function_arg_pass_by_reference (0, TYPE_MODE (type), type, 0))
{
indirect = true;
size = rsize = UNITS_PER_WORD;
align = 0;
}
else
{
indirect = false;
size = int_size_in_bytes (type);
rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
align = 0;
if (TARGET_ARCH64)
{
/* For SPARC64, objects requiring 16-byte alignment get it. */
if (TYPE_ALIGN (type) >= 2 * (unsigned) BITS_PER_WORD)
align = 2 * UNITS_PER_WORD;
/* SPARC-V9 ABI states that structures up to 16 bytes in size
are given whole slots as needed. */
if (AGGREGATE_TYPE_P (type))
{
if (size == 0)
size = rsize = UNITS_PER_WORD;
else
size = rsize;
}
}
}
incr = valist;
if (align)
{
incr = fold (build (PLUS_EXPR, ptr_type_node, incr,
build_int_2 (align - 1, 0)));
incr = fold (build (BIT_AND_EXPR, ptr_type_node, incr,
build_int_2 (-align, -1)));
}
addr = incr = save_expr (incr);
if (BYTES_BIG_ENDIAN && size < rsize)
{
addr = fold (build (PLUS_EXPR, ptr_type_node, incr,
build_int_2 (rsize - size, 0)));
}
incr = fold (build (PLUS_EXPR, ptr_type_node, incr,
build_int_2 (rsize, 0)));
incr = build (MODIFY_EXPR, ptr_type_node, valist, incr);
TREE_SIDE_EFFECTS (incr) = 1;
expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
/* If the address isn't aligned properly for the type,
we may need to copy to a temporary.
FIXME: This is inefficient. Usually we can do this
in registers. */
if (align == 0
&& TYPE_ALIGN (type) > BITS_PER_WORD
&& !indirect)
{
/* FIXME: We really need to specify that the temporary is live
for the whole function because expand_builtin_va_arg wants
the alias set to be get_varargs_alias_set (), but in this
case the alias set is that for TYPE and if the memory gets
reused it will be reused with alias set TYPE. */
rtx tmp = assign_temp (type, 0, 1, 0);
rtx dest_addr;
addr_rtx = force_reg (Pmode, addr_rtx);
addr_rtx = gen_rtx_MEM (BLKmode, addr_rtx);
set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
set_mem_align (addr_rtx, BITS_PER_WORD);
tmp = shallow_copy_rtx (tmp);
PUT_MODE (tmp, BLKmode);
set_mem_alias_set (tmp, 0);
dest_addr = emit_block_move (tmp, addr_rtx, GEN_INT (rsize),
BLOCK_OP_NORMAL);
if (dest_addr != NULL_RTX)
addr_rtx = dest_addr;
else
addr_rtx = XCEXP (tmp, 0, MEM);
}
if (indirect)
{
addr_rtx = force_reg (Pmode, addr_rtx);
addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
}
return addr_rtx;
}
tree
sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
{

View File

@ -1804,8 +1804,7 @@ do { \
sparc_va_start (valist, nextarg)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
sparc_va_arg (valist, type)
#define EXPAND_BUILTIN_VA_ARG(valist, type) (abort (), NULL_RTX)
/* Generate RTL to flush the register windows so as to make arbitrary frames
available. */

View File

@ -3870,11 +3870,15 @@ This hook performs target-specific gimplification of
arguments to @code{va_arg}; the latter two are as in
@code{gimplify.c:gimplify_expr}.
You only need to define this hook if you also define
You only need to define this hook if you previously defined
@code{EXPAND_BUILTIN_VA_ARG}; it is pretty easy to reuse the same code
for both. One significant difference is that
@code{EXPAND_BUILTIN_VA_ARG} returns an address, whereas this hook
produces an expression of type @var{type}, usually an @code{INDIRECT_REF}.
Once you define this macro, you can change
@code{EXPAND_BUILTIN_VA_ARG} to just abort, as it should never be
called.
@end deftypefn
@node Scalar Return

View File

@ -1716,24 +1716,16 @@ tree_could_throw_p (tree t)
return false;
if (TREE_CODE (t) == MODIFY_EXPR)
{
tree sub = TREE_OPERAND (t, 1);
if (TREE_CODE (sub) == CALL_EXPR)
t = sub;
else
{
if (flag_non_call_exceptions)
{
if (tree_could_trap_p (sub))
return true;
return tree_could_trap_p (TREE_OPERAND (t, 0));
}
return false;
}
if (flag_non_call_exceptions
&& tree_could_trap_p (TREE_OPERAND (t, 0)))
return true;
t = TREE_OPERAND (t, 1);
}
if (TREE_CODE (t) == CALL_EXPR)
return (call_expr_flags (t) & ECF_NOTHROW) == 0;
if (flag_non_call_exceptions)
return tree_could_trap_p (t);
return false;
}

View File

@ -821,7 +821,11 @@ get_stmt_operands (tree stmt)
if (TREE_CODE (TREE_OPERAND (stmt, 0)) == ARRAY_REF
|| TREE_CODE (TREE_OPERAND (stmt, 0)) == COMPONENT_REF
|| TREE_CODE (TREE_OPERAND (stmt, 0)) == REALPART_EXPR
|| TREE_CODE (TREE_OPERAND (stmt, 0)) == IMAGPART_EXPR)
|| TREE_CODE (TREE_OPERAND (stmt, 0)) == IMAGPART_EXPR
/* Use a V_MAY_DEF if the RHS might throw, as the LHS won't be
modified in that case. FIXME we should represent somehow
that it is killed on the fallthrough path. */
|| tree_could_throw_p (TREE_OPERAND (stmt, 1)))
get_expr_operands (stmt, &TREE_OPERAND (stmt, 0), opf_is_def,
&prev_vops);
else