Skip to content

Bounded / no-grow cabi_realloc + lowering allocations for MCU single-address-space targets (no memory.grow) — unblocks meld --memory shared fusion #4

@avrabe

Description

@avrabe

Why (grounded, cross-repo chain)

The generated guest cabi_realloc (cabi_realloc_wit_bindgen_0_58_0crate::rt::cabi_realloc, crates/guest-rust/src/rt/) is backed by the global growing allocator, so any component built with these bindings emits memory.grow (the canonical-ABI realloc + Vec/String lifting/lowering paths). That single opcode blocks the embedded lowering pipeline downstream:

  • meld#299meld fuse --memory shared --address-rebase (single-address-space MCU mode) correctly fail-louds on memory.grow (SR-37: a frozen shared static layout can't survive a runtime grow). So a component with one memory.grow cannot be MCU-lowered.
  • gale#89gale-app-demo / gale-kiln each carry exactly one memory.grow "from the default Rust/wit-bindgen wasip2 allocator"; the multi-memory fallback isn't MCU-lowerable (2 × 1088 KB; synth rejects). This blocks the jess → Pixhawk 6X-RT drone pipeline.

So the cleanest place to kill the problem is at the source: let wit-bindgen-generated components link a bounded, no-grow allocator so they never emit memory.grow.

Proposal

A binding option (feature/flag, e.g. cabi_realloc = "static-arena" or a no_std+bounded mode) that backs cabi_realloc and the lifting/lowering temporaries with a fixed static arena sized at build time, failing loud (trap) on exhaustion instead of calling memory.grow. Generated components then satisfy meld's --memory shared --address-rebase precondition directly, no post-processing.

This complements #1 (per-item heap alloc in StreamReader::next/StreamWriter::write_one): both are about making the generated code's allocation behaviour deterministic and bounded for real-time / no_std / MCU targets — the PulseEngine embedded line of work on this fork.

Honest scope notes

  • This is opt-in; it must not change default (host/cloud) codegen.
  • "Bounded arena + trap-on-exhaustion" is the sound analogue of meld#299 Option 1 (bounded static heap) — doing it in the binding generator means the component is born MCU-lowerable rather than rewritten later.
  • Pairs with the gale#89 "components must be no_std/no-grow" contract: this is the wit-bindgen capability that lets a component meet that contract without hand-rolling an allocator.

Refs: meld#299, gale#89, gale#63 (hosting), and #1 (real-time stream alloc) on this fork.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions