pub struct FrameLayout { /* private fields */ }Expand description
A laid-out frame: slot offsets and the prologue and epilogue.
Offsets are from the stack pointer after the prologue; they are negative for locals kept in the red zone.
§Examples
use backend_lang::mir::{Function, SlotKind};
use backend_lang::x86_64::SYSV;
let mut f = Function::new("leaf", &SYSV);
let a = f.stack_slot(SlotKind::Local { size: 8, align: 8 })?;
let frame = f.frame_layout().unwrap();
// A leaf with 8 bytes of locals uses the red zone: nothing is allocated.
assert!(frame.uses_red_zone());
assert_eq!(frame.alloc(), 0);
assert!(frame.slot_offset(a).unwrap() < 0);Implementations§
Source§impl FrameLayout
impl FrameLayout
Sourcepub fn slot_offset(&self, slot: StackSlot) -> Option<i32>
pub fn slot_offset(&self, slot: StackSlot) -> Option<i32>
A slot’s offset from the stack pointer after the prologue, or None
for a slot the layout does not have.
§Examples
use backend_lang::mir::{Function, SlotKind};
use backend_lang::x86_64::SYSV;
let mut f = Function::new("f", &SYSV);
let arg = f.stack_slot(SlotKind::Incoming { offset: 0, size: 8 })?;
let frame = f.frame_layout().unwrap();
// rbp is pushed: [rsp] = saved rbp, [rsp+8] = return address, [rsp+16] = argument.
assert_eq!(frame.slot_offset(arg), Some(16));Sourcepub fn pushed(&self) -> &[PReg]
pub fn pushed(&self) -> &[PReg]
The general-purpose callee-saved registers pushed after the frame pointer, in push order.
§Examples
use backend_lang::mir::Function;
use backend_lang::x86_64::SYSV;
assert!(Function::new("f", &SYSV).frame_layout().unwrap().pushed().is_empty());Sourcepub fn vec_saves(&self) -> &[(PReg, i32)]
pub fn vec_saves(&self) -> &[(PReg, i32)]
Vector callee-saved registers saved into the frame, with their save slots’ offsets.
§Examples
use backend_lang::mir::Function;
use backend_lang::x86_64::SYSV;
assert!(Function::new("f", &SYSV).frame_layout().unwrap().vec_saves().is_empty());Sourcepub fn prologue(&self) -> &[FrameStep]
pub fn prologue(&self) -> &[FrameStep]
The prologue, in execution order.
§Examples
use backend_lang::mir::Function;
use backend_lang::target::frame::FrameStep;
use backend_lang::x86_64::{SYSV, RBP};
let frame = Function::new("f", &SYSV).frame_layout().unwrap();
assert_eq!(frame.prologue(), [FrameStep::Push(RBP), FrameStep::SetFramePointer]);Sourcepub fn epilogue(&self) -> &[FrameStep]
pub fn epilogue(&self) -> &[FrameStep]
The epilogue, in execution order (the return itself is not part of it).
§Examples
use backend_lang::mir::Function;
use backend_lang::target::frame::FrameStep;
use backend_lang::x86_64::{SYSV, RBP};
let frame = Function::new("f", &SYSV).frame_layout().unwrap();
assert_eq!(frame.epilogue(), [FrameStep::Pop(RBP)]);Sourcepub const fn alloc(&self) -> u32
pub const fn alloc(&self) -> u32
Bytes the prologue subtracts from the stack pointer after its pushes.
§Examples
use backend_lang::mir::Function;
use backend_lang::x86_64::SYSV;
assert_eq!(Function::new("f", &SYSV).frame_layout().unwrap().alloc(), 0);Sourcepub const fn cfa_offset(&self) -> u32
pub const fn cfa_offset(&self) -> u32
The canonical frame address (the stack pointer before the call) minus the stack pointer after the prologue: return address, pushes, and allocation.
§Examples
use backend_lang::mir::Function;
use backend_lang::x86_64::SYSV;
// Return address plus the saved rbp.
assert_eq!(Function::new("f", &SYSV).frame_layout().unwrap().cfa_offset(), 16);Sourcepub const fn frame_pointer(&self) -> bool
pub const fn frame_pointer(&self) -> bool
Whether the frame keeps a frame pointer.
§Examples
use backend_lang::mir::Function;
use backend_lang::x86_64::SYSV;
assert!(Function::new("f", &SYSV).frame_layout().unwrap().frame_pointer());Sourcepub const fn uses_red_zone(&self) -> bool
pub const fn uses_red_zone(&self) -> bool
Whether the locals live in the red zone below the stack pointer.
§Examples
use backend_lang::mir::Function;
use backend_lang::x86_64::SYSV;
assert!(!Function::new("f", &SYSV).frame_layout().unwrap().uses_red_zone());