public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Fix E500 unwinding
@ 2007-02-14 17:10 Joseph S. Myers
  2007-02-22 13:17 ` Ping " Joseph S. Myers
  0 siblings, 1 reply; 3+ messages in thread
From: Joseph S. Myers @ 2007-02-14 17:10 UTC (permalink / raw)
  To: gcc-patches

Unwinding on E500 fails to restore the high parts of registers because
__builtin_init_dwarf_reg_size_table fails to fill in information about
the sizes of those high parts which have separate unwind information
from the register low parts.

This patch fixes this by adding a new target hook to fill in such
extra information.  With this fixed, it's possible to see that the
Linux signal unwind support is also missing support for register high
parts, so this patch fixes that as well in the obvious way.

Tested with no regressions with cross to powerpc-none-linux-gnuspe.
OK to commit?

2007-02-14  Joseph Myers  <joseph@codesourcery.com>

	* target.h (init_dwarf_reg_sizes_extra): New target hook.
	* target-def.h (TARGET_INIT_DWARF_REG_SIZES_EXTRA): New default.
	* doc/tm.texi (TARGET_INIT_DWARF_REG_SIZES_EXTRA): Document.
	* dwarf2out.c (expand_builtin_init_dwarf_reg_sizes): Call this
	hook.
	* config/rs6000/rs6000.c (TARGET_INIT_DWARF_REG_SIZES_EXTRA,
	rs6000_init_dwarf_reg_sizes_extra): New.
	* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Support
	SPE register high parts.

testsuite:
2007-02-14  Joseph Myers  <joseph@codesourcery.com>

	* gcc.target/powerpc/spe-unwind-1.c, g++.dg/eh/simd-5.C: New
	tests.

Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 121902)
+++ gcc/doc/tm.texi	(working copy)
@@ -8166,6 +8166,15 @@
 If not defined, the default is to return @code{NULL_RTX}.
 @end deftypefn
 
+@deftypefn {Target Hook} void TARGET_INIT_DWARF_REG_SIZES_EXTRA (tree @var{address})
+If some registers are represented in Dwarf-2 unwind information in
+multiple pieces, define this hook to fill in information about the
+sizes of those pieces in the table used by the unwinder at runtime.
+It will be called by @code{expand_builtin_init_dwarf_reg_sizes} after
+filling in a single size corresponding to each hard register;
+@var{address} is the address of the table.
+@end deftypefn
+
 @deftypefn {Target Hook} bool TARGET_ASM_TTYPE (rtx @var{sym})
 This hook is used to output a reference from a frame unwinding table to
 the type_info object identified by @var{sym}.  It should return @code{true}
Index: gcc/target.h
===================================================================
--- gcc/target.h	(revision 121902)
+++ gcc/target.h	(working copy)
@@ -601,6 +601,12 @@
      hook should return NULL_RTX.  */
   rtx (* dwarf_register_span) (rtx);
 
+  /* If expand_builtin_init_dwarf_reg_sizes needs to fill in table
+     entries not corresponding directly to registers below
+     FIRST_PSEUDO_REGISTER, this hook should generate the necessary
+     code, given the address of the table.  */
+  void (* init_dwarf_reg_sizes_extra) (tree);
+
   /* Fetch the fixed register(s) which hold condition codes, for
      targets where it makes sense to look for duplicate assignments to
      the condition codes.  This should return true if there is such a
Index: gcc/testsuite/gcc.target/powerpc/spe-unwind-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/spe-unwind-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/spe-unwind-1.c	(revision 0)
@@ -0,0 +1,116 @@
+/* Verify that unwinding can find SPE registers in signal frames.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do run { target { powerpc*-*-linux* && powerpc_spe } } } */
+/* { dg-options "-fexceptions -fnon-call-exceptions -O2" } */
+
+#include <unwind.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+
+int count;
+char *null;
+int found_reg;
+
+typedef int v2si __attribute__((__vector_size__(8)));
+
+v2si v1 = { 123, 234 };
+v2si v2 = { 345, 456 };
+
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+                   _Unwind_Exception_Class exc_class,
+                   struct _Unwind_Exception *exc_obj,
+                   struct _Unwind_Context *context,
+                   void *stop_parameter)
+{
+  unsigned int reg;
+  if (actions & _UA_END_OF_STACK)
+    abort ();
+  if (_Unwind_GetGR (context, 1215) == 123)
+    found_reg = 1;
+  return _URC_NO_REASON;
+}
+
+static void force_unwind ()
+{
+  struct _Unwind_Exception *exc = malloc (sizeof (*exc));
+  memset (&exc->exception_class, 0, sizeof (exc->exception_class));
+  exc->exception_cleanup = 0;
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
+#else
+  _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
+#endif
+
+  abort ();
+}
+
+static void counter (void *p __attribute__((unused)))
+{
+  ++count;
+}
+
+static void handler (void *p __attribute__((unused)))
+{
+  if (count != 2)
+    abort ();
+  if (!found_reg)
+    abort ();
+  exit (0);
+}
+
+static int __attribute__((noinline)) fn5 ()
+{
+  char dummy __attribute__((cleanup (counter)));
+  force_unwind ();
+  return 0;
+}
+
+static void fn4 (int sig)
+{
+  char dummy __attribute__((cleanup (counter)));
+  /* Clobber high part without compiler's knowledge so the only saved
+     copy is from the signal frame.  */
+  asm volatile ("evmergelo 15,15,15");
+  fn5 ();
+  null = NULL;
+}
+
+static void fn3 ()
+{
+  abort ();
+}
+
+static int __attribute__((noinline)) fn2 ()
+{
+  register v2si r15 asm("r15");
+  r15 = v1;
+  asm volatile ("" : "+r" (r15));
+  *null = 0;
+  fn3 ();
+  return 0;
+}
+
+static int __attribute__((noinline)) fn1 ()
+{
+  signal (SIGSEGV, fn4);
+  signal (SIGBUS, fn4);
+  fn2 ();
+  return 0;
+}
+
+static int __attribute__((noinline)) fn0 ()
+{
+  char dummy __attribute__((cleanup (handler)));
+  fn1 ();
+  null = 0;
+  return 0;
+}
+
+int main()
+{ 
+  fn0 ();
+  abort ();
+}
Index: gcc/testsuite/g++.dg/eh/simd-5.C
===================================================================
--- gcc/testsuite/g++.dg/eh/simd-5.C	(revision 0)
+++ gcc/testsuite/g++.dg/eh/simd-5.C	(revision 0)
@@ -0,0 +1,44 @@
+// Test EH with V2SI SIMD registers actually restores correct values.
+// Origin: Joseph Myers <joseph@codesourcery.com>
+// { dg-options "-O" }
+// { dg-do run { target powerpc_spe } }
+
+extern "C" void abort (void);
+extern "C" int memcmp (const void *, const void *, __SIZE_TYPE__);
+typedef int __attribute__((vector_size (8))) v2si;
+
+v2si a = { 1, 2 };
+v2si b = { 3, 4 };
+v2si c = { 4, 6 };
+volatile v2si r;
+v2si r2;
+
+void
+f ()
+{
+  register v2si v asm("r15");
+  v = __builtin_spe_evaddw (b, c);
+  asm volatile ("" : "+r" (v));
+  r = v;
+  throw 1;
+}
+
+int
+main ()
+{
+  register v2si v asm("r15");
+  v = __builtin_spe_evaddw (a, b);
+  asm volatile ("" : "+r" (v));
+  try
+    {
+      f ();
+    }
+  catch (int)
+    {
+      r = v;
+      r2 = r;
+      if (memcmp (&r2, &c, sizeof (v2si)))
+	abort ();
+    }
+  return 0;
+}
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 121902)
+++ gcc/dwarf2out.c	(working copy)
@@ -498,6 +498,8 @@
 #ifdef DWARF_ALT_FRAME_RETURN_COLUMN
   init_return_column_size (mode, mem, DWARF_ALT_FRAME_RETURN_COLUMN);
 #endif
+
+  targetm.init_dwarf_reg_sizes_extra (address);
 }
 
 /* Convert a DWARF call frame info. operation to its string name */
Index: gcc/target-def.h
===================================================================
--- gcc/target-def.h	(revision 121902)
+++ gcc/target-def.h	(working copy)
@@ -190,6 +190,7 @@
 #endif
 
 #define TARGET_DWARF_REGISTER_SPAN hook_rtx_rtx_null
+#define TARGET_INIT_DWARF_REG_SIZES_EXTRA hook_void_tree
 
 #ifndef TARGET_ASM_FILE_START
 #define TARGET_ASM_FILE_START default_file_start
@@ -688,6 +689,7 @@
   TARGET_ADDRESS_COST,				\
   TARGET_ALLOCATE_INITIAL_VALUE,		\
   TARGET_DWARF_REGISTER_SPAN,                   \
+  TARGET_INIT_DWARF_REG_SIZES_EXTRA,		\
   TARGET_FIXED_CONDITION_CODE_REGS,		\
   TARGET_CC_MODES_COMPATIBLE,			\
   TARGET_MACHINE_DEPENDENT_REORG,		\
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 121902)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -765,6 +765,7 @@
 int easy_vector_constant (rtx, enum machine_mode);
 static bool rs6000_is_opaque_type (tree);
 static rtx rs6000_dwarf_register_span (rtx);
+static void rs6000_init_dwarf_reg_sizes_extra (tree);
 static rtx rs6000_legitimize_tls_address (rtx, enum tls_model);
 static void rs6000_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
 static rtx rs6000_tls_get_addr (void);
@@ -1028,6 +1029,9 @@
 #undef TARGET_DWARF_REGISTER_SPAN
 #define TARGET_DWARF_REGISTER_SPAN rs6000_dwarf_register_span
 
+#undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
+#define TARGET_INIT_DWARF_REG_SIZES_EXTRA rs6000_init_dwarf_reg_sizes_extra
+
 /* On rs6000, function arguments are promoted, as are function return
    values.  */
 #undef TARGET_PROMOTE_FUNCTION_ARGS
@@ -20618,6 +20622,30 @@
 				   gen_rtx_REG (SImode, regno + 1200)));
 }
 
+/* Fill in sizes for SPE register high parts in table used by unwinder.  */
+
+static void
+rs6000_init_dwarf_reg_sizes_extra (tree address)
+{
+  if (TARGET_SPE)
+    {
+      int i;
+      enum machine_mode mode = TYPE_MODE (char_type_node);
+      rtx addr = expand_expr (address, NULL_RTX, VOIDmode, 0);
+      rtx mem = gen_rtx_MEM (BLKmode, addr);
+      rtx value = gen_int_mode (4, mode);
+
+      for (i = 1201; i < 1232; i++)
+	{
+	  int column = DWARF_REG_TO_UNWIND_COLUMN (i);
+	  HOST_WIDE_INT offset
+	    = DWARF_FRAME_REGNUM (column) * GET_MODE_SIZE (mode);
+
+	  emit_move_insn (adjust_address (mem, mode, offset), value);
+	}
+    }
+}
+
 /* Map internal gcc register numbers to DWARF2 register numbers.  */
 
 unsigned int
Index: gcc/config/rs6000/linux-unwind.h
===================================================================
--- gcc/config/rs6000/linux-unwind.h	(revision 121902)
+++ gcc/config/rs6000/linux-unwind.h	(working copy)
@@ -301,6 +301,17 @@
       fs->regs.reg[VRSAVE_REGNO].loc.offset = (long) &vregs->vsave - new_cfa;
     }
 
+  /* If we have SPE register high-parts... we check at compile-time to
+     avoid expanding the code for all other PowerPC.  */
+#ifdef __SPE__
+  for (i = 0; i < 32; i++)
+    {
+      fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].how = REG_SAVED_OFFSET;
+      fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].loc.offset
+	= (long) &regs->vregs - new_cfa + 4 * i;
+    }
+#endif
+
   return _URC_NO_REASON;
 }
 

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Ping Re: Fix E500 unwinding
  2007-02-14 17:10 Fix E500 unwinding Joseph S. Myers
@ 2007-02-22 13:17 ` Joseph S. Myers
  2007-02-28 22:47   ` Ping " Joseph S. Myers
  0 siblings, 1 reply; 3+ messages in thread
From: Joseph S. Myers @ 2007-02-22 13:17 UTC (permalink / raw)
  To: gcc-patches

Ping.  This patch 
<http://gcc.gnu.org/ml/gcc-patches/2007-02/msg01252.html> is pending 
review.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Ping Re: Ping Re: Fix E500 unwinding
  2007-02-22 13:17 ` Ping " Joseph S. Myers
@ 2007-02-28 22:47   ` Joseph S. Myers
  0 siblings, 0 replies; 3+ messages in thread
From: Joseph S. Myers @ 2007-02-28 22:47 UTC (permalink / raw)
  To: gcc-patches

Ping (again).  This patch 
<http://gcc.gnu.org/ml/gcc-patches/2007-02/msg01252.html> is pending 
review.  Note it includes changes to the target-independent parts of the 
compiler to add a new target hook, as well as PowerPC changes.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-02-28 16:38 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-14 17:10 Fix E500 unwinding Joseph S. Myers
2007-02-22 13:17 ` Ping " Joseph S. Myers
2007-02-28 22:47   ` Ping " Joseph S. Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).