co_linetable maps each instruction to its place in the source: a start
line, an end line, a start column and an end column. This is the location table of
PEP 657. It is a sequence of entries, each covering one or more code units of
co_code, one after the other from offset 0. There are no gaps, and inline
cache units are covered along with their instruction.
Line numbers are kept as a running total. It starts at
co_firstlineno,
and each entry may move it.
Entries
Every entry starts with one byte whose top bit is set, so a reader can find the start of an entry. Below the top bit are a form number and a length.
| Bits | Meaning |
|---|---|
| 7 | Always 1 |
| 3–6 | Form, 0 to 15 |
| 0–2 | Length of the entry in code units, less 1: 1 to 8 units |
A run longer than 8 code units takes several entries.
| Form | Name | Bytes after the first | Effect |
|---|---|---|---|
| 0–9 | Short | One byte b | Same line as the running total. Start column is (form << 3) | (b >> 4); end column is start plus b & 15 |
| 10–12 | One line | Two bytes: start column, end column | The line moves down by form − 10, 0 to 2 |
| 13 | No columns | A signed varint | The line moves by the varint; no column is recorded |
| 14 | Long | Signed varint, then three varints | The line moves by the signed varint; the end line is that line plus the second varint; the third and fourth are the start and end columns plus 1, where 0 means unknown |
| 15 | None | None | No location at all for these code units; the running line does not change |
Varints
Unsigned numbers use 6 bits a byte, lowest first. Bit 6 is set on every byte except the last. Bit 7 is clear, which is how a varint is told from the start of an entry.
A signed number is first turned into an unsigned one: a value s of zero or more
is stored as s << 1, and a negative one as
((−s) << 1) | 1. So an even stored number is positive, and an odd one
is negative.
Worked examples
There is no Python 3.15 interpreter here, so both examples were constructed by hand
from the rules above. The first is the table of a small function whose instructions
are RESUME with its cache unit, LOAD_FAST_BORROW and
RETURN_VALUE, with def f(a): on line 1:
def f(a):
return a
00000000 81 00 D8 0B 0C 80 48
co_linetable for the function above| Bytes | Form | Units | Offsets | Location | Instructions |
|---|---|---|---|---|---|
81 00 | Short 0 | 2 | 0–4 | Line 1, columns 0–0 | RESUME and its cache unit |
D8 0B 0C | One line | 1 | 4–6 | Line +1 → 2, columns 11–12 | LOAD_FAST_BORROW, the a |
80 48 | Short 0 | 1 | 6–8 | Line 2, columns 4–12 | RETURN_VALUE, the whole return a |
Reading 81 00: 81 is 1000 0001, so form 0 and
length bits 1, two units. D8 is 1101 1000: form 11, one line
down, one unit, then the columns 11 and 12. In 80 48, 0x48
gives start column (0 << 3) | 4 = 4 and end column 4 + 8 = 12.
The second example uses the other forms and a varint of two bytes, again with the running line starting at 1:
00000000 81 00 F0 50 01 00 05 11 E8 03 F9
| Bytes | Form | Units | Offsets | Location |
|---|---|---|---|---|
81 00 | Short 0 | 2 | 0–4 | Line 1, columns 0–0 |
F0 50 01 00 05 11 | Long | 1 | 4–6 | Line +40 → 41, to line 41, columns 4–16 |
E8 03 | No columns | 1 | 6–8 | Line −1 → 40 |
F9 | None | 2 | 8–12 | No location |
In the long entry, the signed varint is 50 01. 0x50 has
bit 6 set, so another byte follows; its low 6 bits are 16. 01 adds
1 × 64, making 80. 80 is even, so the line moves by 80 / 2 = +40. The end-line varint
00 keeps the end on the same line, and 05 and
11 are the columns plus 1, giving 4 and 16. E8 is
1110 1000, form 13; its varint 03 is odd, so the line moves
by −1. F9 is form 15 with length bits 1: two code units with no
location.
Python’s code.co_positions() returns the same information, one tuple per code
unit, and code.co_lines() gives the line ranges.