re PR debug/21946 (Invalid DWARF2 debug info emitted)
authorJakub Jelinek <jakub@redhat.com>
Tue, 7 Jun 2005 10:17:34 +0000 (12:17 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 7 Jun 2005 10:17:34 +0000 (12:17 +0200)
PR debug/21946
* dwarf2out.c (add_loc_descr_op_piece): New function.
(multiple_reg_loc_descriptor, concat_loc_descriptor,
loc_descriptor): Use it.
* var-tracking.c: Include regs.h and expr.h.
(emit_note_insn_var_location): Skip over pieces where offset
is smaller than previous offset plus previous piece mode size.
Optimize adjacent hard registers or memory locations.
* Makefile.in (var-tracking.o): Depend on $(REGS_H) and $(EXPR_H).

From-SVN: r100706

gcc/ChangeLog
gcc/Makefile.in
gcc/dwarf2out.c
gcc/var-tracking.c

index 5fc0d27b3e7240d08c4a3cfa2c7365591d4ea890..c56a403aa97de7c1ccd820ef7764da29b08266c3 100644 (file)
@@ -1,3 +1,15 @@
+2005-06-07  Jakub Jelinek  <jakub@redhat.com>
+
+       PR debug/21946
+       * dwarf2out.c (add_loc_descr_op_piece): New function.
+       (multiple_reg_loc_descriptor, concat_loc_descriptor,
+       loc_descriptor): Use it.
+       * var-tracking.c: Include regs.h and expr.h.
+       (emit_note_insn_var_location): Skip over pieces where offset
+       is smaller than previous offset plus previous piece mode size.
+       Optimize adjacent hard registers or memory locations.
+       * Makefile.in (var-tracking.o): Depend on $(REGS_H) and $(EXPR_H).
+
 2005-06-07  Richard Guenther  <rguenth@gcc.gnu.org>
 
        * c-typeck.c (c_finish_if_stmt): Use void_type_node as type
index 5146c78c19b098b7b76dc888fe8674c27bb758f5..67c91e3430b5ca3cf43948f5aac522ef688b1cf8 100644 (file)
@@ -2136,7 +2136,8 @@ df.o : df.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(BASIC_BLOCK_H) $(DF_H) bitmap.h sbitmap.h $(TM_P_H)
 var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h $(FLAGS_H) \
-   $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H)
+   $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \
+   $(REGS_H) $(EXPR_H)
 conflict.o : conflict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(OBSTACK_H) \
    $(HASHTAB_H) $(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H)
 profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
index af62a770e72b07ff415b90be5841fe38c61f651d..e11cd806376605c64616f8bb3839ad89b7e2d5af 100644 (file)
@@ -2659,6 +2659,7 @@ static const char *dwarf_stack_op_name (unsigned);
 static dw_loc_descr_ref new_loc_descr (enum dwarf_location_atom,
                                       unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT);
 static void add_loc_descr (dw_loc_descr_ref *, dw_loc_descr_ref);
+static void add_loc_descr_op_piece (dw_loc_descr_ref *, int);
 static unsigned long size_of_loc_descr (dw_loc_descr_ref);
 static unsigned long size_of_locs (dw_loc_descr_ref);
 static void output_loc_operands (dw_loc_descr_ref);
@@ -3011,6 +3012,27 @@ add_loc_descr (dw_loc_descr_ref *list_head, dw_loc_descr_ref descr)
   *d = descr;
 }
 
+
+/* Optionally add a DW_OP_piece term to a location description expression.
+   DW_OP_piece is only added if the location description expression already
+   doesn't end with DW_OP_piece.  */
+
+static void
+add_loc_descr_op_piece (dw_loc_descr_ref *list_head, int size)
+{
+  dw_loc_descr_ref loc;
+
+  if (*list_head != NULL)
+    {
+      /* Find the end of the chain.  */
+      for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next)
+       ;
+
+      if (loc->dw_loc_opc != DW_OP_piece)
+       loc->dw_loc_next = new_loc_descr (DW_OP_piece, size, 0);
+    }
+}
+
 /* Return the size of a location descriptor.  */
 
 static unsigned long
