LEGACY DOCS · 12.4Stable is 13.2. This page stays because it still owns historical or unchanged contracts.CURRENT 13.2 →
RELEASE LINE13.2 HISTORICAL13.1 PREDECESSOR13.0 PREVIOUS12.4 NATIVE MIRARCHIVE

LEGACY DOCS · 12.4

PAGE ROLE · REGISTER AND FRAME CONTRACT

REGISTER ALLOCATION: PUT THE VALUE SOMEWHERE REAL

Virtual registers are promises. The CPU wants physical registers and memory addresses. v12.4 uses deterministic linear-scan allocation with explicit call clobbers, fixed-operand legalization and reusable spill slots.

00 live intervals

The allocator derives a live interval for each allocatable virtual register. An interval begins when the value becomes live and ends after its last required use. Intervals that overlap cannot occupy the same physical register at the same time. Intervals that do not overlap may reuse one.

This is deliberately less magical than a global graph-coloring research project. Linear scan matches the project's scale: enough quality for the target set, deterministic ordering, and a failure surface one person can still reason through.

A clever allocator you cannot debug is just a random-number generator with a compiler degree.

10 calls destroy registers on purpose

Calling conventions define caller-saved registers. A value live across a call cannot simply remain in a register that the callee may clobber. v12.4 models those clobbers explicitly. The allocator either chooses a safe location, moves the value, or spills it.

Fixed operands are legalized before final instruction selection. Instructions that demand specific registers therefore do not surprise the allocator after the fact.

20 registers the allocator does not own

Target familyReserved by contractReason
DBYTE64RSP, RBP, R11Stack/frame machinery and backend scratch contract.
DBYTE32 / i686ESP, EBPStack/frame machinery.

Callee-saved registers are saved only when allocation actually uses them. A function that never needs one should not pay a ceremonial prologue/epilogue tax.

30 spilling is a measured failure, not a secret

When register pressure exceeds the legal register set, an interval spills to an aligned frame slot. Loads and stores are inserted around the uses that require a register. Spill slots may be reused when their intervals do not overlap.

The inspection report counts spills, reloads, loads and stores because “allocation succeeded” is not enough. A compiler can successfully put every value on the stack and produce garbage code quality. Success needs a cost report.

40 frame size comes from real obligations

Frames contain addressable locals and aggregates, spill storage, and the maximum outgoing-call area required by the ABI. Windows x64 keeps the required 32-byte shadow space rule. Scalar locals that can stay in registers should not consume permanent frame bytes.

FRAME =
    addressable locals
  + aggregate storage
  + live spill slots
  + max outgoing call area
  + ABI-required alignment / shadow space

The enormous x86_64-none frame reduction in the v12.4 code-quality corpus is exactly why this distinction matters: aggregate frame bytes fell from 308832 to 7304 while the semantic contracts stayed fixed.

FRAME RULE. Stack memory is not free just because the compiler allocated it for you. Count the bytes.

50 deterministic tie breaking

Interval ordering and allocation choices are deterministic. Two exact builds must not choose different physical registers because an unordered container happened to enumerate differently. Deterministic binaries are a release property, not a nice debugging option.

60 the allocator does not redefine the ABI

Register allocation works inside the established DBYTE64, SysV AMD64 and Windows x64 contracts from the native foundation. Parameter locations, return values, stack alignment, preserved registers and object formats remain owned by the earlier native documentation. v12.4 improves how values inhabit that contract; it does not invent a fourth calling convention.

70 how to debug bad allocation

  1. Dump Native MIR before allocation.
  2. Record virtual-register intervals and fixed constraints.
  3. Inspect assigned physical registers.
  4. Inspect spill/reload counts and frame size.
  5. Disassemble the object or executable.
  6. Compare O0 and O1 only after confirming they consumed the same semantic input.

Do not start by staring at source syntax. Allocation bugs live much closer to the machine.

80 next wire

Continue to machine inspection. The allocator has made its decisions. Now make it show the evidence.