* 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
+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:
}
}
-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)
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)
\f
/* Tell collect that the object format is ECOFF. */
#define OBJECT_FORMAT_COFF
}
/* 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)
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
/* 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)
{
|| ((REGNO) >= FR_ARG_FIRST && (REGNO) < (FR_ARG_FIRST + MAX_ARGUMENT_SLOTS)))
\f
/* 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)
\f
/* How Scalar Function Values are Returned */
/* 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)
{
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)
/* 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)
{
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. */
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
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;
}
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