Skip to content

debug info, inspect --graph, and honest failure preservation

September 2026 snapshot: the compiler can finally tell a debugger where your code lives, the inspector can walk the semantic graph, and failure artifacts stay where you can find them.

janus build --emit-debug-info now carries real debug metadata end-to-end:

  • DW_TAG_compile_unit (producer Janus compiler) and DW_TAG_subprogram entries with real low_pc/high_pc ranges.
  • Per-instruction DILocation lines resolved from ASTDB source coordinates — addr2line maps call sites back to the correct .jan line.
  • DWARF4 line tables for binutils 2.47 compatibility (Gap 174), including per-thunk subprograms for compiler-generated thunks (Gap 175).

The flag stays off by default: a janus build without it is unchanged, byte for byte. Debug-info carriers are strictly for debuggers — SPEC-259 forbids using !dbg for Traceline carriers, which ride as opaque values instead.

Terminal window
janus inspect app.jan --graph=42 # JSONL dump rooted at ASTDB node 42
janus inspect app.jan --traceline=<uuid> # placeholder: exits non-zero until SPEC-259 P1

--graph=<node_id> (SPEC-259 §7.2) emits a JSONL dump of the semantic graph rooted at the given ASTDB node id — the first P0 piece of the Traceline story. --traceline=<uuid> (§7.3) is accepted but honestly pending: it exits non-zero so CI scripts can detect the unfinished state instead of silently returning nothing.

janus build --keep-temps-on-failure now does what it always claimed (Gap 166): a failed compile preserves the scratch directory and prints its path to stderr, while successful builds clean up as before. Companion tooling: setting TRACE_NODE=<qtjir_node_id> prefixes lowering-pass trace lines with [TRACE_NODE=<id>] so a single node’s lifecycle can be grepped across all emission sites (Gap 169).

  • Gap 149 — checked integer-cast sentinels convert into error unions.
  • Gap 160 — Shr on an unsigned left operand lowers to LShr, not ASHR.
  • Gap 162 — imported structs with slice fields and inline methods keep their layout across module boundaries.
  • Gap 165 — interpreter bitwise/shift ops, EU passthrough, and signed truncate brought in line with the AOT path.
  • Gap 163 (S4) — canonical-prefix mangling for cross-importer alias bridges.
  • std.encoding.msgpack — error paths migrated to fail/error-union contract wording.

scripts/zb (the OOM-protected build wrapper) now throttles the full test suite to -j6 under a hard CPUQuota=480% systemd ceiling — faster suites on big machines without starving the desktop. Tune with ZB_MAX_TEST_JOBS and ZB_TEST_CPU_QUOTA.

Full ./scripts/zb test on this tree: 160 compile steps green, 5 known-red steps in 3 classes, all reproduced identically on the pre-v2026.9.1-alpha binary (pre-existing baseline reds, not regressions): the std/io/adapters_smoke cross-module impl-method symbol (Gap 148 family reopen), the xmod_func_alias_reexport tombstone (Gap 163 reopen), the std/code_graph SliceLen ICE (Gap 176), and the fnptr-capture link failure (Gap 177). Gaps filed in the compiler gap tracker with repros.