@@ -8467,7 +8489,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
 
          t = one_reg_loc_descriptor (reg);
          add_loc_descr (&loc_result, t);
-         add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0));
+         add_loc_descr_op_piece (&loc_result, size);
          ++reg;
        }
       return loc_result;
@@ -8487,7 +8509,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
       t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i)));
       add_loc_descr (&loc_result, t);
       size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0)));
-      add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0));
+      add_loc_descr_op_piece (&loc_result, size);
     }
   return loc_result;
 }
@@ -8790,14 +8812,10 @@ concat_loc_descriptor (rtx x0, rtx x1)
     return 0;
 
   cc_loc_result = x0_ref;
-  add_loc_descr (&cc_loc_result,
-                new_loc_descr (DW_OP_piece,
-                               GET_MODE_SIZE (GET_MODE (x0)), 0));
+  add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x0)));
 
   add_loc_descr (&cc_loc_result, x1_ref);
-  add_loc_descr (&cc_loc_result,
-                new_loc_descr (DW_OP_piece,
-                               GET_MODE_SIZE (GET_MODE (x1)), 0));
+  add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x1)));
 
   return cc_loc_result;
 }
@@ -8862,8 +8880,7 @@ loc_descriptor (rtx rtl, bool can_use_fbreg)
        loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0),
                                     can_use_fbreg);
        mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0));
-       add_loc_descr (&loc_result,
-                      new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0));
+       add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
        for (i = 1; i < num_elem; i++)
          {
            dw_loc_descr_ref temp;
@@ -8872,9 +8889,7 @@ loc_descriptor (rtx rtl, bool can_use_fbreg)
                                   can_use_fbreg);
            add_loc_descr (&loc_result, temp);
            mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0));
-           add_loc_descr (&loc_result,
-                          new_loc_descr (DW_OP_piece,
-                                         GET_MODE_SIZE (mode), 0));
+           add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode));
          }
       }
       break;
index 626a8e04dd992d941c89fb4f00eff66cfa3c1389..6d5c14c6055bf1ec7e5bc92e3de34fd990d9382b 100644 (file)
 #include "alloc-pool.h"
 #include "fibheap.h"
 #include "hashtab.h"
+#include "regs.h"
+#include "expr.h"
 
 /* Type of micro operation.  */
 enum micro_operation_type
@@ -2167,25 +2169,101 @@ emit_note_insn_var_location (void **varp, void *data)
   rtx insn = ((emit_note_data *)data)->insn;
   enum emit_note_where where = ((emit_note_data *)data)->where;
   rtx note;
-  int i;
+  int i, j, n_var_parts;
   bool complete;
   HOST_WIDE_INT last_limit;
   tree type_size_unit;
+  HOST_WIDE_INT offsets[MAX_VAR_PARTS];
+  rtx loc[MAX_VAR_PARTS];
 
   gcc_assert (var->decl);
 
   complete = true;
   last_limit = 0;
