Commit c9ec4f99 by David S. Miller Committed by Jeff Law

explow.c (optimize_save_area_alloca): New function for targets where SETJMP_VIA_SAVE_AREA is true.

        * explow.c (optimize_save_area_alloca): New function for targets
        where SETJMP_VIA_SAVE_AREA is true.
        (allocate_dynamic_stack_space): On SETJMP_VIA_SAVE_AREA targets,
        compute the amount of stack space needed should we find later that
        setjmp is never called by this function, stuff rtl for this inside
        a REG_NOTE of the final SET of stack_pointer_rtx.
        * toplev.c (rest_of_compilation): If SETJMP_VIA_SAVE_AREA and
        current_function_calls_alloca, call optimize_save_area_alloca.
CVS ----------------------------------------------------------------------

From-SVN: r17402
parent ca097615
Sat Jan 17 23:41:36 1998 David S. Miller <davem@tanya.rutgers.edu>
* explow.c (optimize_save_area_alloca): New function for targets
where SETJMP_VIA_SAVE_AREA is true.
(allocate_dynamic_stack_space): On SETJMP_VIA_SAVE_AREA targets,
compute the amount of stack space needed should we find later that
setjmp is never called by this function, stuff rtl for this inside
a REG_NOTE of the final SET of stack_pointer_rtx.
* toplev.c (rest_of_compilation): If SETJMP_VIA_SAVE_AREA and
current_function_calls_alloca, call optimize_save_area_alloca.
Sat Jan 17 23:22:59 1998 John Wehle (john@feith.com) Sat Jan 17 23:22:59 1998 John Wehle (john@feith.com)
* i386.md: Remove redundant integer push patterns. * i386.md: Remove redundant integer push patterns.
......
...@@ -1004,6 +1004,86 @@ emit_stack_restore (save_level, sa, after) ...@@ -1004,6 +1004,86 @@ emit_stack_restore (save_level, sa, after)
emit_insn (fcn (stack_pointer_rtx, sa)); emit_insn (fcn (stack_pointer_rtx, sa));
} }
#ifdef SETJMP_VIA_SAVE_AREA
/* Optimize RTL generated by allocate_dynamic_stack_space for targets
where SETJMP_VIA_SAVE_AREA is true. The problem is that on these
platforms, the dynamic stack space used can corrupt the original
frame, thus causing a crash if a longjmp unwinds to it. */
void
optimize_save_area_alloca (insns)
rtx insns;
{
rtx insn;
for (insn = insns; insn; insn = NEXT_INSN(insn))
{
rtx note;
if (GET_CODE (insn) != INSN)
continue;
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
{
if (REG_NOTE_KIND (note) != REG_SAVE_AREA)
continue;
if (!current_function_calls_setjmp)
{
rtx pat = PATTERN (insn);
/* If we do not see the note in a pattern matching
these precise characteristics, we did something
entirely wrong in allocate_dynamic_stack_space.
Note, one way this could happen if if SETJMP_VIA_SAVE_AREA
was defined on a machine where stacks grow towards higher
addresses.
Right now only supported port with stack that grow upward
is the HPPA and it does not define SETJMP_VIA_SAVE_AREA. */
if (GET_CODE (pat) != SET
|| SET_DEST (pat) != stack_pointer_rtx
|| GET_CODE (SET_SRC (pat)) != MINUS
|| XEXP (SET_SRC (pat), 0) != stack_pointer_rtx)
abort ();
/* This will now be transformed into a (set REG REG)
so we can just blow away all the other notes. */
XEXP (SET_SRC (pat), 1) = XEXP (note, 0);
REG_NOTES (insn) = NULL_RTX;
}
else
{
/* setjmp was called, we must remove the REG_SAVE_AREA
note so that later passes do not get confused by its
presence. */
if (note == REG_NOTES (insn))
{
REG_NOTES (insn) = XEXP (note, 1);
}
else
{
rtx srch;
for (srch = REG_NOTES (insn); srch; srch = XEXP (srch, 1))
if (XEXP (srch, 1) == note)
break;
if (srch == NULL_RTX)
abort();
XEXP (srch, 1) = XEXP (note, 1);
}
}
/* Once we've seen the note of interest, we need not look at
the rest of them. */
break;
}
}
}
#endif /* SETJMP_VIA_SAVE_AREA */
/* Return an rtx representing the address of an area of memory dynamically /* Return an rtx representing the address of an area of memory dynamically
pushed on the stack. This region of memory is always aligned to pushed on the stack. This region of memory is always aligned to
a multiple of BIGGEST_ALIGNMENT. a multiple of BIGGEST_ALIGNMENT.
...@@ -1021,6 +1101,10 @@ allocate_dynamic_stack_space (size, target, known_align) ...@@ -1021,6 +1101,10 @@ allocate_dynamic_stack_space (size, target, known_align)
rtx target; rtx target;
int known_align; int known_align;
{ {
#ifdef SETJMP_VIA_SAVE_AREA
rtx setjmpless_size = NULL_RTX;
#endif
/* If we're asking for zero bytes, it doesn't matter what we point /* If we're asking for zero bytes, it doesn't matter what we point
to since we can't dereference it. But return a reasonable to since we can't dereference it. But return a reasonable
address anyway. */ address anyway. */
...@@ -1074,6 +1158,45 @@ allocate_dynamic_stack_space (size, target, known_align) ...@@ -1074,6 +1158,45 @@ allocate_dynamic_stack_space (size, target, known_align)
rtx dynamic_offset rtx dynamic_offset
= expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx, = expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,
stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN); stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN);
if (!current_function_calls_setjmp)
{
int align = STACK_BOUNDARY / BITS_PER_UNIT;
/* See optimize_save_area_alloca to understand what is being
set up here. */
#if !defined(STACK_BOUNDARY) || !defined(MUST_ALIGN) || (STACK_BOUNDARY != BIGGEST_ALIGNMENT)
/* If anyone creates a target with these characteristics, let them
know that our optimization cannot work correctly in such a case. */
abort();
#endif
if (GET_CODE (size) == CONST_INT)
{
int new = INTVAL (size) / align * align;
if (INTVAL (size) != new)
setjmpless_size = GEN_INT (new);
else
setjmpless_size = size;
}
else
{
/* Since we know overflow is not possible, we avoid using
CEIL_DIV_EXPR and use TRUNC_DIV_EXPR instead. */
setjmpless_size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size,
GEN_INT (align), NULL_RTX, 1);
setjmpless_size = expand_mult (Pmode, setjmpless_size,
GEN_INT (align), NULL_RTX, 1);
}
/* Our optimization works based upon being able to perform a simple
transformation of this RTL into a (set REG REG) so make sure things
did in fact end up in a REG. */
if (!arith_operand (setjmpless_size, Pmode))
setjmpless_size = force_reg (Pmode, setjmpless_size);
}
size = expand_binop (Pmode, add_optab, size, dynamic_offset, size = expand_binop (Pmode, add_optab, size, dynamic_offset,
NULL_RTX, 1, OPTAB_LIB_WIDEN); NULL_RTX, 1, OPTAB_LIB_WIDEN);
} }
...@@ -1145,6 +1268,16 @@ allocate_dynamic_stack_space (size, target, known_align) ...@@ -1145,6 +1268,16 @@ allocate_dynamic_stack_space (size, target, known_align)
#endif #endif
size = convert_modes (Pmode, ptr_mode, size, 1); size = convert_modes (Pmode, ptr_mode, size, 1);
anti_adjust_stack (size); anti_adjust_stack (size);
#ifdef SETJMP_VIA_SAVE_AREA
if (setjmpless_size != NULL_RTX)
{
rtx note_target = get_last_insn ();
REG_NOTES (note_target) = gen_rtx (EXPR_LIST, REG_SAVE_AREA,
setjmpless_size,
REG_NOTES (note_target));
}
#endif /* SETJMP_VIA_SAVE_AREA */
#ifdef STACK_GROWS_DOWNWARD #ifdef STACK_GROWS_DOWNWARD
emit_move_insn (target, virtual_stack_dynamic_rtx); emit_move_insn (target, virtual_stack_dynamic_rtx);
#endif #endif
......
...@@ -3242,6 +3242,12 @@ rest_of_compilation (decl) ...@@ -3242,6 +3242,12 @@ rest_of_compilation (decl)
unshare_all_rtl (insns); unshare_all_rtl (insns);
#ifdef SETJMP_VIA_SAVE_AREA
/* This must be performed before virutal register instantiation. */
if (current_function_calls_alloca)
optimize_save_area_alloca (insns);
#endif
/* Instantiate all virtual registers. */ /* Instantiate all virtual registers. */
instantiate_virtual_regs (current_function_decl, get_insns ()); instantiate_virtual_regs (current_function_decl, get_insns ());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment