mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-30 23:35:00 +08:00
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:
parent
67fc0c0f59
commit
67c605a553
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user