* rtl.def (DEBUG_IMPLICIT_PTR): New rtl code.
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Sep 2010 06:43:47 +0000 (06:43 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Sep 2010 06:43:47 +0000 (06:43 +0000)
* rtl.h (DEBUG_IMPLICIT_PTR_DECL): Define.
* rtl.c (rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_IMPLICIT_PTR.
* print-rtl.c (print_rtx): Likewise.
* cselib.c (rtx_equal_for_cselib_p, cselib_hash_rtx): Likewise.
* cfgexpand.c (expand_debug_expr): Generate DEBUG_IMPLICIT_PTR
for ADDR_EXPR with non-addressable object.
* dwarf2out.c (enum dw_val_class): Add dw_val_class_decl_ref.
(struct dw_val_struct): Add v.val_decl_ref.
(dwarf_stack_op_name, output_loc_operands, output_loc_operands_raw):
Handle DW_OP_GNU_implicit_pointer.
(size_of_loc_descr): Likewise.  Fix up DW_OP_call_ref size.
(get_ref_die_offset_label): New function.
(implicit_ptr_descriptor): New function.
(mem_loc_descriptor): Handle DEBUG_IMPLICIT_PTR.
(loc_descriptor): Likewise.
(gen_variable_die): Put even definitions into decl_die_table.
(resolve_addr_in_expr): Resolve still unresolved
DW_OP_GNU_implicit_pointer operands, if it can't be resolved
return false.
(dwarf2out_finish): Call output_location_lists after outputting
.debug_info and .debug_abbrev instead of before.

* dwarf2.h (DW_OP_GNU_implicit_pointer): New.

2010-09-09  Roland McGrath  <roland@redhat.com>

* dwarf2out.c (DWARF_REF_SIZE): Define.
(size_of_loc_descr): Use it for DW_OP_call_ref.

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

gcc/ChangeLog
gcc/cfgexpand.c
gcc/cselib.c
gcc/dwarf2out.c
gcc/print-rtl.c
gcc/rtl.c
gcc/rtl.def
gcc/rtl.h
include/ChangeLog
include/dwarf2.h

index 5e80ee9..b815a39 100644 (file)
@@ -1,3 +1,33 @@
+2010-09-09  Jakub Jelinek  <jakub@redhat.com>
+
+       * rtl.def (DEBUG_IMPLICIT_PTR): New rtl code.
+       * rtl.h (DEBUG_IMPLICIT_PTR_DECL): Define.
+       * rtl.c (rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_IMPLICIT_PTR.
+       * print-rtl.c (print_rtx): Likewise.
+       * cselib.c (rtx_equal_for_cselib_p, cselib_hash_rtx): Likewise.
+       * cfgexpand.c (expand_debug_expr): Generate DEBUG_IMPLICIT_PTR
+       for ADDR_EXPR with non-addressable object.
+       * dwarf2out.c (enum dw_val_class): Add dw_val_class_decl_ref.
+       (struct dw_val_struct): Add v.val_decl_ref.
+       (dwarf_stack_op_name, output_loc_operands, output_loc_operands_raw):
+       Handle DW_OP_GNU_implicit_pointer.
+       (size_of_loc_descr): Likewise.  Fix up DW_OP_call_ref size.
+       (get_ref_die_offset_label): New function.
+       (implicit_ptr_descriptor): New function.
+       (mem_loc_descriptor): Handle DEBUG_IMPLICIT_PTR.
+       (loc_descriptor): Likewise.
+       (gen_variable_die): Put even definitions into decl_die_table.
+       (resolve_addr_in_expr): Resolve still unresolved
+       DW_OP_GNU_implicit_pointer operands, if it can't be resolved
+       return false.
+       (dwarf2out_finish): Call output_location_lists after outputting
+       .debug_info and .debug_abbrev instead of before.
+
+2010-09-09  Roland McGrath  <roland@redhat.com>
+
+       * dwarf2out.c (DWARF_REF_SIZE): Define.
+       (size_of_loc_descr): Use it for DW_OP_call_ref.
+
 2010-09-09  Alan Modra  <amodra@gmail.com>
 
        * doc/invoke.text: Reinstate mcmodel=medium.
index 4ae541d..4237276 100644 (file)
@@ -2911,7 +2911,32 @@ expand_debug_expr (tree exp)
     case ADDR_EXPR:
       op0 = expand_debug_expr (TREE_OPERAND (exp, 0));
       if (!op0 || !MEM_P (op0))
-       return NULL;
+       {
+         if ((TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL
+              || TREE_CODE (TREE_OPERAND (exp, 0)) == PARM_DECL
+              || TREE_CODE (TREE_OPERAND (exp, 0)) == RESULT_DECL)
+             && !TREE_ADDRESSABLE (TREE_OPERAND (exp, 0)))
+           return gen_rtx_DEBUG_IMPLICIT_PTR (mode, TREE_OPERAND (exp, 0));
+
+         if (handled_component_p (TREE_OPERAND (exp, 0)))
+           {
+             HOST_WIDE_INT bitoffset, bitsize, maxsize;
+             tree decl
+               = get_ref_base_and_extent (TREE_OPERAND (exp, 0),
+                                          &bitoffset, &bitsize, &maxsize);
+             if ((TREE_CODE (decl) == VAR_DECL
+                  || TREE_CODE (decl) == PARM_DECL
+                  || TREE_CODE (decl) == RESULT_DECL)
+                 && !TREE_ADDRESSABLE (decl)
+                 && (bitoffset % BITS_PER_UNIT) == 0
+                 && bitsize > 0
+                 && bitsize == maxsize)
+               return plus_constant (gen_rtx_DEBUG_IMPLICIT_PTR (mode, decl),
+                                     bitoffset / BITS_PER_UNIT);
+           }
+
+         return NULL;
+       }
 
       op0 = convert_debug_memory_address (mode, XEXP (op0, 0));
 
index 64f183f..05029fa 100644 (file)
@@ -700,6 +700,10 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
     case DEBUG_EXPR:
       return 0;
 
+    case DEBUG_IMPLICIT_PTR:
+      return DEBUG_IMPLICIT_PTR_DECL (x)
+            == DEBUG_IMPLICIT_PTR_DECL (y);
+
     case LABEL_REF:
       return XEXP (x, 0) == XEXP (y, 0);
 
@@ -834,6 +838,11 @@ cselib_hash_rtx (rtx x, int create)
              + DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x));
       return hash ? hash : (unsigned int) DEBUG_EXPR;
 
+    case DEBUG_IMPLICIT_PTR:
+      hash += ((unsigned) DEBUG_IMPLICIT_PTR << 7)
+             + DECL_UID (DEBUG_IMPLICIT_PTR_DECL (x));
+      return hash ? hash : (unsigned int) DEBUG_IMPLICIT_PTR;
+
     case CONST_INT:
       hash += ((unsigned) CONST_INT << 7) + INTVAL (x);
       return hash ? hash : (unsigned int) CONST_INT;
index 237d089..11707fb 100644 (file)
@@ -4294,6 +4294,7 @@ enum dw_val_class
   dw_val_class_macptr,
   dw_val_class_file,
   dw_val_class_data8,
+  dw_val_class_decl_ref,
   dw_val_class_vms_delta
 };
 
