Struct regalloc2::moves::MoveAndScratchResolver
source · pub struct MoveAndScratchResolver<GetReg, GetStackSlot, IsStackAlloc>where
GetReg: FnMut() -> Option<Allocation>,
GetStackSlot: FnMut() -> Allocation,
IsStackAlloc: Fn(Allocation) -> bool,{
pub find_free_reg: GetReg,
pub get_stackslot: GetStackSlot,
pub is_stack_alloc: IsStackAlloc,
pub borrowed_scratch_reg: PReg,
}
Expand description
Final stage of move resolution: finding or using scratch registers, creating them if necessary by using stackslots, and ensuring that the final list of moves contains no stack-to-stack moves.
The resolved list of moves may need one or two scratch registers, and maybe a stackslot, to ensure these conditions. Our general strategy is in two steps.
First, we find a scratch register, so we only have to worry about a list of moves, all with real locations as src and dest. If we’re lucky and there are any registers not allocated at this program-point, we can use a real register. Otherwise, we use an extra stackslot. This is fine, because at this step, stack-to-stack moves are OK.
Then, we resolve stack-to-stack moves into stack-to-reg / reg-to-stack pairs. For this, we try to allocate a second free register. If unavailable, we create a new scratch stackslot to serve as a backup of one of the in-use registers, then borrow that register as the scratch register in the middle of stack-to-stack moves.
Fields§
§find_free_reg: GetReg
Closure that finds us a PReg at the current location.
get_stackslot: GetStackSlot
Closure that gets us a stackslot, if needed.
is_stack_alloc: IsStackAlloc
Closure to determine whether an Allocation
refers to a stack slot.
borrowed_scratch_reg: PReg
Use this register if no free register is available to use as a temporary in stack-to-stack moves. If we do use this register for that purpose, its value will be restored by the end of the move sequence. Provided by caller and statically chosen. This is a very last-ditch option, so static choice is OK.