On Mon, Jun 27, 2011 at 7:58 AM, Jason Merrill <ja...@redhat.com> wrote:
> On 06/26/2011 05:58 PM, H.J. Lu wrote:
>>
>> The current unwind library scheme provides only one unwind
>> context and is backward compatible with multiple different unwind
>> contexts from multiple unwind libraries:
>>
>> http://gcc.gnu.org/ml/gcc-patches/2006-12/msg01769.html
>>
>> My patch fixes UNITS_PER_WORD > sizeof (void *) and
>> enforces single unwind context when backward compatibility
>> isn't needed.
>
> OK, there seem to be two things going on in this patch:
>
> 1) Handle registers larger than pointers.
> 2) Require that all code share a single copy of the unwinder.
>
> For #2, how are you avoiding the issues Jakub describes in that message?
>  Isn't his scenario 2 still possible?  Are you deciding that it's better to
> abort at run-time in that case?
>
> It seems to me that for targets newer than Jakub's patch we can hard-wire
> _Unwind_IsExtendedContext to true, but making further assumptions would be a
> mistake.
>
> Then, if we're still trying to handle versioning, I think your earlier patch
> for #1 (r170716) that just changes the type of the reg array is a better way
> to go.  But that change should be dependent on a target macro to avoid ABI
> changes for existing targets.
>

This updated patch.  It allows multiple unwind contexts.  It replaces

char by_value[DWARF_FRAME_REGISTERS+1];

with

_Unwind_Word value[DWARF_FRAME_REGISTERS+1];

The code is cleaner than conditionally replacing

void *reg[DWARF_FRAME_REGISTERS+1];

with

_Unwind_Word reg[DWARF_FRAME_REGISTERS+1];

with a bigger unwind context.  But it is more flexible if we
want to extend unwind context later, like saving/restoring
128bit or vector registers which may be bigger than the current
_Unwind_Word.

Thanks.

-- 
H.J.
----
gcc/

2011-06-28  H.J. Lu  <hongjiu...@intel.com>

        * config.gcc (libgcc_tm_file): Add i386/value-unwind.h for
        Linux/x86.

        * system.h (REG_VALUE_IN_UNWIND_CONTEXT): Poisoned.

        * unwind-dw2.c (_Unwind_Context): If REG_VALUE_IN_UNWIND_CONTEXT
        is defined, add value and remove by_value.
        (SIGNAL_FRAME_BIT): Define if REG_VALUE_IN_UNWIND_CONTEXT is
        defined.
        (EXTENDED_CONTEXT_BIT): Don't define if REG_VALUE_IN_UNWIND_CONTEXT
        is defined.
        (_Unwind_IsExtendedContext): Likewise.
        (_Unwind_GetGR): Support REG_VALUE_IN_UNWIND_CONTEXT.
        (_Unwind_SetGR): Likewise.
        (_Unwind_GetGRPtr): Likewise.
        (_Unwind_SetGRPtr): Likewise.
        (_Unwind_SetGRValue): Likewise.
        (_Unwind_GRByValue): Likewise.
        (__frame_state_for): Likewise.
        (uw_install_context_1): Likewise.

        * doc/tm.texi.in: Document REG_VALUE_IN_UNWIND_CONTEXT.
        * doc/tm.texi: Regenerated.

libgcc/

2011-06-28  H.J. Lu  <hongjiu...@intel.com>

        * config/i386/value-unwind.h: New.
gcc/

2011-06-28  H.J. Lu  <hongjiu...@intel.com>

        * config.gcc (libgcc_tm_file): Add i386/value-unwind.h for
        Linux/x86.

        * system.h (REG_VALUE_IN_UNWIND_CONTEXT): Poisoned.

        * unwind-dw2.c (_Unwind_Context): If REG_VALUE_IN_UNWIND_CONTEXT
        is defined, add value and remove by_value.
        (SIGNAL_FRAME_BIT): Define if REG_VALUE_IN_UNWIND_CONTEXT is
        defined.
        (EXTENDED_CONTEXT_BIT): Don't define if REG_VALUE_IN_UNWIND_CONTEXT
        is defined.
        (_Unwind_IsExtendedContext): Likewise.
        (_Unwind_GetGR): Support REG_VALUE_IN_UNWIND_CONTEXT.
        (_Unwind_SetGR): Likewise.
        (_Unwind_GetGRPtr): Likewise.
        (_Unwind_SetGRPtr): Likewise.
        (_Unwind_SetGRValue): Likewise.
        (_Unwind_GRByValue): Likewise.
        (__frame_state_for): Likewise.
        (uw_install_context_1): Likewise.

        * doc/tm.texi.in: Document REG_VALUE_IN_UNWIND_CONTEXT.
        * doc/tm.texi: Regenerated.

