You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
CPU backend disagrees with plain JavaScript on three control-flow shapes #865
Found by adversarial review while verifying the WebAssembly backend (feature/webasm-backend), which matches plain JS on all three where cpu does not. All three are pre-existing on develop and unrelated to that branch.
1. Early return inside a loop returns the post-loop value for every cell.
The translated loop keeps running after the return.
2. Do-while with continue does not jump to the test correctly — a do/while accumulating with if (i % 3 === 0) continue; returns 56 on cpu where plain JS gives 45.
3. Assignment to a scalar argument leaks across cells — base = base + this.thread.x; return base; with base = 10 returns [10, 11, 13, 16, ...] on cpu (the mutation accumulates across the cell loop) where per-cell JS, the GL backends and webasm give [10, 11, 12, 13].
The webasm suite pins these shapes against per-cell plain-JS references (test/features/webasm/control-flow.js) precisely because the cpu backend cannot serve as ground truth for them. Fixing cpu should add the same three shapes to a cpu regression file.
Fixed on feature/webasm-backend (PR #866) in 11b4c0e — the PR that discovered these now also fixes them, since its webasm suite supplied ready-made plain-JS-referenced fixtures.
All three mechanisms as diagnosed: the early-return continue targeting the user's loop (now a kernelBody: labeled block with break kernelBody; from any depth), the for-wrapped do-while skipping its trailing test on continue (now a native do-while with the loopMaxIterations cap riding in the condition), and run-wide argument bindings (now per-cell user_X$cell shadows routed through both the identifier and member-expression emitters, so reassigned array arguments read correctly too).
test/issues/865-cpu-control-flow.js pins the shapes against plain-JS references across backends; 5 of 10 runnable assertions fail with the fix reverted. Suites: Node 2697/0, browser 4071/0, SwiftShader baseline identical.
One discovery from the cross-backend rows: the GL backends fail the do-while and assigned-argument shapes by their own mechanisms (skipped trailing test in the do-while emulation; can't modify a uniform) — filed as #867, with the scoped test rows as its acceptance test.
Activity
fuzzie360 commentedon Aug 2, 2026
Fixed on
feature/webasm-backend(PR #866) in 11b4c0e — the PR that discovered these now also fixes them, since its webasm suite supplied ready-made plain-JS-referenced fixtures.All three mechanisms as diagnosed: the early-return
continuetargeting the user's loop (now akernelBody:labeled block withbreak kernelBody;from any depth), the for-wrapped do-while skipping its trailing test oncontinue(now a native do-while with the loopMaxIterations cap riding in the condition), and run-wide argument bindings (now per-celluser_X$cellshadows routed through both the identifier and member-expression emitters, so reassigned array arguments read correctly too).test/issues/865-cpu-control-flow.jspins the shapes against plain-JS references across backends; 5 of 10 runnable assertions fail with the fix reverted. Suites: Node 2697/0, browser 4071/0, SwiftShader baseline identical.One discovery from the cross-backend rows: the GL backends fail the do-while and assigned-argument shapes by their own mechanisms (skipped trailing test in the do-while emulation;
can't modify a uniform) — filed as #867, with the scoped test rows as its acceptance test.fix(cpu): three control-flow shapes now match plain JavaScript (#865)
fix: the twelve findings of the webasm adversarial review