Skip to content

Linking

Program module merging, index remapping, unit metadata, and link groups.

Updated View as Markdown

The program linker merges the allocator module and a set of per-unit modules into the single WebAssembly module loaded by a runtime link group.

This is binary composition, not language name resolution. Source calls have already resolved to symbols, and each unit module already validates independently.

Inputs and output

atoll-flat-wasm allocator
        +
ordered per-unit wasm modules
        +
unit methods and placement metadata

validated linked program.wasm

Input unit order is canonical. Program-stable unit index i corresponds to input unit i, independent of how units are partitioned into link groups.

Merge order

The allocator module is merged first. Its memory becomes memory zero, its table becomes table zero, and its internal index space forms the base of the linked module.

Units are appended in canonical order. For each unit the linker:

  1. parses module sections into a summary;
  2. deduplicates compatible function types;
  3. resolves allocator imports to definitions already merged from atoll-flat-wasm;
  4. deduplicates host imports that remain external;
  5. allocates new function and global indices;
  6. rewrites every supported index-bearing instruction and section payload;
  7. renames or preserves exports according to the linked namespace;
  8. carries supported custom-section data forward.

The result is emitted section by section and validated.

Import treatment

Imports have different destinations:

Namespace Link behavior
atoll_flat_wasm Resolve against allocator exports and replace the import with direct linked indices
atoll_scheduler Remain host imports, deduplicated across units
atoll_libm_wasm Remain imports fulfilled through the runtime’s math instance path
Other supported host namespaces Remain imports according to their ABI contract

The math module is not merged in the current linker. Merging it would require additional memory, table, and element remapping work; documentation must not describe it as embedded merely because unit imports use a compiler-owned namespace.

Index remapping

WebAssembly indices are local to a module. Once modules are combined, the linker builds remap tables for types, functions, globals, memories, tables, elements, and data.

Any payload containing one of those indices must be rewritten through the correct input remap. Atoll unit code currently uses a deliberately constrained module shape, which keeps the supported rewrite surface auditable.

An unsupported unit section is a link error. Passing it through unchanged would be unsafe because its local indices could refer to the wrong linked objects.

Input invariants

Current unit modules:

  • import allocator memory rather than declaring their own;
  • import allocator, scheduler, and optional math functions;
  • define and export per-unit globals and functions;
  • do not define their own memory, table, data, or element sections;
  • avoid table-indexed indirect calls in user unit code;
  • may carry known Atoll custom sections.

The allocator module is different: it declares memory, table, globals, data, and elements and is self-contained. Its placement first is what makes its internal indices the linked base.

These are versioned implementation invariants. If unit emission starts using a new index-bearing instruction or section, linker support and tests must land in the same change.

Unit metadata

The linker adds an atoll.units custom section. Version 1 records, in input order:

  • unit name;
  • placement policy;
  • optional replication limit and eviction hint;
  • exposed method names;
  • method signature tags.

The payload is explicitly versioned and length-framed by the Wasm custom section. Readers reject unknown versions, invalid enum tags, truncated fields, invalid UTF-8, and trailing data.

This section is how compiler unit identity reaches the runtime. Export-name scanning alone is not the metadata contract.

A program can be partitioned three ways:

Grouping Result
All in one One linked module containing every unit; current default
One per unit One allocator-bearing linked module per unit for maximal isolation
Custom An exact partition supplied as unit-index groups

Custom groups must cover every unit exactly once. Out-of-range indices, duplicates, and gaps are hard errors. Groups and their member indices are normalized into deterministic order.

All-in-one grouping is required to produce bytes identical to a direct link of the same complete unit list. Other groupings trade allocator/module footprint for isolation and redeployment granularity.

Consistency checks

Linking rejects:

  • malformed input modules;
  • unresolved allocator imports;
  • unsupported sections;
  • incompatible yield-check modes across units;
  • invalid custom grouping;
  • malformed metadata construction;
  • output that fails WebAssembly validation.

Errors identify whether the allocator or a named unit produced the invalid input whenever possible.

Testing changes

A linker change should include:

  1. a minimal module fixture exercising the new section or instruction;
  2. validation of the linked bytes;
  3. execution when the change affects runtime behavior;
  4. multi-unit coverage to expose dedup and index-offset errors;
  5. deterministic output across repeated input;
  6. all-in-one byte-parity coverage;
  7. malformed-input rejection.

The runtime interpretation of the result is documented in Deployment and Units.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close