Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Changed

- **`meld fuse` warns when the `multi` memory default is used**
(issue #172, `meld-cli`). The default `--memory multi` produces a
multi-memory core module that `wasm-opt` rejects without
`--enable-multimemory` and that has no single-address-space (MCU)
lowering for `synth`. A user on the happy path
(`meld fuse a b -o fused.wasm`) previously hit that wall silently
at the next tool. `meld fuse` now prints a warning naming the
downstream implication and pointing at
`--memory shared --address-rebase`, and the `--memory` help text
documents it. The *default itself* is intentionally left at
`multi` — flipping it is a high-blast-radius change, and `shared`
carries its own caveat (broken under `memory.grow`, currently
labelled "legacy mode"), so the default flip is deferred as a
separate decision (#172 option 1) rather than made here.

## [0.9.0] — 2026-05-20

### Fixed
Expand Down
48 changes: 46 additions & 2 deletions meld-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ enum Commands {
#[arg(short, long, default_value = "fused.wasm")]
output: String,

/// Memory strategy: "multi" (default) or "shared"
/// Memory strategy. "multi" (default) keeps one linear memory
/// per input component — the fused module then needs
/// `wasm-opt --enable-multimemory` and has no single-address-
/// space (MCU) lowering. "shared" merges into one memory; pair
/// it with --address-rebase for a module the wasm-opt → synth
/// chain accepts directly. See issue #172.
#[arg(long, default_value = "multi")]
memory: String,

Expand Down Expand Up @@ -214,7 +219,21 @@ fn fuse_command(

// Parse memory strategy
let memory_strategy = match memory.as_str() {
"multi" => MemoryStrategy::MultiMemory,
"multi" => {
// #172: the `multi` default produces a multi-memory module
// that wasm-opt rejects without --enable-multimemory and
// that has no MCU (single-address-space) lowering. Warn so
// a user on the happy path is not surprised at the next
// tool in the chain.
eprintln!(
"warning: --memory multi produced a multi-memory module. \
wasm-opt needs --enable-multimemory to consume it, and \
it has no single-address-space (MCU) lowering. For a \
fused module the wasm-opt → synth chain accepts \
directly, re-run with `--memory shared --address-rebase`."
);
MemoryStrategy::MultiMemory
}
"shared" => {
println!("Using shared memory (legacy mode)");
MemoryStrategy::SharedMemory
Expand Down Expand Up @@ -601,6 +620,31 @@ mod tests {
}
}

#[test]
fn test_cli_memory_default_is_multi() {
// #172: the `--memory` default is `multi`. Pin it so a future
// change to the default is a deliberate edit to this test
// (flipping it is a high-blast-radius decision — see #172).
let cli = Cli::try_parse_from(["meld", "fuse", "a.wasm", "-o", "out.wasm"])
.expect("fuse args parse");
match cli.command {
Some(Commands::Fuse { memory, .. }) => assert_eq!(memory, "multi"),
_ => panic!("Expected Fuse command"),
}
}

#[test]
fn test_cli_memory_shared_parses() {
let cli = Cli::try_parse_from([
"meld", "fuse", "a.wasm", "-o", "out.wasm", "--memory", "shared",
])
.expect("fuse args parse");
match cli.command {
Some(Commands::Fuse { memory, .. }) => assert_eq!(memory, "shared"),
_ => panic!("Expected Fuse command"),
}
}

#[test]
fn test_write_import_map() {
// Build a minimal core module with two function imports
Expand Down
Loading