libgcc/

2011-06-28  H.J. Lu  <hongjiu...@intel.com>

        * config/i386/value-unwind.h: New.

diff --git a/gcc/config.gcc b/gcc/config.gcc
index a1dbd1a..c9867a2 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2627,6 +2648,7 @@ esac
 case ${target} in
 i[34567]86-*-linux* | x86_64-*-linux*)
        tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386"
+       libgcc_tm_file="${libgcc_tm_file} i386/value-unwind.h"
        ;;
 i[34567]86-*-* | x86_64-*-*)
        tmake_file="${tmake_file} i386/t-gmm_malloc i386/t-i386"
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 341628b..2666716 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -3701,6 +3701,14 @@ return @code{@var{regno}}.
 
 @end defmac
 
+@defmac REG_VALUE_IN_UNWIND_CONTEXT
+
+Define this macro if the target stores register values as
+@code{_Unwind_Word} type in unwind context.  The default is to
+store register values as @code{void *} type.
+
+@end defmac
+
 @node Elimination
 @subsection Eliminating Frame Pointer and Arg Pointer
 
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index f7c16e9..690fa52 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3687,6 +3687,14 @@ return @code{@var{regno}}.
 
 @end defmac
 
+@defmac REG_VALUE_IN_UNWIND_CONTEXT
+
+Define this macro if the target stores register values as
+@code{_Unwind_Word} type in unwind context.  The default is to
+store register values as @code{void *} type.
+
+@end defmac
+
 @node Elimination
 @subsection Eliminating Frame Pointer and Arg Pointer
 
diff --git a/gcc/system.h b/gcc/system.h
index e02cbcd..ed39d93 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -764,7 +764,7 @@ extern void fancy_abort (const char *, int, const char *) 
ATTRIBUTE_NORETURN;
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */
  #pragma GCC poison DECLARE_LIBRARY_RENAMES LIBGCC2_GNU_PREFIX         \
-       MD_UNWIND_SUPPORT ENABLE_EXECUTE_STACK
+       MD_UNWIND_SUPPORT ENABLE_EXECUTE_STACK REG_VALUE_IN_UNWIND_CONTEXT
 
 /* Other obsolete target macros, or macros that used to be in target
    headers and were not used, and may be obsolete or may never have
diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c
index 19da299..8014a1b 100644
--- a/gcc/unwind-dw2.c
+++ b/gcc/unwind-dw2.c
@@ -69,16 +69,25 @@ struct _Unwind_Context
   void *ra;
   void *lsda;
   struct dwarf_eh_bases bases;
+#ifdef REG_VALUE_IN_UNWIND_CONTEXT
+  /* Signal frame context.  */
+#define SIGNAL_FRAME_BIT ((_Unwind_Word) 1 >> 0)
+#else
   /* Signal frame context.  */
 #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1)
   /* Context which has version/args_size/by_value fields.  */
 #define EXTENDED_CONTEXT_BIT ((~(_Unwind_Word) 0 >> 2) + 1)
+#endif
   _Unwind_Word flags;
   /* 0 for now, can be increased when further fields are added to
      struct _Unwind_Context.  */
   _Unwind_Word version;
   _Unwind_Word args_size;
+#ifdef REG_VALUE_IN_UNWIND_CONTEXT
+  _Unwind_Word value[DWARF_FRAME_REGISTERS+1];
+#else
   char by_value[DWARF_FRAME_REGISTERS+1];
+#endif
 };
 
 /* Byte size of every register managed by these routines.  */
@@ -144,11 +153,13 @@ _Unwind_SetSignalFrame (struct _Unwind_Context *context, 
int val)
     context->flags &= ~SIGNAL_FRAME_BIT;
 }
 
+#ifndef REG_VALUE_IN_UNWIND_CONTEXT
 static inline _Unwind_Word
 _Unwind_IsExtendedContext (struct _Unwind_Context *context)
 {
   return context->flags & EXTENDED_CONTEXT_BIT;
 }
+#endif
 
 /* Get the value of register INDEX as saved in CONTEXT.  */
 
@@ -168,8 +179,13 @@ _Unwind_GetGR (struct _Unwind_Context *context, int index)
   size = dwarf_reg_size_table[index];
   ptr = context->reg[index];
 
+#ifdef REG_VALUE_IN_UNWIND_CONTEXT
+  if (context->reg[index] == &context->value[index])
+    return context->value[index];
+#else
   if (_Unwind_IsExtendedContext (context) && context->by_value[index])
     return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr;
+#endif
 
   /* This will segfault if the register hasn't been saved.  */
   if (size == sizeof(_Unwind_Ptr))
