Hi!

In the usual case we use .loc directives and don't emit the line table
manually.  And assembler usually uses DW_LNS_advance_pc which has
uleb128 argument and in most cases will have just a single byte operand.
But if we do emit it for whatever reason (old or buggy assembler or
-gno-as-loc{,view}-support option), we do use DW_LNS_fixed_advance_pc
instead, which has fixed 2 byte operand.  That is both wasteful
in the usual case of very small advances, and more importantly will
just result in assembler errors if we need to advance over more than 65535
bytes.
The following patch uses DW_LNS_advance_pc instead if assembler supports
.uleb128 directive with a difference of two labels in the same section.
This is only possible if Minimum Instruction Length in the .debug_line
header is 1 (otherwise DW_LNS_advance_pc operand is multiplied by that
value and DW_LNS_fixed_advance_pc is not), but we emit 1 for that
on all targets.
Looking at dwarf2out.o (from dwarf2out.cc with this patch)
compiled with compilers before/after this change with additional -fpic
-gno-as-loc{,view}-support options, I see .debug_line section shrunk from
878067 bytes to 773381 bytes, so shrink by 12%.
Admittedly gas generated .debug_line is even smaller, 501374 bytes (with
-fpic and without -gno-as-loc{,view}-support options).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2025-08-27  Jakub Jelinek  <ja...@redhat.com>

        PR debug/119367
        * dwarf2out.cc (output_one_line_info_table) <case LI_adv_address>: If
        HAVE_AS_LEB128, use DW_LNS_advance_pc with dw2_asm_output_delta_uleb128
        instead of DW_LNS_fixed_advance_pc with dw2_asm_output_delta.

--- gcc/dwarf2out.cc.jj 2025-06-02 11:00:15.382405745 +0200
+++ gcc/dwarf2out.cc    2025-08-27 12:18:01.336936228 +0200
@@ -12997,9 +12997,25 @@ output_one_line_info_table (dw_line_info
 
            view++;
 
-           dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, "fixed advance PC, 
increment view to %i", view);
-           dw2_asm_output_delta (2, line_label, prev_label,
-                                 "from %s to %s", prev_label, line_label);
+           if (HAVE_AS_LEB128)
+             {
+               /* Using DW_LNS_advance_pc with label delta is only valid if
+                  Minimum Instruction Length in the header is 1, but that is
+                  what we use on all targets.  */
+               dw2_asm_output_data (1, DW_LNS_advance_pc,
+                                    "advance PC, increment view to %i", view);
+               dw2_asm_output_delta_uleb128 (line_label, prev_label,
+                                             "from %s to %s", prev_label,
+                                             line_label);
+             }
+           else
+             {
+               dw2_asm_output_data (1, DW_LNS_fixed_advance_pc,
+                                    "fixed advance PC, increment view to %i",
+                                    view);
+               dw2_asm_output_delta (2, line_label, prev_label,
+                                     "from %s to %s", prev_label, line_label);
+             }
 
            prev_addr = ent;
            break;

        Jakub

Reply via email to