different code of dwarf2out.c.
I had a draft patch to use DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref_udata and
DW_FORM_ref4 which should be slightly smaller than just DW_FORM_ref_udata.
But it produced larger files than just DW_FORM_ref_udata. Assuming it was due
to multiplied abbrev definitions. One would need to decide when if it is
worth to create a new smaller-sized abbrev but that seems too complicated for
such kind of optimization. There exist other project(s) in development for
DWARF optimizations as a post-processing tool, this patch is meant just as
a very simple way to reduce the (possibly intermediate) DWARF files.
It is incompatible with GNU binutils readelf, a pending simple fix is:
[patch] Fix readelf for DW_FORM_ref_udata
http://sourceware.org/ml/binutils/2011-10/msg00201.html
No regressions on {x86_64,x86_64-m32,i686}-fedora16pre-linux-gnu
(4.7.0 20111002). No changes in readelf -w output on libstdc++.so.
My former DW_AT_sibling patch will be updated on top of this one:
Re: [patch#2] dwarf2out: Drop the size + performance overhead of DW_AT_sibling
http://gcc.gnu.org/ml/gcc-patches/2011-10/msg01869.html
These two optimizations are not incremental to each other as both benefit
primarily from common DW_AT_sibling. That size decrease 3.49% will be less
after this patch; moreover when not all DW_AT_sibling attrs will be dropped.
Thanks,
Jan
gcc/
2011-10-21 Jan Kratochvil <jan.kratochvil@redhat.com>
* dwarf2out.c (DW_FORM_ref): Remove.
(size_of_die) <dw_val_class_die_ref>: Use size_of_uleb128 for
!AT_ref_external references.
(calc_die_sizes_change): New variable.
(calc_die_sizes): Permit die_offset incrementals. Set
CALC_DIE_SIZES_CHANGE accordingly.
(value_format) <dw_val_class_die_ref>: Return DW_FORM_ref_udata for
!AT_ref_external references.
(output_die) <dw_val_class_die_ref>: Use dw2_asm_output_data_uleb128
for !AT_ref_external references.
(output_unit_prep): New function, call calc_die_sizes repeatedly based
on CALC_DIE_SIZES_CHANGE.
(output_comp_unit, output_comdat_type_unit): Move some code to
output_unit_prep.
@@ -226,7 +226,6 @@ static GTY(()) rtx current_unit_personality;
/* Data and reference forms for relocatable data. */
#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)
-#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
#ifndef DEBUG_FRAME_SECTION
#define DEBUG_FRAME_SECTION ".debug_frame"
@@ -7700,7 +7699,7 @@ size_of_die (dw_die_ref die)
size += DWARF_OFFSET_SIZE;
}
else
- size += DWARF_OFFSET_SIZE;
+ size += size_of_uleb128 (AT_ref (a)->die_offset);
break;
case dw_val_class_fde_ref:
size += DWARF_OFFSET_SIZE;
@@ -7735,6 +7734,10 @@ size_of_die (dw_die_ref die)
return size;
}
+/* Has calc_die_sizes changed any DIE_OFFSET? */
+
+static bool calc_die_sizes_change;
+
/* Size the debugging information associated with a given DIE. Visits the
DIE's children recursively. Updates the global variable next_die_offset, on
each time through. Uses the current value of next_die_offset to update the
@@ -7745,9 +7748,12 @@ calc_die_sizes (dw_die_ref die)
{
dw_die_ref c;
- gcc_assert (die->die_offset == 0
- || (unsigned long int) die->die_offset == next_die_offset);
- die->die_offset = next_die_offset;
+ gcc_assert ((unsigned long int) die->die_offset <= next_die_offset);
+ if ((unsigned long int) die->die_offset != next_die_offset)
+ {
+ die->die_offset = next_die_offset;
+ calc_die_sizes_change = true;
+ }
next_die_offset += size_of_die (die);
FOR_EACH_CHILD (die, c, calc_die_sizes (c));
@@ -8018,7 +8024,7 @@ value_format (dw_attr_ref a)
if (AT_ref_external (a))
return use_debug_types ? DW_FORM_ref_sig8 : DW_FORM_ref_addr;
else
- return DW_FORM_ref;
+ return DW_FORM_ref_udata;
case dw_val_class_fde_ref:
return DW_FORM_data;
case dw_val_class_lbl_id:
@@ -8397,8 +8403,7 @@ output_die (dw_die_ref die)
else
{
gcc_assert (AT_ref (a)->die_offset);
- dw2_asm_output_data (DWARF_OFFSET_SIZE, AT_ref (a)->die_offset,
- "%s", name);
+ dw2_asm_output_data_uleb128 (AT_ref (a)->die_offset, "%s", name);
}
break;
@@ -8496,6 +8501,28 @@ output_compilation_unit_header (void)
dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
}
+/* Perform initializations common for .debug_info and .debug_types sections. */
+
+static void
+output_unit_prep (dw_die_ref die, unsigned long init_die_offset)
+{
+ /* First mark all the DIEs in this CU so we know which get local refs. */
+ mark_dies (die);
+
+ build_abbrev_table (die);
+
+ /* The DIE sizes can increase, due to DW_FORM_ref_udata size increase
+ dependent on increases of other DIE_OFFSETs. */
+ do
+ {
+ /* Initialize the beginning DIE offset - and calculate sizes/offsets. */
+ next_die_offset = init_die_offset;
+ calc_die_sizes_change = false;
+ calc_die_sizes (die);
+ }
+ while (calc_die_sizes_change);
+}
+
/* Output the compilation unit DIE and its children. */
static void
@@ -8511,15 +8538,8 @@ output_comp_unit (dw_die_ref die, int output_if_empty)
/* Even if there are no children of this DIE, we must output the information
about the compilation unit. Otherwise, on an empty translation unit, we
will generate a present, but empty, .debug_info section. IRIX 6.5 `nm'
- will then complain when examining the file. First mark all the DIEs in
- this CU so we know which get local refs. */
- mark_dies (die);
-
- build_abbrev_table (die);
-
- /* Initialize the beginning DIE offset - and calculate sizes/offsets. */
- next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
- calc_die_sizes (die);
+ will then complain when examining the file. */
+ output_unit_prep (die, DWARF_COMPILE_UNIT_HEADER_SIZE);
oldsym = die->die_id.die_symbol;
if (oldsym)
@@ -8563,14 +8583,7 @@ output_comdat_type_unit (comdat_type_node *node)
tree comdat_key;
#endif
- /* First mark all the DIEs in this CU so we know which get local refs. */
- mark_dies (node->root_die);
-
- build_abbrev_table (node->root_die);
-
- /* Initialize the beginning DIE offset - and calculate sizes/offsets. */
- next_die_offset = DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE;
- calc_die_sizes (node->root_die);
+ output_unit_prep (node->root_die, DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE);
#if defined (OBJECT_FORMAT_ELF)
secname = ".debug_types";