feat(#418): bind cabi-arena-realloc natively on the self-contained dissolve — synthesized in-module arena allocator - #799
Merged
Conversation
…mport dissolve vs wasmtime host arena The fixture is the wit-bindgen cabi-realloc-extern / meld-dissolve shape (exported cabi_realloc routing to env::__cabi_arena_realloc, Rust/wasm-ld layout globals). The gate asserts the default self-contained compile yields ET_EXEC and every export matches wasmtime ground truth where the import is satisfied by a host arena implementing the #418 contract (0/0 -> align, bump, copy-on-grow, bounded + trap on exhaustion). Host arena uses a DIFFERENT base than synth will, so only pointer-independent semantics can green. RED today: the arena import degrades the compile to an ET_REL link-me object (the embedder seam) — script exits at the ET_EXEC assert. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…ealloc import with a synthesized in-module allocator A wasm->wasm transform in synth-core: when env::__cabi_arena_realloc is the module's ONLY import, remove it and prepend a DEFINED allocator function implementing the #418 contract ((i32x4)->i32; old_len==0&&new_len==0 -> align; bump allocation from an appended cursor global; copy-on-realloc of min(old,new) bytes; bounded [arena_base, linmem_end) — traps on exhaustion, never memory.grow). Imports-first index space + sole-import removal + prepend = every call/export/elem index PRESERVED, no remapping; untouched sections are byte-copied verbatim (count-patch only on function/global/code). arena_base mirrors the shipped used-extent rule: max(data_end, i32-const global inits <= linmem) — covering __stack_pointer / __heap_base / __data_end — floor 16, 16-aligned. Loud declines: wrong signature, no/64-bit memory, non-const data offsets, no defined functions, no arena room. Other imports present -> NotApplicable pass-through (the module keeps the host-linked seam). Result is Validator-checked before use. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…arena-realloc importers, decline matrix + CI oracle CLI: on the self-contained Cortex-M --all-exports path (ARM backend, not --relocatable, not --native-pointer-abi), a sole env::__cabi_arena_realloc import is bound via the synth-core arena-bind rewrite — the compile yields a fully self-contained ET_EXEC image (previously: ET_REL 'link me with the Kiln bridge', the embedder seam). Pinned opt-out: --no-bind-cabi-arena. Untouched seams (asserted): --relocatable keeps the #420 TCB layering (undefined symbol, host-link-bound); modules with OTHER imports keep the host seam entirely (never a half-bound hybrid); modules without the import pass through byte-identically. Gates: - scripts/repro/cabi_arena_bind_418_differential.py now GREEN (was red-first): unicorn runs the image's own startup then each export; wasmtime satisfies the import with a host arena at a DIFFERENT base — all six pointer-independent cases match, exhaustion traps on both sides. CI job arena-bind-418-oracle. - cabi_arena_bind_418.rs: ET_EXEC + no undefined arena symbol + binding log; opt-out/relocatable restore the external seam; wrong signature declines loudly; mixed imports keep ET_REL. - Harness anti-vacuity: startup must reach the first compiled function AND leave R11 = __linear_memory_base (a min()-over-symbols bug initially ran nothing and greened 4/6 cases on a zeroed machine — caught and locked). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What (#418, v0.47 Wave-2 Lane 6)
The
--relocatablehalf of #418 was locked in PR #420 (undefined__cabi_arena_reallocsymbol, TCB-bound at native link — untouched here, still asserted). This PR closes the other half: a self-contained dissolve of a module importingenv::__cabi_arena_realloc(the wit-bindgencabi-realloc-extern/ meld-dissolve shape) previously degraded to an ET_REL "link me with the Kiln bridge" object — the arena import was the one unresolved seam blocking a fully self-contained image.The binding: a wasm→wasm rewrite, not new codegen
synth_core::arena_bind: when the arena import is the module's only import, remove it and prepend a defined WebAssembly function implementing the #418 contract, compiled through synth's ordinary pipeline like any other module function (no hand-written machine code, no new selector/encoder paths, target-portable):(old_ptr, old_len, align, new_len) -> ptr(i32×4 → i32);old_len == 0 && new_len == 0→ returnsalignverbatim;min(old_len, new_len)bytes (the RawVec-grow pattern needs this);[arena_base, linmem_end)— exhaustion traps (unreachable→ UDF), nevermemory.grow.Index-preserving by construction: the function index space is imports-first, so sole-import removal + prepend gives the allocator the import's old index — every
call/ref.func/export/element entry keeps its meaning, zero remapping. Untouched sections are byte-copied verbatim (count-patch only on function/global/code); the result iswasmparser::Validator-checked before use.arena_basemirrors the shipped used-extent rule:max(data_end, i32-const global inits ≤ linmem)(covers__stack_pointer, wasm-ld's__heap_base/__data_end), floor 16, 16-aligned.Decline matrix (all asserted in
cabi_arena_bind_418.rs)--relocatable--no-bind-cabi-arena(pinned opt-out)--native-pointer-abi#418 … signature)Gates (red-first)
scripts/repro/cabi_arena_bind_418_differential.py+ CI jobarena-bind-418-oracle: red before (exits at the ET_EXEC assert — the import degraded the compile to ET_REL), green after. unicorn runs the image's own startup (R9/R10/R11 init, globals materialization, default --cortex-m self-contained image silently DROPS active (data) segments: .linear_memory is NoBits, initializer bytes absent -> every load from an initialized region reads 0 (silent miscompile) #758 data copy) then each export; wasmtime satisfies the import with a host arena implementing the contract at a deliberately different base, so only pointer-independent semantics can pass (preserved contents after grow, disjointness, alignment residue,(0,0,align,0) == align); the exhaustion case must trap on both sides.R11 = __linear_memory_base(an initialmin()-over-symbols bug ran no startup and still greened 4/6 cases on a zeroed machine — caught, fixed, asserted).cabi_arena_realloc_linkability_418.rsstill green; full workspace suite green (126 suites); clippy-D warnings+ fmt clean;claim_check21/21.Honest residue
.wasm, add it as a fixture case (issue comment thread already tracks this).--all-exportsself-contained Cortex-M path only (the dissolve path). Single-function compiles and non-Cortex-M targets keep the pass-through.Refs #418, #420, meld#301, gale#89.
🤖 Generated with Claude Code
https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L