debugger: layout table and gdb pretty printers for a native build (step 2 of #42) #469
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Step 2 of #42 (epic: debug native programs, DEBUGGER.md section 4). Step 1 (#405,
torb build --debug, a#lineper statement,tools/debug-lines.sh) is onmain. A debugger now stops on the right TorbScript line, but showstorb_text,torb_listandtorb_mapas raw C structs and a slot ass12_count. Section 4 plans "pretty printers for gdb (Python) and lldb (formatters) ... from a table the emitter writes".Source
DEBUGGER.md sections 4, 11 and 18
Goal
A
torb build --debugbinary written to a gdb session shows aString,List,Map,Setand the program's own records and cases the way section 11 shows them.Acceptance criteria
torb build --debugwrites a layout table next to the binary (build/debug/<name>.layouts, a text format documented in DEBUGGER.md section 4): for each record, tuple and case type the program uses, its C type name, its TorbScript name and its fields (name, C member, element type); for eachList/Map/Setinstance, its element type's C name and size. A debugged build without a layout of some type still builds (the type is then shown raw). Without--debugno table is written and the C is byte for byte unchanged (emit-c.test.trb)tools/gdb/torb_printers.py(gdb Python, loaded by-iex "source ..."; no auto-load into the binary) registers pretty printers fortorb_text("text", cut after 1000 characters),torb_list([1, 2, 3]up to ten items,List(n)beyond, children in item order),torb_map,torb_set([a: 1],Set(n)) and the table's records and cases (Point(x: 1, y: 2),.Circle(radius: 2.0),None); a null storage pointer shows as<none>; it also mapss12_counttocountininfo localstools/debug-values.sh, over a newtests/debug-values/fixture) builds the fixture with--debug, runsgdb --batchto a breakpoint on the fixture's last statement and compares the printed locals with the expected text. Wheregdb(with Python) is not installed it skips with a message, astools/debug-lines.shdoes. The measured result (isgdbon the CI runner image) goes into the PR body; if it is missing, the gate only runs the table check and a follow-up PR installs it on the imagedocs/tooling/mentions the table and the printer scriptSeed
Adds a file
torb build --debugwrites; no syntax, native, driver flag or looked-up std name changes. No seed refresh needed. A refresh would stay Torben's.Size
One PR, two Conventional Commits:
feat(backend): write a layout table for a debugged native build(emitter,emit-cand table tests),feat(debugger): gdb pretty printers for the layout table(script, gate, docs). The lldb formatters are not part of this step: they reuse the same table and become step 3, so the epic's remaining steps become lldb formatters,torb debugfor a native program, docs and editor launch.Dependencies
After #405 (landed). Independent of #39 and #403; DEBUGGER.md sections 11/18/20 overlap, rebase after whichever lands first.
Part of #42.
[loop:torbscript] claim implement by session:loop-torbscript-20261024 until 2026-10-24T13:15:00Z
[loop:torbscript] implement checkpoint (context guard, no code written yet). Tokens used: about 95k
Done: read LOOP.md, #42 and #469 decisions, CLAUDE.md, DEBUGGER.md (sections 4, 11, 18, 20), the
--debugcommit3dc7b716(cli/build.trb, main.trb, usage.trb, tools/debug-lines.sh, tests/debug-lines/) and the C type layer. Worktreews wt new torbscript/language 469 layouts --branch loop/469-layout-table-gdb-printersexists (clean, nothing committed or pushed).Findings for the next worker:
IrProgram.layouts(ir/layout.trb:Layout.nameis the C type name,kindRecord/Variant/Tuple,fieldswithmemberNameOf=f_<name>,variantswithvariantMemberNameOf=v<n>,representationInline/Boxed/Niche(variant, field),commonFieldCount); C type spelling inbackend/c/type.trb(cTypeOf). Only used layouts are emitted (usedLayoutsOfinbackend/c/emit.trb), the table should follow that set. Element descriptors (ElementDescriptor,ir/ir.trb:266) give List/Map/Set element types.torb_text{storage, offset, length},torb_list{storage, offset, length},torb_map{storage} inruntime/include/torb.h:883-931(set at the same place); read those for the gdb printers.feat(backend): write a layout table for a debugged native build(newbackend/c/layouts.trbemitting the text, hook incli/build.trbnext to the binary whenoptions.debug, tests incompiler/tests/emit-c.test.trbor a newlayout-table.test.trb, format documented in DEBUGGER.md section 4); commit 2feat(debugger): gdb pretty printers for the layout table(tools/gdb/torb_printers.py,tools/debug-values.sh+tests/debug-values/, gate line intools/gates.shtier B next to debug-lines, DEBUGGER.md sections 4/11/18 slice 8 Done,docs/tooling/note, regenerateskills/withbuild/release/torb.exe docs skill docs skillsonly if CI-side tooling allows; otherwise check how the docs gate expects it).gdbis on the forge CI runner image (measure in the PR; the gate skips with a message if missing).next: implement continues in a fresh worker (claim stays with session:loop-torbscript-20261024).
[loop:torbscript] implement checkpoint 2 (context guard at ~80k, still no code written; design settled, next worker should only write code). Tokens used: about 85k
Worktree
code/wt/torbscript-language-469-layouts(branchloop/469-layout-table-gdb-printers) is clean, at main45f5ba05, nothing committed or pushed.Settled design (do not re-research):
ir/print.trbdescribeIrType(Int64,String,Record(T_main_Point),Variant(..),Tuple(..),Shared(..),List(Int64),Map(String, Int64),Array(Float64, 3)). Document that grammar in DEBUGGER.md section 4.name+origin: SymbolId). AdddeclaredName: String = ""toLayout(ir/layout.trb), set it inbuildNominalLayout(ir/instantiate.trb~line 395, in thelayout.copy(origin: signature.symbol, ...)) fromsymbolPathOf(checker, signature.symbol).name. Tuples keep"". Does not change the C orprintLayout.compiler/src/backend/c/layouts.trb:layoutTableOf(program, used: List<Bool>): String, pure text, deterministic (layouts sorted byname, elements sorted byname). MakeusedLayoutsOfandemittedFunctionsOf(already public) reachable fromemit.trb(makeusedLayoutsOfpublic) so build.trb can calllayoutTableOf(program, usedLayoutsOf(program, emittedFunctionsOf(program))). Layouts to list: used ones withhasStructDefinitionor niche; skip kinds Environment/Payload/Box/Cell.torb-layouts 1record <CName> <declaredName> <repr>/case <CName> <declaredName> <repr>/tuple <CName> <repr>; repr isinline,boxedorniche/<variant>/<field>field <name> <cMember> <type...>(record, tuple, and the common fields of a case)variant <index> <name>followed byfield <name> <cMember> <type...>per payload field (cMember is thev<n>.f_<name>path inside thepayloadunion:payload.v1.f_radius)element <descriptorName> <size> <alignment> <type...>for everyprogram.elementsentry (the descriptors arestatic const torb_element d_<Type>in the C, so gdb can find them by symbol)The runtime's own
torb_element_int64/torb_element_textare not in the table; the printer knows them (Int64, String).cli/build.trbafteremitProgram(~line 379) andFile.createDirectory(directory), onlyif options.debug: write<binary minus .exe>.layoutsviaFile.writeText; without--debugwrite nothing (also delete a stale table? no, leave it). Binary dir isbuild/debug/.storage->element(torb_list_storage.element,torb_map_storage.key/.value, runtime/include/torb.h:896-920): compare its address with&<descriptorName>of each table element.torb_setistorb_mapwith value descriptortorb_element_unit(size 0). Item order: list items start at storage + round-up(sizeof(torb_list_storage), align) + (offset + i) * size; map entries are insertion ordered inentries(entry_stride,key_offset,value_offset, tombstones marked by... read runtime/map.c for the tombstone test before writing the map printer).compiler/tests/layout-table.test.trb(fixture: record, case with payloads, nested list, map; compare exact table text; second test: a plainemitProgramis byte for byte the same with and without the table call, i.e. assert the C text is independent of it; follow howemit-c.test.trblowers a snippet). Checkcompiler/tests/ir-layout.test.trbfor a lowering helper.tools/gdb/torb_printers.py,tools/debug-values.shmodelled ontools/debug-lines.sh,tests/debug-values/, tier B line intools/gates.sh, DEBUGGER.md 4/11/18,docs/tooling/torb-build.md). Skills regeneration needsbuild/release/torb.exe docs skill docs skills, which needs a bootstrap that is CI-only: if no binary is available, copy the docs change by hand into the matchingskills/torbscript/references/tooling/torb-build.mdas commit3dc7b716did (same text) and let the tier A--checkgate confirm.next: implement continues in a fresh worker (claim stays with session:loop-torbscript-20261024).
[loop:torbscript] implement checkpoint 3 (context guard hit after steps a and b; nothing built or tested yet, CI only). Worker tokens: about 90k.
Pushed branch
loop/469-layout-table-gdb-printers(worktreecode/wt/torbscript-language-469-layouts, remoteorigin= git.torb.dev, token~/.secrets/torbdev-token; the forgejo skill's git.dmb.zone does not host torbscript), no PR yet.Done:
f6ecf7f3Layout.declaredName(ir/layout.trb, set in buildNominalLayout viasymbolPathOf(...).name).2d203cc0backend/c/layouts.trb(layoutTableOf(program, used), format in its header comment,-for an empty declaredName),usedLayoutsOfpublic, hook incli/build.trbunderoptions.debugwriting<binary minus .exe>.layouts. Not compiled yet: first CI run may show syntax/type slips in layouts.trb (e.g.sort({ program.layouts[_].name }),Set.insert,seen.contains xwithout parentheses).Remaining:
tools/gdb/torb_printers.pydoes not exist yet (nothing of gdb printers is written): torb_text/torb_list/torb_map/set printers, element type viastorage->elementaddress vs&<descriptorName>from the table;tools/debug-values.sh+tests/debug-values/; tier B line intools/gates.sh.compiler/tests/layout-table.test.trb(useloweredfrom./lower-harness+insertOwnershiplikeemit-c.test.trb;usedLayoutsOf(found.program, emittedFunctionsOf(found.program))).docs/tooling/torb-build.md, mirrored intoskills/torbscript/references/tooling/torb-build.md.[loop:torbscript] claim implement by session:loop-torbscript-20261024 until 2026-10-24T13:30:00Z (continuation 3 of 3, from checkpoint 5996)
[loop:torbscript] implement checkpoint 4 (context guard hit; nothing built or tested locally, no torb binary here). Worker tokens: about 95k.
Branch
loop/469-layout-table-gdb-printerspushed at59484e9a(worktreecode/wt/torbscript-language-469-layouts), no PR yet.Done in
59484e9a:layouts.trb:seen.contains(...)parenthesized;sort({ ... }),Set.of()/insertmatch existing compiler code.tools/gdb/torb_printers.py(String/List/Map/Set/record/case/tuple printers, element type via descriptor address, frame filters12_count->count, commandstorb-print,torb-locals,torb-layouts; py_compile clean),tools/debug-values.sh(buildstests/debug-values/with --debug, checks the table, then gdb --batchtorb-printper line oftests/debug-values/expected.txt; skips without gdb / off Linux), tier B gate line + header comment +tests/debug-valuesin the manifest --check list oftools/gates.sh.compiler/tests/layout-table.test.trb(4 tests; assumes Int prints asInt64, Float asFloat64, layout namesT_acme_x2f_app_main_*).Remaining:
torb-printform), 18 (slice 8 row), status line;docs/tooling/torb-build.md### --debug(line 218: the.layoutsfile +gdb -x tools/gdb/torb_printers.py), mirrored intoskills/torbscript/references/tooling/torb-build.md(same section, line 218).Closes #469, ci-wait; first CI may show .trb slips or format issues in layouts.trb / layout-table.test.trb.[loop:torbscript] release implement: continuation budget used up, checkpoint above, next: implement
[loop:torbscript] claim implement by session:loop-torbscript-20261024-1000 until 2026-10-24T14:10:28Z
[loop:torbscript] implement checkpoint 5 (context guard). Worker tokens: about 110k.
PR is open: #471 (
Closes #469, two Conventional Commits, check-commits clean, rebased on main). Branchloop/469-layout-table-gdb-printerspushed at3577d553, worktreecode/wt/torbscript-language-469-layouts.Done: docs (DEBUGGER.md 4/11/18/20 + status, torb-build.md and its skills mirror), squashed the 3 earlier commits plus docs into 2.
CI round 1 (bootstrap linux-x64, 4m25s) was red:
layouts.trb:101for field in layout.fieldsOfVariant index {is not valid (a command call in aforheader); fixed tolayout.fieldsOfVariant(index)and force-pushed (3577d553). CI round 2 is not yet watched; further .trb slips inlayouts.trb,layout-table.test.trborcli/build.trbare likely (never compiled), and the first run oftools/debug-values.sh/torb_printers.pyhas not happened.Next worker:
bash /opt/openclaw/skills/dev-workflow/scripts/ci-wait.sh -C <worktree>(the exec yields early; re-run or poll the status API for commit3577d553), fix every red job on the same branch (fixup +git rebase -i --autosquash origin/main,--force-with-lease), then put the measured result "is gdb on the CI runner image" (tier B log ofdebug-values.sh: ran or skipped) into the PR body, then write-back[loop:torbscript] implement: PR #471 open, next: review (waiting on merge gate).CONTINUE: torbscript/language#469