<div dir="ltr">Hi Matthew,<br><br>I'm looking into your issue & I have some broad questions:<br><br>This seems like it'd speed up generics-heavy code, to be sure - though I assume you hit a perf issue in some prototype tool already, that lead you to this issue? Do you have further details on the tooling you've prototyped/the problems you've encountered? Or is this proposal more based on an assumption/predicted issue?<br><br>Also, while I imagine this feature could simplify the situation even when there aren't shared lines/generics (by centralizing the place to update) - I wouldn't've thought a naive... oh, I see, there's no "reset the line number".<br><br>So even between sequences there's no resetting of the line number, so you can't just look for the line at the start of some functions, etc.<br><br>Equally, though, putting some otherwise "random" line numbers in a list in the header of the line table doesn't seem like a generally usable feature - It'd be unclear how the DWARF modifying-tool would know which line numbers to update (couldn't rely on unique numbers - they might collide between different files, and some files might need updating and some not, etc)<br><br><a class="gmail_plusreply" id="plusReplyChip-0" href="mailto:aprantl@apple.com" tabindex="-1">@Adrian Prantl</a> and <a class="gmail_plusreply" id="plusReplyChip-1" href="mailto:jdevlieghere@apple.com" tabindex="-1">@Jonas Devlieghere</a> with the CAS DWARF stuff, how are you folks separating line table fragments for functions? My understanding was the line table header was too large to have one on every function's line table fragment, so I would've thought you'd figured out a way to make line table fragments that could be added/removed from a line table without disturbing the other flags/state and without relying on specific values in/out of the line register?<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jun 26, 2024 at 4:06 PM Matthew Lugg via Dwarf-discuss <<a href="mailto:dwarf-discuss@lists.dwarfstd.org">dwarf-discuss@lists.dwarfstd.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"># Add DW_LNS_indirect_line - update `line` to absolute value stored <br>
indirectly<br>
<br>
## Background<br>
<br>
In many source languages, it is possible for many program-counter <br>
addresses with arbitrary<br>
separation to correspond to the same source line due to features like <br>
templates/generics. When<br>
designing an incremental compiler, the line number program must be <br>
updated when line numbers within<br>
a source file are moved. It would be desirable to have the property that <br>
when moving a source line<br>
corresponding to a large amount of distinct program-counter addresses, <br>
only one line number value in<br>
the DWARF information needs to be updated. For this to be true, the <br>
regions of the line number<br>
program corresponding to each such address must include the line number <br>
of the source construct not<br>
directly, but through an indirect reference. This allows one line number <br>
value stored in the binary<br>
to be shared across arbitrarily many entries in the line number matrix.<br>
<br>
This is not currently possible: all modifications to the `line` register <br>
are given by relative<br>
offsets, and all of these offsets are directly included in the <br>
instruction (or implicit in the case<br>
of a special opcode).<br>
<br>
## Overview<br>
<br>
Introduce new fields to the line number program header, <br>
`indirect_lines_length` (ULEB128) and<br>
`indirect_lines` (opaque block of bytes containing ULEB128 values). The <br>
`indirect_lines_length`<br>
field is the length in bytes of the `indirect_lines` section, rather <br>
than the number of elements.<br>
Introduce a new standard opcode to the line number program, <br>
`DW_LNS_indirect_line`. This opcode<br>
takes a single ULEB128 operand, which represents a byte offset into the <br>
`indirect_lines` stored in<br>
the header. The effect of this instruction is to set the `line` register <br>
to the ULEB128 value stored<br>
at the given byte offset into `indirect_lines`. Note that <br>
`indirect_lines` is not itself validated<br>
to be a valid sequence of ULEB128 values; decoding only occurs when <br>
`DW_LNS_indirect_line` is used.<br>
This allows an incremental compiler to pre-allocate a large amount of <br>
padding space in<br>
`indirect_lines` to fill in later as needed.<br>
<br>
Note that an incremental compiler would not necessarily wish to use <br>
variable-length integers to<br>
represent this information, since certain changes of line numbers could <br>
cause a line number which<br>
was previously encoded using 1 byte to now require 2. However, since the <br>
stored values need not be<br>
densely packed, an implementation is free to reserve as much space as is <br>
necessary for each entry.<br>
For instance, the downstream Zig compiler (which is the original <br>
motivator for this proposal) may<br>
choose to reserve 4 or 5 bytes for each line number, as line numbers in <br>
Zig source files cannot<br>
exceed 1<<32. The use of ULEB128 allows the compiler to make an <br>
appropriate decision here instead of<br>
codifying such a restriction into the DWARF specification.<br>
<br>
## Proposed Changes<br>
<br>
Pages and line numbers are given for the 2024-06-16 working draft of <br>
DWARF Version 6, which is the<br>
latest draft at the time of writing.<br>
<br>
6.2.4 (pg 163; line 27)<br>
<br>
21. indirect_lines_length (ULEB128)<br>
The length in bytes of the data stored in the `indirect_lines` field.<br>
22. indirect_lines (block containing ULEB128 entries)<br>
A collection of line numbers, each stored as a ULEB128 integer. <br>
These values are referenced by<br>
DW_LNS_indirect_line instructions to modify the state of the line <br>
number information state<br>
machine.<br>
<br>
The data stored in this field is not checked to be a valid sequence <br>
of ULEB128 entries. The<br>
contained data may include padding bytes or otherwise invalid data. <br>
As such, it is expected that<br>
bytes of this field be accessed only when a DW_LNS_indirect_line <br>
instruction references them.<br>
<br>
6.2.5.2 (pg 170; line 23)<br>
<br>
14. DW_LNS_indirect_line<br>
The DW_LNS_indirect_line opcode takes a single unsigned LEB128 <br>
operand. This operand is<br>
interpreted as a byte offset into the `indirect_lines` field of the <br>
line number program header.<br>
An unsigned LEB128 value is read from `indirect_lines` at the given <br>
offset, and this value is<br>
stored into the state machine's `line` register.<br>
<br>
7.22 (pg 246; table 7.25)<br>
<br>
Opcode name | Value<br>
----------------------+-------<br>
... | ...<br>
DW_LNS_indirect_line | 0x0d<br>
<br>
-- <br>
Dwarf-discuss mailing list<br>
<a href="mailto:Dwarf-discuss@lists.dwarfstd.org" target="_blank">Dwarf-discuss@lists.dwarfstd.org</a><br>
<a href="https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss" rel="noreferrer" target="_blank">https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss</a><br>
</blockquote></div>