aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c67
1 files changed, 51 insertions, 16 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 39156ebb62e..c5af18d7182 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -710,6 +710,13 @@ expand_builtin_longjmp (rtx buf_addr, rtx value)
{
lab = copy_to_reg (lab);
+ emit_insn (gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_MEM (BLKmode,
+ gen_rtx_SCRATCH (VOIDmode))));
+ emit_insn (gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_MEM (BLKmode,
+ hard_frame_pointer_rtx)));
+
emit_move_insn (hard_frame_pointer_rtx, fp);
emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
@@ -1089,7 +1096,7 @@ result_vector (int savep, rtx result)
static rtx
expand_builtin_apply_args_1 (void)
{
- rtx registers;
+ rtx registers, tem;
int size, align, regno;
enum machine_mode mode;
rtx struct_incoming_value = targetm.calls.struct_value_rtx (cfun ? TREE_TYPE (cfun->decl) : 0, 1);
@@ -1107,8 +1114,6 @@ expand_builtin_apply_args_1 (void)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if ((mode = apply_args_mode[regno]) != VOIDmode)
{
- rtx tem;
-
align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
if (size % align != 0)
size = CEIL (size, align) * align;
@@ -1120,8 +1125,14 @@ expand_builtin_apply_args_1 (void)
}
/* Save the arg pointer to the block. */
- emit_move_insn (adjust_address (registers, Pmode, 0),
- copy_to_reg (virtual_incoming_args_rtx));
+ tem = copy_to_reg (virtual_incoming_args_rtx);
+#ifdef STACK_GROWS_DOWNWARD
+ /* We need the pointer as the caller actually passed them to us, not
+ as we might have pretended they were passed. */
+ tem = plus_constant (tem, current_function_pretend_args_size);
+#endif
+ emit_move_insn (adjust_address (registers, Pmode, 0), tem);
+
size = GET_MODE_SIZE (Pmode);
/* Save the structure value address unless this is passed as an
@@ -1219,12 +1230,16 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
#endif
emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
- /* Push a block of memory onto the stack to store the memory arguments.
- Save the address in a register, and copy the memory arguments. ??? I
- haven't figured out how the calling convention macros effect this,
- but it's likely that the source and/or destination addresses in
- the block copy will need updating in machine specific ways. */
- dest = allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
+ /* Allocate a block of memory onto the stack and copy the memory
+ arguments to the outgoing arguments address. */
+ allocate_dynamic_stack_space (argsize, 0, BITS_PER_UNIT);
+ dest = virtual_outgoing_args_rtx;
+#ifndef STACK_GROWS_DOWNWARD
+ if (GET_CODE (argsize) == CONST_INT)
+ dest = plus_constant (dest, -INTVAL (argsize));
+ else
+ dest = gen_rtx_PLUS (Pmode, dest, negate_rtx (Pmode, argsize));
+#endif
dest = gen_rtx_MEM (BLKmode, dest);
set_mem_align (dest, PARM_BOUNDARY);
src = gen_rtx_MEM (BLKmode, incoming_args);
@@ -1378,7 +1393,7 @@ expand_builtin_return (rtx result)
/* Return whatever values was restored by jumping directly to the end
of the function. */
- expand_null_return ();
+ expand_naked_return ();
}
/* Used by expand_builtin_classify_type and fold_builtin_classify_type. */
@@ -2261,7 +2276,8 @@ expand_builtin_strstr (tree arglist, rtx target, enum machine_mode mode)
/* Return an offset into the constant string argument. */
return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
- s1, ssize_int (r - p1))),
+ s1, convert (TREE_TYPE (s1),
+ ssize_int (r - p1)))),
target, mode, EXPAND_NORMAL);
}
@@ -2318,7 +2334,8 @@ expand_builtin_strchr (tree arglist, rtx target, enum machine_mode mode)
/* Return an offset into the constant string argument. */
return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
- s1, ssize_int (r - p1))),
+ s1, convert (TREE_TYPE (s1),
+ ssize_int (r - p1)))),
target, mode, EXPAND_NORMAL);
}
@@ -2362,7 +2379,8 @@ expand_builtin_strrchr (tree arglist, rtx target, enum machine_mode mode)
/* Return an offset into the constant string argument. */
return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
- s1, ssize_int (r - p1))),
+ s1, convert (TREE_TYPE (s1),
+ ssize_int (r - p1)))),
target, mode, EXPAND_NORMAL);
}
@@ -2408,7 +2426,8 @@ expand_builtin_strpbrk (tree arglist, rtx target, enum machine_mode mode)
/* Return an offset into the constant string argument. */
return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
- s1, ssize_int (r - p1))),
+ s1, convert (TREE_TYPE (s1),
+ ssize_int (r - p1)))),
target, mode, EXPAND_NORMAL);
}
@@ -3910,6 +3929,14 @@ stabilize_va_list (tree valist, int needs_lvalue)
return valist;
}
+/* The "standard" definition of va_list is void*. */
+
+tree
+std_build_builtin_va_list (void)
+{
+ return ptr_type_node;
+}
+
/* The "standard" implementation of va_start: just assign `nextarg' to
the variable. */
@@ -4437,6 +4464,14 @@ expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
ret = get_insns ();
end_sequence ();
+ /* For mildly unsafe builtin jump's, if unsave_expr_now
+ creates a new tree instead of changing the old one
+ TREE_VALUE (arglist) needs to be updated. */
+ if (arg0 != TREE_VALUE (arglist)
+ && TREE_CODE (arg0) == UNSAVE_EXPR
+ && TREE_OPERAND (arg0, 0) != TREE_VALUE (arglist))
+ TREE_VALUE (arglist) = TREE_OPERAND (arg0, 0);
+
/* Now that the __builtin_expect has been validated, go through and add
the expect's to each of the conditional jumps. If we run into an
error, just give up and generate the 'safe' code of doing a SCC