Sign in

    wasm_milkir

    WebAssembly dialect adapter for MilkIR extension operations

    wasm
    webassembly
    milkir
    compiler
    dialect
    Download zip
    Author
    Version
    0.3.2
    License
    Apache-2.0
    Last updated
    3 months ago
    Downloads
    252

    #wasm_milkir

    WebAssembly dialect adapter for MilkIR extension operations.

    wasm_milkir provides the Wasm-specific opcode set, extension descriptors, and builder helpers used with MilkIR. Frontends encode Wasm operations through typed WasmOpcode constructors, then a lowering adapter checks and decodes those extensions before machine lowering.

    Typed Wasm builders only emit IR data; they do not attach validator closures to the MilkIR function. Generic MilkIR finalization checks the extension envelope and its explicit signature, while verify_function applies context-free schema contracts. Operations whose contracts depend on module or linker metadata must use an explicit WasmValidationContext and verify_function_with_context. Wasm lowering requires the same context and validates it immediately before instruction selection.

    Typed constructors, serialized opcode names, and immediate layouts are defined once in wasm_opcodes.schema. During development, dev_build runs the deterministic tools/generate_wasm_opcodes.py generator to refresh the committed dialect_generated.mbt source. Published packages include that generated MoonBit source, so downstream builds neither load the schema at runtime nor execute development build rules.

    #Packages

    • Milky2018/wasm_milkir: Wasm opcode encoding/decoding and builder helpers for Milky2018/milkir.

    #How it fits

    MilkIR represents common SSA operations directly. This package represents WebAssembly operations that need additional immediates or lowering semantics as typed MilkIR extensions. The extension descriptor lets a lowering pipeline validate the encoded operation before decoding it.

    Common arithmetic, calls, references, and SIMD operations use MilkIR's semantic opcode families directly. In particular, the Wasm frontend consumes SIMD memidx, alignment, and offset fields while constructing the effective address; the resulting MilkIR VectorOp carries only vector load/store semantics.

    Linear-memory base pointers use MilkIR GlobalValue declarations rather than a Wasm extension opcode. memory_base_context_field identifies the memory index, the declaration records Heap(memidx) provenance, and the frontend chooses Stable only when the embedding guarantees that the base cannot move during the function invocation. Contextual validation checks that the memory exists; wasm_machv resolves the opaque field through its embedding environment.

    #Example: map Wasm reference types to MilkIR

    ///|
    test "map Wasm reference spelling to generic MilkIR references" {
    inspect(wasm_funcref_type().to_string(), content="callable_ref")
    inspect(wasm_externref_type().to_string(), content="opaque_ref")
    }

    #Example: encode a Wasm memory operation

    ///|
    test "build a Wasm memory.size extension instruction" {
    let builder = @milkir.FunctionBuilder::FunctionBuilder("memory_size")
    let symbols = RuntimeSymbols::with_runtime_prefix("example.runtime")
    let vmctx = builder.add_param(I64)
    builder.add_result(I32)
    let size = memory_size(builder, symbols, vmctx, 0)
    builder.return_([size])
    let func = builder.get_function()
    inspect(func.blocks.length(), content="1")
    verify_function(func)
    match func.blocks[0].instructions[1].opcode {
    Call(Direct(symbol, _)) =>
    inspect(symbol.name, content="example.runtime.memory_size")
    _ => inspect(false, content="true")
    }
    }

    #Example: validate and decode a Wasm extension

    ///|
    test "validate and decode a typed Wasm extension operation" {
    let opcode = WasmOpcode::RefTest(3, true)
    let ext = encode(opcode)
    let desc = descriptor(opcode)
    inspect(ext.matches_descriptor(desc), content="true")
    inspect(decode(ext) == Some(opcode), content="true")
    let malformed = @milkir.ExtOp(
    "wasm",
    "ref_test",
    FixedArray::makei(2, fn(i) { if i == 0 { 3 } else { 2 } }),
    )
    debug_inspect(
    decode_error(malformed),
    content=(
    #|Some("malformed Wasm MilkIR extension 'ref_test': immediate 1 is a bool flag encoded as 0 or 1, got 2")
    ),
    )
    }

    RuntimeSymbols

    pub(all) struct RuntimeSymbols {
    memory_grow : String
    memory_size : String
    memory_fill : String
    memory_copy : String
    memory_init : String
    data_drop : String
    table_grow : String
    table_fill : String
    table_copy : String
    table_init : String
    elem_drop : String
    gc_ref_test : String
    gc_ref_cast : String
    gc_struct_get : String
    gc_struct_set : String
    gc_array_get : String
    gc_array_set : String
    gc_array_len : String
    gc_array_fill : String
    gc_array_copy : String
    gc_array_new_data : String
    gc_array_new_elem : String
    gc_array_init_data : String
    gc_array_init_elem : String
    gc_type_check_subtype : String
    gc_register_struct_inline : String
    gc_register_array_inline : String
    gc_alloc_struct_slow : String
    gc_alloc_array_from_values_slow : String
    gc_alloc_array_slow : String
    exception_try_begin : String
    exception_try_end : String
    exception_throw : String
    exception_throw_tag : String
    exception_throw_ref : String
    exception_delegate : String
    exception_get_tag : String
    exception_get_value : String
    exception_get_value_count : String
    exception_sigsetjmp : String
    exception_spill_locals : String
    exception_get_spilled_local : String
    } derive(Eq,
    Debug
    )

    RuntimeSymbols::with_runtime_prefix

    fn RuntimeSymbols::with_runtime_prefix(prefix : String) -> RuntimeSymbols

    WasmDefinedTypeContract

    pub(all) enum WasmDefinedTypeContract {
    Function(WasmFunctionContract)
    Struct(Array[WasmFieldContract])
    Array(WasmFieldContract)
    } derive(Eq,
    Debug
    )

    The contextual contract for a WebAssembly indexed type.

    WasmFieldContract

    pub(all) struct WasmFieldContract {
    storage : WasmStorageContract
    mutable_ : Bool
    defaultable : Bool
    } derive(Eq,
    Debug
    )

    The contextual contract for one WebAssembly struct field or array element.

    WasmFunctionContract

    pub(all) struct WasmFunctionContract {
    params : Array[
    Type
    ]
    results : Array[
    Type
    ]
    } derive(Eq,
    Debug
    )

    The lowered MilkIR carrier contract for a WebAssembly function type.

    WasmOpcode

    pub(all) enum WasmOpcode {
    WasmCall(Int)
    WasmCallIndirect(Int, Int)
    CallRef(Int)
    ReturnCall(Int)
    ReturnCallIndirect(Int, Int)
    ReturnCallRef(Int)
    GetFuncRef(Int)
    StructNew(Int)
    StructNewDefault(Int)
    StructGet(Int, Int)
    StructGetS(Int, Int, Int)
    StructGetU(Int, Int, Int)
    StructSet(Int, Int)
    ArrayNew(Int)
    ArrayNewDefault(Int)
    ArrayNewFixed(Int, Int)
    ArrayGet(Int)
    ArrayGetS(Int, Int)
    ArrayGetU(Int, Int)
    ArraySet(Int)
    ArrayLen
    ArrayFill(Int)
    ArrayCopy(Int, Int)
    ArrayNewData(Int, Int)
    ArrayNewElem(Int, Int)
    ArrayInitData(Int, Int)
    ArrayInitElem(Int, Int)
    I31New
    I31GetS
    I31GetU
    RefTest(Int, Bool)
    RefCast(Int, Bool)
    AnyConvertExtern
    ExternConvertAny
    RefEq
    Throw(Int)
    ThrowRef
    TryTableBegin(Int)
    TryTableEnd(Int)
    GetExceptionTag
    GetExceptionValue(Int)
    GetExceptionValueCount
    Delegate(Int)
    SpillLocalsForThrow(Int)
    GetSpilledLocal(Int)
    } derive(Eq, Hash,
    Debug
    )

    WasmStorageContract

    pub(all) enum WasmStorageContract {
    Value(
    Type
    )
    Packed8
    Packed16
    } derive(Eq,
    Debug
    )

    The lowered MilkIR carrier and packed representation of a WebAssembly field.

    WasmTableContract

    pub(all) struct WasmTableContract {
    index_type :
    Type

    element_type :
    Type

    } derive(Eq,
    Debug
    )

    The contextual contract for a WebAssembly table.

    WasmValidationContext

    type WasmValidationContext

    Module and linker metadata required to validate Wasm extension operations.

    The context is supplied explicitly at the Wasm adapter seam and is never stored in MilkIR. Linked direct functions use their remapped global index; indexed types, tables, tags, and segments use module-local indices.

    WasmValidationContext::empty

    Construct a context that rejects every module-indexed operation.

    This is useful for lowering functions that contain only context-free Wasm operations; it is not a fallback for module-produced MilkIR.

    WasmValidationContext::new

    Construct an explicit contextual-validation adapter.

    WasmValidationContext::validate_extension

    Validate one Wasm extension against module and linker metadata.

    WasmValidationContext::validate_global_value

    WasmValidationResolvers

    pub(all) struct WasmValidationResolvers {
    function_contract : (Int) -> WasmFunctionContract?
    defined_type_contract : (Int) -> WasmDefinedTypeContract?
    table_contract : (Int) -> WasmTableContract?
    tag_contract : (Int) -> WasmFunctionContract?
    memory_exists : (Int) -> Bool
    data_segment_exists : (Int) -> Bool
    element_segment_type : (Int) ->
    Type
    ?
    }

    Resolver interface used to construct a contextual-validation adapter.

    EXTERNREF_TAG

    let EXTERNREF_TAG : Int64

    Tag for externref values: bit 62 set.

    FUNCREF_TAG

    let FUNCREF_TAG : Int64

    Tag for funcref pointer values: bit 61 set.

    NULL_REF

    let NULL_REF : Int64

    Null reference value in the lowered reference representation.

    WASM_DIALECT

    let WASM_DIALECT : String

    Serialized dialect name used by Wasm MilkIR extension operations.

    array_copy

    fn array_copy(builder :
    FunctionBuilder
    , dst_type_idx : Int, src_type_idx : Int, dst :
    Value
    , dst_offset :
    Value
    , src :
    Value
    , src_offset :
    Value
    , count :
    Value
    ) -> Unit

    array_get_s

    fn array_get_s(builder :
    FunctionBuilder
    , type_idx : Int, array_ref :
    Value
    , index :
    Value
    , byte_width : Int) ->
    Value

    array_get_u

    fn array_get_u(builder :
    FunctionBuilder
    , type_idx : Int, array_ref :
    Value
    , index :
    Value
    , byte_width : Int) ->
    Value

    array_init_data

    fn array_init_data(builder :
    FunctionBuilder
    , type_idx : Int, data_idx : Int, array_ref :
    Value
    , arr_offset :
    Value
    , data_offset :
    Value
    , length :
    Value
    ) -> Unit

    array_init_elem

    fn array_init_elem(builder :
    FunctionBuilder
    , type_idx : Int, elem_idx : Int, array_ref :
    Value
    , arr_offset :
    Value
    , elem_offset :
    Value
    , length :
    Value
    ) -> Unit

    array_new_data

    fn array_new_data(builder :
    FunctionBuilder
    , type_idx : Int, data_idx : Int, data_offset :
    Value
    , length :
    Value
    ) ->
    Value

    array_new_default

    array_new_elem

    fn array_new_elem(builder :
    FunctionBuilder
    , type_idx : Int, elem_idx : Int, elem_offset :
    Value
    , length :
    Value
    ) ->
    Value

    array_new_fixed

    fn array_new_fixed(builder :
    FunctionBuilder
    , type_idx : Int, count : Int, elements : Array[
    Value
    ]) ->
    Value

    array_set

    call_indirect_multi

    data_drop

    fn data_drop(builder :
    FunctionBuilder
    , runtime_symbols : RuntimeSymbols, vmctx :
    Value
    , data_idx : Int) -> Unit

    decode_error

    fn decode_error(ext :
    ExtOp
    ) -> String?

    decode_memory_base_context_field

    fn decode_memory_base_context_field(field :
    ContextField
    ) -> Int?

    decode_opcode

    fn decode_opcode(opcode :
    Opcode
    ) -> WasmOpcode?

    delegate

    fn delegate(builder :
    FunctionBuilder
    , depth : Int) -> Unit

    descriptor_by_name

    fn descriptor_by_name(name : String) ->
    ExtOpDescriptor
    ?

    elem_drop

    fn elem_drop(builder :
    FunctionBuilder
    , runtime_symbols : RuntimeSymbols, vmctx :
    Value
    , elem_idx : Int) -> Unit

    emit_throw

    fn emit_throw(builder :
    FunctionBuilder
    , tag_idx : Int, values : Array[
    Value
    ]) -> Unit

    emit_throw_ref

    encode

    get_exception_value

    get_exception_value_count

    get_func_ref

    get_spilled_local

    memory_base_context_field

    fn memory_base_context_field(memory_index : Int) ->
    ContextField

    memory_copy

    fn memory_copy(builder :
    FunctionBuilder
    , runtime_symbols : RuntimeSymbols, vmctx :
    Value
    , dst_memidx : Int, src_memidx : Int, dst :
    Value
    , src :
    Value
    , size :
    Value
    ) -> Unit

    memory_grow

    fn memory_grow(builder :
    FunctionBuilder
    , runtime_symbols : RuntimeSymbols, vmctx :
    Value
    , memidx : Int, delta :
    Value
    , max_pages? : Int, is_memory64? : Bool) ->
    Value

    memory_init

    fn memory_init(builder :
    FunctionBuilder
    , runtime_symbols : RuntimeSymbols, vmctx :
    Value
    , memidx : Int, data_idx : Int, dst :
    Value
    , src :
    Value
    , size :
    Value
    ) -> Unit

    memory_size

    fn memory_size(builder :
    FunctionBuilder
    , runtime_symbols : RuntimeSymbols, vmctx :
    Value
    , memidx : Int, is_memory64? : Bool) ->
    Value

    ref_cast

    fn ref_cast(builder :
    FunctionBuilder
    , type_idx : Int, nullable : Bool, ref_val :
    Value
    , result_type :
    Type
    ) ->
    Value

    ref_test

    fn ref_test(builder :
    FunctionBuilder
    , type_idx : Int, nullable : Bool, ref_val :
    Value
    ) ->
    Value

    return_call_indirect_multi

    fn return_call_indirect_multi(builder :
    FunctionBuilder
    , type_idx : Int, table_idx : Int, callee :
    Value
    , args : Array[
    Value
    ]) -> Unit

    return_call_multi

    fn return_call_multi(builder :
    FunctionBuilder
    , func_idx : Int, args : Array[
    Value
    ]) -> Unit

    return_call_ref_multi

    fn return_call_ref_multi(builder :
    FunctionBuilder
    , type_idx : Int, func_ref :
    Value
    , args : Array[
    Value
    ]) -> Unit

    spill_locals_for_throw

    fn spill_locals_for_throw(builder :
    FunctionBuilder
    , locals : Array[
    Value
    ]) -> Unit

    struct_get

    fn struct_get(builder :
    FunctionBuilder
    , type_idx : Int, field_idx : Int, struct_ref :
    Value
    , field_type :
    Type
    ) ->
    Value

    struct_get_s

    fn struct_get_s(builder :
    FunctionBuilder
    , type_idx : Int, field_idx : Int, struct_ref :
    Value
    , byte_width : Int) ->
    Value

    struct_get_u

    fn struct_get_u(builder :
    FunctionBuilder
    , type_idx : Int, field_idx : Int, struct_ref :
    Value
    , byte_width : Int) ->
    Value

    struct_new_default

    fn struct_new_default(builder :
    FunctionBuilder
    , type_idx : Int) ->
    Value

    struct_set

    fn struct_set(builder :
    FunctionBuilder
    , type_idx : Int, field_idx : Int, struct_ref :
    Value
    , value :
    Value
    ) -> Unit

    table_copy

    fn table_copy(builder :
    FunctionBuilder
    , runtime_symbols : RuntimeSymbols, vmctx :
    Value
    , dst_table_idx : Int, src_table_idx : Int, dst :
    Value
    , src :
    Value
    , size :
    Value
    ) -> Unit

    table_grow

    fn table_grow(builder :
    FunctionBuilder
    , runtime_symbols : RuntimeSymbols, vmctx :
    Value
    , table_idx : Int, delta :
    Value
    , init_value :
    Value
    , is_table64? : Bool) ->
    Value

    table_init

    fn table_init(builder :
    FunctionBuilder
    , runtime_symbols : RuntimeSymbols, vmctx :
    Value
    , table_idx : Int, elem_idx : Int, dst :
    Value
    , src :
    Value
    , size :
    Value
    ) -> Unit

    try_table_begin

    fn try_table_begin(builder :
    FunctionBuilder
    , handler_id : Int) ->
    Value

    try_table_end

    fn try_table_end(builder :
    FunctionBuilder
    , handler_id : Int) -> Unit

    validate_extension

    fn validate_extension(view :
    ExtensionInstView
    ) -> String?

    Validate one read-only Wasm extension instruction at an adapter seam.

    validate_global_value

    fn validate_global_value(data :
    GlobalValueData
    ) -> String?

    verify_function

    Verify core MilkIR invariants and every extension against the Wasm schema.

    verify_function_with_context

    fn verify_function_with_context(func :
    Function
    , context : WasmValidationContext) -> Unit raise
    VerifyError

    Verify core MilkIR, local Wasm schema, and module-contextual contracts.

    wasm_externref_type

    fn wasm_externref_type() ->
    Type

    wasm_funcref_type

    fn wasm_funcref_type() ->
    Type

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io