13.3 Stack Frame Layout
A stack frame stores the per-call data that does not live entirely in registers. Depending on the target ABI and function, it may contain a return address, saved frame pointer, callee-saved registers, local variables, spill slots, outgoing arguments, temporary call areas, alignment padding, a stack canary, and metadata used by garbage collection or unwinding.
The exact layout is a contract between generated instructions, the calling convention, debuggers, unwinders, and sometimes the runtime. An incorrect offset may read another local; incorrect alignment may fault on vector instructions or violate the ABI at a call.
Assigning slots and offsets
Frame construction begins after register allocation reveals which values spill and which callee-saved registers the function uses. Each stack object has a size, alignment, lifetime, and purpose. The layout algorithm places objects while maintaining alignment and records an offset relative to a stable base such as the frame pointer or post-prologue stack pointer.
high addresses
incoming stack arguments
return address
saved frame pointer
saved registers
local and spill slots
outgoing argument area
alignment padding
low addresses ← stack pointer after prologueObjects with disjoint lifetimes may share a stack slot, just as noninterfering values share a register. Security or debugging modes may disable some reuse. Large-alignment objects can create padding, so placement order matters for total frame size.
Fixed and dynamic frames
A fixed-size frame lets the compiler address every slot with a constant displacement from sp or fp. Variable-length arrays and dynamic alloca move the stack pointer at runtime. A frame pointer then provides a stable reference, or the compiler must track the changing stack pointer precisely.
Some ABIs offer a red zone below the current stack pointer that leaf functions may use without adjusting sp; interrupts and platform rules determine whether it is safe. Windows x64 instead requires caller-provided shadow space for callees. These are ABI-specific features, not universal stack facts.
Stack probing may be required for large frames so the function touches each guard-page interval rather than jumping over protected pages. Stack canaries place a secret value near vulnerable data and verify it before return. Both add instructions and fixed layout obligations.
Prologue and epilogue
The prologue establishes the frame: save required registers, adjust the stack pointer, establish a frame pointer if used, store a canary, and describe the new call-frame address for unwinding. Every normal epilogue restores the inverse state before returning.
Multiple returns may branch to a shared epilogue, but tail calls and exception exits have different rules. Shrink wrapping can save registers only around the region that needs them instead of at function entry, which reduces work on paths that never use those registers but complicates unwind information.
Runtime metadata and verification
Precise garbage collectors need stack maps describing which frame slots and registers contain live pointers at safepoints. Exception handling needs call-frame information (CFI) that reconstructs saved registers while unwinding. Debuggers need mappings from source variables to changing register or stack locations.
Frame verification checks that the final size satisfies alignment, every offset lies within its assigned object, overlapping slots have disjoint lifetimes, call sites restore the required stack alignment, and every saved register is restored on every exit. Test empty leaf frames, high spill pressure, dynamic allocation, large alignments, stack arguments, canaries, exceptions, and tail calls.