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]

Re: [PATCH] Emit .debug_str and DW_FORM_strp where appropriate


On Tue, Nov 06, 2001 at 08:55:02PM -0800, Richard Henderson wrote:
> On Tue, Nov 06, 2001 at 04:04:48PM +0100, Jakub Jelinek wrote:
> > The generic toplev.c cannot be used for 2 reasons: toplev.c emits the
> > variables before doing debug finish and also I wanted to avoid creating
> > some more trees for DECL_INITIAL (ADDR_EXPR, some external type,
> > identifier for the symbol it should relocate to and a decl for it),
> > because the splay tree needs the symbol's name as key anyway.
> > So I'm calling assemble_variable (....., 1); there and output the value
> > myself.
> 
> Hmm.  Ok.
> 
> > I've added .debug_str support into the patch too.
> 
> I wish you hadn't merged the patches.

Sorry, the separated indirect constant patch is attached below.
Bootstrapped on i386-redhat-linux, appart from an unrelated flow Java ICE in
libgcj. No regressions in make check. Ok to commit it?

> (1) I don't think the .debug_str code should go in dwarf2asm.c.

You mean the named_section_flags call, or the whole
dw2_output_indirect_string etc.?
If the former, I could move the dw2_output_indirect_constants routine (under
a different name) to dwarf2out.c, which would in turn call two routines in
dwarf2asm.c and in between them call named_section_flags.

> 
> > +/* If assembler supports SHF_MERGE, we want strings in .debug_str section
> > +   merged.  */
> > +   
> > +#ifdef HAVE_GAS_SHF_MERGE
> > +#define DEBUG_STR_SECTION_FLAGS \
> > +  (SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1)
> > +#endif
> 
> (2) You didn't provide a fallback to plain SECTION_DEBUG.

The fallback is in dwarf2asm.c.

> > -  return strlen (str) + 1;
> > +  unsigned long len = strlen (str) + 1;
> > +#ifdef DEBUG_STR_SECTION_FLAGS
> > +  return len <= DWARF_OFFSET_SIZE ? len : DWARF_OFFSET_SIZE;
> > +#else
> > +  return len;
> > +#endif
> 
> (3) What has DEBUG_STR_SECTION_FLAGS got to do with anything here?

The point was that dw2_output_indirect_string would be able to get reference
to .debug_str strings always, but dwarf2out.c would only use it if it can
expect the linker to do some duplication merging magic, because otherwise
this might as well not be an optimization, but pessimization (the
probability that strings are merged within one object file is lower than
that they are merged accross the whole lib/prog, and if the string is
merged, the result is that DW_FORM_string would take strlen + 1, while
DW_FORM_strp takes offset_size + strlen + 1).
Or should the check be explicitly now if (DEBUG_STR_SECTION_FLAGS & SECTION_MERGE)?

> >  	case dw_val_class_str:
> > +#ifdef DEBUG_STR_SECTION_FLAGS
> > +	  if (strlen (AT_string (a)) + 1 > DWARF_OFFSET_SIZE)
> > +	    {
> > +	      dw2_asm_output_indirect_string (DWARF_OFFSET_SIZE,
> > +					      AT_string (a), "%s", name);
> > +	      break;
> > +	    }
> > +#endif
> 
> Or here?  In fact, I'd warrant that DW_FORM_strp shouldn't have
> gotten this far.  Shouldn't you have transformed this info a plain
> number earlier?  Or at least a different dw_val_class, so that we
> don't choose DW_FORM_strp in one place, and fail to use it in 
> another.

I was trying to follow how e.g. dw_class_die_ref is handled (which can end
up being DW_FORM_ref_addr or DW_FORM_ref{4,8}).
Would it suffice to put the predicate AT_string_indirect() into a separate
inline function and use it in all the places where this distinction is
needed?

Here is the indirect pool patch:

2001-11-06  Jakub Jelinek  <jakub@redhat.com>

	* dwarf2asm.c (mark_indirect_pool_entry, mark_indirect_pool): New.
	(USE_LINKONCE_INDIRECT): Define.
	(dw2_output_indirect_constant_1): Try to output indirect constants
	into linkonce sections if possible.
	(dw2_force_const_mem): Likewise.  Register indirect_pool with GGC.
	(dw2_output_indirect_constants): Likewise.

