*** 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) 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; old_pending_adj = pending_stack_adjust;
pending_stack_adjust = 0; pending_stack_adjust = 0;
} }
@ -1060,7 +1060,7 @@ expand_call (exp, target, ignore)
{ {
if (old_stack_level == 0) 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; old_pending_adj = pending_stack_adjust;
pending_stack_adjust = 0; pending_stack_adjust = 0;
} }
@ -1520,7 +1520,7 @@ expand_call (exp, target, ignore)
if (old_stack_level) 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; pending_stack_adjust = old_pending_adj;
} }
@ -1570,9 +1570,12 @@ expand_call (exp, target, ignore)
} }
#endif #endif
/* If this was alloca, record the new stack level for nonlocal gotos. */ /* If this was alloca, record the new stack level for nonlocal gotos.
if (may_be_alloca && nonlocal_goto_stack_level != 0) Check for the handler slots since we might not have a save area
emit_move_insn (nonlocal_goto_stack_level, stack_pointer_rtx); 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 (); pop_temp_slots ();

View File

@ -2835,9 +2835,7 @@
;; Next come insns related to the calling sequence. ;; Next come insns related to the calling sequence.
;; ;;
;; First, an insn to allocate new stack space for dynamic use (e.g., alloca). ;; 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 ;; We move the back-chain and decrement the stack pointer.
;; less efficient than it needs to be for long constants, but that case
;; should be rare.
(define_expand "allocate_stack" (define_expand "allocate_stack"
[(set (reg:SI 1) [(set (reg:SI 1)
@ -2852,6 +2850,63 @@
emit_move_insn (stack_bot, chain); emit_move_insn (stack_bot, chain);
DONE; 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 ;; 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 ;; the actual address of the function, whose second word contains a pointer

View File

@ -681,6 +681,127 @@ round_push (size)
return 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 /* 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.

View File

@ -539,6 +539,15 @@ extern void adjust_stack ();
/* Add some bytes to the stack. An rtx says how many. */ /* Add some bytes to the stack. An rtx says how many. */
extern void anti_adjust_stack (); 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 /* Allocate some space on the stack dynamically and return its address. An rtx
says how many bytes. */ says how many bytes. */
extern rtx allocate_dynamic_stack_space (); extern rtx allocate_dynamic_stack_space ();

View File

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

View File

@ -586,11 +586,9 @@ declare_nonlocal_label (label)
{ {
nonlocal_goto_handler_slot nonlocal_goto_handler_slot
= assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
nonlocal_goto_stack_level emit_stack_save (SAVE_NONLOCAL,
= assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); &nonlocal_goto_stack_level,
emit_insn_before (gen_move_insn (nonlocal_goto_stack_level, PREV_INSN (tail_recursion_reentry));
stack_pointer_rtx),
tail_recursion_reentry);
} }
} }
@ -609,27 +607,50 @@ expand_goto (label)
struct function *p = find_function_data (context); struct function *p = find_function_data (context);
rtx temp; rtx temp;
p->has_nonlocal_label = 1; 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
if (HAVE_nonlocal_goto) if (HAVE_nonlocal_goto)
emit_insn (gen_nonlocal_goto (lookup_static_chain (label), emit_insn (gen_nonlocal_goto (lookup_static_chain (label),
p->nonlocal_goto_handler_slot, copy_rtx (p->nonlocal_goto_handler_slot),
p->nonlocal_goto_stack_level, copy_rtx (p->nonlocal_goto_stack_level),
gen_rtx (LABEL_REF, Pmode, gen_rtx (LABEL_REF, Pmode,
label_rtx (label)))); label_rtx (label))));
else else
#endif #endif
{ {
rtx addr;
/* Restore frame pointer for containing function. /* Restore frame pointer for containing function.
This sets the actual hard register used for the frame pointer This sets the actual hard register used for the frame pointer
to the location of the function's incoming static chain info. to the location of the function's incoming static chain info.
The non-local goto handler will then adjust it to contain the The non-local goto handler will then adjust it to contain the
proper value and reload the argument pointer, if needed. */ proper value and reload the argument pointer, if needed. */
emit_move_insn (frame_pointer_rtx, lookup_static_chain (label)); 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, /* Get addr of containing function's current nonlocal goto handler,
which will do any cleanups and then jump to the label. */ 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. */ /* 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. */ /* Put in the static chain register the nonlocal label address. */
emit_move_insn (static_chain_rtx, emit_move_insn (static_chain_rtx,
gen_rtx (LABEL_REF, Pmode, label_rtx (label))); 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. */ the stack pointer. This one should be deleted as dead by flow. */
clear_pending_stack_adjust (); clear_pending_stack_adjust ();
do_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)) 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 /* Restore stack level for the biggest contour that this
jump jumps out of. */ jump jumps out of. */
if (f->stack_level) if (f->stack_level)
emit_insn_after (gen_move_insn (stack_pointer_rtx, f->stack_level), emit_stack_restore (SAVE_BLOCK, f->stack_level, f->before_jump);
f->before_jump);
f->before_jump = 0; f->before_jump = 0;
} }
} }
@ -2592,14 +2612,15 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
if (thisblock->data.block.stack_level != 0) if (thisblock->data.block.stack_level != 0)
{ {
emit_move_insn (stack_pointer_rtx, emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
thisblock->data.block.stack_level); thisblock->data.block.stack_level, 0);
if (nonlocal_goto_stack_level != 0) if (nonlocal_goto_handler_slot != 0)
emit_move_insn (nonlocal_goto_stack_level, stack_pointer_rtx); emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, 0);
} }
/* Any gotos out of this block must also do these things. /* 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, fixup_gotos (thisblock,
thisblock->data.block.stack_level, thisblock->data.block.stack_level,
thisblock->data.block.cleanups, thisblock->data.block.cleanups,
@ -2753,8 +2774,9 @@ expand_decl (decl)
if (thisblock->data.block.stack_level == 0) if (thisblock->data.block.stack_level == 0)
{ {
do_pending_stack_adjust (); do_pending_stack_adjust ();
thisblock->data.block.stack_level emit_stack_save (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
= copy_to_reg (stack_pointer_rtx); &thisblock->data.block.stack_level,
thisblock->data.block.first_insn);
stack_block_stack = thisblock; stack_block_stack = thisblock;
} }
@ -2765,11 +2787,14 @@ expand_decl (decl)
0, VOIDmode, 0); 0, VOIDmode, 0);
free_temp_slots (); free_temp_slots ();
/* This is equivalent to calling alloca. */
current_function_calls_alloca = 1;
/* Allocate space on the stack for the variable. */ /* Allocate space on the stack for the variable. */
address = allocate_dynamic_stack_space (size, 0, DECL_ALIGN (decl)); address = allocate_dynamic_stack_space (size, 0, DECL_ALIGN (decl));
if (nonlocal_goto_stack_level != 0) if (nonlocal_goto_handler_slot != 0)
emit_move_insn (nonlocal_goto_stack_level, stack_pointer_rtx); emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, 0);
/* Reference the variable indirect through that rtx. */ /* Reference the variable indirect through that rtx. */
DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl), address); DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl), address);