#include "coretypes.h"
#include "tm.h"
#include "diagnostic-core.h"
-#include "toplev.h"
#include "rtl.h"
#include "tree.h"
#include "tm_p.h"
promote_function_mode (const_tree type, enum machine_mode mode, int *punsignedp,
const_tree funtype, int for_return)
{
+ /* Called without a type node for a libcall. */
+ if (type == NULL_TREE)
+ {
+ if (INTEGRAL_MODE_P (mode))
+ return targetm.calls.promote_function_mode (NULL_TREE, mode,
+ punsignedp, funtype,
+ for_return);
+ else
+ return mode;
+ }
+
switch (TREE_CODE (type))
{
case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
promote_mode (const_tree type ATTRIBUTE_UNUSED, enum machine_mode mode,
int *punsignedp ATTRIBUTE_UNUSED)
{
+#ifdef PROMOTE_MODE
+ enum tree_code code;
+ int unsignedp;
+#endif
+
+ /* For libcalls this is invoked without TYPE from the backends
+ TARGET_PROMOTE_FUNCTION_MODE hooks. Don't do anything in that
+ case. */
+ if (type == NULL_TREE)
+ return mode;
+
/* FIXME: this is the same logic that was there until GCC 4.4, but we
probably want to test POINTERS_EXTEND_UNSIGNED even if PROMOTE_MODE
is not defined. The affected targets are M32C, S390, SPARC. */
#ifdef PROMOTE_MODE
- const enum tree_code code = TREE_CODE (type);
- int unsignedp = *punsignedp;
+ code = TREE_CODE (type);
+ unsignedp = *punsignedp;
switch (code)
{
/* Save the stack pointer for the purpose in SAVE_LEVEL. PSAVE is a pointer
to a previously-created save area. If no save area has been allocated,
this function will allocate one. If a save area is specified, it
- must be of the proper mode.
-
- The insns are emitted after insn AFTER, if nonzero, otherwise the insns
- are emitted at the current position. */
+ must be of the proper mode. */
void
-emit_stack_save (enum save_level save_level, rtx *psave, rtx after)
+emit_stack_save (enum save_level save_level, rtx *psave)
{
rtx sa = *psave;
/* The default is that we use a move insn and save in a Pmode object. */
}
}
- if (after)
- {
- rtx seq;
-
- start_sequence ();
- do_pending_stack_adjust ();
- /* We must validize inside the sequence, to ensure that any instructions
- created by the validize call also get moved to the right place. */
- if (sa != 0)
- sa = validize_mem (sa);
- emit_insn (fcn (sa, stack_pointer_rtx));
- seq = get_insns ();
- end_sequence ();
- emit_insn_after (seq, after);
- }
- else
- {
- do_pending_stack_adjust ();
- if (sa != 0)
- sa = validize_mem (sa);
- emit_insn (fcn (sa, stack_pointer_rtx));
- }
+ do_pending_stack_adjust ();
+ if (sa != 0)
+ sa = validize_mem (sa);
+ emit_insn (fcn (sa, stack_pointer_rtx));
}
/* Restore the stack pointer for the purpose in SAVE_LEVEL. SA is the save
- area made by emit_stack_save. If it is zero, we have nothing to do.
-
- Put any emitted insns after insn AFTER, if nonzero, otherwise at
- current position. */
+ area made by emit_stack_save. If it is zero, we have nothing to do. */
void
-emit_stack_restore (enum save_level save_level, rtx sa, rtx after)
+emit_stack_restore (enum save_level save_level, rtx sa)
{
/* The default is that we use a move insn. */
rtx (*fcn) (rtx, rtx) = gen_move_insn;
discard_pending_stack_adjust ();
- if (after)
- {
- rtx seq;
-
- start_sequence ();
- emit_insn (fcn (stack_pointer_rtx, sa));
- seq = get_insns ();
- end_sequence ();
- emit_insn_after (seq, after);
- }
- else
- emit_insn (fcn (stack_pointer_rtx, sa));
+ emit_insn (fcn (stack_pointer_rtx, sa));
}
/* Invoke emit_stack_save on the nonlocal_goto_save_area for the current
integer_one_node, NULL_TREE, NULL_TREE);
r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
- emit_stack_save (SAVE_NONLOCAL, &r_save, NULL_RTX);
+ emit_stack_save (SAVE_NONLOCAL, &r_save);
}
\f
/* Return an rtx representing the address of an area of memory dynamically
{
HOST_WIDE_INT stack_usage_size = -1;
rtx final_label, final_target, target;
+ unsigned extra_align = 0;
bool must_align;
/* If we're asking for zero bytes, it doesn't matter what we point
that might result from the alignment operation. */
must_align = (crtl->preferred_stack_boundary < required_align);
-#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET)
- must_align = true;
-#endif
-
if (must_align)
{
- unsigned extra, extra_align;
-
if (required_align > PREFERRED_STACK_BOUNDARY)
extra_align = PREFERRED_STACK_BOUNDARY;
else if (required_align > STACK_BOUNDARY)
extra_align = STACK_BOUNDARY;
else
extra_align = BITS_PER_UNIT;
- extra = (required_align - extra_align) / BITS_PER_UNIT;
+ }
+
+ /* ??? STACK_POINTER_OFFSET is always defined now. */
+#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET)
+ must_align = true;
+ extra_align = BITS_PER_UNIT;
+#endif
+
+ if (must_align)
+ {
+ unsigned extra = (required_align - extra_align) / BITS_PER_UNIT;
size = plus_constant (size, extra);
size = force_operand (size, NULL_RTX);
#ifdef HAVE_allocate_stack
if (HAVE_allocate_stack)
{
- enum machine_mode mode = STACK_SIZE_MODE;
- insn_operand_predicate_fn pred;
-
+ struct expand_operand ops[2];
/* We don't have to check against the predicate for operand 0 since
TARGET is known to be a pseudo of the proper mode, which must
- be valid for the operand. For operand 1, convert to the
- proper mode and validate. */
- if (mode == VOIDmode)
- mode = insn_data[(int) CODE_FOR_allocate_stack].operand[1].mode;
-
- pred = insn_data[(int) CODE_FOR_allocate_stack].operand[1].predicate;
- if (pred && ! ((*pred) (size, mode)))
- size = copy_to_mode_reg (mode, convert_to_mode (mode, size, 1));
-
- emit_insn (gen_allocate_stack (target, size));
+ be valid for the operand. */
+ create_fixed_operand (&ops[0], target);
+ create_convert_operand_to (&ops[1], size, STACK_SIZE_MODE, true);
+ expand_insn (CODE_FOR_allocate_stack, 2, ops);
}
else
#endif
plus_constant (size, first)));
emit_library_call (stack_check_libfunc, LCT_NORMAL, VOIDmode, 1, addr,
Pmode);
+ return;
}
/* Next see if we have an insn to check the stack. */
#ifdef HAVE_check_stack
- else if (HAVE_check_stack)
+ if (HAVE_check_stack)
{
+ struct expand_operand ops[1];
rtx addr = memory_address (Pmode,
gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
stack_pointer_rtx,
plus_constant (size, first)));
- insn_operand_predicate_fn pred
- = insn_data[(int) CODE_FOR_check_stack].operand[0].predicate;
- if (pred && !((*pred) (addr, Pmode)))
- addr = copy_to_mode_reg (Pmode, addr);
- emit_insn (gen_check_stack (addr));
+ create_input_operand (&ops[0], addr, Pmode);
+ if (maybe_expand_insn (CODE_FOR_check_stack, 1, ops))
+ return;
}
#endif