/* Expand builtin functions.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GCC.
r_label = convert_memory_address (Pmode, r_label);
r_save_area = expand_normal (t_save_area);
r_save_area = convert_memory_address (Pmode, r_save_area);
+ /* Copy the address of the save location to a register just in case it was based
+ on the frame pointer. */
+ r_save_area = copy_to_reg (r_save_area);
r_fp = gen_rtx_MEM (Pmode, r_save_area);
r_sp = gen_rtx_MEM (STACK_SAVEAREA_MODE (SAVE_NONLOCAL),
plus_constant (r_save_area, GET_MODE_SIZE (Pmode)));
while (TREE_CODE (inner) == COMPONENT_REF)
{
tree field = TREE_OPERAND (inner, 1);
- gcc_assert (! DECL_BIT_FIELD (field));
gcc_assert (TREE_CODE (mem_expr) == COMPONENT_REF);
gcc_assert (field == TREE_OPERAND (mem_expr, 1));
+ /* Bitfields are generally not byte-addressable. */
+ gcc_assert (!DECL_BIT_FIELD (field)
+ || ((tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
+ % BITS_PER_UNIT) == 0
+ && host_integerp (DECL_SIZE (field), 0)
+ && (TREE_INT_CST_LOW (DECL_SIZE (field))
+ % BITS_PER_UNIT) == 0));
+
+ /* If we can prove that the memory starting at XEXP (mem, 0) and
+ ending at XEXP (mem, 0) + LENGTH will fit into this field, we
+ can keep the COMPONENT_REF in MEM_EXPR. But be careful with
+ fields without DECL_SIZE_UNIT like flexible array members. */
if (length >= 0
- && TYPE_SIZE_UNIT (TREE_TYPE (inner))
- && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0))
+ && DECL_SIZE_UNIT (field)
+ && host_integerp (DECL_SIZE_UNIT (field), 0))
{
HOST_WIDE_INT size
- = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (inner)), 0);
- /* If we can prove the memory starting at XEXP (mem, 0)
- and ending at XEXP (mem, 0) + LENGTH will fit into
- this field, we can keep that COMPONENT_REF in MEM_EXPR. */
+ = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field));
if (offset <= size
&& length <= size
&& offset + length <= size)
if (offset >= 0
&& host_integerp (DECL_FIELD_OFFSET (field), 0))
- offset += tree_low_cst (DECL_FIELD_OFFSET (field), 0)
+ offset += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
+ tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
/ BITS_PER_UNIT;
else
int regno, size, align, nelts;
enum machine_mode mode;
rtx reg, mem;
- rtx *savevec = alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
+ rtx *savevec = XALLOCAVEC (rtx, FIRST_PSEUDO_REGISTER);
size = nelts = 0;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
before_call = get_last_insn ();
- target = expand_call (exp, target, target == const0_rtx);
-
- /* If this is a sqrt operation and we don't care about errno, try to
- attach a REG_EQUAL note with a SQRT rtx to the emitted libcall.
- This allows the semantics of the libcall to be visible to the RTL
- optimizers. */
- if (builtin_optab == sqrt_optab && !errno_set)
- {
- /* Search backwards through the insns emitted by expand_call looking
- for the instruction with the REG_RETVAL note. */
- rtx last = get_last_insn ();
- while (last != before_call)
- {
- if (find_reg_note (last, REG_RETVAL, NULL))
- {
- rtx note = find_reg_note (last, REG_EQUAL, NULL);
- /* Check that the REQ_EQUAL note is an EXPR_LIST with
- two elements, i.e. symbol_ref(sqrt) and the operand. */
- if (note
- && GET_CODE (note) == EXPR_LIST
- && GET_CODE (XEXP (note, 0)) == EXPR_LIST
- && XEXP (XEXP (note, 0), 1) != NULL_RTX
- && XEXP (XEXP (XEXP (note, 0), 1), 1) == NULL_RTX)
- {
- rtx operand = XEXP (XEXP (XEXP (note, 0), 1), 0);
- /* Check operand is a register with expected mode. */
- if (operand
- && REG_P (operand)
- && GET_MODE (operand) == mode)
- {
- /* Replace the REG_EQUAL note with a SQRT rtx. */
- rtx equiv = gen_rtx_SQRT (mode, operand);
- set_unique_reg_note (last, REG_EQUAL, equiv);
- }
- }
- break;
- }
- last = PREV_INSN (last);
- }
- }
-
- return target;
+ return expand_call (exp, target, target == const0_rtx);
}
/* Expand a call to the builtin binary math functions (pow and atan2).
&& GET_CODE (len_rtx) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
&& can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
- (void *) src_str, dest_align, false))
+ CONST_CAST (char *, src_str),
+ dest_align, false))
{
dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
builtin_memcpy_read_str,
- (void *) src_str, dest_align, false, 0);
+ CONST_CAST (char *, src_str),
+ dest_align, false, 0);
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
&& GET_CODE (len_rtx) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1
&& can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str,
- (void *) src_str, dest_align, false))
+ CONST_CAST (char *, src_str),
+ dest_align, false))
{
dest_mem = get_memory_rtx (dest, len);
set_mem_align (dest_mem, dest_align);
dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx),
builtin_memcpy_read_str,
- (void *) src_str, dest_align,
- false, endp);
+ CONST_CAST (char *, src_str),
+ dest_align, false, endp);
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
if (!p || dest_align == 0 || !host_integerp (len, 1)
|| !can_store_by_pieces (tree_low_cst (len, 1),
builtin_strncpy_read_str,
- (void *) p, dest_align, false))
+ CONST_CAST (char *, p),
+ dest_align, false))
return NULL_RTX;
dest_mem = get_memory_rtx (dest, len);
store_by_pieces (dest_mem, tree_low_cst (len, 1),
builtin_strncpy_read_str,
- (void *) p, dest_align, false, 0);
+ CONST_CAST (char *, p), dest_align, false, 0);
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
enum machine_mode mode)
{
const char *c = (const char *) data;
- char *p = alloca (GET_MODE_SIZE (mode));
+ char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
memset (p, *c, GET_MODE_SIZE (mode));
if (size == 1)
return (rtx) data;
- p = alloca (size);
+ p = XALLOCAVEC (char, size);
memset (p, 1, size);
coeff = c_readstr (p, mode);
/* If the actual alignment is less than the alignment of the type,
adjust the type accordingly so that we don't assume strict alignment
- when deferencing the pointer. */
+ when dereferencing the pointer. */
boundary *= BITS_PER_UNIT;
if (boundary < TYPE_ALIGN (type))
{
{
/* Create a NUL-terminated string that's one char shorter
than the original, stripping off the trailing '\n'. */
- char *newstr = alloca (len);
+ char *newstr = XALLOCAVEC (char, len);
memcpy (newstr, fmt_str, len - 1);
newstr[len - 1] = 0;
arg = build_string_literal (len, newstr);
lo = 0;
}
- if (imode != rmode)
+ if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
temp = gen_lowpart (rmode, temp);
temp = expand_binop (rmode, and_optab, temp,
immed_double_const (lo, hi, rmode),
if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len))
return NULL_TREE;
/* With memcpy, it is possible to bypass aliasing rules, so without
- this check i. e. execute/20060930-2.c would be misoptimized, because
+ this check i.e. execute/20060930-2.c would be misoptimized, because
it use conflicting alias set to hold argument for the memcpy call.
- This check is probably unnecesary with -fno-strict-aliasing.
+ This check is probably unnecessary with -fno-strict-aliasing.
Similarly for destvar. See also PR29286. */
if (!var_decl_component_p (srcvar)
/* Accept: memcpy (*char_var, "test", 1); that simplify
if (target_char_cast (arg2, &c))
return NULL_TREE;
- r = memchr (p1, c, tree_low_cst (len, 1));
+ r = (char *) memchr (p1, c, tree_low_cst (len, 1));
if (r == NULL)
return build_int_cst (TREE_TYPE (arg1), 0);
int i, j;
va_list ap;
- buffer = alloca (nargs * sizeof (tree));
+ buffer = XALLOCAVEC (tree, nargs);
va_start (ap, n);
for (i = 0; i < n; i++)
buffer[i] = va_arg (ap, tree);
{
/* Create a NUL-terminated string that's one char shorter
than the original, stripping off the trailing '\n'. */
- char *newstr = alloca (len);
+ char *newstr = XALLOCAVEC (char, len);
memcpy (newstr, str, len - 1);
newstr[len - 1] = 0;