This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[vta] handle references to const strings in debug info


If the value of debug variables can be computed by dereferencing
portions of constant strings, not output in non-debug sections,
arrange for the string to be emitted in the .debug_str section, and
set the location of the variable to refer to it.

It would be nicer to just resolve the indirection to a value, but
there's no way (yet) to encode debug information for this case.

Meanwhile, I'm going ahead and installing this in the branch.

Index: gcc/ChangeLog.vta
from  Alexandre Oliva  <aoliva@redhat.com>

	* dwarf2out.c (debug_str_hash_forced): New.
	(add_string): New, split out of...
	(add_AT_string): ... this.
	(gen_label_for_idirect_string): New, split out of...
	(AT_string_form): ... this.
	(get_debug_string_label): New.
	(mem_loc_descriptor): Handle CONST_STRINGs.
	(output_indirect_string): Output if there are label and references.
	(prune_indirect_string): New.
	(prune_unused_types): Preserve forced indirect strings.
	
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c.orig	2008-10-10 09:31:05.000000000 -0300
+++ gcc/dwarf2out.c	2008-11-18 04:12:22.000000000 -0200
@@ -382,6 +382,10 @@ struct indirect_string_node GTY(())
 
 static GTY ((param_is (struct indirect_string_node))) htab_t debug_str_hash;
 
+/* True if the compilation unit has location entries that reference
+   debug strings.  */
+static GTY(()) bool debug_str_hash_forced = false;
+
 static GTY(()) int dw2_string_counter;
 static GTY(()) unsigned long dwarf2out_cfi_label_num;
 
@@ -5926,12 +5930,11 @@ debug_str_eq (const void *x1, const void
 		 (const char *)x2) == 0;
 }
 
-/* Add a string attribute value to a DIE.  */
+/* Add STR to the indirect string hash table.  */
 
-static inline void
-add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str)
+static inline struct indirect_string_node *
+add_string (const char *str)
 {
-  dw_attr_node attr;
   struct indirect_string_node *node;
   void **slot;
 
@@ -5951,6 +5954,17 @@ add_AT_string (dw_die_ref die, enum dwar
   else
     node = (struct indirect_string_node *) *slot;
 
+  return node;
+}
+
+/* Add a string attribute value to a DIE.  */
+
+static inline void
+add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str)
+{
+  dw_attr_node attr;
+  struct indirect_string_node *node = add_string (str);
+
   node->refcount++;
 
   attr.dw_attr = attr_kind;
@@ -5959,6 +5973,38 @@ add_AT_string (dw_die_ref die, enum dwar
   add_dwarf_attr (die, &attr);
 }
 
+/* Create a label for an indirect string node, ensuring it is going to
+   be output, unless its reference count goes down to zero.  */
+
+static inline void
+gen_label_for_indirect_string (struct indirect_string_node *node)
+{
+  char label[32];
+
+  if (node->label)
+    return;
+
+  ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
+  ++dw2_string_counter;
+  node->label = xstrdup (label);
+}
+
+/* Create a SYMBOL_REF rtx whose value is the initial address of a
+   debug string STR.  */
+
+static inline rtx
+get_debug_string_label (const char *str)
+{
+  struct indirect_string_node *node = add_string (str);
+
+  debug_str_hash_forced = true;
+  node->refcount++;
+
+  gen_label_for_indirect_string (node);
+
+  return gen_rtx_SYMBOL_REF (Pmode, node->label);
+}
+
 static inline const char *
 AT_string (dw_attr_ref a)
 {
@@ -5974,7 +6020,6 @@ AT_string_form (dw_attr_ref a)
 {
   struct indirect_string_node *node;
   unsigned int len;
-  char label[32];
 
   gcc_assert (a && AT_class (a) == dw_val_class_str);
 
@@ -5996,9 +6041,7 @@ AT_string_form (dw_attr_ref a)
       && (len - DWARF_OFFSET_SIZE) * node->refcount <= len)
     return node->form = DW_FORM_string;
 
-  ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
-  ++dw2_string_counter;
-  node->label = xstrdup (label);
+  gen_label_for_indirect_string (node);
 
   return node->form = DW_FORM_strp;
 }
@@ -10080,6 +10123,7 @@ mem_loc_descriptor (rtx rtl, enum machin
 	  break;
 	}
 
+    symref:
       mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
       mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr;
       mem_loc_result->dw_loc_oprnd1.v.val_addr = rtl;
@@ -10188,6 +10232,10 @@ mem_loc_descriptor (rtx rtl, enum machin
 	 TLS UNSPECs.  */
       break;
 
+    case CONST_STRING:
+      rtl = get_debug_string_label (XSTR (rtl, 0));
+      goto symref;
+
     default:
       gcc_unreachable ();
     }
@@ -16178,14 +16226,14 @@ dwarf2out_init (const char *filename ATT
 }
 
 /* A helper function for dwarf2out_finish called through
-   ht_forall.  Emit one queued .debug_str string.  */
+   htab_traverse.  Emit one queued .debug_str string.  */
 
 static int
 output_indirect_string (void **h, void *v ATTRIBUTE_UNUSED)
 {
   struct indirect_string_node *node = (struct indirect_string_node *) *h;
 
-  if (node->form == DW_FORM_strp)
+  if (node->label && node->refcount)
     {
       switch_to_section (debug_str_section);
       ASM_OUTPUT_LABEL (asm_out_file, node->label);
@@ -16408,6 +16456,20 @@ prune_unused_types_prune (dw_die_ref die
   } while (c != die->die_child);
 }
 
+/* A helper function for dwarf2out_finish called through
+   htab_traverse.  Clear .debug_str strings that we haven't already
+   decided to emit.  */
+
+static int
+prune_indirect_string (void **h, void *v ATTRIBUTE_UNUSED)
+{
+  struct indirect_string_node *node = (struct indirect_string_node *) *h;
+
+  if (!node->label || !node->refcount)
+    htab_clear_slot (debug_str_hash, h);
+
+  return 1;
+}
 
 /* Remove dies representing declarations that we never use.  */
 
@@ -16438,7 +16500,9 @@ prune_unused_types (void)
     prune_unused_types_mark (arange_table[i], 1);
 
   /* Get rid of nodes that aren't marked; and update the string counts.  */
-  if (debug_str_hash)
+  if (debug_str_hash && debug_str_hash_forced)
+    htab_traverse (debug_str_hash, prune_indirect_string, NULL);
+  else if (debug_str_hash)
     htab_empty (debug_str_hash);
   prune_unused_types_prune (comp_unit_die);
   for (node = limbo_die_list; node; node = node->next)
-- 
Alexandre Oliva           http://www.lsd.ic.unicamp.br/~oliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]