Sign in

    vcode_regalloc

    Target VCode adapter for the reusable register allocator

    compiler
    register-allocation
    vcode
    jit
    Download zip
    Author
    Version
    0.17.1
    License
    Apache-2.0
    Last updated
    yesterday
    Downloads
    80

    #vcode_regalloc

    Target VCode adapter for the reusable register allocator.

    vcode_regalloc bridges Milky2018/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/vcode_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 exposes non-owning indexed CFG access and borrowed operand/clobber ArrayViews through FunctionView. The allocator writes homes, operand locations, stack slots, and resolved transfers directly through a statically dispatched AllocationSink; production does not create an AllocationPlan or translate a completed plan into VCode. Standalone allocator clients keep the AllocationPlan API, backed by the same algorithm and a plan sink. Only unresolved parallel edits remain allocator-owned temporary data.

    The adapter checks each write and requires complete output even when full verification is disabled. VCode owns final safepoint-root construction because those roots refer to its instruction metadata. Safe public entry points enable both the generic dataflow verifier and the independent VCode state verifier; strict mode additionally records generic resolved edits for the former. The Wasmoon JIT enables these checks with VCODE_REGALLOC_VALIDATION=1. Neither mode changes allocation policy or returned results.

    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 = @vcode_regalloc.allocate_vcode(
    function,
    @vcode_regalloc.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
    )

    VCodeAllocationError::output

    fn VCodeAllocationError::output(self : VCodeAllocationError, logger : &Logger) -> Unit

    VCodeAllocationError::to_string

    fn VCodeAllocationError::to_string(self : VCodeAllocationError) -> String

    AllocationSession

    pub struct AllocationSession {
    // private fields
    }

    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.

    AllocationSession::allocate_selected_vcode

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

    AllocationSession::new

    VCodeAllocationEnvironment

    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?, on_statistics? : (
    RegallocLoopStatistics
    ) -> Unit?, verify? : Bool) ->
    Allocation
    raise VCodeAllocationError

    Allocate one selected function with an ephemeral session.

    allocate_vcode

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io