*** empty log message ***

From-SVN: r915
This commit is contained in:
Richard Kenner 1992-05-06 07:35:29 -04:00
parent a196f01fdf
commit 59257ff7b8
6 changed files with 252 additions and 39 deletions

View File

@ -800,7 +800,7 @@ expand_call (exp, target, ignore)
if (old_stack_level == 0)
{
old_stack_level = copy_to_mode_reg (Pmode, stack_pointer_rtx);
emit_stack_save (SAVE_BLOCK, &old_stack_level, 0);
old_pending_adj = pending_stack_adjust;
pending_stack_adjust = 0;
}
@ -1060,7 +1060,7 @@ expand_call (exp, target, ignore)
{
if (old_stack_level == 0)
{
old_stack_level = copy_to_mode_reg (Pmode, stack_pointer_rtx);
emit_stack_save (SAVE_BLOCK, &old_stack_level, 0);
old_pending_adj = pending_stack_adjust;
pending_stack_adjust = 0;
}
@ -1520,7 +1520,7 @@ expand_call (exp, target, ignore)
if (old_stack_level)
{
emit_move_insn (stack_pointer_rtx, old_stack_level);
emit_stack_restore (SAVE_BLOCK, old_stack_level, 0);
pending_stack_adjust = old_pending_adj;
}
@ -1570,9 +1570,12 @@ expand_call (exp, target, ignore)
}
#endif
/* If this was alloca, record the new stack level for nonlocal gotos. */
if (may_be_alloca && nonlocal_goto_stack_level != 0)
emit_move_insn (nonlocal_goto_stack_level, stack_pointer_rtx);
/* If this was alloca, record the new stack level for nonlocal gotos.
Check for the handler slots since we might not have a save area
for non-local gotos. */
if (may_be_alloca && nonlocal_goto_handler_slot != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, 0);
pop_temp_slots ();

View File

