This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [RFC] More compact (100x) -g3 .debug_macinfo (take 2)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Jason Merrill <jason at redhat dot com>, Richard Henderson <rth at redhat dot com>, Tom Tromey <tromey at redhat dot com>, Jan Kratochvil <jkratoch at redhat dot com>, Roland McGrath <roland at redhat dot com>, Cary Coutant <ccoutant at google dot com>, Mark Wielaard <mjw at redhat dot com>
- Date: Fri, 15 Jul 2011 17:42:23 +0200
- Subject: Re: [RFC] More compact (100x) -g3 .debug_macinfo (take 2)
- References: <20110713170053.GX2687@tyan-ft48-01.lab.bos.redhat.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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