///|
fn[F : FunctionView] collect_function_clobber_points(
function : F,
) -> Map[(Int, Int), Array[ProgramPoint]] {
let points_by_reg : Map[(Int, Int), Array[ProgramPoint]] = Map([])
fn record(
points_by_reg : Map[(Int, Int), Array[ProgramPoint]],
reg : PhysicalReg,
point : ProgramPoint,
) -> Unit {
let key = physical_reg_key(reg)
match points_by_reg.get(key) {
Some(points) => points.push(point)
None => points_by_reg[key] = [point]
}
}
for block in 0.. PhysicalReg? {
for reg in environment.operand_scratch_regs {
if reg.class == class && !used.contains(reg) {
return Some(reg)
}
}
None
}
///|
fn add_use_transfer(
plan : AllocationPlan,
instruction : Int,
operand : Operand,
home : Location,
selected : Location,
) -> Unit {
if home == selected || operand.constraint == AnyLocation {
return
}
plan.add_edit({
value: operand.vreg,
from: home,
to: selected,
position: Before(instruction),
})
}
///|
fn[F : FunctionView] assign_edge_transfers(
plan : AllocationPlan,
function : F,
) -> Unit raise VerifyError {
for block_index in 0..= parameters.length() {
break
}
let parameter = parameters[argument_index]
guard plan.value_location(argument.id) is Some(from) else {
raise Unassigned(vreg=argument)
}
guard plan.value_location(parameter.id) is Some(to) else {
raise Unassigned(vreg=parameter)
}
if from != to {
plan.add_edit({
value: argument,
from,
to,
position: Edge(
source_block=function.block_id_at(block_index),
successor_index~,
),
})
}
}
}
}
}
///|
fn[F : FunctionView] verify_operand_preferences(
function : F,
environment : MachineEnv,
) -> Unit raise VerifyError {
for block in 0.. AllocationPlan raise VerifyError {
verify_operand_preferences(function, environment)
let plan = allocate_bundle_plan(function, environment, config.strategy())
resolve_instruction_edits(plan, environment)
if config.verify() {
verify_function_allocation(function, environment, plan)
}
plan
}