feat(coro): add runnable stackless scheduler and panic prototype - #23
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces significant enhancements to the coroutine lowering and runtime ABI, including support for plain Go function value dispatching (EnableCoroPlainDispatch), a pure SSA operation auditor for coroutines, and a five-stage heterogeneous startup program (ValidateRunnableProgramV2). It also adds freestanding WebAssembly target support (wasip2, wasm-unknown) with a leaking GC profile and the llgo.coroPark intrinsic. Feedback on the changes highlights a potential loss of debuggability due to the removal of p.debugParams during the refactoring of compileCoroPhysicalBody.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| func (p *context) compileCoroPhysicalBody(b llssa.Builder, fn *ssa.Function, abi coroPhysicalABI, isInit bool) { | ||
| oldBase := p.sourceParamBase | ||
| oldCoro := p.currentCoro | ||
| oldSourceBlocks := p.coroSourceBlocks | ||
| p.sourceParamBase = 2 | ||
| defer func() { | ||
| p.sourceParamBase = oldBase | ||
| p.currentCoro = oldCoro | ||
| p.coroSourceBlocks = oldSourceBlocks | ||
| }() | ||
|
|
||
| b.SetBlock(p.fn.Block(0)) |
There was a problem hiding this comment.
The call to p.debugParams(b, fn) seems to have been removed during the refactoring of compileCoroPhysicalBody. This function is responsible for emitting debug information for the coroutine's parameters, which is crucial for debugging. Its removal will likely result in a loss of debuggability for coroutines. Was this intentional? If not, please consider reintroducing it.
There was a problem hiding this comment.
It was moved, not dropped. compileCoroPhysicalBody now installs the explicit source-block map and then routes block 0 through compileBlock; that existing path calls p.debugParams after the initial suspend, in the logical source block where parameter locations dominate source instructions. Emitting it in the old physical ramp would use the wrong block mapping. Commit 1734c3a strengthens TestCoroLeafPhysicalABIGlobalDebug to require both DILocalVariable(name: "value", arg: 1) and an actual dbg value/declare location record, so this is now covered explicitly.
Summary
go f(args)through compiler-owned begin/initial-suspend/commit, with no runtime user callback or TLS lookupmainreturns normally, destroying LLVM frames deepest-to-root and reclaiming each task onceSuspendPanicand a no-TLS runtime handoffwasip2andwasm-unknowncore modules without libuv or BDWGCScope and current boundary
This is an incremental integration PR for xgo-dev#1546, not a claim that the complete Go runtime is already supported.
Static spawn is deliberately fail-closed: only top-level, non-capturing, non-generic, non-variadic, zero-result targets are accepted; owner and target use one preemptible
DirectCoroprimary. Command shutdown currently accepts onlyYieldOnly|AwaitStructuredspawned trees and rejects non-empty wait sets.llgo.coro.panic.explicit-status.v0is identity-wired. The compiler now accepts only cleanup-free PhysicalABIV1 bodies whose explicit panic is an empty-interface concrete pointer backed by typed nil or package-global storage. It publishesSuspendPanic/FinalSuspended, calls__llgo_coro_panic_prepare_v1(g, handle, header, typeWord, dataWord), and branches to the same LLVM final suspend as normal completion. The runtime retains the two-word record, destroys the active frame and suspended-await ancestors without resuming them, and returnsPanicComplete.The production
internal/buildcapability gate remains closed. Dynamic interface/scalar/local/parameter payloads, managed plain unwinds, defer/recover/Goexit/implicit faults, dynamicerror.Error/Stringerreporting, and final printer/exit ownership are not implemented.The runnable native smokes are deliberately closed scheduler islands with bounded init no-ops and fail-stop libc/allocation stubs. They prove real compiler/runtime linkage and execution without claiming full standard-library runtime startup.
Other remaining blockers include stable wait-producer unregister/cancellation, real tick/event sources, channel/timer/netpoll/syscall producers, precise suspended-frame GC, dynamic/closure/method spawn, and multi-P scheduling.
All coroutine frames are LLVM stackless coroutine frames; this branch does not add per-G pthread, ucontext, native, or RTOS stacks.
Validation
runtime.Panic/RethrowBefore=1, After=0, Leaf=0)bootstrap → main → panicChild, proving three distinct handles are destroyed once, ancestors do not resume, and the task-local panic record survivesllgo build -target=wasip2and-target=wasm-unknownlink/symbol closure smoke; wasmtime execution when availablePanic/Rethrow/TracePanic/printanyDependency