From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24137 invoked by alias); 25 Jun 2011 16:14:18 -0000 Received: (qmail 24126 invoked by uid 22791); 25 Jun 2011 16:14:15 -0000 X-SWARE-Spam-Status: No, hits=-1.5 required=5.0 tests=AWL,BAYES_00,NO_DNS_FOR_FROM,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mga03.intel.com (HELO mga03.intel.com) (143.182.124.21) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 25 Jun 2011 16:14:01 +0000 Received: from azsmga001.ch.intel.com ([10.2.17.19]) by azsmga101.ch.intel.com with ESMTP; 25 Jun 2011 09:14:00 -0700 X-ExtLoop1: 1 Received: from gnu-6.sc.intel.com ([10.3.194.135]) by azsmga001.ch.intel.com with ESMTP; 25 Jun 2011 09:13:59 -0700 Received: by gnu-6.sc.intel.com (Postfix, from userid 500) id 09455C26F9; Sat, 25 Jun 2011 09:13:57 -0700 (PDT) Date: Sat, 25 Jun 2011 17:02:00 -0000 From: "H.J. Lu" To: gcc-patches@gcc.gnu.org Cc: Jason Merrill , Richard Henderson Subject: PATCH [8/n]: Prepare x32: PR other/48007: Unwind library doesn't work with UNITS_PER_WORD > sizeof (void *) Message-ID: <20110625161357.GA5401@intel.com> Reply-To: "H.J. Lu" MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-06/txt/msg01915.txt.bz2 Hi, This patch introduces UNIQUE_UNWIND_CONTEXT and properly saves/stores registers with UNITS_PER_WORD > sizeof (void *) as suggested in http://gcc.gnu.org/ml/gcc-patches/2011-03/msg01526.html OK for trunk? Thanks. H.J. --- 2011-04-09 H.J. Lu PR other/48007 * unwind-dw2.c (UNIQUE_UNWIND_CONTEXT): New. (_Unwind_Context): If UNIQUE_UNWIND_CONTEXT is defined, add dwarf_reg_size_table and value, remove version and by_value. (EXTENDED_CONTEXT_BIT): Don't define if UNIQUE_UNWIND_CONTEXT is defined. (_Unwind_IsExtendedContext): Likewise. (_Unwind_GetGR): Support UNIQUE_UNWIND_CONTEXT. (_Unwind_SetGR): Likewise. (_Unwind_GetGRPtr): Likewise. (_Unwind_SetGRPtr): Likewise. (_Unwind_SetGRValue): Likewise. (_Unwind_GRByValue): Likewise. (__frame_state_for): Initialize dwarf_reg_size_table field if UNIQUE_UNWIND_CONTEXT is defined. (uw_install_context_1): Likewise. Support UNIQUE_UNWIND_CONTEXT. diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c index 25990b4..5fa2723 100644 --- a/gcc/unwind-dw2.c +++ b/gcc/unwind-dw2.c @@ -59,6 +59,12 @@ #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO) #endif +#ifndef UNIQUE_UNWIND_CONTEXT +#if defined __x86_64 && !defined __LP64__ +# define UNIQUE_UNWIND_CONTEXT +#endif +#endif + /* 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. */ @@ -69,6 +75,15 @@ struct _Unwind_Context void *ra; void *lsda; struct dwarf_eh_bases bases; +#ifdef UNIQUE_UNWIND_CONTEXT + /* Used to check for unique _Unwind_Context. */ + void *dwarf_reg_size_table; + /* Signal frame context. */ +#define SIGNAL_FRAME_BIT ((_Unwind_Word) 1 >> 0) + _Unwind_Word flags; + _Unwind_Word args_size; + _Unwind_Word value[DWARF_FRAME_REGISTERS+1]; +#else /* Signal frame context. */ #define SIGNAL_FRAME_BIT ((~(_Unwind_Word) 0 >> 1) + 1) /* Context which has version/args_size/by_value fields. */ @@ -79,6 +94,7 @@ struct _Unwind_Context _Unwind_Word version; _Unwind_Word args_size; char by_value[DWARF_FRAME_REGISTERS+1]; +#endif }; /* Byte size of every register managed by these routines. */ @@ -144,11 +160,13 @@ _Unwind_SetSignalFrame (struct _Unwind_Context *context, int val) context->flags &= ~SIGNAL_FRAME_BIT; } +#ifndef UNIQUE_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 +186,14 @@ _Unwind_GetGR (struct _Unwind_Context *context, int index) size = dwarf_reg_size_table[index]; ptr = context->reg[index]; +#ifdef UNIQUE_UNWIND_CONTEXT + gcc_assert (context->dwarf_reg_size_table == &dwarf_reg_size_table); + 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 +231,20 @@ _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 UNIQUE_UNWIND_CONTEXT + gcc_assert (context->dwarf_reg_size_table == &dwarf_reg_size_table); + 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 +263,10 @@ static inline void * _Unwind_GetGRPtr (struct _Unwind_Context *context, int index) { index = DWARF_REG_TO_UNWIND_COLUMN (index); +#ifndef UNIQUE_UNWIND_CONTEXT if (_Unwind_IsExtendedContext (context) && context->by_value[index]) return &context->reg[index]; +#endif return context->reg[index]; } @@ -241,8 +276,10 @@ static inline void _Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p) { index = DWARF_REG_TO_UNWIND_COLUMN (index); +#ifndef UNIQUE_UNWIND_CONTEXT if (_Unwind_IsExtendedContext (context)) context->by_value[index] = 0; +#endif context->reg[index] = p; } @@ -254,10 +291,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 UNIQUE_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 +309,11 @@ static inline int _Unwind_GRByValue (struct _Unwind_Context *context, int index) { index = DWARF_REG_TO_UNWIND_COLUMN (index); +#ifdef UNIQUE_UNWIND_CONTEXT + return context->reg[index] == &context->value[index]; +#else return context->by_value[index]; +#endif } /* Retrieve the return address for CONTEXT. */ @@ -1217,7 +1263,11 @@ __frame_state_for (void *pc_target, struct frame_state *state_in) int reg; memset (&context, 0, sizeof (struct _Unwind_Context)); +#ifdef UNIQUE_UNWIND_CONTEXT + context.dwarf_reg_size_table = &dwarf_reg_size_table; +#else context.flags = EXTENDED_CONTEXT_BIT; +#endif context.ra = pc_target + 1; if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON) @@ -1455,7 +1505,11 @@ uw_init_context_1 (struct _Unwind_Context *context, memset (context, 0, sizeof (struct _Unwind_Context)); context->ra = ra; +#ifdef UNIQUE_UNWIND_CONTEXT + context->dwarf_reg_size_table = &dwarf_reg_size_table; +#else context->flags = EXTENDED_CONTEXT_BIT; +#endif code = uw_frame_state_for (context, &fs); gcc_assert (code == _URC_NO_REASON); @@ -1537,8 +1591,13 @@ uw_install_context_1 (struct _Unwind_Context *current, void *c = current->reg[i]; void *t = target->reg[i]; +#ifdef UNIQUE_UNWIND_CONTEXT + gcc_assert (current->reg[i] != ¤t->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;