Repository navigation
Architecture: Meld Platform — WRT as Embedded Host Runtime with Embassy HAL Bridge #34
Description
Activity
Update: Meld Already Exists as Static Component Fuser
The initial issue assumed Meld was only a concept. It turns out
pulseengine/meldalready exists (in/Users/r/git/unkown-project/) as a static WebAssembly component fuser with a working implementation:- meld-core: Parser → Resolver → Merger → Adapter Generator → Encoder pipeline
- meld-cli: CLI with
meld fusecommand - Supports multi-memory and shared memory strategies
- Generates Canonical ABI trampolines for cross-component calls
- Formally verified with Rocq 9.0 proofs
- Supply chain attestation via wsc-attestation
Revised Pipeline
This significantly simplifies Synth's job. The pipeline is:
Components → Meld (fuse to single module) → Loom (optimize) → Synth (compile to ARM) ↓ WRT (runtime) + Embassy (HAL)Synth receives a single fused core module from Meld+Loom — not raw components. This means:
- No component linking needed in Synth — Meld already resolved all cross-component imports
- No Canonical ABI in Synth — Meld already generated adapter trampolines
- Simpler import story — remaining imports are only host/WASI imports (everything internal was fused)
- Whole-program visible — Synth sees all functions, can optimize globally
What Changes in This Issue
The Synth↔WRT ABI section remains valid. The changes to Synth's import handling are simpler:
- Imports in the fused module are ONLY host imports (WASI, platform)
- No inter-component imports to resolve
- Generate
BL __wrt_dispatch_importfor each remaining import - Link with WRT static library that provides the dispatcher
The four-tool story:
- Meld fuses (build time, eliminates component boundaries)
- Loom optimizes (build time, whole-program optimization)
- Synth compiles (build time, WASM → native ARM)
- WRT executes (deploy time, runtime services + Embassy HAL bridge)
Cross-Repo Architecture Audit — Confirming the Design
Explored all four PulseEngine repos to validate the architecture in this issue. Key findings:
Meld (component fuser)
- Uses shared-everything linking — after fusion, all component-to-component imports are resolved to direct internal function calls
- Component Model boundaries (instances, canonical ABI lift/lower) are eliminated statically
- Output is a single core WASM module with only host imports remaining
- This means post-Meld, only host function connectors need runtime dispatch
Loom (optimizer)
- Has 6 additional optimization passes specifically for Meld output (fused-component passes)
- These clean up fusion seams: dead import tables, redundant type canonicalization, inlined adapter thunks
- By the time Synth sees the module, no Component Model artifacts remain
Kiln/wrt2 (runtime)
- Component Model is a facade implementation — infrastructure exists but execution paths are incomplete
- Stackless execution model for no_std embedded (aligned with this issue's design)
- WASI dispatch works for primitives; complex types bypass Canonical ABI
- 20+ crates with bounded collections throughout (no_std ready)
- No current integration with Synth
Implication for This Issue
The architecture described here is correct and validated by the actual codebases:
- Synth receives a flat core WASM module (post-Meld/Loom), not components
- The only external symbols are host imports (WASI, HAL)
- is the right abstraction — a host function trampoline, not Component Model runtime
- Kiln's StacklessEngine can handle residual WASM (floats, i64) that Synth doesn't transcode
Starting M1: Import Pipeline
Beginning implementation of import metadata preservation and stub generation.
- added a commit that references this issue
on Mar 1, 2026 M1: Import Pipeline — Complete
Commit
c10d9c4implements M1 on the Synth side:What was added
Component Change wasm_decoder.rs ImportEntry/ImportKindstructs,imports+num_imported_funcsfields onDecodedModuleinstruction_selector.rs Call(idx)whereidx < num_importsemitsMOV R0, #idx; BL __meld_dispatch_importelf_builder.rs Relocationstruct,.rel.textsection,add_undefined_symbol()forSHN_UNDEFexternalslinker_script.rs .meld_import_table,.wasm_linear_memory,EXTERN(__meld_dispatch_import)CompileConfig num_importsfield threaded through CLI → backend → instruction selectorABI contract (Synth side)
Synth-compiled code calls imports via:
MOV R0, #<import_index> ; Which import to dispatch BL __meld_dispatch_import ; Provided by Meld static libraryThe ELF contains:
R_ARM_CALLrelocation at eachBL __meld_dispatch_importsite__meld_dispatch_importasSTB_GLOBAL/SHN_UNDEFsymbol.meld.importssection with import descriptor table
Next: M2 (Meld ABI)
- Define
__meld_dispatch_import(import_index: u32, ...) -> u32in Meld/wrt2 - Static linking proof-of-concept: Synth
.o+ Meld.a→firmware.elf
M2 Complete: Kiln-Synth Bridge Crate + ABI Integration Tests
kiln-synth-bridge (Kiln/wrt2 repo)
Branch:
feat/kiln-synth-bridge(kiln@07bb45f)New crate providing the C-ABI bridge between Synth-compiled ARM code and the Kiln runtime:
__meld_dispatch_import(import_index: u32, arg0: u32) -> u32—extern "C"symbol that Synth BL instructions target__meld_get_memory_base() -> *mut u8— returns WASM linear memory pointermeld_bridge_init()/meld_bridge_register_import()— initialization API- Fixed-size import descriptor table (64 entries, deterministic memory)
- Builds as both
rlib(Rust) andstaticlib(ARM linker) - Edition 2024 compliant (
unsafe(no_mangle), raw pointer static access) - 4 tests passing
Meld ABI Integration Tests (Synth repo)
Commit: synth@53d046f
5 new tests in
crates/synth-backend/tests/meld_abi_test.rs:- Import dispatch stub generation — verifies
Call(0)withnum_imports=1generatesMOV R0, #0; BL __meld_dispatch_import - Local function call not dispatch — verifies
Call(1)withnum_imports=1generatesBL func_1(not dispatch) - ELF relocation for Meld dispatch — verifies
add_undefined_symbol+add_relocation(R_ARM_CALL)produces valid ELF - Full Meld ABI pipeline — end-to-end: WASM with imports → instruction selection → ARM encoding → ELF with .rel.text
- Multiple import dispatch — verifies 2 imports get distinct index MOVs
ABI Contract (frozen)
Synth side: Kiln side: MOV R0, #import_index → __meld_dispatch_import(index, arg0) BL __meld_dispatch_import looks up ImportDescriptor[index] ; result in R0 calls registered DispatchFn returns result in R0Next: M3 (Mixed-Mode Demo)
Link a Synth
.owith Kilnlibkiln_synth_bridge.ainto a single firmware ELF and execute on QEMU/Renode.Triage Update: M1 + M2 Complete, M3 Next
M1: Import Pipeline — DONE
ImportEntry/ImportKindstructs insynth-core/src/wasm_decoder.rsimportsandnum_imported_funcsfields onDecodedModule- Import calls generate
MOV R0, #idx; BL __meld_dispatch_importin instruction selector - ELF builder supports
Relocation,.rel.textsection,add_undefined_symbol() - Linker script supports
.meld_import_table,EXTERN(__meld_dispatch_import)
M2: Meld ABI — DONE
kiln-synth-bridgecrate exists in Kiln repo withextern "C"dispatch function- 5 integration tests in
crates/synth-backend/tests/meld_abi_test.rs - Full pipeline tested: WASM with imports → instruction selection → ARM encoding → ELF with .rel.text
- ABI contract frozen (see M2 comment above)
M3: Mixed-Mode Demo — NOT STARTED
- Need to link Synth
.o+ Kilnlibkiln_synth_bridge.a→firmware.elf - Need Embassy HAL bridge for UART on STM32F4 or nRF52
- Blocked on Create ARM cross-compilation toolchain #27 (ARM cross-compilation toolchain for linking)
M4: Multi-Component — NOT STARTED
- Requires M3 completion first
Closing here — this is meld's architecture, tracked in the meld repo. Since this was filed, the platform split solidified: synth = compiler (this repo), kiln = interpreter/runtime, meld = platform/fusion — and the WRT-as-embedded-host-runtime + Embassy HAL bridge design belongs to meld's scope. synth's side of the contract (compile components to native ARM, call into the runtime for imports) is being worked concretely in #237/#181 (native-pointer ABI) and #275 (self-contained firmware). If the Embassy-bridge architecture is still live, it should be (re)filed in pulseengine/meld where the owning code lives.
Summary
This issue defines the architecture for integrating Synth into the Meld Platform — a unified system where Loom optimizes, Synth compiles, and WRT/Meld provides the runtime, component composition, and hardware bridge for safety-critical embedded deployments.
The core insight: WRT already implements all host component functionality (WASI dispatch, component linking, capability enforcement, memory management). Instead of reimplementing this for bare metal, we cross-compile WRT as a
no_stdstatic library and bridge itsHostImportHandlerto Embassy'sembedded-haltraits. Synth's job becomes narrower: compile application components to native ARM, generating calls into the Meld runtime for imports.The Meld Platform
Architecture
Deployment Stack
Mixed-Mode Execution
The Component Model doesn't care how an export is implemented. This enables:
All three execution modes are wired together by Meld's ComponentLinker using the same WIT interface contracts.
Synth's Narrowed Responsibility
With Meld handling host dispatch, Synth only needs to:
Synth does NOT need to:
Implement WASI(Meld handles this)Resolve host functions(Meld's ComponentLinker does this)Manage memory layout for host access(Meld's MemoryAccessor handles this)Implement capability checking(Meld's CapabilityEngine handles this)Changes Required in Synth
1. Preserve Import Metadata
File:
synth-core/src/wasm_decoder.rsCurrently import metadata (module name, function name, type) is discarded during parsing. Store it in
DecodedModule:2. Generate Meld-Compatible Import Stubs
File:
synth-synthesis/src/instruction_selector.rsFor imported functions, generate a call to
meld_dispatch_importinstead of a directBL:3. ELF Relocation Support
File:
synth-backend/src/elf_builder.rsGenerate proper relocations for calls to Meld runtime:
.rel.textsection withR_ARM_CALLentries__meld_dispatch_importasSTB_GLOBAL/SHN_UNDEFSTB_GLOBALwith addressesarm-none-eabi-ld4. Define the Synth↔Meld ABI
A stable calling convention between Synth-compiled code and Meld runtime:
5. Linker Script Updates
File:
synth-backend/src/linker_script.rsAdd sections and symbols for Meld integration:
Changes Required in Meld (WRT)
Tracked separately in the WRT/Meld repository. Key items:
meld-platform-embassy/wrt-platform-embassy)HostImportHandlertrait: replaceVec<Value>withBoundedVecfor no_stdthumbv7em-none-eabihf__meld_dispatch_importas C-linkage function for Synth interopChanges Required in Loom
Minimal:
meld optimizedelegates to Loom)Naming Alignment
Tagline: "Loom optimizes. Synth compiles. Meld deploys."
Milestones
M1: Import Pipeline
DecodedModule__meld_dispatch_importcalls for imported functionsM2: Meld ABI
__meld_dispatch_importin Meld asextern "C"functionM3: Mixed-Mode Demo
M4: Multi-Component
References