pub struct Frame { /* private fields */ }Expand description
What a function’s stack looks like while it runs.
Implementations§
Source§impl Frame
impl Frame
Sourcepub fn of(func: &Func, allocation: &Allocation, layout: &Layout<'_>) -> Self
pub fn of(func: &Func, allocation: &Allocation, layout: &Layout<'_>) -> Self
Works out the frame of a function the allocator has finished with.
§Panics
Panics on a frame of two gigabytes or more, which is a stack no machine here gives a thread, and on a local whose alignment is not a power of two.
Sourcepub fn saved_int(&self) -> &[PhysReg]
pub fn saved_int(&self) -> &[PhysReg]
The general purpose registers the prologue pushes, in the order it pushes them.
The frame pointer is not among them even when the convention calls it a saved register, because a function that keeps one saves it as part of setting it up.
Sourcepub fn saved_sse(&self) -> &[Save]
pub fn saved_sse(&self) -> &[Save]
The vector registers the prologue stores into the frame, and where each of them goes.
Sourcepub fn slot(&self, slot: u32) -> Option<i32>
pub fn slot(&self, slot: u32) -> Option<i32>
Where a spill slot is, from the stack pointer in the body of the function.
Sourcepub fn local(&self, local: usize) -> Option<i32>
pub fn local(&self, local: usize) -> Option<i32>
Where a local is, from the stack pointer in the body of the function.
Sourcepub fn from_frame_base(&self, local: usize) -> Option<i32>
pub fn from_frame_base(&self, local: usize) -> Option<i32>
Where a local is, from the call frame address, which is what a debugger counts from.
The call frame address is the stack pointer the caller held when it made the call, and
Frame::incoming is already the distance up to it, since the first argument passed on the
stack sits there. So the answer is one subtraction, and it is a negative number, because the
frame is below the address the call was made from.
None in a frame whose alignment the prologue had to force, where there is no answer to
give. Rounding the stack pointer down throws away however far it was from where the caller
left it, so the distance from the body’s stack pointer up to the call frame address is not a
constant in such a function, and the two numbers subtracted here are counted from different
registers on top of that. What the locals of such a function want is a location counted from
the frame pointer, which is a different expression from the one a frame base gives.
None as well for a local this frame never placed.
Sourcepub fn canary(&self) -> Option<i32>
pub fn canary(&self) -> Option<i32>
Where the stack protector’s canary is, from the stack pointer in the body of the function,
or None in a frame that has none.
Sourcepub fn size(&self) -> u32
pub fn size(&self) -> u32
How many bytes the prologue takes off the stack pointer, which is nothing for a function small enough and quiet enough to live in the red zone.
Sourcepub fn outgoing(&self) -> u32
pub fn outgoing(&self) -> u32
How many bytes at the bottom of the frame belong to the arguments of calls this function makes, which is where the shadow space goes on Windows.
Sourcepub fn below(&self) -> u32
pub fn below(&self) -> u32
How many bytes at the bottom of the frame nothing else may be placed in, which is that area padded to the alignment everything above it asked for.
What a variable length array has to step over. It takes its bytes off the stack pointer, which leaves them at the bottom of the frame where the next call is going to write its arguments, so the address it hands out is this far above the stack pointer rather than the stack pointer itself.
Sourcepub fn grows(&self) -> bool
pub fn grows(&self) -> bool
Whether the function moves the stack pointer while it runs.
Every offset in the body of such a frame is from the frame pointer rather than from the
stack pointer, because a variable length array leaves the stack pointer somewhere no
constant reaches the rest of the frame from. See Growing in the module documentation.
Sourcepub fn realign(&self) -> Option<u32>
pub fn realign(&self) -> Option<u32>
What the prologue has to force the stack pointer to be a multiple of, when a local wants more alignment than a call leaves it with.
Sourcepub fn incoming(&self) -> Incoming
pub fn incoming(&self) -> Incoming
Where the first argument the caller passed on the stack is, and which register reaches it.
The only offset here that is not always from the stack pointer. A realigned frame counts from the frame pointer instead, because forcing the alignment threw away however far the caller’s stack pointer was from where the prologue wanted it, and the frame pointer is what reaches the caller’s stack afterwards.
Sourcepub fn frame_pointer(&self) -> bool
pub fn frame_pointer(&self) -> bool
Whether the function keeps a frame pointer.
Sourcepub fn naked(&self) -> bool
pub fn naked(&self) -> bool
Whether nothing at all is to be written around the body, which __attribute__((naked))
asks for. See Layout::naked.
Such a frame is empty, since crate::pipeline refuses a naked function that wanted any
bytes rather than handing it a frame no prologue sets up. What is left for this to say is
that the prologue and the epilogue are not to be written, and the epilogue is the point:
the ret at the end of a function is written there, and a naked function ends where its
own text ends.
Sourcepub fn late(&self) -> bool
pub fn late(&self) -> bool
Whether the prologue points the frame pointer at the frame after taking it rather than
before, which is rucc_target::CallRegs::late_frame_pointer and the one frame that cannot
have it whatever the platform says. See Late in the module documentation.