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]

Re: [RFC] More compact (100x) -g3 .debug_macinfo (take 2)


On Wed, Jul 13, 2011 at 07:00:53PM +0200, Jakub Jelinek wrote:
The patch below implements that slight change, in particular the "4"
suffixes from the op names were dropped, DW_MACINFO_GNU_*_indirect
have DW_FORM_udata and DW_FORM_strp arguments now (i.e. DWARF_OFFSET_SIZE
large) and DW_MACINFO_GNU_transparent_include has DW_FORM_sec_offset
argument (i.e. again 4 bytes long for 32-bit DWARF and 8 bytes long for
64-bit DWARF).  GCC assures that no merging will happen between
.debug_macinfo chunks with 32-bit and 64-bit DWARF by adding the byte size
in the comdat GROUP name.  I think that's cleaner than hardcoding
4 bytes and not optimizing anything on MIPS.

The newly added opcodes:
DW_MACINFO_GNU_define_indirect		0xe0
	This opcode has two arguments, one is uleb128 lineno and the
	other is offset size long byte offset into .debug_str.  Except
	for the encoding of the string it is similar to DW_MACINFO_define.
DW_MACINFO_GNU_undef_indirect		0xe1
	This opcode has two arguments, one is uleb128 lineno and the
	other is offset size long byte offset into .debug_str.  Except
	for the encoding of the string it is similar to DW_MACINFO_undef.
DW_MACINFO_GNU_transparent_include	0xe2
	This opcode has a single argument, a offset size long byte offset into
	.debug_macinfo.  It instructs the debug info consumer that
	this opcode during reading should be replaced with the sequence
	of .debug_macinfo opcodes from the mentioned offset, up to
	a terminating 0 opcode (not including that 0).
DW_MACINFO_GNU_define_opcode		0xe3
	This is an opcode for future extensibility through which
	a debugger could skip unknown opcodes.  It has 3 arguments:
	1 byte opcode number, uleb128 count of arguments and
	a count bytes long array, with a DW_FORM_* code how the
	argument is encoded.

DW_MACINFO_GNU_define_opcode <0, 0 []>
DW_MACINFO_GNU_define_opcode <DW_MACINFO_define, 2 [DW_FORM_udata, DW_FORM_string]>
DW_MACINFO_GNU_define_opcode <DW_MACINFO_undef, 2 [DW_FORM_udata, DW_FORM_string]>
DW_MACINFO_GNU_define_opcode <DW_MACINFO_start_file, 2 [DW_FORM_udata, DW_FORM_udata]>
DW_MACINFO_GNU_define_opcode <DW_MACINFO_end_file, 1 [DW_FORM_udata]>
DW_MACINFO_GNU_define_opcode <DW_MACINFO_GNU_define_indirect, 2 [DW_FORM_udata, DW_FORM_strp]>
DW_MACINFO_GNU_define_opcode <DW_MACINFO_GNU_undef_indirect, 2 [DW_FORM_udata, DW_FORM_strp]>
DW_MACINFO_GNU_define_opcode <DW_MACINFO_GNU_transparent_include, 1 [DW_FORM_sec_offset]>
DW_MACINFO_GNU_define_opcode <DW_MACINFO_GNU_define_opcode, 2 [DW_FORM_data1, DW_FORM_block]>
DW_MACINFO_GNU_define_opcode <DW_MACINFO_vendor_ext, 2 [DW_FORM_udata, DW_FORM_string]>

2011-07-15  Jakub Jelinek  <jakub@redhat.com>

	* dwarf2.h (DW_MACINFO_lo_user, DW_MACINFO_hi_user): Add.
	(DW_MACINFO_GNU_define_indirect, DW_MACINFO_GNU_undef_indirect,
	DW_MACINFO_GNU_transparent_include, DW_MACINFO_GNU_define_opcode):
	Add.

	* dwarf2out.c (dwarf2out_undef): Remove redundant semicolon.
	(htab_macinfo_hash, htab_macinfo_eq, output_macinfo_op): New
	functions.
	(output_macinfo): Use them.  If !dwarf_strict and .debug_str is
	mergeable, optimize longer strings using
	DW_MACINFO_GNU_{define,undef}_indirect and if HAVE_COMDAT and ELF,
	optimize longer sequences of define/undef ops from headers
	using DW_MACINFO_GNU_transparent_include.

--- include/dwarf2.h.jj	2011-06-23 10:14:06.000000000 +0200
+++ include/dwarf2.h	2011-07-13 11:39:49.000000000 +0200
@@ -877,7 +877,13 @@ enum dwarf_macinfo_record_type
     DW_MACINFO_undef = 2,
     DW_MACINFO_start_file = 3,
     DW_MACINFO_end_file = 4,
