Sign in

    machv

    Reusable virtual-register machine IR

    compiler
    machine-ir
    codegen
    jit
    Download zip
    Author
    Version
    0.2.1
    License
    Apache-2.0
    Last updated
    3 months ago
    Downloads
    296

    #machv

    Reusable virtual-register machine IR.

    machv models low-level machine code before final register allocation and emission. It provides virtual registers, physical-register descriptions, machine instructions, blocks, ABI data, target ISA descriptors, printing, and machine-function helpers.

    #Packages

    • Milky2018/machv: root facade for machine functions and common helpers.
    • Milky2018/machv/abi: ABI locations, registers, calling-convention data, and runtime-context layout abstractions.
    • Milky2018/machv/instr: virtual machine instruction and terminator model.
    • Milky2018/machv/block: basic-block representation.
    • Milky2018/machv/isa: generic ISA descriptions and target selection.
    • Milky2018/machv/isa/aarch64, Milky2018/machv/isa/amd64: target-specific register descriptions.

    #When to use it

    Use MachV after instruction selection, but before final physical register allocation and encoding. It is the place to model virtual registers, machine instructions, ABI locations, block successors, call metadata, and terminators.

    #Example: build a virtual-register function

    FunctionBuilder is the public construction API. Passes can read the finished Function directly, while mutation stays behind the builder or internal transformation helpers.

    ///|
    test "build a virtual-register copy" {
    let builder = FunctionBuilder::FunctionBuilder("copy")
    let src = builder.add_param(Int)
    let dst = builder.new_vreg(Int)
    builder.append(Move, uses=[Virtual(src)], defs=[{ reg: Virtual(dst) }])
    |> ignore
    builder.terminate(Return([Virtual(dst)]))
    let func = builder.finish()
    inspect(func.blocks.length(), content="1")
    inspect(func.blocks[0].insts.length(), content="1")
    inspect(func.blocks[0].terminator is Some(Return(_)), content="true")
    }

    #Example: build control flow

    Blocks are created through the builder and terminated explicitly.

    ///|
    test "build a branch" {
    let builder = FunctionBuilder::FunctionBuilder("branch")
    let cond = builder.add_param(Int)
    let then_block = builder.create_block()
    let else_block = builder.create_block()
    builder.terminate(Branch(Virtual(cond), then_block, else_block))
    builder.switch_to_block(then_block)
    builder.terminate(Return([]))
    builder.switch_to_block(else_block)
    builder.terminate(Return([]))
    let func = builder.finish()
    inspect(func.blocks.length(), content="3")
    inspect(func.blocks[0].terminator is Some(Branch(_, _, _)), content="true")
    }

    #Boundary

    machv should remain independent from Wasmoon. Product-specific runtime symbols, WASI, embedding context fields, and native FFI glue belong in embedding modules such as wasmoon_jit.

    Block

    MachV block - a basic block in MachV

    CallClobberClass

    Call-site clobber class for register allocation and optimization barriers.

    CallType

    Call type - classifies instructions that behave like calls CallType enum for different call variants

    CmpKind

    Comparison kind for integer comparisons

    CodeSymbol

    Symbolic name for code owned by the embedding.

    MachV treats this as an opaque relocation key. Frontends may use the scope and ordinal to map their own function identifiers to this generic code target without exposing those identifiers in MachV opcodes.

    Cond

    AArch64 condition codes (for conditional branches and traps) Condition codes for comparisons

    ExtendKind

    Extend kind - how to extend a value

    ExternalName

    Symbolic name for a runtime or external helper address.

    MachV treats this as an opaque relocation key. Embedding packages own the mapping from names to native addresses.

    FCmpKind

    Comparison kind for float comparisons

    FloatToIntKind

    Float to Int conversion kind Encodes: source float type, destination int type, signedness

    IndexExtend

    AArch64 addressing-mode extend for register-offset loads/stores.

    Mirrors Cranelift's AMode.{RegExtended,RegScaledExtended} options:
    • None: use X register offset (LSL option)
    • Uxtw/Sxtw: extend Wm to X, optionally scaled by access size (S bit)

    Inst

    MachV instruction - a machine-level instruction with virtual registers Operand constraints for fixed register allocation

    IntToFloatKind

    Int to Float conversion kind Encodes: source int type, destination float type, signedness

    LaneSize

    SIMD lane size for vector operations

    MemType

    Memory type for load/store

    Opcode

    MachV opcode - machine-level operation (target-independent subset)

    OperandConstraint

    Operand constraint for register allocation Fixed register constraint handling

    PReg

    using @Milky2018/machv/abi { type PReg }

    Physical register - a real machine register

    Reg

    using @Milky2018/machv/abi { type Reg }

    A register reference - either virtual or physical

    RegClass

    Register class - categorizes registers by their purpose

    RelocTarget

    Target for a relocatable code address or direct call.

    SIMDCmpKind

    SIMD comparison kind for integer vector comparisons

    SIMDFCmpKind

    SIMD floating-point comparison kind

    ShiftType

    Shift type for shifted operand instructions

    Terminator

    MachV terminator - how a block ends

    VReg

    using @Milky2018/machv/abi { type VReg }

    Virtual register - an abstract register before register allocation

    Writable

    A writable register reference (for instruction destinations)

    Function

    pub struct Function {
    name : String
    params : Array[
    VReg
    ]
    results : Array[
    RegClass
    ]
    result_kinds : Array[ValueKind]
    blocks : Array[
    Block
    ]
    next_vreg_id : Int
    num_spill_slots : Int
    param_pregs : Array[
    PReg
    ?]
    int_stack_params : Int
    max_outgoing_args_size : Int
    uses_context_cache_0_source : Bool
    }

    MachV function - a complete machine-level function in virtual-register form.
    impl Show for Function

    Function::Function

    fn Function::Function(name : String) -> Function

    Function::add_param_preg

    fn Function::add_param_preg(self : Function, preg :
    PReg
    ?) -> Unit

    Add a parameter physical register mapping (called by register allocator)

    Function::add_result

    fn Function::add_result(self : Function, class :
    RegClass
    ) -> Unit

    Function::add_result_kind

    fn Function::add_result_kind(self : Function, ty : ValueKind) -> Unit

    Add a result kind with full kind information for multi-value returns

    Function::blocks

    Function::calls_multi_value_function_for_call_conv

    fn Function::calls_multi_value_function_for_call_conv(self : Function, call_conv :
    CallConventionLayout
    ) -> Bool

    Check whether this function calls anything whose result count exceeds the selected call convention's register-result capacity.

    Function::clone_base

    fn Function::clone_base(self : Function) -> Function

    Clone the base structure of a function for regalloc transformations. Copies: name, next_vreg_id, int_stack_params, max_outgoing_args_size, uses_context_cache_0_source Empty: params, results, result_kinds, blocks, param_pregs Zero: num_spill_slots

    Function::get_blocks

    Function::get_max_outgoing_args_size

    fn Function::get_max_outgoing_args_size(self : Function) -> Int

    Function::get_name

    fn Function::get_name(self : Function) -> String

    Function::get_num_spill_slots

    fn Function::get_num_spill_slots(self : Function) -> Int

    Function::get_param_pregs

    fn Function::get_param_pregs(self : Function) -> Array[
    PReg
    ?]

    Function::get_params

    Function::get_result_kinds

    fn Function::get_result_kinds(self : Function) -> Array[ValueKind]

    Function::has_calls

    fn Function::has_calls(self : Function) -> Bool

    Returns true if this function contains any call-like instruction.

    Function::mark_uses_context_cache_0_source

    fn Function::mark_uses_context_cache_0_source(self : Function) -> Unit

    Function::needs_extra_results_ptr_for_call_conv

    fn Function::needs_extra_results_ptr_for_call_conv(self : Function, call_conv :
    CallConventionLayout
    ) -> Bool

    Check if this function needs an embedding-provided extra-results pointer.

    Function::new_block

    Function::params

    Function::print

    fn Function::print(self : Function) -> String

    Function::push_param

    fn Function::push_param(self : Function, vreg :
    VReg
    ) -> Unit

    Push a parameter vreg directly (used during regalloc reconstruction)

    Function::set_int_stack_params

    fn Function::set_int_stack_params(self : Function, n : Int) -> Unit

    Set the number of integer stack parameters (called during lowering)

    Function::set_num_spill_slots

    fn Function::set_num_spill_slots(self : Function, n : Int) -> Unit

    Set the number of spill slots (called by register allocator)

    Function::should_reserve_context_cache_0

    fn Function::should_reserve_context_cache_0(self : Function) -> Bool

    Returns true if context cache 0 caching should be enabled for this function.

    Function::should_reserve_context_cache_1

    fn Function::should_reserve_context_cache_1(self : Function) -> Bool

    Returns true if context cache 1 pointer caching should be enabled for this function.

    Function::update_max_outgoing_args_size

    fn Function::update_max_outgoing_args_size(self : Function, size : Int) -> Unit

    Update max outgoing args size if the new size is larger (called during lowering)

    Function::uses_context_cache_0_source

    fn Function::uses_context_cache_0_source(self : Function) -> Bool

    Function::uses_context_cache_1

    fn Function::uses_context_cache_1(self : Function) -> Bool

    Returns true if the function loads the module context cache 1 from embedding context. Used to reserve a dedicated register for caching the context cache 1 pointer.

    FunctionBuilder

    pub struct FunctionBuilder {
    func : Function
    current_block :
    Block

    }

    FunctionBuilder::FunctionBuilder

    fn FunctionBuilder::FunctionBuilder(name : String) -> FunctionBuilder

    FunctionBuilder::add_result

    fn FunctionBuilder::add_result(self : FunctionBuilder, kind : ValueKind) -> Unit

    FunctionBuilder::create_block

    fn FunctionBuilder::create_block(self : FunctionBuilder) -> Int

    FunctionBuilder::finish

    FunctionBuilder::switch_to_block

    fn FunctionBuilder::switch_to_block(self : FunctionBuilder, block_id : Int) -> Unit

    FunctionBuilder::terminate

    ValueKind

    pub(all) enum ValueKind {
    I32
    I64
    F32
    F64
    V128
    Ptr
    } derive(Eq,
    Debug
    )

    Machine-level value kind needed after MilkIR lowering.

    Keep this in MachV instead of carrying @milkir.Type through register allocation and emission.

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io