pub struct Stack {
pub calls: Option<u32>,
pub locals: Vec<Local>,
pub addresses: Vec<(Inst, usize)>,
pub dynamic: Vec<Inst>,
pub grown_at: Option<Inst>,
pub arguments: Vec<(Inst, u32)>,
pub walks_frames: bool,
}Expand description
What a function’s stack has to hold, as far as selection is able to say.
All of it is answered here because selection is where a call is built and where an alloca
is read, and nothing after it could tell what either of them needed.
Fields§
§calls: Option<u32>How many bytes the widest call in the function needs below the stack pointer for the
arguments it passes there, or None for a function that makes no call at all.
None is a leaf, which is the function that may use the red zone and the one whose stack
pointer does not have to be left aligned for anybody.
locals: Vec<Local>The memory the function asked for itself, one entry for every alloca in it, in the order
the walk reached them.
addresses: Vec<(Inst, usize)>Which instruction computes the address of which of those locals.
An address in the frame is a distance from the stack pointer, and there is no frame until
after allocation, so the instruction is written here with nothing in its displacement and
crate::finish writes the number in once crate::frame::Frame knows it.
dynamic: Vec<Inst>Which instruction computes the address of a piece of memory whose size the function works out while it runs, which is what a variable length array is.
Waiting on crate::finish for a different number from the one the addresses above are:
the bytes were taken off the stack pointer by the instruction in front of this one, so where
they start is however much of the bottom of the frame belongs to the arguments of a call,
and that is not known until the frame is.
grown_at: Option<Inst>Where the function first moves the stack pointer while it runs, if it does at all.
Two things are read off this. One is whether at all, which is what crate::frame::Layout
wants, because a frame that moves its stack pointer has a different shape from one that does
not and the layout is built before the instructions are looked at again. See Growing in
crate::frame. The other is where, so that a caller that cannot accept such a frame has
somewhere to point when it says so.
arguments: Vec<(Inst, u32)>Which instruction reads which of the arguments the caller passed on the stack, as how far up the caller’s argument area it reads.
Waiting on crate::finish for the same reason the addresses above are, and on one thing
more: where the caller’s argument area is from inside this function depends on whether the
prologue had to force the stack pointer’s alignment, so which register the load reads
through is not settled here either.
walks_frames: boolWhether the function asked where its own frame is, which is what __builtin_frame_address
and __builtin_return_address both start from.
A function like that keeps a frame pointer whatever the flags say, because the register is the answer to the first of them and the start of the walk for every depth above zero. There is no other way to reach it: the distance from the stack pointer to the frame is a number the layout works out, and what a walk up the chain needs is the link the prologue saved.
Implementations§
Source§impl Stack
impl Stack
Sourcepub fn layout<'a>(&'a self, base: Layout<'a>) -> Layout<'a>
pub fn layout<'a>(&'a self, base: Layout<'a>) -> Layout<'a>
The layout given, with the three fields only the lowering knows the answer to filled in.
Everything else in a layout comes from the flags the function is compiled under or from the allocation, so this takes one and returns it rather than building one.