re PR middle-end/37275 (ICE when compile libgomp/task.c)
authorJakub Jelinek <jakub@redhat.com>
Fri, 26 Sep 2008 20:59:03 +0000 (22:59 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 26 Sep 2008 20:59:03 +0000 (22:59 +0200)
PR middle-end/37275
* dwarf2out.c (tls_mem_loc_descriptor): New function.
(mem_loc_descriptor): Use it for MEM.  For PLUS fail if second
mem_loc_descriptor failed.  Accept UNSPEC.
(loc_descriptor): Use tls_mem_loc_descriptor for MEM.  For PARALLEL
fail if one of the loc_descriptor calls for pieces failed.
(loc_descriptor_from_tree_1): Handle even DECL_EXTERNAL __thread vars,
as long as they bind locally.  For COMPONENT_REF, ARRAY_REF etc. fail
if loc_descriptor_from_tree_1 on offset failed.

* gcc.target/i386/pr37275.c: New test.

From-SVN: r140712

gcc/ChangeLog
gcc/dwarf2out.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr37275.c [new file with mode: 0644]

index e3e9f0006ab7a0ec5a8bf2cd56a47cb86858960f..740a943fbae246befb55752fd4500ae797a9a523 100644 (file)
@@ -1,5 +1,15 @@
 2008-09-26  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/37275
+       * dwarf2out.c (tls_mem_loc_descriptor): New function.
+       (mem_loc_descriptor): Use it for MEM.  For PLUS fail if second
+       mem_loc_descriptor failed.  Accept UNSPEC.
+       (loc_descriptor): Use tls_mem_loc_descriptor for MEM.  For PARALLEL
+       fail if one of the loc_descriptor calls for pieces failed.
+       (loc_descriptor_from_tree_1): Handle even DECL_EXTERNAL __thread vars,
+       as long as they bind locally.  For COMPONENT_REF, ARRAY_REF etc. fail
+       if loc_descriptor_from_tree_1 on offset failed.
+
        PR middle-end/37576
        * opts.c (common_handle_option): Don't call print_specific_help with
        CL_SAVE as first argument.
index 27b2ca1960c7033973e5dca8539088ab3812f830..98b98a808027764152b5eda5cb732c69544932d5 100644 (file)
@@ -9890,6 +9890,48 @@ concatn_mem_loc_descriptor (rtx concatn, enum machine_mode mode,
   return cc_loc_result;
 }
 
+/* Try to handle TLS MEMs, for which mem_loc_descriptor on XEXP (mem, 0)
+   failed.  */
+
+static dw_loc_descr_ref
+tls_mem_loc_descriptor (rtx mem)
+{
+  tree base;
+  dw_loc_descr_ref loc_result, loc_result2;
+
+  if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX)
+    return NULL;
+
+  base = get_base_address (MEM_EXPR (mem));
+  if (base == NULL
+      || TREE_CODE (base) != VAR_DECL
+      || !DECL_THREAD_LOCAL_P (base))
+    return NULL;
+
+  loc_result = loc_descriptor_from_tree_1 (MEM_EXPR (mem), 2);
+  if (loc_result == NULL)
+    return NULL;
+
+  if (INTVAL (MEM_OFFSET (mem)))
+    {
+      if (INTVAL (MEM_OFFSET (mem)) >= 0)
+       add_loc_descr (&loc_result,
+                      new_loc_descr (DW_OP_plus_uconst,
+                                     INTVAL (MEM_OFFSET (mem)), 0));
+      else
+       {
+         loc_result2 = mem_loc_descriptor (MEM_OFFSET (mem), GET_MODE (mem),
+                                           VAR_INIT_STATUS_INITIALIZED);
+         if (loc_result2 == 0)
+           return NULL;
+         add_loc_descr (&loc_result, loc_result2);
+         add_loc_descr (&loc_result, new_loc_descr (DW_OP_plus, 0, 0));
+       }
+    }
+
+  return loc_result;
+}
+
 /* The following routine converts the RTL for a variable or parameter
    (resident in memory) into an equivalent Dwarf representation of a
    mechanism for getting the address of that same variable onto the top of a
@@ -9963,6 +10005,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
     case MEM:
       mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
                                           VAR_INIT_STATUS_INITIALIZED);
+      if (mem_loc_result == NULL)
+       mem_loc_result = tls_mem_loc_descriptor (rtl);
       if (mem_loc_result != 0)
        add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
       break;
@@ -10045,9 +10089,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
                                          INTVAL (XEXP (rtl, 1)), 0));
          else
            {
-             add_loc_descr (&mem_loc_result,
-                            mem_loc_descriptor (XEXP (rtl, 1), mode,
-                                                VAR_INIT_STATUS_INITIALIZED));
+             dw_loc_descr_ref mem_loc_result2
+               = mem_loc_descriptor (XEXP (rtl, 1), mode,
+                                     VAR_INIT_STATUS_INITIALIZED);
+             if (mem_loc_result2 == 0)
+               break;
+             add_loc_descr (&mem_loc_result, mem_loc_result2);
              add_loc_descr (&mem_loc_result,
                             new_loc_descr (DW_OP_plus, 0, 0));
            }
@@ -10097,6 +10144,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
                                                   VAR_INIT_STATUS_INITIALIZED);
       break;
 
+    case UNSPEC:
+      /* If delegitimize_address couldn't do anything with the UNSPEC, we
+        can't express it in the debug info.  This can happen e.g. with some
+        TLS UNSPECs.  */
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -10193,6 +10246,8 @@ loc_descriptor (rtx rtl, enum var_init_status initialized)
     case MEM:
       loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl),
                                       initialized);