@@ -4332,6 +4333,7 @@ typedef struct GTY(()) dw_val_struct {
       unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag;
       struct dwarf_file_data * GTY ((tag ("dw_val_class_file"))) val_file;
       unsigned char GTY ((tag ("dw_val_class_data8"))) val_data8[8];
+      tree GTY ((tag ("dw_val_class_decl_ref"))) val_decl_ref;
       struct dw_val_vms_delta_union
        {
          char * lbl1;
@@ -4695,6 +4697,8 @@ dwarf_stack_op_name (unsigned int op)
       return "DW_OP_GNU_uninit";
     case DW_OP_GNU_encoded_addr:
       return "DW_OP_GNU_encoded_addr";
+    case DW_OP_GNU_implicit_pointer:
+      return "DW_OP_GNU_implicit_pointer";
 
     default:
       return "OP_<unknown>";
@@ -4798,6 +4802,9 @@ loc_list_plus_const (dw_loc_list_ref list_head, HOST_WIDE_INT offset)
     loc_descr_plus_const (&d->expr, offset);
 }
 
+#define DWARF_REF_SIZE \
+  (dwarf_version == 2 ? DWARF2_ADDR_SIZE : DWARF_OFFSET_SIZE)
+
 /* Return the size of a location descriptor.  */
 
 static unsigned long
@@ -4904,12 +4911,15 @@ size_of_loc_descr (dw_loc_descr_ref loc)
       size += 4;
       break;
     case DW_OP_call_ref:
-      size += DWARF2_ADDR_SIZE;
+      size += DWARF_REF_SIZE;
       break;
     case DW_OP_implicit_value:
       size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned)
              + loc->dw_loc_oprnd1.v.val_unsigned;
       break;