+  n_var_parts = 0;
   for (i = 0; i < var->n_var_parts; i++)
     {
+      enum machine_mode mode, wider_mode;
+
       if (last_limit < var->var_part[i].offset)
        {
          complete = false;
          break;
        }
-      last_limit
-       = (var->var_part[i].offset
-          + GET_MODE_SIZE (GET_MODE (var->var_part[i].loc_chain->loc)));
+      else if (last_limit > var->var_part[i].offset)
+       continue;
+      offsets[n_var_parts] = var->var_part[i].offset;
+      loc[n_var_parts] = var->var_part[i].loc_chain->loc;
+      mode = GET_MODE (loc[n_var_parts]);
+      last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
+
+      /* Attempt to merge adjacent registers or memory.  */
+      wider_mode = GET_MODE_WIDER_MODE (mode);
+      for (j = i + 1; j < var->n_var_parts; j++)
+       if (last_limit <= var->var_part[j].offset)
+         break;
+      if (j < var->n_var_parts
+         && wider_mode != VOIDmode
+         && GET_CODE (loc[n_var_parts])
+            == GET_CODE (var->var_part[j].loc_chain->loc)
+         && mode == GET_MODE (var->var_part[j].loc_chain->loc)
+         && last_limit == var->var_part[j].offset)
+       {
+         rtx new_loc = NULL;
+         rtx loc2 = var->var_part[j].loc_chain->loc;
+
+         if (REG_P (loc[n_var_parts])
+             && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2
+                == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode]
+             && REGNO (loc[n_var_parts])
+                + hard_regno_nregs[REGNO (loc[n_var_parts])][mode]
+                == REGNO (loc2))
+           {
+             if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN)
+               new_loc = simplify_subreg (wider_mode, loc[n_var_parts],
+                                          mode, 0);
+             else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
+               new_loc = simplify_subreg (wider_mode, loc2, mode, 0);
+             if (new_loc)
+               {
+                 if (!REG_P (new_loc)
+                     || REGNO (new_loc) != REGNO (loc[n_var_parts]))
+                   new_loc = NULL;
+                 else
+                   REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]);
+               }
+           }
+         else if (MEM_P (loc[n_var_parts])
+                  && GET_CODE (XEXP (loc2, 0)) == PLUS
+                  && GET_CODE (XEXP (XEXP (loc2, 0), 0)) == REG
+                  && GET_CODE (XEXP (XEXP (loc2, 0), 1)) == CONST_INT)
+           {
+             if ((GET_CODE (XEXP (loc[n_var_parts], 0)) == REG
+                  && rtx_equal_p (XEXP (loc[n_var_parts], 0),
+                                  XEXP (XEXP (loc2, 0), 0))
+                  && INTVAL (XEXP (XEXP (loc2, 0), 1))
+                     == GET_MODE_SIZE (mode))
+                 || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS
+                     && GET_CODE (XEXP (XEXP (loc[n_var_parts], 0), 1))
+                        == CONST_INT
+                     && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0),
+                                     XEXP (XEXP (loc2, 0), 0))
+                     && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1))
+                        + GET_MODE_SIZE (mode)
+                        == INTVAL (XEXP (XEXP (loc2, 0), 1))))
+               new_loc = adjust_address_nv (loc[n_var_parts],
+                                            wider_mode, 0);
+           }
+
+         if (new_loc)
+           {
+             loc[n_var_parts] = new_loc;
+             mode = wider_mode;
+             last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
+             i = j;
+           }
+       }
+      ++n_var_parts;
     }
   type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (var->decl));
   if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
@@ -2201,26 +2279,24 @@ emit_note_insn_var_location (void **varp, void *data)
       NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
                                                       NULL_RTX);
     }
-  else if (var->n_var_parts == 1)
+  else if (n_var_parts == 1)
     {
       rtx expr_list
-       = gen_rtx_EXPR_LIST (VOIDmode,
-                            var->var_part[0].loc_chain->loc,
-                            GEN_INT (var->var_part[0].offset));
+       = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0]));
 
       NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
                                                       expr_list);
     }
-  else if (var->n_var_parts)
+  else if (n_var_parts)
     {
-      rtx argp[MAX_VAR_PARTS];
       rtx parallel;
 
-      for (i = 0; i < var->n_var_parts; i++)
-       argp[i] = gen_rtx_EXPR_LIST (VOIDmode, var->var_part[i].loc_chain->loc,
-                                    GEN_INT (var->var_part[i].offset));
+      for (i = 0; i < n_var_parts; i++)
+       loc[i]
+         = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i]));
+
       parallel = gen_rtx_PARALLEL (VOIDmode,
-                                  gen_rtvec_v (var->n_var_parts, argp));
+                                  gen_rtvec_v (n_var_parts, loc));
       NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl,
                                                       parallel);
     }