mirror of
https://github.com/imjasonh/nescript
synced 2026-07-08 00:45:38 +00:00
analyzer+ir: automatically overlay state-local variables
Before this change, state-local variables (`state Foo { var x: u8 = 0 }`)
were silently no-ops: the analyzer allocated a ZP slot for them, but
the codegen's `var_addrs` map only covered IR globals and scope-qualified
function locals — so every `LoadVar` / `StoreVar` whose `VarId` pointed
at a state-local resolved to no address and emitted nothing. Existing
examples compiled and matched their goldens because none of them observed
the dropped writes within the 180-frame harness window.
The overlay changes the analyzer's state-local pass to snapshot both the
ZP and RAM cursors after the globals have been laid out, then rewind to
that snapshot before each state's locals and track the running max.
`ZP_CURRENT_STATE` keeps exactly one state active at runtime, so every
state's locals are mutually exclusive with every other state's and can
share the same bytes. The IR lowerer now pushes each state's locals into
the IR globals table (with `init_value=None`) so the codegen resolves
their addresses the same way it does program globals, and prepends the
declared initializers to each state's `on_enter` handler (synthesizing
an empty one where needed) so a freshly-entered state re-establishes its
bytes before user code runs.
`--memory-map` now tags each allocation with its owning state
(`[@Title]`, `[@Playing]`, ...) and counts distinct bytes rather than
summed allocation sizes so overlaid slots don't double-count. The
`AnalysisResult.state_local_owners` map exposes the ownership to any
tool that wants to group allocations the same way.
Only `state_machine.ne` and `platformer.ne` declare state-level vars,
so they're the only example ROMs whose bytes change. `platformer.ne`'s
audio golden shifts slightly (the now-working `blink` counter in Title
adds a few cycles per frame before the auto-transition to Playing, which
offsets APU register writes within each frame); its video golden and
every other example ROM stay byte-for-byte identical.
Fixes #22.
https://claude.ai/code/session_015kvJu3iEFLSRJoShPBfm3X
This commit is contained in:
parent
77d55bc16b
commit
73dcf08c7a
11 changed files with 446 additions and 19 deletions
|
|
@ -186,6 +186,33 @@ peephole pass mops up the most obvious waste, but a real CFG-aware allocator
|
|||
that holds short-lived temps in `A`/`X`/`Y` would cut a noticeable number of
|
||||
LDA/STA pairs.
|
||||
|
||||
### State-local memory overlay follow-ups
|
||||
|
||||
State-local variables are now overlaid across mutually-exclusive states
|
||||
(see the analyzer's per-state allocation cursor rewind and the IR
|
||||
lowerer's `on_enter` initializer prologue), but a few pieces are still
|
||||
missing:
|
||||
|
||||
- **Same-named locals across different states.** `register_var` stores
|
||||
state-locals under their bare name, so two states each declaring
|
||||
`var timer: u8` collide with E0501. A per-state symbol-table scope
|
||||
prefix would let each state carve its own namespace while keeping
|
||||
the overlay.
|
||||
- **Struct-literal and array-literal initializers on state-locals.**
|
||||
The on-enter prologue lowers scalar initializers cleanly, and
|
||||
struct-literal initializers fall back to per-field stores, but
|
||||
array-literal initializers (`var xs: u8[4] = [1,2,3,4]`) are
|
||||
skipped. A runtime `memcpy` from a ROM blob into the overlay
|
||||
slot (mirroring the reset-time global path) is the natural
|
||||
lowering.
|
||||
- **Handler-local overlay.** Handler-local `var`s declared inside
|
||||
`on_frame { ... }` are already per-handler scoped via
|
||||
`current_scope_prefix`, but they get a dedicated RAM slot for the
|
||||
program's lifetime. Overlaying them inside each handler's stack
|
||||
frame — using a per-handler bump allocator that resets on each
|
||||
call — would shave a few bytes more on programs with many deep
|
||||
handlers.
|
||||
|
||||
### Cross-block temp live-range analysis
|
||||
|
||||
The slot recycler is function-local per-block. Temps that flow across block
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue