mirror of
https://github.com/hanzoai/wasm2go.git
synced 2026-10-30 15:06:48 +00:00
* codegen: auto-detect runtime-built f16 tables; fail on stale asserts The f16->f32 table's address had to be asserted from outside (-f16-table): ggml-style engines build the table at runtime, so the static byte-check cannot see it. That external magic number proved a liability twice over — the address moves with any layout shift (source changes, even build-cache state), a stale value silently disables every table-keyed rewrite (the llama-wasm v0.2.1 release shipped ~35% slower decode this way), and the existing staleness warning never ran for multi-package modules because that layout returns before the check. Derive the address from the module's own initialization code instead: an init loop that streams constant-strided stores from a constant base and provably covers the table's whole 256KiB range. Detection is structural over the lowered SSA — a loop-carried pointer phi with constant start and advance, a counter phi with a computable trip count, stores through the pointer — so it does not depend on how the compiler vectorized the conversion arithmetic inside the loop. The scan runs lazily on the first gather-site query. -f16-table remains as an explicit override, now cross-checked: a set address that contradicts a module-verified base FAILS the build, naming the address to adopt; the no-evidence case keeps the old warning, which now also runs on the multi-package path. Verified against the llama engine module: flagless transpile auto-detects the table and produces a byte-identical bundle to the correctly-asserted build (121 FCVT conversions intact); a stale assert aborts with the actionable error. Co-Authored-By: Claude Fable 5 <[email protected]> * codegen: drop the f16-table address input; keep only a boolean opt-out With auto-detection proven equivalent (flagless transpile of the engine module is byte-identical to the previously asserted build), an address-carrying override has no remaining legitimate use — it only reintroduces the stale-value hazard. -f16-table is gone; -no-f16-table disables the table-keyed rewrites outright. The end-of-translation diagnostic is now unconditional: gather sites whose base verified neither statically nor through init-loop coverage are reported, so a detection miss after a module change is loud in every pipeline log. Co-Authored-By: Claude Fable 5 <[email protected]> --------- Co-authored-by: Claude Fable 5 <[email protected]>
42 lines
1.2 KiB
Go
42 lines
1.2 KiB
Go
package codegen
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
|
|
"github.com/goccy/wasm2go/internal/testfixture"
|
|
"github.com/goccy/wasm2go/internal/wasm"
|
|
)
|
|
|
|
// TestDetectRuntimeTables drives the init-loop detector over the
|
|
// fixture's two store loops: one covering a full f16-table range
|
|
// (verifies) and one covering half of it (must not).
|
|
func TestDetectRuntimeTables(t *testing.T) {
|
|
bin := testfixture.Wasm(t, "f16_init_loop.wat")
|
|
mod, err := wasm.Parse(bytes.NewReader(bin))
|
|
if err != nil {
|
|
t.Fatalf("parse: %v", err)
|
|
}
|
|
tr := &translator{mod: mod}
|
|
tr.detectRuntimeTables()
|
|
if len(tr.runtimeTables) == 0 {
|
|
t.Fatal("no init-loop store regions detected")
|
|
}
|
|
if !tr.runtimeInitCovered(4096) {
|
|
t.Fatalf("full-range init loop not covering base 4096: %+v", tr.runtimeTables)
|
|
}
|
|
if tr.runtimeInitCovered(4100) {
|
|
t.Fatal("misaligned base must not verify (range ends short)")
|
|
}
|
|
if tr.runtimeInitCovered(266240) {
|
|
t.Fatalf("half-range init loop must not verify: %+v", tr.runtimeTables)
|
|
}
|
|
// The detection feeds f16TableOK without any assertion.
|
|
if !tr.f16TableOK(4096) {
|
|
t.Fatal("f16TableOK rejected an init-covered base")
|
|
}
|
|
if tr.f16TableOK(266240) {
|
|
t.Fatal("f16TableOK accepted a half-covered base")
|
|
}
|
|
}
|