{
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);
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);
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;
}
/* 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. Make sure it's a valid
+ operand, as emit_move_insn isn't expected to handle a PLUS. */
+ tem
+ = force_operand (plus_constant (tem, current_function_pretend_args_size),
+ NULL_RTX);
+#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
#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);
/* 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. */
/* 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);
}
/* 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);
}
/* 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);
}
/* 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);
}
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. */
break;
}
}
- /* FALLTHROUGH */
+ /* Fall through. */
case 1: /* length is greater than 1, call fwrite. */
{
tree string_arg;
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