///|
/// Final VCode output; only strict verification records generic edits.
priv struct VCodeAllocationSink[Inst] {
builder : @vcode.AllocationBuilder[Inst]
view : VCodeFunctionView[Inst]
validation_edits : Array[@regalloc.AllocationEdit]?
mut rejected : Bool
}
///|
impl[Inst] @regalloc.AllocationSink for VCodeAllocationSink[Inst] with fn assign_value(
self,
value,
location,
) {
if !self.builder.assign_value(value.id, location) {
self.rejected = true
}
}
///|
impl[Inst] @regalloc.AllocationSink for VCodeAllocationSink[Inst] with fn assign_operand(
self,
instruction,
operand,
location,
) {
if !self.builder.assign_operand(instruction, operand, location) {
self.rejected = true
}
}
///|
impl[Inst] @regalloc.AllocationSink for VCodeAllocationSink[Inst] with fn create_spill_slot(
self,
owner,
size,
alignment,
) {
if owner < 0 || owner >= @regalloc.FunctionView::value_count(self.view) {
self.rejected = true
return -1
}
let minimum = @regalloc.FunctionView::value_spill_size(self.view, owner)
if size < minimum || alignment < minimum || (alignment & (alignment - 1)) != 0 {
self.rejected = true
return -1
}
self.builder.create_stack_slot(owner, size, alignment)
}
///|
impl[Inst] @regalloc.AllocationSink for VCodeAllocationSink[Inst] with fn value_location(
self,
value,
) {
self.builder.value_location(value)
}
///|
impl[Inst] @regalloc.AllocationSink for VCodeAllocationSink[Inst] with fn operand_location(
self,
instruction,
operand,
) {
self.builder.finish().allocated_operand_location_at(instruction, operand)
}
///|
impl[Inst] @regalloc.AllocationSink for VCodeAllocationSink[Inst] with fn spill_slot(
self,
index,
) {
let allocation = self.builder.finish()
allocation
.stack_slot_at(index)
.map(slot => {
@regalloc.SpillSlotSpec::new(
allocation.stack_slot_size(slot).unwrap(),
allocation.stack_slot_alignment(slot).unwrap(),
)
})
}
///|
impl[Inst] @regalloc.AllocationSink for VCodeAllocationSink[Inst] with fn add_edit(
self,
edit,
) {
if self.validation_edits is Some(edits) {
edits.push(edit)
}
let accepted = match edit.position {
Before(instruction) =>
self.builder.add_transfer(
instruction,
Before,
edit.value.id,
edit.from,
edit.to,
)
After(instruction) =>
self.builder.add_transfer(
instruction,
After,
edit.value.id,
edit.from,
edit.to,
)
Edge(source_block~, successor_index~) =>
self.builder.add_edge_transfer(
source_block,
successor_index,
edit.value.id,
edit.from,
edit.to,
)
}
if !accepted {
self.rejected = true
}
}
///|
impl[Inst] @regalloc.AllocationSink for VCodeAllocationSink[Inst] with fn edits(
self,
) {
match self.validation_edits {
Some(edits) => edits.copy()
None => []
}
}