unwind-dw2.c (uw_update_context_1): Only set cfa as sp if previous frame didn't save sp.

        * unwind-dw2.c (uw_update_context_1): Only set cfa as sp if
        previous frame didn't save sp.  Clear sp for next frame.
        (uw_install_context_1): Honor saved sp from frame.

From-SVN: r66527
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8f14981..a6e456c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2003-05-06  Richard Henderson  <rth@redhat.com>
+
+        * unwind-dw2.c (uw_update_context_1): Only set cfa as sp if 
+        previous frame didn't save sp.  Clear sp for next frame.
+        (uw_install_context_1): Honor saved sp from frame.
+
 2003-05-03  Richard Henderson  <rth@redhat.com>
 
         * builtins.c (expand_builtin) <BUILT_IN_DWARF_FP_REGNUM>: Remove.
diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c
index d4269df..52b0b8d 100644
--- a/gcc/unwind-dw2.c
+++ b/gcc/unwind-dw2.c
@@ -1033,11 +1033,17 @@
      In very special situations (such as unwind info for signal return),
      there may be location expressions that use the stack pointer as well.
 
-     Given that other unwind mechanisms generally won't work if you try
-     to represent stack pointer saves and restores directly, we don't
-     bother conditionalizing this at all.  */
-  tmp_sp = (_Unwind_Ptr) context->cfa;
-  orig_context.reg[__builtin_dwarf_sp_column ()] = &tmp_sp;
+     Do this conditionally for one frame.  This allows the unwind info
+     for one frame to save a copy of the stack pointer from the previous
+     frame, and be able to use much easier CFA mechanisms to do it.
+     Always zap the saved stack pointer value for the next frame; carrying
+     the value over from one frame to another doesn't make sense.  */
+  if (!orig_context.reg[__builtin_dwarf_sp_column ()])
+    {
+      tmp_sp = (_Unwind_Ptr) context->cfa;
+      orig_context.reg[__builtin_dwarf_sp_column ()] = &tmp_sp;
+    }
+  context->reg[__builtin_dwarf_sp_column ()] = NULL;
 
   /* Compute this frame's CFA.  */
   switch (fs->cfa_how)
@@ -1170,6 +1176,7 @@
 		      struct _Unwind_Context *target)
 {
   long i;
+  void *target_cfa;
 
 #if __GTHREADS
   {
@@ -1191,11 +1198,18 @@
 	memcpy (c, t, dwarf_reg_size_table[i]);
     }
 
+  /* If the last frame records a saved stack pointer, use it.  */
+  if (target->reg[__builtin_dwarf_sp_column ()])
+    target_cfa = (void *)(_Unwind_Ptr)
+      _Unwind_GetGR (target, __builtin_dwarf_sp_column ());
+  else
+    target_cfa = target->cfa;
+
   /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */
   if (STACK_GROWS_DOWNWARD)
-    return target->cfa - current->cfa + target->args_size;
+    return target_cfa - current->cfa + target->args_size;
   else
-    return current->cfa - target->cfa - target->args_size;
+    return current->cfa - target_cfa - target->args_size;
 }
 
 static inline _Unwind_Ptr