diff options
author | Jakub Jelinek <jakub@redhat.com> | 2009-10-02 17:01:22 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2009-10-02 17:01:22 +0200 |
commit | e1b243a800307b7a731b5b3cf69a2d784498923b (patch) | |
tree | c18228efb40a0e59c5eb72d9e3b4378820263cdd | |
parent | b1d42460aef1a4c02d7c35301c2c4e81d5ed3419 (diff) | |
download | gcc-e1b243a800307b7a731b5b3cf69a2d784498923b.zip gcc-e1b243a800307b7a731b5b3cf69a2d784498923b.tar.gz gcc-e1b243a800307b7a731b5b3cf69a2d784498923b.tar.bz2 |
re PR bootstrap/41404 (expr.c undefined reference while linking jc1)
PR debug/41404
PR debug/41353
* cfgexpand.c (expand_debug_expr) <case STRING_CST>: Don't create
CONST_STRING if STRING_CST contains embedded '\0's or doesn't end with
'\0'.
(expand_debug_expr) <case VAR_DECL>: For TREE_STATIC !DECL_EXTERNAL
vars use DECL_RTL with resetting it back to NULL afterwards.
* dwarf2out.c (same_dw_val_p): For dw_val_class_addr compare with
rtx_equal_p instead of asserting it is a SYMBOL_REF.
(value_format): For dw_val_class_addr only use DW_FORM_addr if
the attribute type allows it, otherwise use DW_FORM_dataN.
(mem_loc_descriptor): Handle CONST_STRING.
(add_const_value_attribute): Handle CONST_STRING using add_AT_addr.
Handle MEM with CONST_STRING address using add_AT_string.
(rtl_for_decl_init): Return MEM with CONST_STRING address instead of
CONST_STRING for const arrays initialized with a string literal.
(resolve_one_addr, resolve_addr_in_expr, resolve_addr): New functions.
(dwarf2out_finish): Call resolve_addr.
* gcc.dg/guality/pr41404-1.c: New test.
* gcc.dg/guality/pr41353-2.c: New test.
From-SVN: r152403
-rw-r--r-- | gcc/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/cfgexpand.c | 23 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 156 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/guality/pr41353-2.c | 24 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/guality/pr41404-1.c | 41 |
6 files changed, 261 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 37b433f..00a6055 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2009-10-02 Jakub Jelinek <jakub@redhat.com> + + PR debug/41404 + PR debug/41353 + * cfgexpand.c (expand_debug_expr) <case STRING_CST>: Don't create + CONST_STRING if STRING_CST contains embedded '\0's or doesn't end with + '\0'. + (expand_debug_expr) <case VAR_DECL>: For TREE_STATIC !DECL_EXTERNAL + vars use DECL_RTL with resetting it back to NULL afterwards. + * dwarf2out.c (same_dw_val_p): For dw_val_class_addr compare with + rtx_equal_p instead of asserting it is a SYMBOL_REF. + (value_format): For dw_val_class_addr only use DW_FORM_addr if + the attribute type allows it, otherwise use DW_FORM_dataN. + (mem_loc_descriptor): Handle CONST_STRING. + (add_const_value_attribute): Handle CONST_STRING using add_AT_addr. + Handle MEM with CONST_STRING address using add_AT_string. + (rtl_for_decl_init): Return MEM with CONST_STRING address instead of + CONST_STRING for const arrays initialized with a string literal. + (resolve_one_addr, resolve_addr_in_expr, resolve_addr): New functions. + (dwarf2out_finish): Call resolve_addr. + 2009-10-02 Andreas Schwab <schwab@linux-m68k.org> Maxim Kuvyrkov <maxim@codesourcery.com> diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index f4a9f5e..2117ee3 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -2337,6 +2337,9 @@ expand_debug_expr (tree exp) case STRING_CST: if (!lookup_constant_def (exp)) { + if (strlen (TREE_STRING_POINTER (exp)) + 1 + != (size_t) TREE_STRING_LENGTH (exp)) + return NULL_RTX; op0 = gen_rtx_CONST_STRING (Pmode, TREE_STRING_POINTER (exp)); op0 = gen_rtx_MEM (BLKmode, op0); set_mem_attributes (op0, exp, 0); @@ -2368,9 +2371,23 @@ expand_debug_expr (tree exp) /* This decl was probably optimized away. */ if (!op0) - return NULL; - - op0 = copy_rtx (op0); + { + if (TREE_CODE (exp) != VAR_DECL + || DECL_EXTERNAL (exp) + || !TREE_STATIC (exp) + || !DECL_NAME (exp) + || DECL_HARD_REGISTER (exp)) + return NULL; + + op0 = DECL_RTL (exp); + SET_DECL_RTL (exp, NULL); + if (!MEM_P (op0) + || GET_CODE (XEXP (op0, 0)) != SYMBOL_REF + || SYMBOL_REF_DECL (XEXP (op0, 0)) != exp) + return NULL; + } + else + op0 = copy_rtx (op0); if (GET_MODE (op0) == BLKmode) { diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 43e1a7b..3a0e4f3 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -5948,6 +5948,7 @@ static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx, static dw_loc_descr_ref based_loc_descr (rtx, HOST_WIDE_INT, enum var_init_status); static int is_based_loc (const_rtx); +static int resolve_one_addr (rtx *, void *); static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode, enum var_init_status); static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx, @@ -7905,8 +7906,7 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark) r2 = v2->v.val_addr; if (GET_CODE (r1) != GET_CODE (r2)) return 0; - gcc_assert (GET_CODE (r1) == SYMBOL_REF); - return !strcmp (XSTR (r1, 0), XSTR (r2, 0)); + return !rtx_equal_p (r1, r2); case dw_val_class_offset: return v1->v.val_offset == v2->v.val_offset; @@ -8662,7 +8662,30 @@ value_format (dw_attr_ref a) switch (a->dw_attr_val.val_class) { case dw_val_class_addr: - return DW_FORM_addr; + /* Only very few attributes allow DW_FORM_addr. */ + switch (a->dw_attr) + { + case DW_AT_low_pc: + case DW_AT_high_pc: + case DW_AT_entry_pc: + case DW_AT_trampoline: + return DW_FORM_addr; + default: + break; + } + switch (DWARF2_ADDR_SIZE) + { + case 1: + return DW_FORM_data1; + case 2: + return DW_FORM_data2; + case 4: + return DW_FORM_data4; + case 8: + return DW_FORM_data8; + default: + gcc_unreachable (); + } case dw_val_class_range_list: case dw_val_class_offset: case dw_val_class_loc_list: @@ -11345,6 +11368,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, if (!const_ok_for_output (rtl)) break; + symref: mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0); mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr; mem_loc_result->dw_loc_oprnd1.v.val_addr = rtl; @@ -11759,8 +11783,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, break; case CONST_STRING: - /* These can't easily be tracked, see PR41404. */ - break; + resolve_one_addr (&rtl, NULL); + goto symref; default: #ifdef ENABLE_CHECKING @@ -13525,7 +13549,9 @@ add_const_value_attribute (dw_die_ref die, rtx rtl) return true; case CONST_STRING: - add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0)); + resolve_one_addr (&rtl, NULL); + add_AT_addr (die, DW_AT_const_value, rtl); + VEC_safe_push (rtx, gc, used_rtx_array, rtl); return true; case CONST: @@ -13558,6 +13584,16 @@ add_const_value_attribute (dw_die_ref die, rtx rtl) case CONST_FIXED: return false; + case MEM: + if (GET_CODE (XEXP (rtl, 0)) == CONST_STRING + && MEM_READONLY_P (rtl) + && GET_MODE (rtl) == BLKmode) + { + add_AT_string (die, DW_AT_const_value, XSTR (XEXP (rtl, 0), 0)); + return true; + } + return false; + default: /* No other kinds of rtx should be possible here. */ gcc_unreachable (); @@ -13629,8 +13665,12 @@ rtl_for_decl_init (tree init, tree type) TREE_STRING_LENGTH (init) - 1) == 0 && ((size_t) TREE_STRING_LENGTH (init) == strlen (TREE_STRING_POINTER (init)) + 1)) - rtl = gen_rtx_CONST_STRING (VOIDmode, - ggc_strdup (TREE_STRING_POINTER (init))); + { + rtl = gen_rtx_CONST_STRING (VOIDmode, + ggc_strdup (TREE_STRING_POINTER (init))); + rtl = gen_rtx_MEM (BLKmode, rtl); + MEM_READONLY_P (rtl) = 1; + } } /* Other aggregates, and complex values, could be represented using CONCAT: FIXME! */ @@ -18982,6 +19022,104 @@ move_linkage_attr (dw_die_ref die) } } +/* Helper function for resolve_addr, attempt to resolve + one CONST_STRING, return non-zero if not successful. Similarly verify that + SYMBOL_REFs refer to variables emitted in the current CU. */ + +static int +resolve_one_addr (rtx *addr, void *data ATTRIBUTE_UNUSED) +{ + rtx rtl = *addr; + + if (GET_CODE (rtl) == CONST_STRING) + { + size_t len = strlen (XSTR (rtl, 0)) + 1; + tree t = build_string (len, XSTR (rtl, 0)); + tree tlen = build_int_cst (NULL_TREE, len - 1); + TREE_TYPE (t) + = build_array_type (char_type_node, build_index_type (tlen)); + rtl = lookup_constant_def (t); + if (!rtl || !MEM_P (rtl)) + return 1; + rtl = XEXP (rtl, 0); + VEC_safe_push (rtx, gc, used_rtx_array, rtl); + *addr = rtl; + return 0; + } + + if (GET_CODE (rtl) == SYMBOL_REF + && SYMBOL_REF_DECL (rtl) + && TREE_CODE (SYMBOL_REF_DECL (rtl)) == VAR_DECL + && !TREE_ASM_WRITTEN (SYMBOL_REF_DECL (rtl))) + return 1; + + if (GET_CODE (rtl) == CONST + && for_each_rtx (&XEXP (rtl, 0), resolve_one_addr, NULL)) + return 1; + + return 0; +} + +/* Helper function for resolve_addr, handle one location + expression, return false if at least one CONST_STRING or SYMBOL_REF in + the location list couldn't be resolved. */ + +static bool +resolve_addr_in_expr (dw_loc_descr_ref loc) +{ + for (; loc; loc = loc->dw_loc_next) + if ((loc->dw_loc_opc == DW_OP_addr + && resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL)) + || (loc->dw_loc_opc == DW_OP_implicit_value + && loc->dw_loc_oprnd2.val_class == dw_val_class_addr + && resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL))) + return false; + return true; +} + +/* Resolve DW_OP_addr and DW_AT_const_value CONST_STRING arguments to + an address in .rodata section if the string literal is emitted there, + or remove the containing location list or replace DW_AT_const_value + with DW_AT_location and empty location expression, if it isn't found + in .rodata. Similarly for SYMBOL_REFs, keep only those that refer + to something that has been emitted in the current CU. */ + +static void +resolve_addr (dw_die_ref die) +{ + dw_die_ref c; + dw_attr_ref a; + dw_loc_list_ref curr; + unsigned ix; + + for (ix = 0; VEC_iterate (dw_attr_node, die->die_attr, ix, a); ix++) + switch (AT_class (a)) + { + case dw_val_class_loc_list: + for (curr = AT_loc_list (a); curr != NULL; curr = curr->dw_loc_next) + if (!resolve_addr_in_expr (curr->expr)) + curr->expr = NULL; + break; + case dw_val_class_loc: + if (!resolve_addr_in_expr (AT_loc (a))) + a->dw_attr_val.v.val_loc = NULL; + break; + case dw_val_class_addr: + if (a->dw_attr == DW_AT_const_value + && resolve_one_addr (&a->dw_attr_val.v.val_addr, NULL)) + { + a->dw_attr = DW_AT_location; + a->dw_attr_val.val_class = dw_val_class_loc; + a->dw_attr_val.v.val_loc = NULL; + } + break; + default: + break; + } + + FOR_EACH_CHILD (die, c, resolve_addr (c)); +} + /* Output stuff that dwarf requires at the end of every file, and generate the DWARF-2 debugging info. */ @@ -19072,6 +19210,8 @@ dwarf2out_finish (const char *filename) limbo_die_list = NULL; + resolve_addr (comp_unit_die); + for (node = deferred_asm_name; node; node = node->next) { tree decl = node->created_for; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b52d1f1..4bbabcb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2009-10-02 Jakub Jelinek <jakub@redhat.com> + + PR debug/41404 + PR debug/41353 + * gcc.dg/guality/pr41404-1.c: New test. + * gcc.dg/guality/pr41353-2.c: New test. + 2009-10-02 H.J. Lu <hongjiu.lu@intel.com> PR testsuite/41546 diff --git a/gcc/testsuite/gcc.dg/guality/pr41353-2.c b/gcc/testsuite/gcc.dg/guality/pr41353-2.c new file mode 100644 index 0000000..3ff8d36 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr41353-2.c @@ -0,0 +1,24 @@ +/* PR debug/41353 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +int varh; +int vari = 17, varj; + +__attribute__((noinline)) int +f1 (void) +{ + int vari1 = 2 * vari; /* { dg-final { gdb-test 13 "vari1" "2 * 17" } } */ + int vari2 = 3 * vari; /* { dg-final { gdb-test 13 "vari2" "3 * 17" } } */ + return varj; +} + +int (*volatile fnp1) (void) = f1; + +int +main (int argc, char *argv[]) +{ + asm volatile ("" : : "r" (&fnp1) : "memory"); + fnp1 (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/guality/pr41404-1.c b/gcc/testsuite/gcc.dg/guality/pr41404-1.c new file mode 100644 index 0000000..59a8293 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr41404-1.c @@ -0,0 +1,41 @@ +/* PR debug/41404 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +__attribute__ ((noinline)) +int bar1 (int i) +{ + const char *foo = "foo"; + asm volatile ("" : "+r" (i) : : "memory"); + i++; /* { dg-final { gdb-test 10 "*foo" "'f'" } } */ + asm volatile ("" : "+r" (i) : : "memory"); + foo = "bar"; + asm volatile ("" : "+r" (i) : : "memory"); + i++; /* { dg-final { gdb-test 14 "*foo" "'b'" } } */ + asm volatile ("" : "+r" (i) : : "memory"); + return i; +} + +__attribute__ ((noinline)) +int bar2 (int i) +{ + const char *foo = "foo"; + asm volatile ("" : "+r" (i) : : "memory"); + i++; /* { dg-final { gdb-test 24 "*foo" "'f'" } } */ + asm volatile ("" : "+r" (i) : : "memory"); + return i; +} + +__attribute__ ((noinline)) +const char *baz (int i) +{ + return i ? "foo" : "bar"; +} + +int +main (void) +{ + bar1 (6); + bar2 (6); + return 0; +} |