--- gcc/dwarf2asm.c.jj	Tue Nov  6 20:02:22 2001
+++ gcc/dwarf2asm.c	Tue Nov  6 20:06:54 2001
@@ -720,11 +720,39 @@ dw2_asm_output_delta_sleb128 VPARAMS ((c
   VA_CLOSE (ap);
 }
 
+static int mark_indirect_pool_entry PARAMS ((splay_tree_node, void *));
+static void mark_indirect_pool PARAMS ((PTR arg));
 static rtx dw2_force_const_mem PARAMS ((rtx));
 static int dw2_output_indirect_constant_1 PARAMS ((splay_tree_node, void *));
 
 static splay_tree indirect_pool;
 
+#if defined(HAVE_GAS_HIDDEN) && defined(SUPPORTS_ONE_ONLY)
+# define USE_LINKONCE_INDIRECT 1
+#else
+# define USE_LINKONCE_INDIRECT 0
+#endif
+
+/* Mark all indirect constants for GC.  */
+
+static int
+mark_indirect_pool_entry (node, data)
+     splay_tree_node node;
+     void* data ATTRIBUTE_UNUSED;
+{
+  ggc_mark_nonnull_tree ((tree) node->value);
+  return 0;
+}
+
+/* Mark all indirect constants for GC.  */
+
+static void
+mark_indirect_pool (arg)
+     PTR arg ATTRIBUTE_UNUSED;
+{
+  splay_tree_foreach (indirect_pool, mark_indirect_pool_entry, NULL);
+}
+
 /* Put X, a SYMBOL_REF, in memory.  Return a SYMBOL_REF to the allocated
    memory.  Differs from force_const_mem in that a single pool is used for
    the entire unit of translation, and the memory is not guaranteed to be
@@ -735,35 +763,56 @@ dw2_force_const_mem (x)
      rtx x;
 {
   splay_tree_node node;
-  const char *const_sym;
+  tree decl;
 
   if (! indirect_pool)
-    indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
+    {
+      indirect_pool = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
+      ggc_add_root (&indirect_pool, 1, sizeof indirect_pool, mark_indirect_pool);
+    }
 
   if (GET_CODE (x) != SYMBOL_REF)
     abort ();
   node = splay_tree_lookup (indirect_pool, (splay_tree_key) XSTR (x, 0));
   if (node)
-    const_sym = (const char *) node->value;
+    decl = (tree) node->value;
   else
     {
-      extern int const_labelno;
-      char label[32];
       tree id;
 
-      ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
-      ++const_labelno;
-      const_sym = ggc_strdup (label);
+      if (USE_LINKONCE_INDIRECT)
+	{
+	  char *ref_name = alloca (strlen (XSTR (x, 0) + sizeof "DW.ref."));
+
+	  sprintf (ref_name, "DW.ref.%s", XSTR (x, 0));
+	  id = get_identifier (ref_name);
+	  decl = build_decl (VAR_DECL, id, ptr_type_node);
+	  DECL_ARTIFICIAL (decl) = 1;
+	  DECL_INITIAL (decl) = decl;
+	  make_decl_one_only (decl);
+	}
+      else
+	{
+	  extern int const_labelno;
+	  char label[32];
+
+	  ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
+	  ++const_labelno;
+	  id = get_identifier (label);
+	  decl = build_decl (VAR_DECL, id, ptr_type_node);
+	  DECL_ARTIFICIAL (decl) = 1;
+	  DECL_INITIAL (decl) = decl;
+	}
 
       id = maybe_get_identifier (XSTR (x, 0));
       if (id)
 	TREE_SYMBOL_REFERENCED (id) = 1;
 
       splay_tree_insert (indirect_pool, (splay_tree_key) XSTR (x, 0),
-			 (splay_tree_value) const_sym);
+			 (splay_tree_value) decl);
     }
 
-  return gen_rtx_SYMBOL_REF (Pmode, const_sym);
+  return XEXP (DECL_RTL (decl), 0);
 }
 
 /* A helper function for dw2_output_indirect_constants called through
@@ -774,14 +823,14 @@ dw2_output_indirect_constant_1 (node, da
      splay_tree_node node;
      void* data ATTRIBUTE_UNUSED;
 {
-  const char *label, *sym;
+  const char *sym;
   rtx sym_ref;
 
-  label = (const char *) node->value;
   sym = (const char *) node->key;
   sym_ref = gen_rtx_SYMBOL_REF (Pmode, sym);
-
-  ASM_OUTPUT_LABEL (asm_out_file, label);
+  if (USE_LINKONCE_INDIRECT)
+    fprintf (asm_out_file, "\t.hidden DW.ref.%s\n", sym);
+  assemble_variable ((tree) node->value, 1, 1, 1);
   assemble_integer (sym_ref, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
 
   return 0;
@@ -792,19 +841,8 @@ dw2_output_indirect_constant_1 (node, da
 void
 dw2_output_indirect_constants ()
 {
-  if (! indirect_pool)
-    return;
-
-  /* Assume that the whole reason we're emitting these symbol references
-     indirectly is that they contain dynamic relocations, and are thus
-     read-write.  If there was no possibility of a dynamic relocation, we
-     might as well have used a direct relocation.  */
-  data_section ();
-
-  /* Everything we're emitting is a pointer.  Align appropriately.  */
-  assemble_align (POINTER_SIZE);
-
-  splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
+  if (indirect_pool)
+    splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
 }
 
 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.  */


	Jakub


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