aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2008-09-26 22:59:03 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2008-09-26 22:59:03 +0200
commit9c2b3df10a547f360f7ee8b0393f4b7fa3e5014b (patch)
treeb364d416e69c31df3bbb3c47c5f77ad3f3b4c57c /gcc
parentbb3da4f27b9d7241a626695e80edc285561f2506 (diff)
downloadgcc-9c2b3df10a547f360f7ee8b0393f4b7fa3e5014b.zip
gcc-9c2b3df10a547f360f7ee8b0393f4b7fa3e5014b.tar.gz
gcc-9c2b3df10a547f360f7ee8b0393f4b7fa3e5014b.tar.bz2
re PR middle-end/37275 (ICE when compile libgomp/task.c)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/dwarf2out.c72
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr37275.c137
4 files changed, 219 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e3e9f00..740a943 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 27b2ca1..98b98a8 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -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));
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8169b88..cc430ac 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..ca9612b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr37275.c
@@ -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);
+ }
+}