+    case DW_OP_GNU_implicit_pointer:
+      size += DWARF_REF_SIZE + size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int);
+      break;
     default:
       break;
     }
@@ -4946,6 +4956,7 @@ size_of_locs (dw_loc_descr_ref loc)
 }
 
 static HOST_WIDE_INT extract_int (const unsigned char *, unsigned);
+static void get_ref_die_offset_label (char *, dw_die_ref);
 
 /* Output location description stack opcode's operands (if any).  */
 
@@ -5165,6 +5176,17 @@ output_loc_operands (dw_loc_descr_ref loc)
        }
       break;
 
+    case DW_OP_GNU_implicit_pointer:
+      {
+       char label[MAX_ARTIFICIAL_LABEL_BYTES
+                  + HOST_BITS_PER_WIDE_INT / 2 + 2];
+       gcc_assert (val1->val_class == dw_val_class_die_ref);
+       get_ref_die_offset_label (label, val1->v.val_die_ref.die);
+       dw2_asm_output_offset (DWARF_REF_SIZE, label, debug_info_section, NULL);
+       dw2_asm_output_data_sleb128 (val2->v.val_int, NULL);
+      }
+      break;
+
     default:
       /* Other codes have no operands.  */
       break;
@@ -5303,6 +5325,10 @@ output_loc_operands_raw (dw_loc_descr_ref loc)
       dw2_asm_output_data_sleb128_raw (val2->v.val_int);
       break;
 
+    case DW_OP_GNU_implicit_pointer:
+      gcc_unreachable ();
+      break;
+
     default:
       /* Other codes have no operands.  */
       break;
@@ -6514,6 +6540,15 @@ is_tagged_type (const_tree type)
          || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
 }
 
+/* Set label to debug_info_section_label + die_offset of a DIE reference.  */
+
+static void
+get_ref_die_offset_label (char *label, dw_die_ref ref)
+{
+  sprintf (label, "%s+" HOST_WIDE_INT_PRINT_DEC,
+          debug_info_section_label, ref->die_offset);
+}
+
 /* Convert a DIE tag into its string name.  */
 
 static const char *
@@ -13651,6 +13686,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
     case CONCAT:
     case CONCATN:
     case VAR_LOCATION:
+    case DEBUG_IMPLICIT_PTR:
       expansion_failed (NULL_TREE, rtl,
                        "CONCAT/CONCATN/VAR_LOCATION is handled only by loc_descriptor");
       return 0;
@@ -14240,6 +14276,35 @@ concatn_loc_descriptor (rtx concatn, enum var_init_status initialized)
   return cc_loc_result;
 }
 
