Skip to content

t27b(wasm): floor 17 -- the LOCALS MOUNT (statement bodies lower, fact word 11 feeds the walk) - #12378

Closed
gHashTag wants to merge 2 commits into
masterfrom
feat/wasm32-floor-locals
Closed

gHashTag wants to merge 2 commits into
masterfrom
feat/wasm32-floor-locals

Conversation

@gHashTag

Copy link
Copy Markdown
Collaborator

What

Floor 17 of the t27b wasm32 emitter: the LOCALS MOUNT. The stateful floor set 12-16 (#12178) opened the local window as law, and #12044 deleted the emitter onto the law -- but the mount fed the window nothing: ir::wasm_facts projected no statement shape and wrote fact word 11 as 0, so every fn with an intermediate still refused as fn body. This PR closes that gap: a straight-line body with an intermediate now emits, in 49 bytes, and runs in a standard runtime.

The law (commit 1, spec + gen + seal)

specs/tri/t27b/wasm.t27 floor 17 -- the three pieces the mount calls, nothing else:

  • stmts_refusal_w: the windowed verdict of a BS_STMTS_RETURN payload. Statements are opcode spellings, the window rides the EK_VAR reads through expr_refusal_w, the value stack closes on exactly one return value, and a store refuses when the value it stores refused -- the verdict never rides under a local.set, or the lowering would emit a body missing those bytes. The loop/call/load/store kinds fail closed: their mounts carry the label-depth, callee-arity and memarg facts; the law already spells their bytes.
  • bodies_cap_l: bodies_cap plus one local group's six bytes per locals-carrying row -- walk_prog_locals' own reserve.
  • compose_module_with_image_l: the emit_with_image composer carrying the locals rows; an empty image over all-zero rows delegates to compose_module_with_image, so the scalar and mounted cuts cannot move.

Five tests pin every byte: the window walk, fail-closed (unbalanced streams, mountless kinds, the adapter's 255 marker, a partial fact row), the capacity +6, the delegation pinned by byte equality in both cuts, and the 49-byte locals leaf (inc: t = a + 1; return t * 2;) through walk_prog_locals, with its 66-byte image twin in section id order 1, 3, 5, 7, 10, 11. 103/103, resealed.

The mount (commit 2, paid by shrink: +10/-61)

  • ir.rs wasm_facts: assignments-then-return bodies project as BS_STMTS_RETURN; fact_put_locals writes word 11; the body verdict is the law's own windowed fold. Any other statement (If, While, Call, Store) keeps BS_OTHER's refusal; a zero-param fn still owes the const shape -- every old refusal line is byte-stable.
  • lib.rs emit_with_image: walk_prog_locals + bodies_cap_l + compose_module_with_image_l. All-zero locals rows are byte-identical to the old path.
  • tests/wasm32.rs: the mount's end-to-end gate (the inc leaf instantiates in Node's WebAssembly, inc(7) = 16). The M-B byte-pin test folds -- the law pins the identical two-fn framing byte for byte and the same source keeps its runtime gate in the neighboring Node test.

A/B evidence

Same spec, one command apart:

  • pre-mount: unsupported construct fn body at line 4 (fn inc: the wasm32 emitter lowers ... only)
  • post-mount: a 49-byte module; Node: inc(7)=16, inc(0)=2, byte-identical across rebuilds.

Refs #11840 (wasm32 floor table), #12148 / #12178 (the stateful floor set this mounts), #5980 (the struct-path gap: this is the locals rung of the dependency order -- the gx_ setters' var intermediates now express), #6198 (port epic).

T27 work report

{
  "lane": "feat/wasm32-floor-locals",
  "head_sha": "736b575485224e2b657f1ae8420d9c62c49ba5a5",
  "base": "origin/master",
  "commits": [
    "spec(tri/t27b): wasm.t27 floor 17 -- the LOCALS MOUNT (spec+gen+seal)",
    "t27b(wasm): the local window mounts -- statement bodies lower, word 11 feeds the walk"
  ],
  "tests": [
    {"name": "wasm.t27 law suite (t27b test + t27c test-report)", "result": "103 passed, 0 failed, 0 vacuous -- 98 prior plus 5 new floor-17 tests"},
    {"name": "cargo test -p t27b --test wasm32", "result": "12 passed, 0 failed -- includes the new local-window end-to-end Node gate"},
    {"name": "cargo test -p t27b --test wasm32_equality", "result": "1 passed, 0 failed -- native vs wasm32 stays equal through the CLI battery"},
    {"name": "tri preflight", "result": "9 of 9 gates ok on the rebased branch before push"},
    {"name": "lefthook pre-commit on both commits", "result": "own-language ok, foreign-budget ok, secret-gate ok -- no bypass used"},
    {"name": "A/B probe on one spec", "result": "pre-mount refuses fn body at line 4; post-mount emits 49 bytes, Node answers inc(7)=16"}
  ],
  "budget": {
    "commit_1": "spec+gen+seal only -- no hand-written foreign files",
    "commit_2": "+10 added / -61 deleted hand-written foreign lines (ir.rs +28/-14, lib.rs +11/-14, tests/wasm32.rs +22/-50); counted files +1/-32"
  },
  "limitations": [
    "Only i32-carried locals are claimed (the law's own scope); a fn whose locals ride another carrier keeps the old refusal.",
    "Only straight-line statement bodies: If/While/Call/Store in a body keep BS_OTHER's refusal -- their mounts are the later floors of the stateful set (loads/globals, loops/calls, u64 carriers, void fns, pointer params).",
    "The windowed fold refuses the loop/call/load/store node kinds until those mounts teach it their facts; the law's lowering already spells their bytes for the floors that do.",
    "One duplicated M-B byte-pin test folded into the law's own byte-identical pins; the same source's runtime gate stays in tests/wasm32.rs."
  ]
}

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-25 10:33:08 UTC

Summary

Status Count
Total Open PRs 49
PRs with Failing Checks 40
PRs with All Checks Green 9
READY 5
FAILING 40
PENDING 0
NO CHECKS YET 0

These columns do not partition: 5 + 40 + 0 + 0 = 45, and there are 49 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=75249fe1efad != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

…12148, #5980)

Floor 14 opened the local window as law (#12178), but the deleted emitter's
mount fed it nothing: ir::wasm_facts projected no statement shape and wrote
fact word 11 as 0, so every fn with an intermediate still refused as fn body.
Floor 17 is the adapter floor -- the three pieces the mount calls, nothing
else:

- stmts_refusal_w: the windowed verdict of a BS_STMTS_RETURN payload.
  Statements are opcode spellings, the window rides the EK_VAR reads through
  expr_refusal_w, the value stack closes on exactly one return value, and a
  store REFUSES when the value it stores refused -- the verdict never rides
  under a local.set, or the lowering would emit a body missing those bytes.
  The loop/call/load/store kinds fail closed (their mounts carry the label
  depth, callee arity and memarg facts; the law already spells their bytes).
- bodies_cap_l: bodies_cap plus one local group's six bytes per
  locals-carrying row -- walk_prog_locals' own reserve.
- compose_module_with_image_l: the emit_with_image composer carrying the
  locals rows; an empty image over all-zero rows delegates to
  compose_module_with_image, so the scalar and mounted cuts cannot move.

Five tests: the window walk, fail-closed (unbalanced, mountless kinds, the
adapter's 255 marker, a partial fact row), the capacity +6, and the two
composers -- the delegation pinned by byte equality in both cuts, the
49-byte locals leaf (inc: t = a + 1; return t * 2;) pinned byte for byte
through walk_prog_locals, its 66-byte image twin in section id order
1, 3, 5, 7, 10, 11. 103/103 via t27b test and t27c test-report; wasm32.rs
12/12 and wasm32_equality 1/1 stay green; resealed.

The mount itself (ir.rs projection + lib.rs adapter) lands in the next
commit, paid by shrink.
…1 feeds the walk (floor 17's mount; Refs #11840, #12148, #5980)

Floor 17's law landed in the previous commit; this is the mount it serves.
The diff shrinks: +10 hand-written foreign lines, -61 (the counted files
+1/-32; one duplicated test folded, see below).

- ir.rs wasm_facts: a straight-line body (assignments then the trailing
  return, all-i32-carried locals) projects as BS_STMTS_RETURN -- each
  assignment lowers postfix(value) then EK_LOCAL_SET, the return walks
  last -- and fact word 11 carries the local count through
  fact_put_locals. The body verdict is the law's own windowed fold
  (stmts_refusal_w), so a var read past nparams + locals_n still refuses
  with floor 8's construct and detail byte for byte. Any other statement
  (If, While, Call, Store) keeps BS_OTHER's refusal; a zero-param fn still
  owes the const shape.
- lib.rs emit_with_image: walk_prog_locals + bodies_cap_l +
  compose_module_with_image_l. All-zero locals rows delegate byte for byte
  to the old composer, so the 43-byte leaf, the 117-byte trio and the
  60-byte mounted cut cannot move.
- tests/wasm32.rs: the mount's end-to-end gate -- the inc leaf (the law's
  49 bytes, group 01 7F inside the entry) instantiates in Node's
  WebAssembly and answers inc(7) = 16. The M-B byte-pin test folds: the
  law pins the identical two-fn framing byte for byte (the 87-byte duo and
  117-byte trio, Node-verified per their law tests) and the same
  latency/frame source keeps its runtime gate in the neighboring Node
  test; stale narration prose trimmed beside it.

A/B on the same spec: pre-mount the wasm32 build refused "unsupported
construct fn body at line 4 (fn inc: ...)"; post-mount it emits the
49-byte module and Node answers inc(7)=16, inc(0)=2, byte-identical
across rebuilds. wasm32.rs 12/12, wasm32_equality 1/1, wasm.t27 103/103.
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-25 11:05:43 UTC

Summary

Status Count
Total Open PRs 47
PRs with Failing Checks 38
PRs with All Checks Green 9
READY 3
FAILING 38
PENDING 0
NO CHECKS YET 0

These columns do not partition: 3 + 38 + 0 + 0 = 41, and there are 47 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=75249fe1efad != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@tri-claw

tri-claw Bot commented Oct 25, 2026

Copy link
Copy Markdown

Summary by t27-bees

Checked by the t27 compiler

t27c parse, parse-complete and typecheck on each changed .t27 file at b81e86f. Nothing was generated, built or run. A pass means the file is well formed, not that it is right.

  • specs/tri/t27b/wasm.t27: parses and typechecks.

Read by the model

This PR implements Floor 17 (the LOCALS MOUNT) for the t27b wasm32 emitter. The stateful floor set 12-16 established the local window as law, but the deleted emitter's mount fed it nothing—ir::wasm_facts projected no statement shape and wrote fact word 11 as 0, so every function with an intermediate variable refused as fn body. This PR closes that gap: straight-line assignment-then-return bodies now emit through the windowed fold (stmts_refusal_w), the capacity reserves 6 bytes per locals-carrying row (bodies_cap_l), and the module composer carries the locals rows (compose_module_with_image_l), with byte-identical delegation to the old path when rows are all-zero.

Worth a look

  • cli/t27b/src/ir.rs:845-870 — The new BS_STMTS_RETURN pattern only matches when all locals are i32 (w::carrier(v.ty.name().as_bytes()) == w::VT_I32). If a function declares a non-i32 local (e.g., i64), it falls through to BS_OTHER refusal even if the statement shape is otherwise valid. The carrier check uses the type's name bytes; if the IR ever carries a type with a different spelling (e.g., I32 vs i32), the check could silently misclassify.

  • cli/t27b/src/ir.rs:872-878 — fact_put_locals receives locals_n as (f.vars.len() - f.nparams) as u32 only for BS_STMTS_RETURN; all other shapes pass 0. The law's fact_put_locals must interpret word 11 as the locals count only for this shape, or the walk will read garbage for other bodies.

  • cli/t27b/src/lib.rs:135-138 — The locals buffer is allocated as k * 4 bytes (one u32le per descriptor). walk_prog_locals writes into it, and compose_module_with_image_l fails closed if k * 4 > locals.len. If walk_prog_locals ever writes more than 4 bytes per row (e.g., a uleb128 count > 127), the buffer overflows silently in safe Rust (panic) or the fail-closed check triggers incorrectly.

  • gen/rust/tri/t27b/wasm.rs:2101-2160 — stmts_refusal_w refuses EK_LOCAL_SET when the stored value's verdict is not REF_OK (the verdict never rides under a store). However, it returns the child verdict directly without checking that the local index is in bounds (var < nparams + locals_n). An out-of-bounds local.set would pass the windowed fold and produce invalid Wasm. The stmt_refusal_w helper (used for EK_VAR) does check bounds, but EK_LOCAL_SET bypasses it.

  • gen/rust/tri/t27b/wasm.rs:2162-2195 — compose_module_with_image_l delegates to compose_module_with_image when image.len == 0 && !any (all locals rows zero). The test compose_module_with_image_l_is_the_mount_cut_over_zero_rows asserts byte equality, but the delegation path omits the locals buffer entirely. If walk_prog_locals writes non-zero rows for a function that the old walk_prog would have accepted (e.g., a zero-locals function incorrectly marked), the delegation is skipped and the new code path runs with a zero locals row—which code_entries_locals must handle identically to the old code_entries.


Read: 6 files, +532 -88, the whole diff. Head b81e86f. Model: openai-compatible/nvidia/nemotron-3-ultra-550b-a55b. Commands: @t27-bees review | summary | help | pause | resume. Free for every repository.

This was referenced Oct 26, 2026
@gHashTag

Copy link
Copy Markdown
Collaborator Author

; SUPERSEDED -- content landed in spec form. Master a3e7947 ('wasm floor 18 -- the LOCALS MOUNT rides beside the landed pointer-carrier floor 17',Refs #12148 #12378, PR #12610) carries this PR's core: the floor-17 pointer-carrier work landed, and floor 18's LOCALS MOUNT rides beside it -- in specs/tri/t27b/wasm.t27 with its seal, per the t27b-in-t27 law, not as the hand-written ir.rs/lib.rs variant this PR carried.

; WHERE THE CONTENT LIVES (SELF-CRITICAL):
; landed: master a3e7947 -- specs/tri/t27b/wasm.t27 (1 'LOCALS MOUNT' hit) + .trinity/seals/t27b_T27bWasm.json (re-sealed on the 18 merge; the sweep's class-A stale-seal note is tracked separately in #12708)
; leftover: branch 'feat/wasm32-floor-locals' -- the hand-written variant (ir.rs, lib.rs, wasm32.rs tests, gen/rust/tri/t27b/wasm.rs). Superseded by the spec form; keep for archaeology, delete at will.

@gHashTag gHashTag closed this Oct 26, 2026
auto-merge was automatically disabled October 26, 2026 17:17

Pull request was closed

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