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  <ja...@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

Reply via email to