@@ -207,11 +223,19 @@ _Unwind_SetGR (struct _Unwind_Context *context, int 
index, _Unwind_Word val)
   gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
   size = dwarf_reg_size_table[index];
 
+#ifdef REG_VALUE_IN_UNWIND_CONTEXT
+  if (context->reg[index] == &context->value[index])
+    {
+      context->value[index] = val;
+      return;
+    }
+#else
   if (_Unwind_IsExtendedContext (context) && context->by_value[index])
     {
       context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
       return;
     }
+#endif
 
   ptr = context->reg[index];
 
@@ -230,8 +254,10 @@ static inline void *
 _Unwind_GetGRPtr (struct _Unwind_Context *context, int index)
 {
   index = DWARF_REG_TO_UNWIND_COLUMN (index);
+#ifndef REG_VALUE_IN_UNWIND_CONTEXT
   if (_Unwind_IsExtendedContext (context) && context->by_value[index])
     return &context->reg[index];
+#endif
   return context->reg[index];
 }
 
@@ -241,8 +267,10 @@ static inline void
 _Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p)
 {
   index = DWARF_REG_TO_UNWIND_COLUMN (index);
+#ifndef REG_VALUE_IN_UNWIND_CONTEXT
   if (_Unwind_IsExtendedContext (context))
     context->by_value[index] = 0;
+#endif
   context->reg[index] = p;
 }
 
@@ -254,10 +282,15 @@ _Unwind_SetGRValue (struct _Unwind_Context *context, int 
index,
 {
   index = DWARF_REG_TO_UNWIND_COLUMN (index);
   gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
+#ifdef REG_VALUE_IN_UNWIND_CONTEXT
+  gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Word));
+  context->value[index] = val;
+  context->reg[index] = &context->value[index];
+#else
   gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr));
-
   context->by_value[index] = 1;
   context->reg[index] = (void *) (_Unwind_Internal_Ptr) val;
+#endif
 }
 
 /* Return nonzero if register INDEX is stored by value rather than
@@ -267,7 +300,11 @@ static inline int
 _Unwind_GRByValue (struct _Unwind_Context *context, int index)
 {
   index = DWARF_REG_TO_UNWIND_COLUMN (index);
+#ifdef REG_VALUE_IN_UNWIND_CONTEXT
+  return context->reg[index] == &context->value[index];
+#else
   return context->by_value[index];
+#endif
 }
 
 /* Retrieve the return address for CONTEXT.  */
@@ -1215,7 +1252,9 @@ __frame_state_for (void *pc_target, struct frame_state 
*state_in)
   int reg;
 
   memset (&context, 0, sizeof (struct _Unwind_Context));
+#ifndef REG_VALUE_IN_UNWIND_CONTEXT
   context.flags = EXTENDED_CONTEXT_BIT;
+#endif
   context.ra = pc_target + 1;
 
   if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON)
@@ -1453,7 +1492,9 @@ uw_init_context_1 (struct _Unwind_Context *context,
 
   memset (context, 0, sizeof (struct _Unwind_Context));
   context->ra = ra;
+#ifndef REG_VALUE_IN_UNWIND_CONTEXT
   context->flags = EXTENDED_CONTEXT_BIT;
+#endif
 
   code = uw_frame_state_for (context, &fs);
   gcc_assert (code == _URC_NO_REASON);
@@ -1535,8 +1576,13 @@ uw_install_context_1 (struct _Unwind_Context *current,
       void *c = current->reg[i];
       void *t = target->reg[i];
 
+#ifdef REG_VALUE_IN_UNWIND_CONTEXT
+      gcc_assert (current->reg[i] != &current->value[i]);
+      if (target->reg[i] == &target->value[i] && c)
+#else
       gcc_assert (current->by_value[i] == 0);
       if (target->by_value[i] && c)
+#endif
        {
          _Unwind_Word w;
          _Unwind_Ptr p;
diff --git a/libgcc/config/i386/value-unwind.h 
b/libgcc/config/i386/value-unwind.h
new file mode 100644
index 0000000..0dceb5c
--- /dev/null
+++ b/libgcc/config/i386/value-unwind.h
@@ -0,0 +1,26 @@
+/* Store register values as _Unwind_Word type in DWARF2 EH unwind context.
+   Copyright (C) 2011
+   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 3, or (at your
+   option) any later version.
+
+   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 and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Define this macro if the target stores register values as _Unwind_Word
+   type in unwind context.  Only enable it for x32.  */
+#if defined __x86_64 && !defined __LP64__
+# define REG_VALUE_IN_UNWIND_CONTEXT
+#endif

Reply via email to