+/* Helper function for loc_descriptor.  Return DW_OP_GNU_implicit_pointer
+   for DEBUG_IMPLICIT_PTR RTL.  */
+
+static dw_loc_descr_ref
+implicit_ptr_descriptor (rtx rtl, HOST_WIDE_INT offset)
+{
+  dw_loc_descr_ref ret;
+  dw_die_ref ref;
+
+  gcc_assert (TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == VAR_DECL
+             || TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == PARM_DECL
+             || TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == RESULT_DECL);
+  ref = lookup_decl_die (DEBUG_IMPLICIT_PTR_DECL (rtl));
+  ret = new_loc_descr (DW_OP_GNU_implicit_pointer, 0, offset);
+  ret->dw_loc_oprnd2.val_class = dw_val_class_const;
+  if (ref)
+    {
+      ret->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+      ret->dw_loc_oprnd1.v.val_die_ref.die = ref;
+      ret->dw_loc_oprnd1.v.val_die_ref.external = 0;
+    }
+  else
+    {
+      ret->dw_loc_oprnd1.val_class = dw_val_class_decl_ref;
+      ret->dw_loc_oprnd1.v.val_decl_ref = DEBUG_IMPLICIT_PTR_DECL (rtl);
+    }
+  return ret;
+}
+
 /* Output a proper Dwarf location descriptor for a variable or parameter
    which is either allocated in a register or in a memory location.  For a
    register, we just generate an OP_REG and the register number.  For a
@@ -14457,6 +14522,19 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
        }
       break;
 
+    case DEBUG_IMPLICIT_PTR:
+      loc_result = implicit_ptr_descriptor (rtl, 0);
+      break;
+
+    case PLUS:
+      if (GET_CODE (XEXP (rtl, 0)) == DEBUG_IMPLICIT_PTR
+         && CONST_INT_P (XEXP (rtl, 1)))
+       {
+         loc_result
+           = implicit_ptr_descriptor (XEXP (rtl, 0), INTVAL (XEXP (rtl, 1)));
+         break;
+       }
+      /* FALLTHRU */
     default:
       if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE (rtl) == mode
          && GET_MODE_SIZE (GET_MODE (rtl)) <= DWARF2_ADDR_SIZE
@@ -19190,7 +19268,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   if (declaration)
     add_AT_flag (var_die, DW_AT_declaration, 1);
 
-  if (decl && (DECL_ABSTRACT (decl) || declaration))
+  if (decl && (DECL_ABSTRACT (decl) || declaration || old_die == NULL))
     equate_decl_number_to_die (decl, var_die);
 
   if (! declaration
@@ -22150,6 +22228,17 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
            && loc->dw_loc_oprnd2.val_class == dw_val_class_addr
            && resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL)))
       return false;
+    else if (loc->dw_loc_opc == DW_OP_GNU_implicit_pointer
+            && loc->dw_loc_oprnd1.val_class == dw_val_class_decl_ref)
+      {
+       dw_die_ref ref
+         = lookup_decl_die (loc->dw_loc_oprnd1.v.val_decl_ref);
+       if (ref == NULL)
+         return false;
+       loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+       loc->dw_loc_oprnd1.v.val_die_ref.die = ref;
+       loc->dw_loc_oprnd1.v.val_die_ref.external = 0;
+      }
   return true;
 }
 
@@ -22429,17 +22518,6 @@ dwarf2out_finish (const char *filename)
        add_ranges (NULL);
     }
 
-  /* Output location list section if necessary.  */
-  if (have_location_lists)
-    {
-      /* Output the location lists info.  */
-      switch_to_section (debug_loc_section);
-      ASM_GENERATE_INTERNAL_LABEL (loc_section_label,
-                                  DEBUG_LOC_SECTION_LABEL, 0);
-      ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
-      output_location_lists (die);
-    }
-
   if (debug_info_level >= DINFO_LEVEL_NORMAL)
     add_AT_lineptr (comp_unit_die, DW_AT_stmt_list,
                    debug_line_section_label);
@@ -22481,6 +22559,17 @@ dwarf2out_finish (const char *filename)
   switch_to_section (debug_abbrev_section);
   output_abbrev_section ();
 
