machv_regalloc

Target VCode adapter for the reusable register allocator

compiler
register-allocation
machv
jit
moon add Milky2018/machv_regalloc@0.6.2
Download zip
Author
Version
0.6.2
License
Apache-2.0
Last updated
2 days ago
Downloads
105
README

#machv_regalloc

Target VCode adapter for the reusable register allocator.

machv_regalloc bridges Milky2018/machv/vcode functions to the target-independent Milky2018/regalloc algorithm. The adapter reads compact operand and clobber side tables without inspecting target instructions. It returns a separate Allocation containing value locations, operand locations, spill and reload edits, edge moves, stack slots, and safepoint root locations.

#Packages

  • Milky2018/machv_regalloc: read-only Target VCode adapter, allocation entry points, validation, spill handling, and output construction.

#When to use it

Use allocate_vcode after target instruction selection. Callers provide an explicit set of allocatable registers and spill scratch registers. The result is verified against fixed and tied operands, clobbers, stack slots, insertion edits, edge moves, and safepoint roots before it is returned.

The production adapter reads Target VCode directly through FunctionView; it does not build a second instruction or CFG graph. The aggregate target pipeline first verifies selected VCode, runs the root bundle-aware allocator, materializes its AllocationPlan into VCode Allocation side tables, and then runs the independent VCode allocation verifier. Production enables both the reusable plan verifier and the materialized VCode state verifier; the latter follows resident values through edits, clobbers, and CFG joins. There is no second backtracking policy package and no alternate allocation strategy.

Ordinary Input::any operands require a register at the instruction. A target operation that can consume a register or spill slot directly uses Input::any_location; its emitter then reads the allocated Location without forcing every such input through a simultaneous scratch-register reload. Input::with_preference may additionally request a same-class allocatable register without turning that request into a hard constraint. Production call lowering uses this for ABI argument registers, while the post-allocation call transfer planner remains responsible for the actual register and stack shuffle. ABI pseudos that materialize an implicit incoming register or stack value use Output::any_location, so the result is written directly to its stable home. Output::with_preference keeps the move-free incoming-register case cheap when that register is allocatable, without pinning the value's full live range.

#Example

The instruction payload stays opaque to the allocator. In this small example Unit stands in for a target-owned instruction type.

///|
test "allocate Target VCode" {
let builder : @vcode.Builder[Unit] = @vcode.Builder::new("copy", [I64])
let entry = builder.entry_block()
let source = builder.parameter(0)
let (_, result) = builder.append_body(
entry,
(),
[@vcode.Input::any(source)],
[@vcode.Output::any(I64)],
[],
@vcode.InstructionMetadata::empty(),
)
builder.set_terminator(
entry,
(),
[@vcode.Input::any(result[0])],
[],
[],
@vcode.InstructionMetadata::empty(),
)
|> ignore
let function = builder.finish()
let allocation = allocate_vcode(
function,
VCodeAllocationEnvironment::new([@vcode.PhysicalReg::new(0, Int)], [
@vcode.PhysicalReg::new(1, Int),
]),
)
inspect(allocation.source_instruction_count(), content="2")
}

#Integration

Each target emitter consumes its unchanged Function[TargetInst] together with the returned Allocation and a verified frame layout. Physical-register lookups and insertion edits are constant-time or linear side-table queries; the adapter never introduces runtime dispatch over target instructions.

#
VCodeAllocationError

pub suberror VCodeAllocationError {
InvalidSelected(cause~ :
VCodeVerifyError
)
RegallocFailure(cause~ :
VerifyError
)
AllocationConstructionRejected
InvalidAllocation(cause~ :
AllocationVerifyError
)
} derive(
Debug
)

#
VCodeAllocationEnvironment

pub struct VCodeAllocationEnvironment {
allocatable_regs : Array[
PhysicalReg
]
spill_scratch_regs : Array[
PhysicalReg
]
fixed_operand_regs : Array[
PhysicalReg
]
}

#
VCodeAllocationEnvironment::with_fixed_operand_regs

Declare reserved registers that selected VCode may name only through fixed operand constraints.

#
allocate_selected_vcode

fn[Inst] allocate_selected_vcode(function :
Function
[Inst], environment : VCodeAllocationEnvironment, on_phase? : (String?) -> Unit?, verify? : Bool) ->
Allocation
raise VCodeAllocationError

Allocates VCode that has already passed @vcode.verify_selected.

The caller must not mutate function between validation and this call. Prefer allocate_vcode unless validation is owned by an aggregate compile pipeline.

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io