public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Xtensa] use DWARF unwinding
@ 2007-11-13 23:44 Bob Wilson
  2007-11-14  9:18 ` [wwwdocs] document Xtensa backend changes for 4.3 Bob Wilson
  0 siblings, 1 reply; 2+ messages in thread
From: Bob Wilson @ 2007-11-13 23:44 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 915 bytes --]

I'm committing this patch to (finally) stop using setjmp/longjmp unwinding for 
exception handling in the Xtensa port.  I'm assuming here that no one cares if I 
make Xtensa changes like this during stage 3.  Unwinding Xtensa's variable-size 
register windows doesn't fit nicely into the standard DWARF unwinding mechanism, 
so we used a customized version of the DWARF unwinder.  This passes all the C 
and C++ testsuites for an xtensa-elf target.

2007-11-13  Sterling Augustine  <sterling@tensilica.com>
	    Bob Wilson  <bob.wilson@acm.org>
	
	* config/xtensa/unwind-dw2-xtensa.c: New.
	* config/xtensa/unwind-dw2-xtensa.h: New.
	* config/xtensa/xtensa.h (MUST_USE_SJLJ_EXCEPTIONS): Remove.
	(DWARF2_UNWIND_INFO): Remove.
	(DWARF_FRAME_REGISTERS): Define.
	(EH_RETURN_DATA_REGNO): Define.
	* config/xtensa/xtensa.md (UNSPECV_EH_RETURN): Define.
	(eh_return): New.
	* config/xtensa/t-xtensa (LIB2ADDEH): Define.

[-- Attachment #2: gcc-unwind-dw2.patch --]
[-- Type: text/x-diff, Size: 21707 bytes --]

Index: config/xtensa/unwind-dw2-xtensa.c
===================================================================
--- config/xtensa/unwind-dw2-xtensa.c	(revision 0)
+++ config/xtensa/unwind-dw2-xtensa.c	(revision 0)
@@ -0,0 +1,546 @@
+/* DWARF2 exception handling and frame unwinding for Xtensa.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2007
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   In addition to the permissions in the GNU General Public License, the
+   Free Software Foundation gives you unlimited permission to link the
+   compiled version of this file into combinations with other programs,
+   and to distribute those combinations without any restriction coming
+   from the use of this file.  (The General Public License restrictions
+   do apply in other respects; for example, they cover modification of
+   the file, and distribution when not linked into a combined
+   executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "dwarf2.h"
+#include "unwind.h"
+#ifdef __USING_SJLJ_EXCEPTIONS__
+# define NO_SIZE_OF_ENCODED_VALUE
+#endif
+#include "unwind-pe.h"
+#include "unwind-dw2-fde.h"
+#include "unwind-dw2-xtensa.h"
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+
+/* The standard CIE and FDE structures work fine for Xtensa but the
+   variable-size register window save areas are not a good fit for the rest
+   of the standard DWARF unwinding mechanism.  Nor is that mechanism
+   necessary, since the register save areas are always in fixed locations
+   in each stack frame.  This file is a stripped down and customized version
+   of the standard DWARF unwinding code.  It needs to be customized to have
+   builtin logic for finding the save areas and also to track the stack
+   pointer value (besides the CFA) while unwinding since the primary save
+   area is located below the stack pointer.  It is stripped down to reduce
+   code size and ease the maintenance burden of tracking changes in the
+   standard version of the code.  */
+
+#ifndef DWARF_REG_TO_UNWIND_COLUMN
+#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
+#endif
+
+#define XTENSA_RA_FIELD_MASK 0x3FFFFFFF
+
+/* This is the register and unwind state for a particular frame.  This
+   provides the information necessary to unwind up past a frame and return
+   to its caller.  */
+struct _Unwind_Context
+{
+  /* Track register window save areas of 4 registers each, instead of
+     keeping separate addresses for the individual registers.  */
+  _Unwind_Word *reg[4];
+
+  void *cfa;
+  void *sp;
+  void *ra;
+
+  /* Cache the 2 high bits to replace the window size in return addresses.  */
+  _Unwind_Word ra_high_bits;
+
+  void *lsda;
+  struct dwarf_eh_bases bases;
+  /* Signal frame context.  */
+#define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
+  _Unwind_Word flags;
+  /* 0 for now, can be increased when further fields are added to
+     struct _Unwind_Context.  */
+  _Unwind_Word version;
+};
+
+\f
+/* Read unaligned data from the instruction buffer.  */
+
+union unaligned
+{
+  void *p;
+} __attribute__ ((packed));
+
+static void uw_update_context (struct _Unwind_Context *, _Unwind_FrameState *);
+static _Unwind_Reason_Code uw_frame_state_for (struct _Unwind_Context *,
+					       _Unwind_FrameState *);
+
+static inline void *
+read_pointer (const void *p) { const union unaligned *up = p; return up->p; }
+\f
+static inline _Unwind_Word
+_Unwind_IsSignalFrame (struct _Unwind_Context *context)
+{
+  return (context->flags & SIGNAL_FRAME_BIT) ? 1 : 0;
+}
+
+static inline void
+_Unwind_SetSignalFrame (struct _Unwind_Context *context, int val)
+{
+  if (val)
+    context->flags |= SIGNAL_FRAME_BIT;
+  else
+    context->flags &= ~SIGNAL_FRAME_BIT;
+}
+\f
+/* Get the value of register INDEX as saved in CONTEXT.  */
+
+inline _Unwind_Word
+_Unwind_GetGR (struct _Unwind_Context *context, int index)
+{
+  _Unwind_Word *ptr;
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  ptr = context->reg[index >> 2] + (index & 3);
+
+  return *ptr;
+}
+
+/* Get the value of the CFA as saved in CONTEXT.  */
+
+_Unwind_Word
+_Unwind_GetCFA (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->cfa;
+}
+
+/* Overwrite the saved value for register INDEX in CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
+{
+  _Unwind_Word *ptr;
+
+  index = DWARF_REG_TO_UNWIND_COLUMN (index);
+  ptr = context->reg[index >> 2] + (index & 3);
+
+  *ptr = val;
+}
+
+/* Retrieve the return address for CONTEXT.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIP (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Retrieve the return address and flag whether that IP is before
+   or after first not yet fully executed instruction.  */
+
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+  *ip_before_insn = _Unwind_IsSignalFrame (context);
+  return (_Unwind_Ptr) context->ra;
+}
+
+/* Overwrite the return address for CONTEXT with VAL.  */
+
+inline void
+_Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val)
+{
+  context->ra = (void *) val;
+}
+
+void *
+_Unwind_GetLanguageSpecificData (struct _Unwind_Context *context)
+{
+  return context->lsda;
+}
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.func;
+}
+
+void *
+_Unwind_FindEnclosingFunction (void *pc)
+{
+  struct dwarf_eh_bases bases;
+  const struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases);
+  if (fde)
+    return bases.func;
+  else
+    return NULL;
+}
+
+_Unwind_Ptr
+_Unwind_GetDataRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.dbase;
+}
+
+_Unwind_Ptr
+_Unwind_GetTextRelBase (struct _Unwind_Context *context)
+{
+  return (_Unwind_Ptr) context->bases.tbase;
+}
+
+#ifdef MD_UNWIND_SUPPORT
+#include MD_UNWIND_SUPPORT
+#endif
+\f
+/* Extract any interesting information from the CIE for the translation
+   unit F belongs to.  Return a pointer to the byte after the augmentation,
+   or NULL if we encountered an undecipherable augmentation.  */
+
+static const unsigned char *
+extract_cie_info (const struct dwarf_cie *cie, struct _Unwind_Context *context,
+		  _Unwind_FrameState *fs)
+{
+  const unsigned char *aug = cie->augmentation;
+  const unsigned char *p = aug + strlen ((const char *)aug) + 1;
+  const unsigned char *ret = NULL;
+  _uleb128_t utmp;
+  _sleb128_t stmp;
+
+  /* g++ v2 "eh" has pointer immediately following augmentation string,
+     so it must be handled first.  */
+  if (aug[0] == 'e' && aug[1] == 'h')
+    {
+      fs->eh_ptr = read_pointer (p);
+      p += sizeof (void *);
+      aug += 2;
+    }
+
+  /* Immediately following the augmentation are the code and
+     data alignment and return address column.  */
+  p = read_uleb128 (p, &utmp);
+  p = read_sleb128 (p, &stmp);
+  if (cie->version == 1)
+    fs->retaddr_column = *p++;
+  else
+    {
+      p = read_uleb128 (p, &utmp);
+      fs->retaddr_column = (_Unwind_Word)utmp;
+    }
+  fs->lsda_encoding = DW_EH_PE_omit;
+
+  /* If the augmentation starts with 'z', then a uleb128 immediately
+     follows containing the length of the augmentation field following
+     the size.  */
+  if (*aug == 'z')
+    {
+      p = read_uleb128 (p, &utmp);
+      ret = p + utmp;
+
+      fs->saw_z = 1;
+      ++aug;
+    }
+
+  /* Iterate over recognized augmentation subsequences.  */
+  while (*aug != '\0')
+    {
+      /* "L" indicates a byte showing how the LSDA pointer is encoded.  */
+      if (aug[0] == 'L')
+	{
+	  fs->lsda_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "R" indicates a byte indicating how FDE addresses are encoded.  */
+      else if (aug[0] == 'R')
+	{
+	  fs->fde_encoding = *p++;
+	  aug += 1;
+	}
+
+      /* "P" indicates a personality routine in the CIE augmentation.  */
+      else if (aug[0] == 'P')
+	{
+	  _Unwind_Ptr personality;
+	  
+	  p = read_encoded_value (context, *p, p + 1, &personality);
+	  fs->personality = (_Unwind_Personality_Fn) personality;
+	  aug += 1;
+	}
+
+      /* "S" indicates a signal frame.  */
+      else if (aug[0] == 'S')
+	{
+	  fs->signal_frame = 1;
+	  aug += 1;
+	}
+
+      /* Otherwise we have an unknown augmentation string.
+	 Bail unless we saw a 'z' prefix.  */
+      else
+	return ret;
+    }
+
+  return ret ? ret : p;
+}
+\f
+/* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for
+   its caller and decode it into FS.  This function also sets the
+   lsda member of CONTEXT, as it is really information
+   about the caller's frame.  */
+
+static _Unwind_Reason_Code
+uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  const struct dwarf_fde *fde;
+  const struct dwarf_cie *cie;
+  const unsigned char *aug;
+  int window_size;
+  _Unwind_Word *ra_ptr;
+
+  memset (fs, 0, sizeof (*fs));
+  context->lsda = 0;
+
+  ra_ptr = context->reg[0];
+  if (ra_ptr && *ra_ptr == 0)
+    return _URC_END_OF_STACK;
+
+  fde = _Unwind_Find_FDE (context->ra + _Unwind_IsSignalFrame (context) - 1,
+			  &context->bases);
+  if (fde == NULL)
+    {
+#ifdef MD_FALLBACK_FRAME_STATE_FOR
+      _Unwind_Reason_Code reason;
+      /* Couldn't find frame unwind info for this function.  Try a
+	 target-specific fallback mechanism.  This will necessarily
+	 not provide a personality routine or LSDA.  */
+      reason = MD_FALLBACK_FRAME_STATE_FOR (context, fs);
+      if (reason != _URC_END_OF_STACK)
+	return reason;
+      /* The frame was not recognized and handled by the fallback function,
+	 but it is not really the end of the stack.  Fall through here and
+	 unwind it anyway.  */
+#endif
+      fs->pc = context->ra;
+    }
+  else
+    {
+      fs->pc = context->bases.func;
+
+      cie = get_cie (fde);
+      if (extract_cie_info (cie, context, fs) == NULL)
+	/* CIE contained unknown augmentation.  */
+	return _URC_FATAL_PHASE1_ERROR;
+
+      /* Locate augmentation for the fde.  */
+      aug = (const unsigned char *) fde + sizeof (*fde);
+      aug += 2 * size_of_encoded_value (fs->fde_encoding);
+      if (fs->saw_z)
+	{
+	  _uleb128_t i;
+	  aug = read_uleb128 (aug, &i);
+	}
+      if (fs->lsda_encoding != DW_EH_PE_omit)
+	{
+	  _Unwind_Ptr lsda;
+
+	  aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda);
+	  context->lsda = (void *) lsda;
+	}
+    }
+
+  /* Find the window size from the high bits of the return address.  */
+  if (ra_ptr)
+    window_size = (*ra_ptr >> 30) * 4;
+  else
+    window_size = 8;
+
+  fs->retaddr_column = window_size;
+
+  return _URC_NO_REASON;
+}
+\f
+static void
+uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  struct _Unwind_Context orig_context = *context;
+  _Unwind_Word *sp, *cfa, *next_cfa;
+  int i;
+
+  if (fs->signal_frame)
+    {
+      cfa = (_Unwind_Word *) fs->signal_regs[1];
+      next_cfa = (_Unwind_Word *) cfa[-3];
+
+      for (i = 0; i < 4; i++)
+	context->reg[i] = fs->signal_regs + (i << 2);
+    }
+  else
+    {
+      int window_size = fs->retaddr_column >> 2;
+
+      sp = (_Unwind_Word *) orig_context.sp;
+      cfa = (_Unwind_Word *) orig_context.cfa;
+      next_cfa = (_Unwind_Word *) cfa[-3];
+
+      /* Registers a0-a3 are in the save area below sp.  */
+      context->reg[0] = sp - 4;
+
+      /* Find the extra save area below next_cfa.  */
+      for (i = 1; i < window_size; i++)
+	context->reg[i] = next_cfa - 4 * (1 + window_size - i);
+
+      /* Remaining registers rotate from previous save areas.  */
+      for (i = window_size; i < 4; i++)
+	context->reg[i] = orig_context.reg[i - window_size];
+    }
+
+  context->sp = cfa;
+  context->cfa = next_cfa;
+
+  _Unwind_SetSignalFrame (context, fs->signal_frame);
+}
+
+/* CONTEXT describes the unwind state for a frame, and FS describes the FDE
+   of its caller.  Update CONTEXT to refer to the caller as well.  Note
+   that the lsda member is not updated here, but later in
+   uw_frame_state_for.  */
+
+static void
+uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context_1 (context, fs);
+
+  /* Compute the return address now, since the return address column
+     can change from frame to frame.  */
+  context->ra = (void *) ((_Unwind_GetGR (context, fs->retaddr_column)
+			   & XTENSA_RA_FIELD_MASK) | context->ra_high_bits);
+}
+
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+  uw_update_context (context, fs);
+}
+\f
+/* Fill in CONTEXT for top-of-stack.  The only valid registers at this
+   level will be the return address and the CFA.  */
+
+#define uw_init_context(CONTEXT)					   \
+  do									   \
+    {									   \
+      __builtin_unwind_init ();						   \
+      uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),		   \
+			 __builtin_return_address (0));			   \
+    }									   \
+  while (0)
+
+static void
+uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa,
+		   void *outer_ra)
+{
+  void *ra = __builtin_return_address (0);
+  void *cfa = __builtin_dwarf_cfa ();
+  _Unwind_FrameState fs;
+
+  memset (context, 0, sizeof (struct _Unwind_Context));
+  context->ra = ra;
+
+  memset (&fs, 0, sizeof (fs));
+  fs.retaddr_column = 8;
+  context->sp = cfa;
+  context->cfa = outer_cfa;
+  context->ra_high_bits =
+    ((_Unwind_Word) uw_init_context_1) & ~XTENSA_RA_FIELD_MASK;
+  uw_update_context_1 (context, &fs);
+
+  context->ra = outer_ra;
+}
+
+
+/* Install TARGET into CURRENT so that we can return to it.  This is a
+   macro because __builtin_eh_return must be invoked in the context of
+   our caller.  */
+
+#define uw_install_context(CURRENT, TARGET)				 \
+  do									 \
+    {									 \
+      long offset = uw_install_context_1 ((CURRENT), (TARGET));		 \
+      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	 \
+      __builtin_eh_return (offset, handler);				 \
+    }									 \
+  while (0)
+
+static long
+uw_install_context_1 (struct _Unwind_Context *current,
+		      struct _Unwind_Context *target)
+{
+  long i;
+
+  /* The eh_return insn assumes a window size of 8, so don't bother copying
+     the save areas for registers a8-a15 since they won't be reloaded.  */
+  for (i = 0; i < 2; ++i)
+    {
+      void *c = current->reg[i];
+      void *t = target->reg[i];
+
+      if (t && c && t != c)
+	memcpy (c, t, 4 * sizeof (_Unwind_Word));
+    }
+
+  return 0;
+}
+
+static inline _Unwind_Ptr
+uw_identify_context (struct _Unwind_Context *context)
+{
+  return _Unwind_GetCFA (context);
+}
+
+
+#include "unwind.inc"
+
+#if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
+alias (_Unwind_Backtrace);
+alias (_Unwind_DeleteException);
+alias (_Unwind_FindEnclosingFunction);
+alias (_Unwind_ForcedUnwind);
+alias (_Unwind_GetDataRelBase);
+alias (_Unwind_GetTextRelBase);
+alias (_Unwind_GetCFA);
+alias (_Unwind_GetGR);
+alias (_Unwind_GetIP);
+alias (_Unwind_GetLanguageSpecificData);
+alias (_Unwind_GetRegionStart);
+alias (_Unwind_RaiseException);
+alias (_Unwind_Resume);
+alias (_Unwind_Resume_or_Rethrow);
+alias (_Unwind_SetGR);
+alias (_Unwind_SetIP);
+#endif
+
+#endif /* !USING_SJLJ_EXCEPTIONS */
Index: config/xtensa/unwind-dw2-xtensa.h
===================================================================
--- config/xtensa/unwind-dw2-xtensa.h	(revision 0)
+++ config/xtensa/unwind-dw2-xtensa.h	(revision 0)
@@ -0,0 +1,57 @@
+/* DWARF2 frame unwind data structure for Xtensa.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2007
+   Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   In addition to the permissions in the GNU General Public License, the
+   Free Software Foundation gives you unlimited permission to link the
+   compiled version of this file into combinations with other programs,
+   and to distribute those combinations without any restriction coming
+   from the use of this file.  (The General Public License restrictions
+   do apply in other respects; for example, they cover modification of
+   the file, and distribution when not linked into a combined
+   executable.)
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+/* A target can override (perhaps for backward compatibility) how
+   many dwarf2 columns are unwound.  */
+#ifndef DWARF_FRAME_REGISTERS
+#define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
+#endif
+
+/* Xtensa's variable-size register window save areas can be unwound without
+   any unwind info.  This is a stripped down version of the standard DWARF
+   _Unwind_FrameState.  */
+typedef struct
+{
+  /* The PC described by the current frame state.  */
+  void *pc;
+
+  /* The information we care about from the CIE/FDE.  */
+  _Unwind_Personality_Fn personality;
+  _Unwind_Word retaddr_column;
+  unsigned char fde_encoding;
+  unsigned char lsda_encoding;
+  unsigned char saw_z;
+  unsigned char signal_frame;
+  void *eh_ptr;
+
+  /* Saved registers for a signal frame.  */
+  _Unwind_Word *signal_regs;
+} _Unwind_FrameState;
+
Index: config/xtensa/xtensa.h
===================================================================
--- config/xtensa/xtensa.h	(revision 130053)
+++ config/xtensa/xtensa.h	(working copy)
@@ -1062,12 +1062,15 @@
 /* How to start an assembler comment.  */
 #define ASM_COMMENT_START "#"
 
-/* Generate DWARF2 unwind info to get the DW_AT_frame_base set correctly,
-   even though we don't yet use it for unwinding.  */
-#define MUST_USE_SJLJ_EXCEPTIONS 1
-#define DWARF2_UNWIND_INFO 1
+/* Exception handling.  Xtensa uses much of the standard DWARF2 unwinding
+   machinery, but the variable size register window save areas are too
+   complicated to efficiently describe with CFI entries.  The CFA must
+   still be specified in DWARF so that DW_AT_frame_base is set correctly
+   for debugging.  */
 #define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 0)
 #define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (0)
+#define DWARF_FRAME_REGISTERS 16
+#define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) + 2 : INVALID_REGNUM)
 
 /* Xtensa constant pool breaks the devices in crtstuff.c to control
    section in where code resides.  We have to write it as asm code.  Use
Index: config/xtensa/xtensa.md
===================================================================
--- config/xtensa/xtensa.md	(revision 130053)
+++ config/xtensa/xtensa.md	(working copy)
@@ -35,6 +35,7 @@
   (UNSPECV_MEMW		3)
   (UNSPECV_S32RI	4)
   (UNSPECV_S32C1I	5)
+  (UNSPECV_EH_RETURN	6)
 ])
 
 ;; This code iterator allows signed and unsigned widening multiplications
@@ -1600,6 +1601,26 @@
   DONE;
 })
 
+;; Stuff an address into the return address register along with the window
+;; size in the high bits.  Because we don't have the window size of the
+;; previous frame, assume the function called out with a CALL8 since that
+;; is what compilers always use.  Note: __builtin_frob_return_addr has
+;; already been applied to the handler, but the generic version doesn't
+;; allow us to frob it quite enough, so we just frob here.
+
+(define_insn_and_split "eh_return"
+  [(set (reg:SI A0_REG)
+	(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
+			    UNSPECV_EH_RETURN))
+   (clobber (match_scratch:SI 1 "=r"))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (match_dup 1) (ashift:SI (match_dup 0) (const_int 2)))
+   (set (match_dup 1) (plus:SI (match_dup 1) (const_int 2)))
+   (set (reg:SI A0_REG) (rotatert:SI (match_dup 1) (const_int 2)))]
+  "")
+
 ;; Setting up a frame pointer is tricky for Xtensa because GCC doesn't
 ;; know if a frame pointer is required until the reload pass, and
 ;; because there may be an incoming argument value in the hard frame
Index: config/xtensa/t-xtensa
===================================================================
--- config/xtensa/t-xtensa	(revision 130053)
+++ config/xtensa/t-xtensa	(working copy)
@@ -11,6 +11,8 @@
 	_truncdfsf2 _extendsfdf2
 
 LIB2FUNCS_EXTRA = $(srcdir)/config/xtensa/lib2funcs.S
+LIB2ADDEH = $(srcdir)/config/xtensa/unwind-dw2-xtensa.c \
+   $(srcdir)/unwind-dw2-fde.c $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
 
 $(T)crti.o: $(srcdir)/config/xtensa/crti.asm $(GCC_PASSES)
 	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \

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

* [wwwdocs] document Xtensa backend changes for 4.3
  2007-11-13 23:44 [Xtensa] use DWARF unwinding Bob Wilson
@ 2007-11-14  9:18 ` Bob Wilson
  0 siblings, 0 replies; 2+ messages in thread
