Local variable tracking: emit, decode, and render values in the tracer#270
Open
gnidan wants to merge 3 commits into
Open
Local variable tracking: emit, decode, and render values in the tracer#270gnidan wants to merge 3 commits into
gnidan wants to merge 3 commits into
Conversation
Contributor
|
gnidan
force-pushed
the
ui-local-value-reduce
branch
from
July 16, 2026 21:54
8cbe0b0 to
2a69399
Compare
Emit a `variables` context at each instruction naming the in-scope
locals and, for each, a pointer to the memory word holding its current
value — a per-instruction snapshot the tracer resolves and decodes.
A sub-word scalar (address, bool, intN/uintN, bytesN) is homed by a
full-word MSTORE, so its value occupies the whole 32-byte word. Name the
full word and let the type-directed decoder extract the meaningful bytes,
rather than the type's narrow byte width at the word start — which, for a
right-aligned value, is the zero padding, so an address or bool would
otherwise resolve to zero. uint256 was already correct (its width is a
full word).
Attach the pointer only when the local solely occupies its word: the
allocator byte-packs several sub-word scalars into one word and their
full-word stores clobber each other, so a packed sub-word local has no
recoverable value — it is emitted type-only ("in scope, no value") until
codegen stops byte-packing sub-word scalars.
gnidan
force-pushed
the
ui-local-value-reduce
branch
from
July 16, 2026 22:38
2a69399 to
a1d63c1
Compare
Resolve each local to the pointer region holding its current value rather than every region it has occupied, narrow the trace drawer's local rendering to that region, and decode the resolved bytes to a typed value (replacing the raw formatAsDecimal fallback). Add an address round-trip trace-playground example (`idn(owner: address)`) so a decoded, EIP-55-checksummed non-uint value is visible when stepping into the call.
gnidan
force-pushed
the
ui-local-value-reduce
branch
from
July 16, 2026 23:22
a1d63c1 to
a682ed6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds end-to-end local-variable value tracking to the tracer, from
compiler emission through decoding to the rendered value in the drawer. It
reassembles three pieces the team is reviewing as one coherent change.
Format / packages
pointers: add a scalar-first, type-directed value decoder — resolves aregion's bytes to a typed value (uint, EIP-55-checksummed address, bool,
intN, bytesN).
bugc: emit a sound per-instruction local-variable debug snapshot —variablescontexts naming each in-scope local and a pointer to thememory word holding its current value. A sub-word scalar points at its
full 32-byte word (the decoder type-aligns within it), gated on sole
occupancy: a byte-packed sub-word local carries no recoverable value and
lists as type-only rather than a wrong one.
Implementation
web/programs-react: resolve each local to the region holding itscurrent value (not every region it has occupied), narrow the trace
drawer's rendering to that region, and decode the resolved bytes to a
typed value. Adds an address round-trip trace-playground example so a
decoded, checksummed address is visible when stepping into the call.
Together these render a local's live value as a single decoded value that
persists across the call, rather than a raw region dump.
Scope (O0): a value pointer is emitted for frame-spilled values —
parameters and memory-homed locals. A
letthat stays stack-resident hasno memory home, so it lists as type-only ("in scope, no value") regardless
of occupancy — intended at O0, not a gap.