OSDN Git Service

runtime: Tweak __go_can_recover for SPARC.
[pf3gnuchains/gcc-fork.git] / libgo / runtime / go-recover.c
index 4de122e..d6403e0 100644 (file)
@@ -4,6 +4,7 @@
    Use of this source code is governed by a BSD-style
    license that can be found in the LICENSE file.  */
 
+#include "runtime.h"
 #include "interface.h"
 #include "go-panic.h"
 #include "go-defer.h"
 _Bool
 __go_can_recover (const void* retaddr)
 {
+  G *g;
   struct __go_defer_stack *d;
   const char* ret;
   const char* dret;
 
-  if (__go_panic_defer == NULL)
-    return 0;
-  d = __go_panic_defer->__defer;
+  g = runtime_g ();
+
+  d = g->defer;
   if (d == NULL)
     return 0;
 
@@ -31,7 +33,7 @@ __go_can_recover (const void* retaddr)
      of the panic stack.  We do not want to recover it if that panic
      was on the top of the panic stack when this function was
      deferred.  */
-  if (d->__panic == __go_panic_defer->__panic)
+  if (d->__panic == g->panic)
     return 0;
 
   /* D->__RETADDR is the address of a label immediately following the
@@ -41,6 +43,14 @@ __go_can_recover (const void* retaddr)
      such as an instruction to adjust the stack pointer.  */
 
   ret = (const char *) retaddr;
+
+#ifdef __sparc__
+  /* On SPARC the address we get, from __builtin_return_address, is
+     the address of the call instruction.  Adjust forward, also
+     skipping the delayed instruction following the call.  */
+  ret += 8;
+#endif
+
   dret = (const char *) d->__retaddr;
   return ret <= dret && ret + 16 >= dret;
 }
@@ -51,11 +61,12 @@ __go_can_recover (const void* retaddr)
 struct __go_empty_interface
 __go_recover ()
 {
+  G *g;
   struct __go_panic_stack *p;
 
-  if (__go_panic_defer == NULL
-      || __go_panic_defer->__panic == NULL
-      || __go_panic_defer->__panic->__was_recovered)
+  g = runtime_g ();
+
+  if (g->panic == NULL || g->panic->__was_recovered)
     {
       struct __go_empty_interface ret;
 
@@ -63,7 +74,7 @@ __go_recover ()
       ret.__object = NULL;
       return ret;
     }
-  p = __go_panic_defer->__panic;
+  p = g->panic;
   p->__was_recovered = 1;
   return p->__arg;
 }