Re: [IA-64] Work around bug in unwinder

2012-03-31 Thread Eric Botcazou
 Looks ok, given the other ugliness in this macro.

Thanks.  There is another pending workaround for IA-64:
  http://gcc.gnu.org/ml/gcc-patches/2012-03/msg00451.html
as well as an implementation of stack checking in the back-end:
  http://gcc.gnu.org/ml/gcc-patches/2012-03/msg00452.html

-- 
Eric Botcazou


Re: [IA-64] Work around bug in unwinder

2012-03-30 Thread Richard Henderson
On 03/21/2012 01:03 PM, Eric Botcazou wrote:
 2012-03-21  Eric Botcazou  ebotca...@adacore.com
 
   * config/ia64/unwind-ia64.c (uw_install_context): Manually save LC
   if it hasn't been previously saved.

Looks ok, given the other ugliness in this macro.


r~


[IA-64] Work around bug in unwinder

2012-03-21 Thread Eric Botcazou
Another latent issue exposed on IA-64 (both Linux and VMS) by GCC 4.7: the LC 
(Loop Counter) register isn't preserved by the unwinder.

The compiler generates unwind info for LC and unwind-ia64.c:uw_install_context 
restores it if this is deemed necessary.  The hitch is that deemed necessary 
means register saved at some point along the path between thrower and catcher 
and going through _Unwind_RaiseException. Now if a register isn't saved along 
this path but clobbered very late, namely in uw_install_context, then nothing 
restores it before the longjmp.

unwind-ia64.c:uw_install_context reads:

static void __attribute__((noreturn))
uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
struct _Unwind_Context *target)
{
  unsigned long ireg_buf[4], ireg_nat = 0, ireg_pr = 0;
  long i;

  /* Copy integer register data from the target context to a
 temporary buffer.  Do this so that we can frob AR.UNAT
 to get the NaT bits for these registers set properly.  */
  for (i = 4; i = 7; ++i)
{
  char nat;
  void *t = target-ireg[i - 2].loc;
  if (t)
{
  unw_access_gr (target, i, ireg_buf[i - 4], nat, 0);
  ireg_nat |= (long)nat  (((size_t)ireg_buf[i - 4]  3)  0x3f);
  /* Set p6 - p9.  */
  ireg_pr |= 4L  i;
}
}

and it clobbers LC because of the loop when compiled with GCC 4.7 and above.

Bootstrapped/regtested on IA-64/Linux, OK for the mainline?  Do we also want it 
for 4.7.1?


2012-03-21  Eric Botcazou  ebotca...@adacore.com

* config/ia64/unwind-ia64.c (uw_install_context): Manually save LC
if it hasn't been previously saved.


-- 
Eric Botcazou
Index: libgcc/config/ia64/unwind-ia64.c
===
--- libgcc/config/ia64/unwind-ia64.c	(revision 185395)
+++ libgcc/config/ia64/unwind-ia64.c	(working copy)
@@ -2171,8 +2171,20 @@ uw_install_context (struct _Unwind_Conte
 		struct _Unwind_Context *target)
 {
   unsigned long ireg_buf[4], ireg_nat = 0, ireg_pr = 0;
+  unsigned long saved_lc;
   long i;
 
+  /* ??? LC is a fixed register so the call to __builtin_unwind_init in
+ uw_init_context doesn't cause it to be saved.  In case it isn't in
+ the user frames either, we need to manually do it here, lest it be
+ clobbered by the loop just below.  */
+  if (target-lc_loc == NULL)
+{
+  register unsigned long lc asm (ar.lc);
+  saved_lc = lc;
+  target-lc_loc = saved_lc;
+}
+
   /* Copy integer register data from the target context to a
  temporary buffer.  Do this so that we can frob AR.UNAT
  to get the NaT bits for these registers set properly.  */