std/sections
std/sections
Section titled “std/sections”std/wasm/sections — section composers for the WebAssembly Core 1.0 binary format. One step up from the per-element primitives in encode.fern / leb128.fern / inst.fern / etc.: each function here takes the section’s logical input (a list of typeidxs, a list of function bodies, etc.) and emits the complete id : u8 + size : uleb + body envelope. Spec: https://webassembly.github.io/spec/core/binary/modules.html Seventh slice of Phase 1 of docs/TOOLCHAIN-SELF-HOSTING.md. With these composers in place, an IR-walking driver only has to arrange its inputs as the right Lang arrays and call through — no more re-implementing the section-header / vec-length / memarg / memtype / export-desc bookkeeping at each call site. Sections covered: type, function, table, memory, global (via a single-const-global helper since that’s all today’s backend needs), export, start, element, code, data. Import lives in imports.fern — its descriptor is a four-variant union (func / table / mem / global) that warrants its own module. Table + element are here because they’re what call_indirect (closures + indirect dispatch in the production backend) needs.
export_func
Section titled “export_func”pub function export_func(): u8---- Export-kind constants ----------------------------------- (https://webassembly.github.io/spec/core/binary/modules.html#export-section)
export_table
Section titled “export_table”pub function export_table(): u8export_memory
Section titled “export_memory”pub function export_memory(): u8export_global
Section titled “export_global”pub function export_global(): u8encode_custom_section
Section titled “encode_custom_section”pub function encode_custom_section(buf: u8[], name: string, payload: u8[]): u8[]---- Custom section ------------------------------------------
Body: name : uleb-prefixed UTF-8 + payload : bytes. The
outer section’s size covers both. wasm engines ignore custom
sections semantically but tools (wasm-tools, the names
section, debug-info, the component-type marker that
component-embed writes) all hang their data here.
encode_type_section
Section titled “encode_type_section”pub function encode_type_section(buf: u8[], params_per_type: u8[][], results_per_type: u8[][]): u8[]---- Type section --------------------------------------------
Body: vec(functype). Each functype is 0x60 + vec(params) + vec(results), encoded by encode.put_func_type. The two
parallel arrays let callers compose the param / result valtype
byte sequences per entry without needing struct-of-arrays
composite types.
encode_function_section
Section titled “encode_function_section”pub function encode_function_section(buf: u8[], typeidxs: u32[]): u8[]---- Function section ----------------------------------------
Body: vec(typeidx). Each function declared in the module gets one typeidx here, in declaration order — the i-th typeidx in this section binds the i-th body in the code section to one of the types from the type section.
encode_table_section
Section titled “encode_table_section”pub function encode_table_section(buf: u8[], reftype: u8, min: u32, max: i32): u8[]---- Table section -------------------------------------------
Body: vec(tabletype). Each tabletype is reftype + limits —
the same limits shape the memory section uses. wasm 1.0 caps a
module at one table, so this helper writes exactly one entry.
reftype is funcref (0x70) for the call_indirect dispatch
table; max = -1 means “no maximum”.
encode_memory_section
Section titled “encode_memory_section”pub function encode_memory_section(buf: u8[], min_pages: u32, max_pages: i32): u8[]---- Memory section ------------------------------------------
Body: vec(memtype). Wasm 1.0 allows at most one memory, so
this helper writes exactly one entry. memtype is a limits
record: a flag byte (0 = no max, 1 = with max), the initial
page count, and optionally the max page count.
max_pages = -1 means “no maximum”.
encode_export_section
Section titled “encode_export_section”pub function encode_export_section(buf: u8[], names: string[], kinds: u8[], indices: u32[]): u8[]---- Export section ------------------------------------------
Body: vec(export). Each export is name : utf8 + kind : u8 + idx : u32. The three parallel arrays cover the three fields
— same shape as the type section’s params/results split.
encode_start_section
Section titled “encode_start_section”pub function encode_start_section(buf: u8[], funcidx: u32): u8[]---- Start section -------------------------------------------
Body: one funcidx (no length prefix — this section holds at
most one value, like a Maybe<funcidx>).
encode_element_section
Section titled “encode_element_section”pub function encode_element_section(buf: u8[], offsets: i32[], funcidxs_per_seg: u32[][]): u8[]---- Element section -----------------------------------------
Body: vec(elem). Each segment here is the MVP “active, table 0,
funcref” kind (flag 0): a 0x00 flag, an offset expression
(i32.const <off> ; end), and a vec(funcidx) that initialises
the table starting at that offset. This is what populates the
call_indirect dispatch table — funcidxs_per_seg[i][j] becomes
table slot offsets[i] + j.
offsets and funcidxs_per_seg are parallel arrays — one
offset and one funcidx list per segment.
encode_code_section
Section titled “encode_code_section”pub function encode_code_section(buf: u8[], bodies: u8[][]): u8[]---- Code section --------------------------------------------
Body: vec(code). Each code entry is itself a size : uleb + locals_vec + expr — produced by inst.put_function_body, which
already prefixes the size. So the caller passes pre-wrapped
bodies and we just emit the count + concatenation.
encode_data_section
Section titled “encode_data_section”pub function encode_data_section(buf: u8[], offsets: i32[], init_bytes: u8[][]): u8[]---- Data section --------------------------------------------
Body: vec(data). Each data segment in wasm 1.0 is the “active”
kind: memidx (always 0 in MVP) + offset (an i32.const expr) +
init bytes (vec(byte)). The offset expr is just i32.const <offset>; end, four to six bytes total.
offsets and init_bytes are parallel arrays — one offset and
one byte sequence per segment.