A.2.1 Codegen Notes
The x86_64 backend still follows udewy's logical value-stack model, but it does not map every save_value() directly to a machine push.
- The current visible expression result stays in
rax. - A small prefix of the logical saved-value stack is cached in callee-saved registers before falling back to spill slots on the real stack.
- When a call has more than 6 arguments, the extra arguments are written into an outbound stack-argument area and the first 6 are placed in
rdi,rsi,rdx,rcx,r8, andr9. - Call lowering also keeps the machine stack aligned to the ABI-required 16-byte boundary.
- Busy locals live in
rbx/r15(across calls) orr8/r9/r11(between calls) through the shared local register allocation described in Backend Architecture; ordinary builds only. - The visible value may be pending instead of in
rax: a local plus a constant offset that was named but not yet loaded, a constant, a load not yet performed, or the flags of the last comparison.save_valuemoves a pending local, constant or load straight into its cache register; a comparison uses a pending local, constant or load as thecmpqoperand; a load or store through a pending local uses it as the base register (movq 24(%rbx), %r12,movq %r12, 24(%rbx)); a constant stores directly (movq $0, %r15); andif, loop and short-circuit tests branch on the pending flags (jne,jge, ...) instead of materializing-1/0;noton a pending comparison inverts it. Every other operation materializes the value first. A loop test such asi <? nis thereforemovq,cmpq,jge, and a tag test__load_i64__(cell + 8) =? 140iscmpq $140, 8(%rbx),jne. While a local is still in memory, a site may hold two instructions in one code line (the slot load, then the operation throughrax); allocation rewrites it to the one-instruction register form.