]> gcc.gnu.org Git - gcc.git/commitdiff
*** empty log message ***
authorRichard Kenner <kenner@gcc.gnu.org>
Wed, 6 May 1992 11:35:29 +0000 (07:35 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Wed, 6 May 1992 11:35:29 +0000 (07:35 -0400)
From-SVN: r915

gcc/calls.c
gcc/config/rs6000/rs6000.md
gcc/explow.c
gcc/expr.h
gcc/function.c
gcc/stmt.c

index 90cdb8acbc996d09c3b9fc86a628678fdf045a49..8541d16a9e4a13d0ab9677ae8c4a7239d007fb02 100644 (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 ();
 
index 775d8fc56a78831b17831d1e5957a0d5eadd894f..d3e6bce9ccfe8f3c403b37825c1d8b47c5c9db29 100644 (file)
 ;; 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)
   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;
+}")
 \f
 ;; 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
index f2b72f6969c52b979f5b58e646076060c9d15dd8..4504a73cd09eadab3dbc13f143bee6716de43b4e 100644 (file)
@@ -681,6 +681,127 @@ round_push (size)
   return size;
 }
 \f
+/* 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));
+}
+\f
 /* 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.
index f255b78e4e1e779e3d7961f865084dee01a3db84..3a140d2db9bae9f20f861bb8112ea210872842c1 100644 (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 ();
index c9a9e9520842351ffebd7ad5f11c5aadd48c0684..45dc777581afdcf69656e7e80b68eee27bfa94a8 100644 (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,
index 3f085971db6b57524c7946a2bc5bbf33c4ebf005..e2c52bfed17ed3dd5e9f35d026b1c3ac4464c155 100644 (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);
This page took 0.08342 seconds and 5 git commands to generate.