← board

Port the stackful coroutine backend to all targets

Motivation

The stackful coroutine backend (heap stack + context-switch primitive; yield/ await anywhere, managed locals across suspension, try/except across suspension) is x86-64 only today — the context switch is hand-written asm (compiler/coroutine_emit.inc). Every other target (i386, ARM32, AArch64, RISC-V/esp32c3, Xtensa/esp32s3) can run only the stackless backend. That blocks:

Memory is not the blocker: the saved stack lives on the heap, allocated on start and freed on completion, so even hundreds of live stackful coroutines are affordable (cheaper than threads; trivial next to a MicroPython heap). The blocker is purely the missing per-target context-switch primitive.

Scope

Port the context-switch primitive (save callee-saved regs + sp + return address, swap to the coroutine's heap stack, and back) per target. Once the first 32-bit port is done, the rest are largely mechanical copies with the target's callee-saved register set and ABI.

Validation

Mirror the existing x86-64 coroutine/generator tests on each target; on ESP, output-equality vs the x86-64 oracle under tools/esp_run_bare.sh / tools/esp_run.sh. make test + make cross-bootstrap byte-identical after each target.

Acceptance