diff options
author | Jakub Jelinek <jakub@redhat.com> | 2008-09-26 22:59:03 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2008-09-26 22:59:03 +0200 |
commit | 9c2b3df10a547f360f7ee8b0393f4b7fa3e5014b (patch) | |
tree | b364d416e69c31df3bbb3c47c5f77ad3f3b4c57c /gcc | |
parent | bb3da4f27b9d7241a626695e80edc285561f2506 (diff) | |
download | gcc-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/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 72 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr37275.c | 137 |
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); + } +} |