+      if (loc_result == NULL)
+       loc_result = tls_mem_loc_descriptor (rtl);
       break;
 
     case CONCAT:
@@ -10225,6 +10280,8 @@ loc_descriptor (rtx rtl, enum var_init_status initialized)
        /* Create the first one, so we have something to add to.  */
        loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
                                     initialized);
+       if (loc_result == NULL)
+         return NULL;
        mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
        add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
        for (i = 1; i < num_elem; i++)
@@ -10233,6 +10290,8 @@ loc_descriptor (rtx rtl, enum var_init_status initialized)
 
            temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0),
                                   initialized);
+           if (temp == NULL)
+             return NULL;
            add_loc_descr (&loc_result, temp);
            mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
            add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
@@ -10311,7 +10370,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
               /* The way DW_OP_GNU_push_tls_address is specified, we
                  can only look up addresses of objects in the current
                  module.  */
-             if (DECL_EXTERNAL (loc))
+             if (DECL_EXTERNAL (loc) && !targetm.binds_local_p (loc))
                return 0;
              first_op = INTERNAL_DW_OP_tls_addr;
              second_op = DW_OP_GNU_push_tls_address;
@@ -10433,7 +10492,10 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
        if (offset != NULL_TREE)
          {
            /* Variable offset.  */
-           add_loc_descr (&ret, loc_descriptor_from_tree_1 (offset, 0));
+           ret1 = loc_descriptor_from_tree_1 (offset, 0);
+           if (ret1 == 0)
+             return 0;
+           add_loc_descr (&ret, ret1);
            add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
          }
 
index 8169b88a56f4a82c0099e425e0b701b00ae9e1dc..cc430ac855968532fe07a55dc0ba740d5b39945c 100644 (file)
@@ -1,3 +1,8 @@
+2008-09-26  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/37275
+       * gcc.target/i386/pr37275.c: New test.
+
 2008-09-26  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/specs/static_initializer4.ads: New test.
diff --git a/gcc/testsuite/gcc.target/i386/pr37275.c b/gcc/testsuite/gcc.target/i386/pr37275.c
new file mode 100644 (file)
index 0000000..ca9612b
--- /dev/null
@@ -0,0 +1,137 @@
+/* PR middle-end/37275 */
+/* { dg-do compile { target ilp32 } } */
+/* { dg-options "-g -dA -O2 -march=i686 -fstack-protector" } */
+
+typedef __SIZE_TYPE__ size_t;
+extern void *memcpy (void *, const void *, size_t);
+extern void *malloc (size_t);
+
+typedef int A;
+
+struct B
+{
+  int x;
+};
+
+struct C
+{
+  struct F *c1;
+  void *c2;
+};
+
+enum D
+{
+  D0,
+  D1
+};
+
+struct E
+{
+  struct E *e1;
+  struct E *e2;
+  struct B e3;
+  void (*fn) (void *);
+  void *fn_data;
+  enum D e4;
+  _Bool e5;
+  _Bool e6;
+};
+
+struct F
+{
+  unsigned f1;
+  A f2;
+  int f3;
+};
+
+struct G
+{
+  void (*fn) (void *data);
+  void *data;
+  struct C g1;
+  struct E *t;
+};
+
+extern void fn1 (A * m);
+static inline void
+fn2 (A *x)
+{
+  if (!__sync_bool_compare_and_swap (x, 0, 1))
+    fn1 (x);
+}
+
+extern __thread struct G thr __attribute__ ((visibility ("hidden")));
+static inline struct G *
+fn3 (void)
+{
+  return &thr;
+}
+
+extern struct B *fn4 (void);
+extern struct B a;
+
+static inline struct B *
+fn5 (_Bool x)
+{
+  struct E *t = fn3 ()->t;
+  if (t)
+    return &t->e3;
+  else if (x)
+    return fn4 ();
+  else
+    return &a;
+}
+
+void
+fn6 (struct E *t, struct E *e1_t,
+               struct B *prev_e3)
+{
+  t->e1 = e1_t;
+  t->e3 = *prev_e3;
+  t->e4 = D0;
+  t->e5 = 0;
+  t->e6 = 0;
+  t->e2 = ((void *) 0);
+}
+
+void
+test (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *), long x, long y, _Bool z)
+{
+  struct G *thr = fn3 ();
+  struct F *c1 = thr->g1.c1;
+  if (!z || c1 == 0 || (unsigned) c1->f3 > 64 * c1->f1)
+    {
+      struct E t;
+
+      fn6 (&t, thr->t, fn5 (0));
+      if (thr->t)
+       t.e6 = thr->t->e6;
+      thr->t = &t;
+      if (__builtin_expect (cpyfn != ((void *) 0), 0))
+       {
+         char buf[x + y - 1];
+         char *arg = (char *) (((unsigned long) buf + y - 1)
+                               & ~(unsigned long) (y - 1));
+         cpyfn (arg, data);
+         fn (arg);
+       }
+    }
+  else
+    {
+      struct E *t;
+      struct E *e1 = thr->t;
+      char *arg;
+
+      t = malloc (sizeof (*t) + x + y - 1);
+      arg = (char *) (((unsigned long) (t + 1) + y - 1)
+                     & ~(unsigned long) (y - 1));
+      fn6 (t, e1, fn5 (0));
+      thr->t = t;
+      if (cpyfn)
+       cpyfn (arg, data);
+      else
+       memcpy (arg, data, x);
+      thr->t = e1;
+      fn2 (&c1->f2);
+    }
+}