aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2009-10-02 17:01:22 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2009-10-02 17:01:22 +0200
commite1b243a800307b7a731b5b3cf69a2d784498923b (patch)
treec18228efb40a0e59c5eb72d9e3b4378820263cdd /gcc
parentb1d42460aef1a4c02d7c35301c2c4e81d5ed3419 (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/cfgexpand.c23
-rw-r--r--gcc/dwarf2out.c156
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr41353-2.c24
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr41404-1.c41
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;
+}