Skip to content

std/encode

std/wasm/encode — container-level binary writers for the WebAssembly Core 1.0 binary format. Spec: https://webassembly.github.io/spec/core/binary/modules.html Second slice of Phase 1 of docs/TOOLCHAIN-SELF-HOSTING.md. The leb128 sibling module handles variable-length integers; this module sits on top of it and handles: - the module preamble (magic + version) - generic section wrapping (id + uleb length + body bytes) - the type section’s function-type encoding - utility byte writers (raw byte append, u32 little-endian for the version field, uleb-prefixed names for imports/exports) The big remaining Phase 1 piece is the per-IR-op instruction encoder (opcode + immediates), which becomes the body of the code section. That goes in its own module / slice. Same shape as leb128: every writer takes a u8[], appends to it, and returns the extended buffer. No I/O, no globals.

pub function valtype_i32(): u8

Valtype byte constants — one per primitive wasm number type. Spec: https://webassembly.github.io/spec/core/binary/types.html#binary-valtype Lang doesn’t have source-level const decls wired through the codegen everywhere yet, so these are zero-arg functions — inliner / constant-folder collapse them to a single byte at the call site.

pub function valtype_i64(): u8
pub function valtype_f32(): u8
pub function valtype_f64(): u8
pub function section_custom(): u8

Section IDs (https://webassembly.github.io/spec/core/binary/modules.html#sections). section_custom is shipped as a constant for symmetry with the rest of the table; the per-section composer lives in sections.fern::encode_custom_section because its body needs a name prefix that the generic put_section doesn’t handle.

pub function section_type(): u8
pub function section_import(): u8
pub function section_function(): u8
pub function section_table(): u8
pub function section_memory(): u8
pub function section_global(): u8
pub function section_export(): u8
pub function section_start(): u8
pub function section_element(): u8
pub function section_code(): u8
pub function section_data(): u8
pub function put_bytes(buf: u8[], src: u8[]): u8[]

put_bytes — append the raw contents of src to buf. Used to splice a precomputed section body onto a growing module, or to concatenate two preallocated chunks.

pub function put_u32_le(buf: u8[], v: u32): u8[]

put_u32_le — append a fixed 4-byte little-endian u32. The wasm preamble’s version field is the only place the binary format uses a fixed-width integer (everything else is leb128); this is what writes those four bytes.

pub function put_module_header(buf: u8[]): u8[]

put_module_header — append the wasm preamble: magic “\0asm” (0x00 0x61 0x73 0x6D) followed by version 1 as a fixed-width u32 LE (0x01 0x00 0x00 0x00). Always 8 bytes.

pub function put_name(buf: u8[], s: string): u8[]

put_name — append a wasm “name” (UTF-8 bytes, uleb-prefixed length). Used by import / export descriptors and by the names custom section. Iterating s by index gives the raw bytes — Lang’s string is a byte sequence underneath, and this matches the wasm spec’s “name = vec(byte)” definition.

pub function put_section(buf: u8[], id: u8, body: u8[]): u8[]

put_section — wrap a precomputed section body with its header: id : u8 + size : uleb + body bytes. The caller builds body first, in its own buffer, so the size prefix can be written before the body bytes themselves. Spec: https://webassembly.github.io/spec/core/binary/modules.html#sections

pub function put_func_type(buf: u8[], params: u8[], results: u8[]): u8[]

put_func_type — append a function type to a type-section body: 0x60 + vec(params) + vec(results), where each param / result element is a single valtype byte. params and results arrive as u8[] of valtype bytes — the caller composes them from the valtype_* helpers above. Spec: https://webassembly.github.io/spec/core/binary/types.html#function-types