Blob Blame History Raw
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++) { }
+}