Skip to content

Preserve DWARF local indices through local reordering - #9199

Open
cpunion wants to merge 4 commits into
WebAssembly:mainfrom
cpunion:codex/dwarf-local-indices-20261003
Open

cpunion wants to merge 4 commits into
WebAssembly:mainfrom
cpunion:codex/dwarf-local-indices-20261003

Conversation

@cpunion

@cpunion cpunion commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Problem

ReorderLocals updates Wasm instructions but leaves DW_OP_WASM_location operands pointing at the old local indices. Execution remains correct, but the debugger can silently show another variable's value.

extern int touch(int);
volatile int observed;
__attribute__((noinline)) int run(void) {
  int a = touch(11);
  int b = touch(22);
  int c = touch(33);
  observed = a;
  observed = b;
  observed = c;
  observed = b;
  observed = b;
  return a + b + c; // Inspect a, b, c here after wasm-opt -O1 -g.
}
Check Before After
GDB / LLDB: a, b, c 22, 11, 33 11, 22, 33
Program result 66 66
Deleted local Can point at an unrelated surviving local Unavailable

The interactive comparison includes #9194 on both sides to separate this bug from the independent line-table problems. This PR is based directly on main (82439ad0); its automated regression tests need no other PR.

Fix

Compose input-to-IR local mappings across reordering and coalescing, then apply the writer's final binary-local mapping to DWARF locations. This also handles the coalescing performed internally by Asyncify. Coalescing's existing DWARF-invalidating status remains: repairing indices does not repair changed variable live ranges.

Rewrite inline expressions and location lists, including shared suffixes, nested expressions and expression-level DIE/type references. If an operand grows across a LEB boundary, relocate the affected list offsets, DIE references, CU lengths and public-name tables. Collection, expression/layout relocation and public-table updates are separate stages. The common same-width case skips the .debug_info layout pass; expressions without DIE references are not decoded again on subsequent iterations. Instruction boundaries use a small ordered vector instead of per-instruction hash allocations. No optimization is disabled.

Validation

  • All 17 focused DWARF tests pass. Coverage includes repeated passes, StackIR, removed locals, coalescing, LEB boundaries, legacy forms, short-form overflow, multiple CUs, shared list heads/suffixes and expression-level references. The new suffix and expression-reference checks also reproduce failures in the initial PR implementation, before this follow-up fix. Independent LLVM verification is used when available; typed operations unsupported by that verifier still have exact operand and structural assertions.
  • All 100 Python tests and the wasm-opt pass suite pass; 437 C++ tests pass, with one existing Linux-only size test skipped on macOS. The Python run excludes V8-dependent checks because local d8 is not V8.
  • TinyGo output passes LLVM DWARF verification; O1 + Asyncify runs and prints {"name":"dwarf","value":42}. GDB on Linux arm64 and LLDB on macOS arm64 read the correct values in the combined verification above.

TinyGo sample, seven alternating warmed runs on macOS arm64; timings are medians, not evidence of a speedup:

Configuration Output bytes, before → after wasm-opt time, before → after
O1 + Asyncify, no debug 1,791,971 → 1,791,971 727.4 → 730.6 ms
O1, debug 1,912,371 → 1,912,371 353.0 → 362.6 ms
O1 + Asyncify, debug 2,185,951 → 2,185,947 924.5 → 884.0 ms

Stripped outputs are byte-identical in all three configurations. This fixes local-index relocation, not all remaining DWARF limitations or variable live-range transformations.

Developed with AI assistance; the validation above was executed locally.

@cpunion
cpunion requested a review from a team as a code owner October 3, 2026 04:07
@cpunion
cpunion requested review from tlively and removed request for a team October 3, 2026 04:07

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant