Skip to content

wasm #

Description

The wasm module is a pure V implementation of the WebAssembly bytecode module format, available in the form of a builder.

It allows users to generate WebAssembly modules in memory.

With the V wasm module, users can create functions, opcodes, and utilize the entire wasm specification without the need for a large dependency like binaryen. All of this functionality is available within V itself, making the module a valuable resource for V developers seeking to build high-performance web applications.

The module is designed to generate a []u8, which can be written to a .wasm file or executed in memory.

Examples are present in examples/wasm_codegen.

import wasm
import os

fn main() {
    mut m := wasm.Module{}
    mut func := m.new_function('add', [.i32_t, .i32_t], [.i32_t])
    {
        func.local_get(0) // | local.get 0
        func.local_get(1) // | local.get 1
        func.add(.i32_t) // | i32.add
    }
    m.commit(func, true) // `export: true`

    mod := m.compile() // []u8

    os.write_file_array('add.wasm', mod)!
}

This module does not perform verification of the WebAssembly output. Use a tool like wasm-validate to validate, and wasm-dis to show a decompiled form.

fn constexpr_ref_null #

fn constexpr_ref_null(rt RefType) ConstExpression

constexpr_ref_null returns a constant expression that evaluates to a null reference.

fn constexpr_value #

fn constexpr_value[T](v T) ConstExpression

constexpr_value returns a constant expression that evaluates to a single value.

fn constexpr_value_zero #

fn constexpr_value_zero(v ValType) ConstExpression

constexpr_value_zero returns a constant expression that evaluates to zero.

type DataSegmentIndex #

type DataSegmentIndex = int

type GlobalImportIndex #

type GlobalImportIndex = int

type GlobalIndex #

type GlobalIndex = int

type LabelIndex #

type LabelIndex = int

type LocalIndex #

type LocalIndex = int

type PatchPos #

type PatchPos = int

enum NumType #

enum NumType as u8 {
	i32_t = 0x7f
	i64_t = 0x7e
	f32_t = 0x7d
	f64_t = 0x7c
}

enum RefType #

enum RefType as u8 {
	funcref_t   = 0x70
	externref_t = 0x6f
}

enum ValType #

enum ValType as u8 {
	i32_t       = 0x7f
	i64_t       = 0x7e
	f32_t       = 0x7d
	f64_t       = 0x7c
	v128_t      = 0x7b
	funcref_t   = 0x70
	externref_t = 0x6f
}

struct ConstExpression #

struct ConstExpression {
mut:
	call_patches []CallPatch
	code         []u8
}

WebAssembly constant expressions are permitted to use a subset of valid instructions.

fn (ConstExpression) i32_const #

fn (mut expr ConstExpression) i32_const(v i32)

i32_const places a constant i32 value on the stack. WebAssembly instruction: i32.const.

fn (ConstExpression) i64_const #

fn (mut expr ConstExpression) i64_const(v i64)

i64_const places a constant i64 value on the stack. WebAssembly instruction: i64.const.

fn (ConstExpression) f32_const #

fn (mut expr ConstExpression) f32_const(v f32)

f32_const places a constant f32 value on the stack. WebAssembly instruction: f32.const.

fn (ConstExpression) f64_const #

fn (mut expr ConstExpression) f64_const(v f64)

f64_const places a constant f64 value on the stack. WebAssembly instruction: f64.const.

fn (ConstExpression) add #

fn (mut expr ConstExpression) add(typ NumType)

add adds two values on the stack with type typ. WebAssembly instructions: i32|i64.add.

fn (ConstExpression) sub #

fn (mut expr ConstExpression) sub(typ NumType)

sub subtracts two values on the stack with type typ. WebAssembly instructions: i32|i64.sub.

fn (ConstExpression) mul #

fn (mut expr ConstExpression) mul(typ NumType)

mul multiplies two values on the stack with type typ. WebAssembly instructions: i32|i64.mul.

fn (ConstExpression) global_get #

fn (mut expr ConstExpression) global_get(global GlobalImportIndex)

global_get places the value of the global at the index global on the stack. Constant expressions are only allowed to refer to imported globals. WebAssembly instruction: global.get.

fn (ConstExpression) ref_null #

fn (mut expr ConstExpression) ref_null(rt RefType)

ref_null places a null reference on the stack. WebAssembly instruction: ref.null.

fn (ConstExpression) ref_func #

fn (mut expr ConstExpression) ref_func(name string)

ref_func places a reference to a function with name on the stack. If this function does not exist when calling compile on the module, it will panic. WebAssembly instruction: ref.func.

fn (ConstExpression) ref_func_import #

fn (mut expr ConstExpression) ref_func_import(mod string, name string)

ref_func places a reference to an imported function with name on the stack. If the imported function does not exist when calling compile on the module, it will panic. WebAssembly instruction: ref.func.

struct FuncType #

struct FuncType {
pub:
	parameters []ValType
	results    []ValType
	name       ?string
}

struct Function #

struct Function {
	tidx int
	idx  int
mut:
	patches []FunctionPatch // sorted
	label   int
	export  bool
	mod     &Module = unsafe { nil }
	code    []u8
	locals  []FunctionLocal
pub:
	name string
pub mut:
	export_name ?string
}

fn (Function) abs #

fn (mut func Function) abs(typ NumType)

abs gets the absolute value of a float with type typ. WebAssembly instruction: f32|f64.abs.

fn (Function) add #

fn (mut func Function) add(typ NumType)

add adds two values on the stack with type typ. WebAssembly instructions: i32|i64|f32|f64.add.

fn (Function) b_and #

fn (mut func Function) b_and(typ NumType)

and takes the bitwise and of two values on the stack with type typ. WebAssembly instruction: i32|i64.and.

fn (Function) b_or #

fn (mut func Function) b_or(typ NumType)

or takes the bitwise or of two values on the stack with type typ. WebAssembly instruction: i32|i64.or.

fn (Function) b_shl #

fn (mut func Function) b_shl(typ NumType)

shl performs bitwise left-shift on a value with type typ. WebAssembly instruction: i32|i64.shl.

fn (Function) b_shr #

fn (mut func Function) b_shr(typ NumType, is_signed bool)

shr performs bitwise right-shift on a value with type typ, with respect to is_signed. WebAssembly instructions: i32|i64.shr_s, i32|i64.shr_u.

fn (Function) b_xor #

fn (mut func Function) b_xor(typ NumType)

xor takes the bitwise xor of two values on the stack with type typ. WebAssembly instruction: i32|i64.xor.

fn (Function) c_block #

fn (mut func Function) c_block(parameters []ValType, results []ValType) LabelIndex

c_block creates a label that can later be branched out of with c_br and c_br_if. Blocks are strongly typed, you must supply a list of types for parameters and results. All blocks must be ended, see the c_end function.

fn (Function) c_br #

fn (mut func Function) c_br(label LabelIndex)

c_br branches to a loop or block with the label passed in at label. WebAssembly instruction: br.

fn (Function) c_br_if #

fn (mut func Function) c_br_if(label LabelIndex)

c_br_if branches to a loop or block with the label passed in at label, based on an i32 condition. WebAssembly instruction: br_if.

fn (Function) c_else #

fn (mut func Function) c_else(label LabelIndex)

c_else opens the else case of an if expression, it must be closed by calling c_end.

fn (Function) c_end #

fn (mut func Function) c_end(label LabelIndex)

c_end ends the block, loop or if expression with the label passed in at label.

fn (Function) c_if #

fn (mut func Function) c_if(parameters []ValType, results []ValType) LabelIndex

c_if opens an if expression. It executes a statement if the last item on the stack is true. It creates a label that can later be branched out of with c_br and c_br_if. If expressions are strongly typed, you must supply a list of types for parameters and results. Call c_else to open the else case of an if expression, or close it by calling c_end_if. All if expressions must be ended, see the c_end function.

fn (Function) c_loop #

fn (mut func Function) c_loop(parameters []ValType, results []ValType) LabelIndex

c_loop creates a label that can later be branched to with c_br and c_br_if. Loops are strongly typed, you must supply a list of types for parameters and results. All loops must be ended, see the c_end function.

fn (Function) c_return #

fn (mut func Function) c_return()

c_return returns from a function. WebAssembly instruction: return.

fn (Function) c_select #

fn (mut func Function) c_select()

c_select selects one of its first two operands based on an i32 condition. WebAssembly instruction: select.

fn (Function) call #

fn (mut func Function) call(name string)

call calls a locally defined function. If this function does not exist when calling compile on the module, it will panic. WebAssembly instruction: call.

fn (Function) call_import #

fn (mut func Function) call_import(mod string, name string)

call calls an imported function. If the imported function does not exist when calling compile on the module, it will panic. WebAssembly instruction: call.

fn (Function) cast #

fn (mut func Function) cast(a NumType, is_signed bool, b NumType)

cast casts a value of type a with respect to is_signed, to type b. A generic utility function over a large amount of WebAssembly instructions.

Note: This function uses non-trapping float conversion operators, see cast_trapping to use opcodes that cause a runtime exception. WebAssembly instructions:- i32|i64.trunc_sat_f32_s, i32|i64.trunc_sat_f64_s.

  • f32.demote_f64, f64.promote_f32.
  • i32.wrap_i64, i64.extend_i32_s, i64.extend_i32_u.
  • f32|f64.convert_i32_s, f32|f64.convert_i32_u.
  • f32|f64.convert_i64_s, f32|f64.convert_i64_u.

fn (Function) cast_trapping #

fn (mut func Function) cast_trapping(a NumType, is_signed bool, b NumType)

cast_trapping casts a value of type a with respect to is_signed, to type b. A generic utility function over a large amount of WebAssembly instructions.

Note: This function uses trapping float conversion operators, see cast to use opcodes that do NOT cause a runtime exception. WebAssembly instructions:- i32|i64.trunc_f32_s, i32|i64.trunc_f64_s.

  • See function cast for the rest.

fn (Function) ceil #

fn (mut func Function) ceil(typ NumType)

ceil rounds up the value of a float with type typ to the nearest integer. WebAssembly instruction: f32|f64.ceil.

fn (Function) clz #

fn (mut func Function) clz(typ NumType)

clz counts the amount of leading zeros in the numbers binary representation. WebAssembly instruction: i32|i64.clz.

fn (Function) copysign #

fn (mut func Function) copysign(typ NumType)

copysign copies the sign bit of one float value to another float, both with type typ. WebAssembly instruction: f32|f64.copysign.

fn (Function) ctz #

fn (mut func Function) ctz(typ NumType)

ctz counts the amount of trailing zeros in the numbers binary representation. WebAssembly instruction: i32|i64.ctz.

fn (Function) data_drop #

fn (mut func Function) data_drop(idx DataSegmentIndex)

data_drop prevents further use of a passive memory segment. WebAssembly instruction: data.drop.

fn (Function) div #

fn (mut func Function) div(typ NumType, is_signed bool)

div divides two values on the stack with type typ, with respect to is_signed. WebAssembly instructions: i32|i64.div_s, i32|i64.div_u, f32|f64.div.

fn (Function) drop #

fn (mut func Function) drop()

drop drops the value on the stack WebAssembly instruction: drop.

fn (Function) eq #

fn (mut func Function) eq(typ NumType)

eq checks if two values with type typ are equal, places an i32 boolean value on the stack. WebAssembly instruction: i32|i64|f32|f64.eq.

fn (Function) eqz #

fn (mut func Function) eqz(typ NumType)

eqz checks if the value with type typ is equal to zero, places an i32 boolean value on the stack. WebAssembly instruction: i32|i64.eqz.

fn (Function) export_name #

fn (mut func Function) export_name(name string)

export_name sets the export name of the function to name

fn (Function) f32_const #

fn (mut func Function) f32_const(v f32)

f32_const places a constant f32 value on the stack. WebAssembly instruction: f32.const.

fn (Function) f64_const #

fn (mut func Function) f64_const(v f64)

f64_const places a constant f64 value on the stack. WebAssembly instruction: f64.const.

fn (Function) floor #

fn (mut func Function) floor(typ NumType)

floor rounds down the value of a float with type typ to the nearest integer. WebAssembly instruction: f32|f64.floor.

fn (Function) ge #

fn (mut func Function) ge(typ NumType, is_signed bool)

ge checks if two values with type typ with respect to is_signed are greater than or equal to another, places an i32 boolean value on the stack. WebAssembly instructions: i32|i64.ge_s, i32|i64.ge_u, f32|f64.ge.

fn (Function) global_get #

fn (mut func Function) global_get(global GlobalIndices)

global_get places the value of the global at the index global on the stack. WebAssembly instruction: global.get.

fn (Function) global_set #

fn (mut func Function) global_set(global GlobalIndices)

global_set sets the global at the index global to the value on the stack. WebAssembly instruction: global.set.

fn (Function) gt #

fn (mut func Function) gt(typ NumType, is_signed bool)

gt checks if two values with type typ with respect to is_signed are greater than another, places an i32 boolean value on the stack. WebAssembly instructions: i32|i64.gt_s, i32|i64.gt_u, f32|f64.gt.

fn (Function) i32_const #

fn (mut func Function) i32_const(v i32)

i32_const places a constant i32 value on the stack. WebAssembly instruction: i32.const.

fn (Function) i64_const #

fn (mut func Function) i64_const(v i64)

i64_const places a constant i64 value on the stack. WebAssembly instruction: i64.const.

fn (Function) le #

fn (mut func Function) le(typ NumType, is_signed bool)

le checks if two values with type typ with respect to is_signed are less than or equal to another, places an i32 boolean value on the stack. WebAssembly instructions: i32|i64.le_s, i32|i64.le_u, f32|f64.le.

fn (Function) load #

fn (mut func Function) load(typ NumType, align int, offset int)

load loads a value with type typ from memory. WebAssembly instruction: i32|i64|f32|f64.load.

fn (Function) load16 #

fn (mut func Function) load16(typ NumType, is_signed bool, align int, offset int)

load16 loads a 16-bit value with type typ with respect to is_signed from memory. WebAssembly instructions: i32|i64.load16_s, i32|i64.load16_u.

fn (Function) load32_i64 #

fn (mut func Function) load32_i64(is_signed bool, align int, offset int)

load32_i64 loads a 32-bit value of type i64 with respect to is_signed from memory. WebAssembly instructions: i64.load32_s, i64.load32_u.

fn (Function) load8 #

fn (mut func Function) load8(typ NumType, is_signed bool, align int, offset int)

load8 loads a 8-bit value with type typ with respect to is_signed from memory. WebAssembly instructions: i32|i64.load8_s, i32|i64.load8_u.

fn (Function) local_get #

fn (mut func Function) local_get(local LocalIndex)

local_get places the value of the local at the index local on the stack. WebAssembly instruction: local.get.

fn (Function) local_set #

fn (mut func Function) local_set(local LocalIndex)

local_get sets the local at the index local to the value on the stack. WebAssembly instruction: local.set.

fn (Function) local_tee #

fn (mut func Function) local_tee(local LocalIndex)

local_tee sets the local at the index local to the value on the stack, then places it's value on the stack. WebAssembly instruction: local.tee.

fn (Function) lt #

fn (mut func Function) lt(typ NumType, is_signed bool)

lt checks if two values with type typ with respect to is_signed are less than another, places an i32 boolean value on the stack. WebAssembly instructions: i32|i64.lt_s, i32|i64.lt_u, f32|f64.lt.

fn (Function) max #

fn (mut func Function) max(typ NumType)

max gets the higher value of two floats with type typ. WebAssembly instruction: f32|f64.max.

fn (Function) memory_copy #

fn (mut func Function) memory_copy()

memory_copy copies one region of memory to another. Similar to memcpy and memmove, memory regions can overlap. WebAssembly instruction: memory.copy.

fn (Function) memory_fill #

fn (mut func Function) memory_fill()

memory_fill sets a memory region to a byte value. Similar to memset. WebAssembly instruction: memory.copy.

fn (Function) memory_grow #

fn (mut func Function) memory_grow()

memory_grow increases the size of the memory instance. WebAssembly instruction: memory.grow.

fn (Function) memory_init #

fn (mut func Function) memory_init(idx DataSegmentIndex)

memory_init copies from a passive memory segment to the memory instance. WebAssembly instruction: memory.init.

fn (Function) memory_size #

fn (mut func Function) memory_size()

memory_size gets the size of the memory instance. WebAssembly instruction: memory.size.

fn (Function) min #

fn (mut func Function) min(typ NumType)

min gets the smaller value of two floats with type typ. WebAssembly instruction: f32|f64.min.

fn (Function) mul #

fn (mut func Function) mul(typ NumType)

mul multiplies two values on the stack with type typ. WebAssembly instructions: i32|i64|f32|f64.mul.

fn (Function) ne #

fn (mut func Function) ne(typ NumType)

ne checks if two values with type typ are not equal, places an i32 boolean value on the stack. WebAssembly instruction: i32|i64|f32|f64.ne.

fn (Function) nearest #

fn (mut func Function) nearest(typ NumType)

nearest rounds the value of a float with type typ to the nearest integer. WebAssembly instruction: f32|f64.nearest.

fn (Function) neg #

fn (mut func Function) neg(typ NumType)

neg negates the value of a float with type typ. WebAssembly instruction: f32|f64.neg.

fn (Function) new_local #

fn (mut func Function) new_local(v ValType) LocalIndex

new_local creates a function local and returns it's index. See local_get, local_set, local_tee.

fn (Function) new_local_named #

fn (mut func Function) new_local_named(v ValType, name string) LocalIndex

new_local_named creates a function local with a name and returns it's index. The name is used in debug information, where applicable. See local_get, local_set, local_tee.

fn (Function) nop #

fn (mut func Function) nop()

nop instruction, does nothing. WebAssembly instruction: nop.

fn (Function) patch #

fn (mut func Function) patch(loc PatchPos, begin PatchPos)

patch "patches" the code generated starting from the last patch_pos call in begin to loc.

start := func.patch_pos()

...

patch_block := func.patch_pos()
{
    func.i32_const(10)
    func.local_set(idx)
}
func.patch(start, patch_block) // will patch code to the `start`.
// func.code[patch_block..]

fn (Function) patch_pos #

fn (func Function) patch_pos() PatchPos

patch_pos returns a PatchPos for use with patch.

fn (Function) popcnt #

fn (mut func Function) popcnt(typ NumType)

popcnt counts the amount of 1s in a numbers binary representation. WebAssembly instruction: i32|i64.popcnt.

fn (Function) ref_func #

fn (mut func Function) ref_func(name string)

ref_func places a reference to a function with name on the stack. If this function does not exist when calling compile on the module, it will panic. WebAssembly instruction: ref.func.

fn (Function) ref_func_import #

fn (mut func Function) ref_func_import(mod string, name string)

ref_func_import places a reference to an imported function with name on the stack. If the imported function does not exist when calling compile on the module, it will panic. WebAssembly instruction: ref.func.

fn (Function) ref_is_null #

fn (mut func Function) ref_is_null(rt RefType)

ref_is_null checks if the reference value on the stack is null, places an i32 boolean value on the stack. WebAssembly instruction: ref_is_null.

fn (Function) ref_null #

fn (mut func Function) ref_null(rt RefType)

ref_null places a null reference on the stack. WebAssembly instruction: ref.null.

fn (Function) reinterpret #

fn (mut func Function) reinterpret(a NumType)

reinterpret returns a value which has the same bit-pattern as its operand value, in its result type. WebAssembly instruction: f32.reinterpret_i32, i32.reinterpret_f32, f64.reinterpret_i64, i64.reinterpret_f64.

fn (Function) rem #

fn (mut func Function) rem(typ NumType, is_signed bool)

rem takes the remainder of two values on the stack with type typ, with respect to is_signed. WebAssembly instructions: i32|i64.rem_s, i32|i64.rem_u.

fn (Function) rotl #

fn (mut func Function) rotl(typ NumType)

rotl performs bitwise left-rotate on a value with type typ. WebAssembly instruction: i32|i64.rotl.

fn (Function) rotr #

fn (mut func Function) rotr(typ NumType)

rotr performs bitwise right-rotate on a value with type typ. WebAssembly instruction: i32|i64.rotr.

fn (Function) sign_extend16 #

fn (mut func Function) sign_extend16(typ ValType)

sign_extend16 extends the value of a 16-bit integer of type typ. WebAssembly instruction: i32|i64.extend16_s.

fn (Function) sign_extend32 #

fn (mut func Function) sign_extend32()

sign_extend32_i64 extends the value of a 32-bit integer of type i64. WebAssembly instruction: i64.extend32_s.

fn (Function) sign_extend8 #

fn (mut func Function) sign_extend8(typ ValType)

sign_extend8 extends the value of a 8-bit integer of type typ. WebAssembly instruction: i32|i64.extend8_s.

fn (Function) sqrt #

fn (mut func Function) sqrt(typ NumType)

sqrt performs the square root on the value of a float with type typ. WebAssembly instruction: f32|f64.sqrt.

fn (Function) store #

fn (mut func Function) store(typ NumType, align int, offset int)

store stores a value with type typ into memory. WebAssembly instruction: i32|i64|f32|f64.store.

fn (Function) store16 #

fn (mut func Function) store16(typ NumType, align int, offset int)

store16 stores a 16-bit value with type typ into memory. WebAssembly instruction: i32|i64.store16.

fn (Function) store32_i64 #

fn (mut func Function) store32_i64(align int, offset int)

store16 stores a 32-bit value of type i64 into memory. WebAssembly instruction: i64.store32.

fn (Function) store8 #

fn (mut func Function) store8(typ NumType, align int, offset int)

store8 stores a 8-bit value with type typ into memory. WebAssembly instruction: i32|i64.store8.

fn (Function) sub #

fn (mut func Function) sub(typ NumType)

sub subtracts two values on the stack with type typ. WebAssembly instructions: i32|i64|f32|f64.sub.

fn (Function) trunc #

fn (mut func Function) trunc(typ NumType)

trunc discards the fractional part of the value of a float with type typ. WebAssembly instruction: f32|f64.trunc.

fn (Function) unreachable #

fn (mut func Function) unreachable()

unreachable denotes a point in code that should not be reachable, it is an unconditional trap. WebAssembly instruction: unreachable.

struct Module #

@[heap]
struct Module {
mut:
	buf            []u8
	functypes      []FuncType
	functions      map[string]Function
	globals        []Global
	memory         ?Memory
	start          ?string
	fn_imports     []FunctionImport
	global_imports []GlobalImport
	segments       []DataSegment
	debug          bool
	mod_name       ?string
}

Module contains the WebAssembly module. Use the compile method to compile the module into a pure byte array.

fn (Module) assign_global_init #

fn (mut mod Module) assign_global_init(global GlobalIndex, init ConstExpression)

assign_global_init assigns a global with the constant expression init. See new_global.

fn (Module) assign_memory #

fn (mut mod Module) assign_memory(name string, export bool, min u32, max ?u32)

assign_memory assigns memory to the current module.

fn (Module) assign_start #

fn (mut mod Module) assign_start(name string)

assign_start assigns the start function to the current module.

fn (Module) commit #

fn (mut mod Module) commit(func Function, export bool)

commit commits a function to the module, use export to export the function.

fn (Module) compile #

fn (mut mod Module) compile() []u8

compile serialises the WebAssembly module into a byte array. The returned byte array can be written out into a .wasm, or executed in memory.

fn (Module) enable_debug #

fn (mut mod Module) enable_debug(mod_name ?string)

enable_debug sets whether to emit debug information for not.

fn (Module) new_data_segment #

fn (mut mod Module) new_data_segment(name ?string, pos int, data []u8) DataSegmentIndex

new_data_segment inserts a new data segment at the memory index pos. name is optional, it is used for debug info.

fn (Module) new_debug_function #

fn (mut mod Module) new_debug_function(name string, typ FuncType, argument_names []?string) Function

new_debug_function creates a function struct with extra debug information. argument_names must be the same length as the parameters in the function type typ.

fn (Module) new_function #

fn (mut mod Module) new_function(name string, parameters []ValType, results []ValType) Function

new_function creates a function struct.

fn (Module) new_function_import #

fn (mut mod Module) new_function_import(modn string, name string, parameters []ValType, results []ValType)

new_function_import imports a new function into the current module.

fn (Module) new_function_import_debug #

fn (mut mod Module) new_function_import_debug(modn string, name string, typ FuncType)

new_function_import_debug imports a new function into the current module with extra debug information.

fn (Module) new_global #

fn (mut mod Module) new_global(name string, export bool, typ ValType, is_mut bool, init ConstExpression) GlobalIndex

new_global creates a global and returns it's index. See global_get, global_set.

fn (Module) new_global_import #

fn (mut mod Module) new_global_import(modn string, name string, typ ValType, is_mut bool) GlobalImportIndex

new_global_import imports a new global into the current module and returns it's index. See global_get, global_set.

fn (Module) new_passive_data_segment #

fn (mut mod Module) new_passive_data_segment(name ?string, data []u8)

new_passive_data_segment inserts a new passive data segment. name is optional, it is used for debug info.