///|
/// The point within an instruction where an allocation operand is read or
/// written.
pub(all) enum OperandTiming {
Early
Late
} derive(Eq, Debug)
///|
pub extend OperandTiming with Debug::{to_repr}
///|
pub extend OperandTiming with Eq::{not_equal, equal}
///|
/// Whether an allocation operand reads, writes, or both reads and writes its
/// virtual register.
///
/// SSA VCode producers use `Use` and `Def`. `UseDef` remains available to
/// standalone register-allocation clients that model in-place updates.
pub(all) enum OperandRole {
Use
Def
UseDef
} derive(Eq, Debug)
///|
pub extend OperandRole with Debug::{to_repr}
///|
pub extend OperandRole with Eq::{not_equal, equal}
///|
/// A normalized register-allocation constraint.
///
/// Operand ties are represented separately by a shared nonnegative tie label,
/// so this type contains only location constraints.
pub(all) enum AllocationConstraint {
AnyReg
AnyLocation
/// Keep this operand at a canonical home that survives the instruction's
/// clobbers without materializing a temporary. This is used for stack maps.
PreservedHome
FixedReg(PhysicalReg)
} derive(Eq, Debug)
///|
pub extend AllocationConstraint with Debug::{to_repr}
///|
pub extend AllocationConstraint with Eq::{not_equal, equal}
///|
/// A dense virtual-register identity within one allocation session.
#valtype
pub(all) struct VirtualReg {
id : Int
class : RegClass
} derive(Eq, Debug)
///|
pub extend VirtualReg with Debug::{to_repr}
///|
pub extend VirtualReg with Eq::{not_equal, equal}
///|
/// The canonical allocation facts for one instruction operand.
pub(all) struct AllocationOperand {
vreg : VirtualReg
role : OperandRole
constraint : AllocationConstraint
preference : PhysicalReg?
tie_id : Int
timing : OperandTiming
} derive(Eq, Debug)
///|
pub fn AllocationOperand::use_reg(vreg : VirtualReg) -> AllocationOperand {
{
vreg,
role: Use,
constraint: AnyReg,
preference: None,
tie_id: -1,
timing: Early,
}
}
///|
pub fn AllocationOperand::def(vreg : VirtualReg) -> AllocationOperand {
{
vreg,
role: Def,
constraint: AnyReg,
preference: None,
tie_id: -1,
timing: Late,
}
}
///|
pub fn AllocationOperand::with_constraint(
self : AllocationOperand,
constraint : AllocationConstraint,
) -> AllocationOperand {
{ ..self, constraint, }
}
///|
/// Prefer a physical register without making it a correctness constraint.
pub fn AllocationOperand::with_preference(
self : AllocationOperand,
preference : PhysicalReg,
) -> AllocationOperand {
{ ..self, preference: Some(preference), }
}
///|
/// Tie operands in one instruction by a shared nonnegative label.
pub fn AllocationOperand::with_tie(
self : AllocationOperand,
tie_id : Int,
) -> AllocationOperand {
{ ..self, tie_id, }
}
///|
pub fn AllocationOperand::with_timing(
self : AllocationOperand,
timing : OperandTiming,
) -> AllocationOperand {
{ ..self, timing, }
}
///|
pub extend AllocationOperand with Debug::{to_repr}
///|
pub extend AllocationOperand with Eq::{not_equal, equal}