OSDN Git Service

* dwarf2out.c (loc_descr_plus_const): New function.
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 26 Apr 2009 18:45:41 +0000 (18:45 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 26 Apr 2009 18:45:41 +0000 (18:45 +0000)
(build_cfa_aligned_loc, tls_mem_loc_descriptor,
mem_loc_descriptor, loc_descriptor_from_tree_1,
descr_info_loc, gen_variable_die): Use it.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146809 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/dwarf2out.c

index b7bd93b..251d78f 100644 (file)
@@ -1,5 +1,10 @@
 2009-04-26  Jakub Jelinek  <jakub@redhat.com>
 
+       * dwarf2out.c (loc_descr_plus_const): New function.
+       (build_cfa_aligned_loc, tls_mem_loc_descriptor,
+       mem_loc_descriptor, loc_descriptor_from_tree_1,
+       descr_info_loc, gen_variable_die): Use it.
+
        * tree.h (DECL_BY_REFERENCE): Note that it is also valid for
        !TREE_STATIC VAR_DECLs.
        * dwarf2out.c (loc_by_reference, gen_decl_die): Handle
index 0b25382..3c72dc6 100644 (file)
@@ -3879,6 +3879,47 @@ add_loc_descr (dw_loc_descr_ref *list_head, dw_loc_descr_ref descr)
   *d = descr;
 }
 
+/* Add a constant OFFSET to a location expression.  */
+
+static void
+loc_descr_plus_const (dw_loc_descr_ref *list_head, HOST_WIDE_INT offset)
+{
+  dw_loc_descr_ref loc;
+  HOST_WIDE_INT *p;
+
+  gcc_assert (*list_head != NULL);
+
+  if (!offset)
+    return;
+
+  /* Find the end of the chain.  */
+  for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next)
+    ;
+
+  p = NULL;
+  if (loc->dw_loc_opc == DW_OP_fbreg
+      || (loc->dw_loc_opc >= DW_OP_breg0 && loc->dw_loc_opc <= DW_OP_breg31))
+    p = &loc->dw_loc_oprnd1.v.val_int;
+  else if (loc->dw_loc_opc == DW_OP_bregx)
+    p = &loc->dw_loc_oprnd2.v.val_int;
+
+  /* If the last operation is fbreg, breg{0..31,x}, optimize by adjusting its
+     offset.  Don't optimize if an signed integer overflow would happen.  */
+  if (p != NULL
+      && ((offset > 0 && *p <= INTTYPE_MAXIMUM (HOST_WIDE_INT) - offset)
+         || (offset < 0 && *p >= INTTYPE_MINIMUM (HOST_WIDE_INT) - offset)))
+    *p += offset;
+
+  else if (offset > 0)
+    loc->dw_loc_next = new_loc_descr (DW_OP_plus_uconst, offset, 0);
+
+  else
+    {
+      loc->dw_loc_next = int_loc_descriptor (offset);
+      add_loc_descr (&loc->dw_loc_next, new_loc_descr (DW_OP_plus, 0, 0));
+    }
+}
+
 /* Return the size of a location descriptor.  */
 
 static unsigned long
@@ -4398,9 +4439,7 @@ build_cfa_aligned_loc (HOST_WIDE_INT offset, HOST_WIDE_INT alignment)
       head = new_reg_loc_descr (dwarf_fp, 0);
       add_loc_descr (&head, int_loc_descriptor (alignment));
       add_loc_descr (&head, new_loc_descr (DW_OP_and, 0, 0));
-
-      add_loc_descr (&head, int_loc_descriptor (offset));
-      add_loc_descr (&head, new_loc_descr (DW_OP_plus, 0, 0));
+      loc_descr_plus_const (&head, offset);
     }
   else
     head = new_reg_loc_descr (dwarf_fp, offset);
@@ -9904,7 +9943,7 @@ static dw_loc_descr_ref
 tls_mem_loc_descriptor (rtx mem)
 {
   tree base;
-  dw_loc_descr_ref loc_result, loc_result2;
+  dw_loc_descr_ref loc_result;
 
   if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX)
     return NULL;