@ -2835,9 +2835,7 @@
;; Next come insns related to the calling sequence.
;;
;; First, an insn to allocate new stack space for dynamic use (e.g., alloca).
;; We move the back-chain and decrement the stack pointer. This is slightly
;; less efficient than it needs to be for long constants, but that case
;; should be rare.
;; We move the back-chain and decrement the stack pointer.
(define_expand "allocate_stack"
[(set (reg:SI 1)
@ -2852,6 +2850,63 @@
emit_move_insn (stack_bot, chain);
DONE;
}")
;; These patterns say how to save and restore the stack pointer. We need not
;; save the stack pointer at function level since we are careful to
;; preserve the backchain. At block level, we have to restore the backchain
;; when we restore the stack pointer.
;;
;; For nonlocal gotos, we must save both the stack pointer and its
;; backchain and restore both. Note that in the nonlocal case, the
;; save area is a memory location.
(define_expand "save_stack_function"
[(use (const_int 0))]
""
"")
(define_expand "restore_stack_function"
[(use (const_int 0))]
""
"")
(define_expand "restore_stack_block"
[(set (match_dup 2) (mem:SI (match_operand:SI 0 "register_operand" "")))
(set (match_dup 0) (match_operand:SI 1 "register_operand" ""))
(set (mem:SI (match_dup 0)) (match_dup 2))]
""
"
{ operands[2] = gen_reg_rtx (SImode); }")
(define_expand "save_stack_nonlocal"
[(match_operand:DI 0 "memory_operand" "")
(match_operand:SI 1 "register_operand" "")]
""
"
{
rtx temp = gen_reg_rtx (SImode);
/* Copy the backchain to the first word, sp to the second. */
emit_move_insn (temp, gen_rtx (MEM, SImode, operands[1]));
emit_move_insn (operand_subword (operands[0], 0, 0, DImode), temp);
emit_move_insn (operand_subword (operands[0], 1, 0, DImode), operands[1]);
DONE;
}")
(define_expand "restore_stack_nonlocal"
[(match_operand:SI 0 "register_operand" "")
(match_operand:DI 1 "memory_operand" "")]
""
"
{
rtx temp = gen_reg_rtx (SImode);
/* Restore the backchain from the first word, sp from the second. */
emit_move_insn (temp, operand_subword (operands[1], 0, 0, DImode));
emit_move_insn (operands[0], operand_subword (operands[1], 1, 0, DImode));
emit_move_insn (gen_rtx (MEM, SImode, operands[0]), temp);
DONE;
}")
;; A function pointer is a pointer to a data area whose first word contains
;; the actual address of the function, whose second word contains a pointer

View File

@ -681,6 +681,127 @@ round_push (size)
return size;
}
/* 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. */
void
emit_stack_save (save_level, psave, after)
enum save_level save_level;
rtx *psave;
rtx after;
{
rtx sa = *psave;
/* The default is that we use a move insn and save in a Pmode object. */
rtx (*fcn) () = gen_move_insn;
enum machine_mode mode = Pmode;
/* See if this machine has anything special to do for this kind of save. */
switch (save_level)
{
#ifdef HAVE_save_stack_block
case SAVE_BLOCK:
if (HAVE_save_stack_block)
{
fcn = gen_save_stack_block;
mode = insn_operand_mode[CODE_FOR_save_stack_block][0];
}
break;
#endif
#ifdef HAVE_save_stack_function
case SAVE_FUNCTION:
if (HAVE_save_stack_function)
{
fcn = gen_save_stack_function;
mode = insn_operand_mode[CODE_FOR_save_stack_function][0];
}
break;
#endif
#ifdef HAVE_save_stack_nonlocal
case SAVE_NONLOCAL:
if (HAVE_save_stack_nonlocal)
{
fcn = gen_save_stack_nonlocal;
mode = insn_operand_mode[CODE_FOR_save_stack_nonlocal][0];
}
break;
#endif
}
/* If there is no save area and we have to allocate one, do so. Otherwise
verify the save area is the proper mode. */
if (sa == 0)
{
if (mode != VOIDmode)
{
if (save_level == SAVE_NONLOCAL)
*psave = sa = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
else
*psave = sa = gen_reg_rtx (mode);
}
}
else
{
if (mode == VOIDmode || GET_MODE (sa) != mode)
abort ();
}
if (after)
emit_insn_after (fcn (sa, stack_pointer_rtx), after);
else
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. */
void
emit_stack_restore (save_level, sa, after)
enum save_level save_level;
rtx after;
rtx sa;
{
/* The default is that we use a move insn. */
rtx (*fcn) () = gen_move_insn;
/* See if this machine has anything special to do for this kind of save. */
switch (save_level)
{
#ifdef HAVE_restore_stack_block
case SAVE_BLOCK:
if (HAVE_restore_stack_block)
fcn = gen_restore_stack_block;
break;
#endif
#ifdef HAVE_restore_stack_function
case SAVE_FUNCTION:
if (HAVE_restore_stack_function)
fcn = gen_restore_stack_function;
break;
#endif
#ifdef HAVE_restore_stack_nonlocal
case SAVE_NONLOCAL:
if (HAVE_restore_stack_nonlocal)
fcn = gen_restore_stack_nonlocal;
break;
#endif
}
if (after)
emit_insn_after (fcn (stack_pointer_rtx, sa), after);
else
emit_insn (fcn (stack_pointer_rtx, sa));
}
/* Return an rtx representing the address of an area of memory dynamically
pushed on the stack. This region of memory is always aligned to
a multiple of BIGGEST_ALIGNMENT.

View File

@ -539,6 +539,15 @@ extern void adjust_stack ();
/* Add some bytes to the stack. An rtx says how many. */
extern void anti_adjust_stack ();
/* This enum is used for the following two functions. */
enum save_level {SAVE_BLOCK, SAVE_FUNCTION, SAVE_NONLOCAL};
/* Save the stack pointer at the specified level. */
extern void emit_stack_save ();
/* Restore the stack pointer from a save area of the specified level. */
extern void emit_stack_restore ();
/* Allocate some space on the stack dynamically and return its address. An rtx
says how many bytes. */
extern rtx allocate_dynamic_stack_space ();

View File

@ -2317,11 +2317,11 @@ delete_handlers ()
if (GET_CODE (insn) == CODE_LABEL)
LABEL_PRESERVE_P (insn) = 0;
if (GET_CODE (insn) == INSN
&& GET_CODE (PATTERN (insn)) == SET
&& (SET_DEST (PATTERN (insn)) == nonlocal_goto_handler_slot
|| SET_SRC (PATTERN (insn)) == nonlocal_goto_handler_slot
|| SET_DEST (PATTERN (insn)) == nonlocal_goto_stack_level
|| SET_SRC (PATTERN (insn)) == nonlocal_goto_stack_level))
&& ((nonlocal_goto_handler_slot != 0
&& reg_mentioned_p (nonlocal_goto_handler_slot, PATTERN (insn)))
|| (nonlocal_goto_stack_level != 0
&& reg_mentioned_p (nonlocal_goto_stack_level,
PATTERN (insn)))))
delete_insn (insn);
}
}
@ -3961,10 +3961,10 @@ expand_function_end (filename, line)
#endif
if (current_function_calls_alloca)
{
rtx tem = gen_reg_rtx (Pmode);
emit_insn_after (gen_rtx (SET, VOIDmode, tem, stack_pointer_rtx),
parm_birth_insn);
emit_insn (gen_rtx (SET, VOIDmode, stack_pointer_rtx, tem));
rtx tem = 0;
emit_stack_save (SAVE_FUNCTION, &tem, parm_birth_insn);
emit_stack_restore (SAVE_FUNCTION, tem, 0);
}
/* If scalar return value was computed in a pseudo-reg,

View File

@ -586,11 +586,9 @@ declare_nonlocal_label (label)
{
nonlocal_goto_handler_slot
= assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
nonlocal_goto_stack_level
= assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
emit_insn_before (gen_move_insn (nonlocal_goto_stack_level,
stack_pointer_rtx),
tail_recursion_reentry);
emit_stack_save (SAVE_NONLOCAL,
&nonlocal_goto_stack_level,
PREV_INSN (tail_recursion_reentry));
}
}
@ -609,27 +607,50 @@ expand_goto (label)
struct function *p = find_function_data (context);
rtx temp;
p->has_nonlocal_label = 1;
/* Copy the rtl for the slots so that they won't be shared in
case the virtual stack vars register gets instantiated differently
in the parent than in the child. */
#if HAVE_nonlocal_goto
if (HAVE_nonlocal_goto)
emit_insn (gen_nonlocal_goto (lookup_static_chain (label),
p->nonlocal_goto_handler_slot,
p->nonlocal_goto_stack_level,
copy_rtx (p->nonlocal_goto_handler_slot),
copy_rtx (p->nonlocal_goto_stack_level),
gen_rtx (LABEL_REF, Pmode,
label_rtx (label))));
else
#endif
{
rtx addr;
/* Restore frame pointer for containing function.
This sets the actual hard register used for the frame pointer
to the location of the function's incoming static chain info.
The non-local goto handler will then adjust it to contain the
proper value and reload the argument pointer, if needed. */
emit_move_insn (frame_pointer_rtx, lookup_static_chain (label));
/* We have now loaded the frame pointer hardware register with
the address of that corresponds to the start of the virtual
stack vars. So replace virtual_stack_vars_rtx in all
addresses we use with stack_pointer_rtx. */
/* Get addr of containing function's current nonlocal goto handler,
which will do any cleanups and then jump to the label. */
temp = copy_to_reg (p->nonlocal_goto_handler_slot);
addr = copy_rtx (p->nonlocal_goto_handler_slot);
temp = copy_to_reg (replace_rtx (addr, virtual_stack_vars_rtx,
frame_pointer_rtx));
/* Restore the stack pointer. Note this uses fp just restored. */
emit_move_insn (stack_pointer_rtx, p->nonlocal_goto_stack_level);
addr = p->nonlocal_goto_stack_level;
if (addr)
addr = replace_rtx (copy_rtx (p->nonlocal_goto_stack_level),
replace_rtx (addr, virtual_stack_vars_rtx,
frame_pointer_rtx));
emit_stack_restore (SAVE_NONLOCAL, addr, 0);
/* Put in the static chain register the nonlocal label address. */
emit_move_insn (static_chain_rtx,
gen_rtx (LABEL_REF, Pmode, label_rtx (label)));
@ -691,7 +712,7 @@ expand_goto_internal (body, label, last_insn)
the stack pointer. This one should be deleted as dead by flow. */
clear_pending_stack_adjust ();
do_pending_stack_adjust ();
emit_move_insn (stack_pointer_rtx, stack_level);
emit_stack_restore (SAVE_BLOCK, stack_level, 0);
}
if (body != 0 && DECL_TOO_LATE (body))
@ -902,8 +923,7 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
/* Restore stack level for the biggest contour that this
jump jumps out of. */
if (f->stack_level)
emit_insn_after (gen_move_insn (stack_pointer_rtx, f->stack_level),
f->before_jump);
emit_stack_restore (SAVE_BLOCK, f->stack_level, f->before_jump);
f->before_jump = 0;
}
}
@ -2592,14 +2612,15 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
if (thisblock->data.block.stack_level != 0)
{
emit_move_insn (stack_pointer_rtx,
thisblock->data.block.stack_level);
if (nonlocal_goto_stack_level != 0)
emit_move_insn (nonlocal_goto_stack_level, stack_pointer_rtx);
emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
thisblock->data.block.stack_level, 0);
if (nonlocal_goto_handler_slot != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, 0);
}
/* Any gotos out of this block must also do these things.
Also report any gotos with fixups that came to labels in this level. */
Also report any gotos with fixups that came to labels in this
level. */
fixup_gotos (thisblock,
thisblock->data.block.stack_level,
thisblock->data.block.cleanups,
@ -2753,8 +2774,9 @@ expand_decl (decl)
if (thisblock->data.block.stack_level == 0)
{
do_pending_stack_adjust ();
thisblock->data.block.stack_level
= copy_to_reg (stack_pointer_rtx);
emit_stack_save (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
&thisblock->data.block.stack_level,
thisblock->data.block.first_insn);
stack_block_stack = thisblock;
}
@ -2765,11 +2787,14 @@ expand_decl (decl)
0, VOIDmode, 0);
free_temp_slots ();
/* This is equivalent to calling alloca. */
current_function_calls_alloca = 1;
/* Allocate space on the stack for the variable. */
address = allocate_dynamic_stack_space (size, 0, DECL_ALIGN (decl));
if (nonlocal_goto_stack_level != 0)
emit_move_insn (nonlocal_goto_stack_level, stack_pointer_rtx);
if (nonlocal_goto_handler_slot != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, 0);
/* Reference the variable indirect through that rtx. */
DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl), address);