From: Bob Wilson @ 2007-11-14  9:18 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 234 bytes --]

I have updated the 4.3 release notes to mention the Xtensa backend's change from 
sjlj to DWARF unwinding, and while I was at it, I included a few other less 
significant changes.  I checked the revised file with the HTML validator.


[-- Attachment #2: gcc-changes.patch --]
[-- Type: text/x-diff, Size: 1061 bytes --]

Index: changes.html
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/gcc-4.3/changes.html,v
retrieving revision 1.82
diff -u -r1.82 changes.html
--- changes.html	2 Nov 2007 07:27:23 -0000	1.82
+++ changes.html	14 Nov 2007 01:23:55 -0000
@@ -745,6 +745,20 @@
         option and can be accessed using new built-in functions.</li>
   </ul>
 
+<h3>Xtensa</h3>
+  <ul>
+    <li>Stack unwinding for exception handling now uses by default a
+	specialized version of DWARF unwinding.  This is not
+	binary-compatible with the setjmp/longjmp (sjlj) unwinding used 
+	for Xtensa with previous versions of GCC.</li>
+    <li>For Xtensa processors that include the Conditional Store option,
+	the built-in functions for atomic memory access are now implemented
+	using <code>S32C1I</code> instructions.</li>
+    <li>If the Xtensa NSA option is available, GCC will use it to implement
+	the <code>__builtin_ctz</code> and <code>__builtin_clz</code>
+	functions.</li>
+  </ul>
+
 
 <h2>Documentation improvements</h2>
 

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

end of thread, other threads:[~2007-11-14  1:32 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-13 23:44 [Xtensa] use DWARF unwinding Bob Wilson
2007-11-14  9:18 ` [wwwdocs] document Xtensa backend changes for 4.3 Bob Wilson

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).