OSDN Git Service

gcc/ChangeLog:
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 23 Sep 2009 16:29:38 +0000 (16:29 +0000)
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 23 Sep 2009 16:29:38 +0000 (16:29 +0000)
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
gcc/cfgexpand.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr41248.c [new file with mode: 0644]

index 47bef8c..22941d3 100644 (file)
@@ -1,3 +1,11 @@
+2009-09-23  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.
+
 2009-09-23  Richard Guenther  <rguenther@suse.de>
 
        * alias.c (ao_ref_from_mem): Correct for negative MEM_OFFSET
 2009-09-23  Richard Guenther  <rguenther@suse.de>
 
        * alias.c (ao_ref_from_mem): Correct for negative MEM_OFFSET
index 0ed6bd5..f4a9f5e 100644 (file)
@@ -2234,6 +2234,38 @@ unwrap_constant (rtx x)
   return ret;
 }
 
   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.  */
 
 /* 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
        return NULL;
 
       gcc_assert (GET_MODE (op0) == Pmode
+                 || GET_MODE (op0) == ptr_mode
                  || GET_CODE (op0) == CONST_INT
                  || GET_CODE (op0) == CONST_DOUBLE);
 
                  || 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
        return NULL;
 
       gcc_assert (GET_MODE (op0) == Pmode
+                 || GET_MODE (op0) == ptr_mode
                  || GET_CODE (op0) == CONST_INT
                  || GET_CODE (op0) == CONST_DOUBLE);
 
                  || GET_CODE (op0) == CONST_INT
                  || GET_CODE (op0) == CONST_DOUBLE);
 
@@ -2468,13 +2502,32 @@ expand_debug_expr (tree exp)
 
        if (offset)
          {
 
        if (offset)
          {
+           enum machine_mode addrmode, offmode;
+
            gcc_assert (MEM_P (op0));
 
            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;
 
            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))
          }
 
        if (MEM_P (op0))
@@ -2785,7 +2838,9 @@ expand_debug_expr (tree exp)
       if (!op0 || !MEM_P (op0))
        return NULL;
 
       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),
 
     case VECTOR_CST:
       exp = build_constructor_from_list (TREE_TYPE (exp),
index 5fa33fd..4c8e14e 100644 (file)
@@ -1,3 +1,8 @@
+2009-09-23  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR debug/41248
+       * gcc.dg/pr41248.c: New.
+
  2009-09-23  Dodji Seketeli  <dodji@redhat.com>
 
        PR debug/41065
  2009-09-23  Dodji Seketeli  <dodji@redhat.com>
 
        PR debug/41065
diff --git a/gcc/testsuite/gcc.dg/pr41248.c b/gcc/testsuite/gcc.dg/pr41248.c
new file mode 100644 (file)
index 0000000..0d5a749
--- /dev/null
@@ -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++) { }
+}