-    DW_MACINFO_vendor_ext = 255
+    DW_MACINFO_lo_user = 0xe0,
+    DW_MACINFO_GNU_define_indirect = 0xe0,
+    DW_MACINFO_GNU_undef_indirect = 0xe1,
+    DW_MACINFO_GNU_transparent_include = 0xe2,
+    DW_MACINFO_GNU_define_opcode = 0xe3,
+    DW_MACINFO_hi_user = 0xfe,
+    DW_MACINFO_vendor_ext = 0xff
   };
 
 /* @@@ For use with GNU frame unwind information.  */
--- gcc/dwarf2out.c.jj	2011-07-12 17:59:01.000000000 +0200
+++ gcc/dwarf2out.c	2011-07-13 17:04:17.000000000 +0200
@@ -20383,17 +20383,117 @@ dwarf2out_undef (unsigned int lineno ATT
       macinfo_entry e;
       e.code = DW_MACINFO_undef;
       e.lineno = lineno;
-      e.info = xstrdup (buffer);;
+      e.info = xstrdup (buffer);
       VEC_safe_push (macinfo_entry, gc, macinfo_table, &e);
     }
 }
 
+/* Routines to manipulate hash table of CUs.  */
+static hashval_t
+htab_macinfo_hash (const void *of)
+{
+  const macinfo_entry *const entry =
+    (const macinfo_entry *) of;
+
+  return htab_hash_string (entry->info);
+}
+
+static int
+htab_macinfo_eq (const void *of1, const void *of2)
+{
+  const macinfo_entry *const entry1 = (const macinfo_entry *) of1;
+  const macinfo_entry *const entry2 = (const macinfo_entry *) of2;
+
+  return !strcmp (entry1->info, entry2->info);
+}
+
+/* Output a single .debug_macinfo entry.  */
+
+static void
+output_macinfo_op (macinfo_entry *ref)
+{
+  int file_num;
+  size_t len;
+  struct indirect_string_node *node;
+  char label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+  switch (ref->code)
+    {
+    case DW_MACINFO_start_file:
+      file_num = maybe_emit_file (lookup_filename (ref->info));
+      dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file");
+      dw2_asm_output_data_uleb128 (ref->lineno,
+				   "Included from line number %lu", 
+				   (unsigned long) ref->lineno);
+      dw2_asm_output_data_uleb128 (file_num, "file %s", ref->info);
+      break;
+    case DW_MACINFO_end_file:
+      dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
+      break;
+    case DW_MACINFO_define:
+    case DW_MACINFO_undef:
+      len = strlen (ref->info) + 1;
+      if (!dwarf_strict
+	  && len > DWARF_OFFSET_SIZE
+	  && !DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET
+	  && (debug_str_section->common.flags & SECTION_MERGE) != 0)
+	{
+	  ref->code = ref->code == DW_MACINFO_define
+		      ? DW_MACINFO_GNU_define_indirect
+		      : DW_MACINFO_GNU_undef_indirect;
+	  output_macinfo_op (ref);
+	  return;
+	}
+      dw2_asm_output_data (1, ref->code,
+			   ref->code == DW_MACINFO_define
+			   ? "Define macro" : "Undefine macro");
+      dw2_asm_output_data_uleb128 (ref->lineno, "At line number %lu", 
+				   (unsigned long) ref->lineno);
+      dw2_asm_output_nstring (ref->info, -1, "The macro");
+      break;
+    case DW_MACINFO_GNU_define_indirect:
+    case DW_MACINFO_GNU_undef_indirect:
+      node = find_AT_string (ref->info);
+      if (node->form != DW_FORM_strp)
+	{
+	  char label[32];
+	  ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter);
+	  ++dw2_string_counter;
+	  node->label = xstrdup (label);
+	  node->form = DW_FORM_strp;
+	}
+      dw2_asm_output_data (1, ref->code,
+			   ref->code == DW_MACINFO_GNU_define_indirect
+			   ? "Define macro indirect"
+			   : "Undefine macro indirect");
+      dw2_asm_output_data_uleb128 (ref->lineno, "At line number %lu",
+				   (unsigned long) ref->lineno);
+      dw2_asm_output_offset (DWARF_OFFSET_SIZE, node->label,
+			     debug_str_section, "The macro: \"%s\"",
+			     ref->info);
+      break;
+    case DW_MACINFO_GNU_transparent_include:
+      dw2_asm_output_data (1, ref->code, "Transparent include");
+      ASM_GENERATE_INTERNAL_LABEL (label,
+				   DEBUG_MACINFO_SECTION_LABEL, ref->lineno);
+      dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
+      break;
+    default:
+      fprintf (asm_out_file, "%s unrecognized macinfo code %lu\n",
+	       ASM_COMMENT_START, (unsigned long) ref->code);
+      break;
+    }
+}
+
 static void
 output_macinfo (void)
 {
   unsigned i;
   unsigned long length = VEC_length (macinfo_entry, macinfo_table);
-  macinfo_entry *ref;
+  macinfo_entry *ref, *ref2;
+  VEC (macinfo_entry, gc) *files = NULL;
+  unsigned long transparent_includes = 0;
+  htab_t macinfo_htab = NULL;
 
   if (! length)
     return;
@@ -20402,37 +20503,184 @@ output_macinfo (void)
     {
       switch (ref->code)
 	{
-	  case DW_MACINFO_start_file:
+	case DW_MACINFO_start_file:
+	  VEC_safe_push (macinfo_entry, gc, files, ref);
+	  break;
+	case DW_MACINFO_end_file:
+	  if (!VEC_empty (macinfo_entry, files))
 	    {
-	      int file_num = maybe_emit_file (lookup_filename (ref->info));
-	      dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file");
-	      dw2_asm_output_data_uleb128 
-			(ref->lineno, "Included from line number %lu", 
-			 			(unsigned long)ref->lineno);
-	      dw2_asm_output_data_uleb128 (file_num, "file %s", ref->info);
+	      ref2 = VEC_last (macinfo_entry, files);
+	      free (CONST_CAST (char *, ref2->info));
+	      VEC_pop (macinfo_entry, files);
 	    }
-	    break;
-	  case DW_MACINFO_end_file:
-	    dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
-	    break;
-	  case DW_MACINFO_define:
-	    dw2_asm_output_data (1, DW_MACINFO_define, "Define macro");
-	    dw2_asm_output_data_uleb128 (ref->lineno, "At line number %lu", 
-			 			(unsigned long)ref->lineno);
-	    dw2_asm_output_nstring (ref->info, -1, "The macro");
-	    break;
-	  case DW_MACINFO_undef:
-	    dw2_asm_output_data (1, DW_MACINFO_undef, "Undefine macro");
-	    dw2_asm_output_data_uleb128 (ref->lineno, "At line number %lu",
-			 			(unsigned long)ref->lineno);
-	    dw2_asm_output_nstring (ref->info, -1, "The macro");
-	    break;
-	  default:
-	   fprintf (asm_out_file, "%s unrecognized macinfo code %lu\n",
-	     ASM_COMMENT_START, (unsigned long)ref->code);
+	  break;
+	case DW_MACINFO_define:
+	case DW_MACINFO_undef:
+#ifdef OBJECT_FORMAT_ELF
+	  if (!dwarf_strict
+	      && HAVE_COMDAT_GROUP
+	      && VEC_length (macinfo_entry, files) != 1
+	      && i > 0
+	      && i + 1 < length
+	      && VEC_index (macinfo_entry, macinfo_table, i - 1)->code == 0)
+	    {
+	      char linebuf[sizeof (HOST_WIDE_INT) * 3 + 1];
+	      unsigned char checksum[16];
+	      struct md5_ctx ctx;
+	      char *tmp, *tail;
+	      const char *base;
+	      unsigned int j = i, k, l;
+	      void **slot;
+
+	      ref2 = VEC_index (macinfo_entry, macinfo_table, i + 1);
+	      if (ref2->code != DW_MACINFO_define
+		  && ref2->code != DW_MACINFO_undef)
+		break;
+
+	      if (VEC_empty (macinfo_entry, files))
+		{
+		  if (ref->lineno != 0 || ref2->lineno != 0)
+		    break;
+		}
+	      else if (ref->lineno == 0)
+		break;
+	      md5_init_ctx (&ctx);
+	      for (; VEC_iterate (macinfo_entry, macinfo_table, j, ref2); j++)
+		if (ref2->code != DW_MACINFO_define
+		    && ref2->code != DW_MACINFO_undef)
+		  break;
+		else if (ref->lineno == 0 && ref2->lineno != 0)
+		  break;
+		else
+		  {
+		    unsigned char code = ref2->code;
+		    md5_process_bytes (&code, 1, &ctx);
+		    checksum_uleb128 (ref2->lineno, &ctx);
+		    md5_process_bytes (ref2->info, strlen (ref2->info) + 1,
+				       &ctx);
+		  }
+	      md5_finish_ctx (&ctx, checksum);
+	      if (ref->lineno == 0)
+		base = "";
+	      else
+		base = lbasename (VEC_last (macinfo_entry, files)->info);
+	      for (l = 0, k = 0; base[k]; k++)
+		if (ISIDNUM (base[k]) || base[k] == '.')
+		  l++;
+	      if (l)
+		l++;
+	      sprintf (linebuf, HOST_WIDE_INT_PRINT_UNSIGNED,
+		       VEC_index (macinfo_entry, macinfo_table, i)->lineno);
+	      tmp = XNEWVEC (char, 4 + l + strlen (linebuf) + 1 + 16 * 2 + 1);
+	      strcpy (tmp, DWARF_OFFSET_SIZE == 4 ? "wm4." : "wm8.");
+	      tail = tmp + 4;
+	      if (l)
+		{
+		  for (k = 0; base[k]; k++)
+		    if (ISIDNUM (base[k]) || base[k] == '.')
+		      *tail++ = base[k];
+		  *tail++ = '.';
+		}
+	      l = strlen (linebuf);
+	      memcpy (tail, linebuf, l);
+	      tail += l;
+	      *tail++ = '.';
+	      for (k = 0; k < 16; k++)
+		sprintf (tail + k * 2, "%02x", checksum[k] & 0xff);
+	      ref2 = VEC_index (macinfo_entry, macinfo_table, i - 1);
+	      ref2->code = DW_MACINFO_GNU_transparent_include;
+	      ref2->lineno = 0;
+	      ref2->info = tmp;
+	      if (macinfo_htab == NULL)
+		macinfo_htab = htab_create (10, htab_macinfo_hash,
+					    htab_macinfo_eq, NULL);
+	      slot = htab_find_slot (macinfo_htab, ref2, INSERT);
+	      if (*slot != NULL)
+		{
+		  free (CONST_CAST (char *, ref2->info));
+		  ref2->code = 0;
+		  ref2->info = NULL;
+		  ref2 = (macinfo_entry *) *slot;
+		  output_macinfo_op (ref2);
+		  for (j = i;
+		       VEC_iterate (macinfo_entry, macinfo_table, j, ref2);
+		       j++)
+		    if (ref2->code != DW_MACINFO_define
+			&& ref2->code != DW_MACINFO_undef)
+		      break;
+		    else if (ref->lineno == 0 && ref2->lineno != 0)
+		      break;
+		    else
+		      {
+			ref2->code = 0;
+			free (CONST_CAST (char *, ref2->info));
+			ref2->info = NULL;
+		      }
+		}
+	      else
+		{
+		  *slot = ref2;
+		  ref2->lineno = ++transparent_includes;
+		  output_macinfo_op (ref2);
+		}
+	      i = j - 1;
+	      continue;
+	    }
+#endif
+	  break;
+	default:
 	  break;
 	}
+      output_macinfo_op (ref);
+      /* For DW_MACINFO_start_file ref->info has been copied into files
+	 vector.  */
+      if (ref->code != DW_MACINFO_start_file)
+	free (CONST_CAST (char *, ref->info));
+      ref->info = NULL;
+      ref->code = 0;
     }
+
+  if (!transparent_includes)
+    return;
+
+  htab_delete (macinfo_htab);
+
+#ifdef OBJECT_FORMAT_ELF
+  for (i = 0; VEC_iterate (macinfo_entry, macinfo_table, i, ref); i++)
+    switch (ref->code)
+      {
+      case 0:
+	continue;
+      case DW_MACINFO_GNU_transparent_include:
+	{
+	  char label[MAX_ARTIFICIAL_LABEL_BYTES];
+	  tree comdat_key = get_identifier (ref->info);
+	  /* Terminate the previous .debug_macinfo section.  */
+	  dw2_asm_output_data (1, 0, "End compilation unit");
+	  targetm.asm_out.named_section (DEBUG_MACINFO_SECTION,
+					 SECTION_DEBUG
+					 | SECTION_LINKONCE,
+					 comdat_key);
+	  ASM_GENERATE_INTERNAL_LABEL (label,
+				       DEBUG_MACINFO_SECTION_LABEL,
+				       ref->lineno);
+	  ASM_OUTPUT_LABEL (asm_out_file, label);
+	  ref->code = 0;
+	  free (CONST_CAST (char *, ref->info));
+	  ref->info = NULL;
+	}
+	break;
+      case DW_MACINFO_define:
+      case DW_MACINFO_undef:
+	output_macinfo_op (ref);
+	ref->code = 0;
+	free (CONST_CAST (char *, ref->info));
+	ref->info = NULL;
+	break;
+      default:
+	gcc_unreachable ();
+      }
+#endif
 }
 
 /* Set up for Dwarf output at the start of compilation.  */

	Jakub


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