for gcc/ChangeLog from 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. for gcc/testsuite/ChangeLog from Alexandre Oliva 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++) { } +}