From d89c81d61e152e07cfca199601d7c32e26ebbf5f Mon Sep 17 00:00:00 2001 From: aoliva Date: Wed, 23 Sep 2009 16:29:38 +0000 Subject: [PATCH] gcc/ChangeLog: 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. gcc/testsuite/ChangeLog: PR debug/41248 * gcc.dg/pr41248.c: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152087 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 8 ++++++ gcc/cfgexpand.c | 59 ++++++++++++++++++++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/pr41248.c | 27 +++++++++++++++++++ 4 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr41248.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 47bef8cab0b..22941d311ab 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2009-09-23 Alexandre Oliva + + 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. + 2009-09-23 Richard Guenther * alias.c (ao_ref_from_mem): Correct for negative MEM_OFFSET diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 0ed6bd5903d..f4a9f5e478c 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -2234,6 +2234,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. */ @@ -2410,6 +2442,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); @@ -2436,6 +2469,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); @@ -2468,13 +2502,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)) @@ -2785,7 +2838,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), diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5fa33fdabd2..4c8e14e3332 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-09-23 Alexandre Oliva + + PR debug/41248 + * gcc.dg/pr41248.c: New. + 2009-09-23 Dodji Seketeli PR debug/41065 diff --git a/gcc/testsuite/gcc.dg/pr41248.c b/gcc/testsuite/gcc.dg/pr41248.c new file mode 100644 index 00000000000..0d5a74919ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr41248.c @@ -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++) { } +} -- 2.11.0