+  /* Output location list section if necessary.  */
+  if (have_location_lists)
+    {
+      /* Output the location lists info.  */
+      switch_to_section (debug_loc_section);
+      ASM_GENERATE_INTERNAL_LABEL (loc_section_label,
+                                  DEBUG_LOC_SECTION_LABEL, 0);
+      ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
+      output_location_lists (die);
+    }
+
   /* Output public names table if necessary.  */
   if (!VEC_empty (pubname_entry, pubname_table))
     {
index 8801a88..04d7959 100644 (file)
@@ -533,7 +533,10 @@ print_rtx (const_rtx in_rtx)
 
       case 't':
 #ifndef GENERATOR_FILE
-       dump_addr (outfile, " ", XTREE (in_rtx, i));
+       if (i == 0 && GET_CODE (in_rtx) == DEBUG_IMPLICIT_PTR)
+         print_mem_expr (outfile, DEBUG_IMPLICIT_PTR_DECL (in_rtx));
+       else
+         dump_addr (outfile, " ", XTREE (in_rtx, i));
 #endif
        break;
 
index 79dafcb..3a6affc 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -407,6 +407,10 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
     case CONST_FIXED:
       return 0;
 
+    case DEBUG_IMPLICIT_PTR:
+      return DEBUG_IMPLICIT_PTR_DECL (x)
+            == DEBUG_IMPLICIT_PTR_DECL (y);
+
     default:
       break;
     }
@@ -527,6 +531,10 @@ rtx_equal_p (const_rtx x, const_rtx y)
     case CONST_FIXED:
       return 0;
 
+    case DEBUG_IMPLICIT_PTR:
+      return DEBUG_IMPLICIT_PTR_DECL (x)
+            == DEBUG_IMPLICIT_PTR_DECL (y);
+
     default:
       break;
     }
index 26014ae..282cca6 100644 (file)
@@ -711,6 +711,10 @@ DEF_RTL_EXPR(US_TRUNCATE, "us_truncate", "e", RTX_UNARY)
    initialization status of variables.  */
 DEF_RTL_EXPR(VAR_LOCATION, "var_location", "tei", RTX_EXTRA)
 
+/* Used in VAR_LOCATION for a pointer to a decl that is no longer
+   addressable.  */
+DEF_RTL_EXPR(DEBUG_IMPLICIT_PTR, "debug_implicit_ptr", "t", RTX_OBJ)
+
 /* All expressions from this point forward appear only in machine
    descriptions.  */
 #ifdef GENERATOR_FILE
index 873c792..f490a0c 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -933,6 +933,9 @@ extern const char * const reg_note_name[];
 /* DEBUG_EXPR_DECL corresponding to a DEBUG_EXPR RTX.  */
 #define DEBUG_EXPR_TREE_DECL(RTX) XCTREE (RTX, 0, DEBUG_EXPR)
 
+/* VAR_DECL/PARM_DECL DEBUG_IMPLICIT_PTR takes address of.  */
+#define DEBUG_IMPLICIT_PTR_DECL(RTX) XCTREE (RTX, 0, DEBUG_IMPLICIT_PTR)
+
 /* Possible initialization status of a variable.   When requested
    by the user, this information is tracked and recorded in the DWARF
    debug information, along with the variable's location.  */
index 3fc2fa5..ec24917 100644 (file)
@@ -1,3 +1,7 @@
+2010-09-09  Jakub Jelinek  <jakub@redhat.com>
+
+       * dwarf2.h (DW_OP_GNU_implicit_pointer): New.
+
 2010-07-06  Ken Werner  <ken.werner@de.ibm.com>
 
        * floatformat.h (floatformat_ieee_half_big): Add declaration.
index 03c2581..fea23ad 100644 (file)
@@ -622,6 +622,7 @@ enum dwarf_location_atom
     /* The following is for marking variables that are uninitialized.  */
     DW_OP_GNU_uninit     = 0xf0,
     DW_OP_GNU_encoded_addr = 0xf1,
+    DW_OP_GNU_implicit_pointer = 0xf2,
     /* HP extensions.  */
     DW_OP_HP_unknown     = 0xe0, /* Ouch, the same as GNU_push_tls_address.  */
     DW_OP_HP_is_value    = 0xe1,