@@ -9920,21 +9959,7 @@ tls_mem_loc_descriptor (rtx mem)
     return NULL;
 
   if (INTVAL (MEM_OFFSET (mem)))
-    {
-      if (INTVAL (MEM_OFFSET (mem)) >= 0)
-       add_loc_descr (&loc_result,
-                      new_loc_descr (DW_OP_plus_uconst,
-                                     INTVAL (MEM_OFFSET (mem)), 0));
-      else
-       {
-         loc_result2 = mem_loc_descriptor (MEM_OFFSET (mem), GET_MODE (mem),
-                                           VAR_INIT_STATUS_INITIALIZED);
-         if (loc_result2 == 0)
-           return NULL;
-         add_loc_descr (&loc_result, loc_result2);
-         add_loc_descr (&loc_result, new_loc_descr (DW_OP_plus, 0, 0));
-       }
-    }
+    loc_descr_plus_const (&loc_result, INTVAL (MEM_OFFSET (mem)));
 
   return loc_result;
 }
@@ -10099,11 +10124,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
          if (mem_loc_result == 0)
            break;
 
-         if (GET_CODE (XEXP (rtl, 1)) == CONST_INT
-             && INTVAL (XEXP (rtl, 1)) >= 0)
-           add_loc_descr (&mem_loc_result,
-                          new_loc_descr (DW_OP_plus_uconst,
-                                         INTVAL (XEXP (rtl, 1)), 0));
+         if (GET_CODE (XEXP (rtl, 1)) == CONST_INT)
+           loc_descr_plus_const (&mem_loc_result, INTVAL (XEXP (rtl, 1)));
          else
            {
              dw_loc_descr_ref mem_loc_result2
@@ -10517,13 +10539,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
          }
 
        bytepos = bitpos / BITS_PER_UNIT;
-       if (bytepos > 0)
-         add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0));
-       else if (bytepos < 0)
-         {
-           add_loc_descr (&ret, int_loc_descriptor (bytepos));
-           add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0));
-         }
+       loc_descr_plus_const (&ret, bytepos);
 
        have_address = 1;
        break;
@@ -10607,11 +10623,7 @@ loc_descriptor_from_tree_1 (tree loc, int want_address)
          if (ret == 0)
            return 0;
 
-         add_loc_descr (&ret,
-                        new_loc_descr (DW_OP_plus_uconst,
-                                       tree_low_cst (TREE_OPERAND (loc, 1),
-                                                     0),
-                                       0));
+         loc_descr_plus_const (&ret, tree_low_cst (TREE_OPERAND (loc, 1), 0));
          break;
        }
 
@@ -12994,10 +13006,7 @@ descr_info_loc (tree val, tree base_decl)
          loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
          if (!loc)
            break;
-         add_loc_descr (&loc,
-                        new_loc_descr (DW_OP_plus_uconst,
-                                       tree_low_cst (TREE_OPERAND (val, 1),
-                                                     1), 0));
+         loc_descr_plus_const (&loc, tree_low_cst (TREE_OPERAND (val, 1), 0));
        }
       else
        {
@@ -13913,9 +13922,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
                        loc->dw_loc_oprnd1.v.val_addr
                          = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
                        else
-                         add_loc_descr (&loc,
-                                        new_loc_descr (DW_OP_plus_uconst,
-                                                       off, 0));
+                         loc_descr_plus_const (&loc, off);
                    }
                  add_AT_loc (var_die, DW_AT_location, loc);
                  remove_AT (var_die, DW_AT_declaration);
@@ -13978,8 +13985,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
                loc->dw_loc_oprnd1.v.val_addr
                  = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off);
              else
-               add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst,
-                                                   off, 0));
+               loc_descr_plus_const (&loc, off);
            }
          add_AT_loc (var_die, DW_AT_location, loc);
        }