Repository navigation
fix(lower-go): unbox a native prim's direct-call result into a typed slot - #1084
Conversation
nooga
left a comment
There was a problem hiding this comment.
Approving. This fixes the root cause: the (vm.Value, error) branch now unboxes into a natively typed slot through boxed-call-stmts, the same path the trampoline branch has used since #1044. boxed-call-stmts falls back to emit-call-stmts when the slot is vm.Value or the result is dead, so only sites that used to be Go type errors emit different code. The tb/tv/tk temps are registered the same way in both branches, so the prologue doesn't get duplicate declarations. The fixture covers all three shapes from #1081, and the .lg edit is regenerated.
Nit for the record: this touches only the Go-AOT lowerer, so pkg/compiler and ir-compile are unaffected. A line saying so in the body would satisfy the three-paths note in AGENTS.md.
…slot #1057 gave aget, alength and byte-array guarded direct calls to their Go entries (rt.CoreAgetf and friends), taken while rt.NativePrimsIntact holds. Those entries return (vm.Value, error), but typeinfer can give the call's node a native slot: float64 for aget on a ^doubles array, int64 for alength, *vm.TypedArray for byte-array. typed-call-result-stmts assigned the vm.Value straight into that slot, so the generated Go did not build. The trampoline branch of the same if already unboxed, through boxed-call-stmts (#1044). The (vm.Value, error) case of typed-call-result-stmts now goes through boxed-call-stmts too, so both branches take the result into tb<nid>, check the error, and comma-ok assert it to the slot's type. A vm.Value slot, or a dead result, emits what it did before. test/gogen/native_prim_typed_slot.lg covers aget with a boxed index, alength of an unhinted array, and a byte-array local. On main all three sites fail to build. Fixes #1081 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ba66471 to
8d5ac38
Compare
Why
#1057 gave
aget,alengthandbyte-arrayguarded direct calls to their Go entries, taken whilert.NativePrimsIntact()holds. Those entries (rt.CoreAgetfand friends) return(vm.Value, error), but typeinfer can give the call's node a native slot:float64forageton a^doublesarray,int64foralength,*vm.TypedArrayfor abyte-arraylocal.typed-call-result-stmtsassigns thevm.Valuestraight into that slot, so the lowered Go doesn't build:The
elsebranch is already right: it reusestrampoline-call-stmts, which unboxes throughboxed-call-stmtssince #1044. The direct branch never got the same step.What
The
(vm.Value, error)case oftyped-call-result-stmtscallsboxed-call-stmtsinstead ofemit-call-stmts. Both branches now take the result intotb<nid>, check the error, and comma-ok assert it to the slot's vm type, returning avm.TypeErroron mismatch. They register the same temp names and types, and the prologue'sdistinctemits each declaration once.A
vm.Valueslot or a dead result goes throughemit-call-stmtsunchanged, so only sites that were Go type errors emit different code.Only the Go-AOT lowerer changes.
pkg/compilerand*ir-compile*are unaffected.Verification
test/gogen/native_prim_typed_slot.lg:agetwith an index boxed by a var,alengthof an unhinted array into an int slot, and abyte-arraylocal filled in a loop. Onmainits lowered Go fails to build at all three sites. With this change the gogen trampoline builds it and matches the bytecode VM ([13.0 3.0 [0 2 4 6]]).test/gogenfixtures pass the trampoline.make check-generated-manifestandmake lintpass;go test ./pkg/ir/passes. I didn't run the fullmake testlocally.13.0.lg compilewith no workarounds, and the native binary renders plasma and milk scenes.Fixes #1081
🤖 Generated with Claude Code