152 lines
4.2 KiB
Diff
152 lines
4.2 KiB
Diff
for gcc/ChangeLog
|
|
from Alexandre Oliva <aoliva@redhat.com>
|
|
|
|
PR debug/41248
|
|
* cfgexpand.c (convert_debug_memory_address): New.
|
|
(expand_debug_expr): Convert base address and offset to the same
|
|
mode. Use it to convert addresses to other modes. Accept
|
|
ptr_mode addresses.
|
|
|
|
for gcc/testsuite/ChangeLog
|
|
from Alexandre Oliva <aoliva@redhat.com>
|
|
|
|
PR debug/41248
|
|
* gcc.dg/pr41248.c: New.
|
|
|
|
Index: gcc/cfgexpand.c
|
|
===================================================================
|
|
--- gcc/cfgexpand.c.orig 2009-09-07 19:00:20.000000000 -0300
|
|
+++ gcc/cfgexpand.c 2009-09-07 19:17:27.000000000 -0300
|
|
@@ -1966,6 +1966,38 @@ unwrap_constant (rtx x)
|
|
return ret;
|
|
}
|
|
|
|
+/* Convert X to MODE, that must be Pmode or ptr_mode, without emitting
|
|
+ any rtl. */
|
|
+
|
|
+static rtx
|
|
+convert_debug_memory_address (enum machine_mode mode, rtx x)
|
|
+{
|
|
+ enum machine_mode xmode = GET_MODE (x);
|
|
+
|
|
+#ifndef POINTERS_EXTEND_UNSIGNED
|
|
+ gcc_assert (mode == Pmode);
|
|
+ gcc_assert (xmode == mode || xmode == VOIDmode);
|
|
+#else
|
|
+ gcc_assert (mode == Pmode || mode == ptr_mode);
|
|
+
|
|
+ if (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode)
|
|
+ return x;
|
|
+
|
|
+ if (GET_MODE_BITSIZE (mode) < GET_MODE_BITSIZE (xmode))
|
|
+ x = simplify_gen_subreg (mode, x, xmode,
|
|
+ subreg_lowpart_offset
|
|
+ (mode, xmode));
|
|
+ else if (POINTERS_EXTEND_UNSIGNED > 0)
|
|
+ x = gen_rtx_ZERO_EXTEND (mode, x);
|
|
+ else if (!POINTERS_EXTEND_UNSIGNED)
|
|
+ x = gen_rtx_SIGN_EXTEND (mode, x);
|
|
+ else
|
|
+ gcc_unreachable ();
|
|
+#endif /* POINTERS_EXTEND_UNSIGNED */
|
|
+
|
|
+ return x;
|
|
+}
|
|
+
|
|
/* Return an RTX equivalent to the value of the tree expression
|
|
EXP. */
|
|
|
|
@@ -2141,6 +2173,7 @@ expand_debug_expr (tree exp)
|
|
return NULL;
|
|
|
|
gcc_assert (GET_MODE (op0) == Pmode
|
|
+ || GET_MODE (op0) == ptr_mode
|
|
|| GET_CODE (op0) == CONST_INT
|
|
|| GET_CODE (op0) == CONST_DOUBLE);
|
|
|
|
@@ -2167,6 +2200,7 @@ expand_debug_expr (tree exp)
|
|
return NULL;
|
|
|
|
gcc_assert (GET_MODE (op0) == Pmode
|
|
+ || GET_MODE (op0) == ptr_mode
|
|
|| GET_CODE (op0) == CONST_INT
|
|
|| GET_CODE (op0) == CONST_DOUBLE);
|
|
|
|
@@ -2199,13 +2233,32 @@ expand_debug_expr (tree exp)
|
|
|
|
if (offset)
|
|
{
|
|
+ enum machine_mode addrmode, offmode;
|
|
+
|
|
gcc_assert (MEM_P (op0));
|
|
|
|
+ op0 = XEXP (op0, 0);
|
|
+ addrmode = GET_MODE (op0);
|
|
+ if (addrmode == VOIDmode)
|
|
+ addrmode = Pmode;
|
|
+
|
|
op1 = expand_debug_expr (offset);
|
|
if (!op1)
|
|
return NULL;
|
|
|
|
- op0 = gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode, XEXP (op0, 0), op1));
|
|
+ offmode = GET_MODE (op1);
|
|
+ if (offmode == VOIDmode)
|
|
+ offmode = TYPE_MODE (TREE_TYPE (offset));
|
|
+
|
|
+ if (addrmode != offmode)
|
|
+ op1 = simplify_gen_subreg (addrmode, op1, offmode,
|
|
+ subreg_lowpart_offset (addrmode,
|
|
+ offmode));
|
|
+
|
|
+ /* Don't use offset_address here, we don't need a
|
|
+ recognizable address, and we don't want to generate
|
|
+ code. */
|
|
+ op0 = gen_rtx_MEM (mode, gen_rtx_PLUS (addrmode, op0, op1));
|
|
}
|
|
|
|
if (MEM_P (op0))
|
|
@@ -2525,7 +2578,9 @@ expand_debug_expr (tree exp)
|
|
if (!op0 || !MEM_P (op0))
|
|
return NULL;
|
|
|
|
- return XEXP (op0, 0);
|
|
+ op0 = convert_debug_memory_address (mode, XEXP (op0, 0));
|
|
+
|
|
+ return op0;
|
|
|
|
case VECTOR_CST:
|
|
exp = build_constructor_from_list (TREE_TYPE (exp),
|
|
Index: gcc/testsuite/gcc.dg/pr41248.c
|
|
===================================================================
|
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
|
+++ gcc/testsuite/gcc.dg/pr41248.c 2009-09-07 19:17:27.000000000 -0300
|
|
@@ -0,0 +1,27 @@
|
|
+/* { dg-do compile } */
|
|
+/* { dg-options "-O2 -g" } */
|
|
+
|
|
+struct __gcov_var {
|
|
+ unsigned int offset;
|
|
+ unsigned int buffer[(1 << 10) + 1];
|
|
+} __gcov_var;
|
|
+unsigned int * gcov_write_words (unsigned int words) {
|
|
+ unsigned int *result;
|
|
+ result = &__gcov_var.buffer[__gcov_var.offset];
|
|
+ return result;
|
|
+}
|
|
+
|
|
+struct gcov_ctr_summary { };
|
|
+struct gcov_summary {
|
|
+ unsigned int checksum;
|
|
+ struct gcov_ctr_summary ctrs[1];
|
|
+};
|
|
+void __gcov_write_unsigned (unsigned int);
|
|
+void __gcov_write_summary (unsigned int tag,
|
|
+ const struct gcov_summary *summary)
|
|
+{
|
|
+ unsigned ix;
|
|
+ const struct gcov_ctr_summary *csum;
|
|
+ __gcov_write_unsigned (summary->checksum);
|
|
+ for (csum = summary->ctrs, ix = 1; ix--; csum++) { }
|
|
+}
|