///|
priv struct VCodeFunctionView[Inst] {
function : @vcode.Function[Inst]
layout : Array[@vcode.Block]
value_classes : Array[@regalloc.RegClass]
value_sizes : Array[Int]
entry : Array[@regalloc.VirtualReg]
parameters : Array[Array[@regalloc.VirtualReg]]
instructions : Array[Array[Int]]
successors : Array[Array[Int]]
edge_args : Array[Array[Array[@regalloc.VirtualReg]]]
operands : Array[Array[@regalloc.Operand]]
clobbers : Array[Array[@regalloc.PhysicalReg]]
}
///|
fn[Inst] VCodeFunctionView::new(
function : @vcode.Function[Inst],
) -> VCodeFunctionView[Inst] {
let layout = function.layout()
let block_to_layout = Array::make(function.block_count(), -1)
for layout_index, block in layout {
block_to_layout[function.block_index(block).unwrap()] = layout_index
}
let value_classes : Array[@regalloc.RegClass] = []
let value_sizes : Array[Int] = []
for value_index in 0.. {
to_regalloc_vreg(function, function.parameter_at(index).unwrap())
})
let parameters : Array[Array[@regalloc.VirtualReg]] = []
let instructions : Array[Array[Int]] = []
let successors : Array[Array[Int]] = []
let edge_args : Array[Array[Array[@regalloc.VirtualReg]]] = []
for block in layout {
parameters.push(
function
.block_parameters(block)
.map(value => to_regalloc_vreg(function, value)),
)
let block_instructions = function.block_body(block)
let terminator = function.block_terminator(block).unwrap()
block_instructions.push(terminator)
instructions.push(
block_instructions.map(instruction => {
function.instruction_index(instruction).unwrap()
}),
)
let block_successors : Array[Int] = []
let block_edge_args : Array[Array[@regalloc.VirtualReg]] = []
for edge in function.instruction_successors(terminator) {
block_successors.push(
block_to_layout[function.block_index(edge.target).unwrap()],
)
block_edge_args.push(
edge.arguments.map(value => to_regalloc_vreg(function, value)),
)
}
successors.push(block_successors)
edge_args.push(block_edge_args)
}
let operands : Array[Array[@regalloc.Operand]] = []
let clobbers : Array[Array[@regalloc.PhysicalReg]] = []
for instruction_index in 0.. to_regalloc_operand(function, operand)),
)
clobbers.push(
function
.instruction_clobbers(instruction)
.map(reg => to_regalloc_preg(reg)),
)
}
{
function,
layout,
value_classes,
value_sizes,
entry,
parameters,
instructions,
successors,
edge_args,
operands,
clobbers,
}
}
///|
fn regalloc_value_size(ty : @semantic.ValueType) -> Int {
match ty {
I32 | F32 => 4
I64 | F64 | Ptr64 | GcRef64 => 8
V128 => 16
}
}
///|
fn to_regalloc_operand_role(role : @vcode.OperandRole) -> @regalloc.OperandRole {
match role {
Use => Use
Def => Def
}
}
///|
fn to_regalloc_operand_timing(
timing : @vcode.OperandTiming,
) -> @regalloc.OperandTiming {
match timing {
Early => Early
Late => Late
}
}
///|
fn to_regalloc_operand_constraint(
constraint : @vcode.OperandConstraint,
) -> @regalloc.OperandConstraint {
match constraint {
Any => AnyReg
AnyLocation => AnyLocation
Fixed(reg) => FixedReg(to_regalloc_preg(reg))
TiedTo(_) => AnyReg
}
}
///|
fn[Inst] to_regalloc_operand(
function : @vcode.Function[Inst],
operand : @vcode.Operand,
) -> @regalloc.Operand {
{
vreg: to_regalloc_vreg(function, operand.value),
role: to_regalloc_operand_role(operand.role),
constraint: to_regalloc_operand_constraint(operand.constraint),
preference: operand.preference.map(to_regalloc_preg),
tie_id: operand.tie_id,
timing: to_regalloc_operand_timing(operand.timing),
}
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn value_count(
self,
) -> Int {
self.function.value_count()
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn value_class(
self,
value,
) -> @regalloc.RegClass {
self.value_classes[value]
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn value_spill_size(
self,
value,
) -> Int {
self.value_sizes[value]
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn value_spill_alignment(
self,
value,
) -> Int {
self.value_sizes[value]
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn values_share_spill_slot(
self,
lhs,
rhs,
) -> Bool {
self.function.value_type(self.function.value_at(lhs).unwrap()) ==
self.function.value_type(self.function.value_at(rhs).unwrap())
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn entry_values(
self,
) -> Array[@regalloc.VirtualReg] {
self.entry
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn block_count(
self,
) -> Int {
self.layout.length()
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn block_id_at(
self,
index,
) -> Int {
self.function.block_index(self.layout[index]).unwrap()
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn block_parameters(
self,
block,
) -> Array[@regalloc.VirtualReg] {
self.parameters[block]
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn block_instructions(
self,
block,
) -> Array[Int] {
self.instructions[block]
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn block_successors(
self,
block,
) -> Array[Int] {
self.successors[block]
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn edge_arguments(
self,
block,
successor,
) -> Array[@regalloc.VirtualReg] {
self.edge_args[block][successor]
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn instruction_operands(
self,
instruction,
) -> Array[@regalloc.Operand] {
self.operands[instruction]
}
///|
impl[Inst] @regalloc.FunctionView for VCodeFunctionView[Inst] with fn instruction_clobbers(
self,
instruction,
) -> Array[@regalloc.PhysicalReg] {
self.clobbers[instruction]
}