diff --git a/crates/moon/tests/test_cases/import_shared_memory.in/.gitignore b/crates/moon/tests/test_cases/import_shared_memory.in/.gitignore new file mode 100644 index 00000000..b1283a74 --- /dev/null +++ b/crates/moon/tests/test_cases/import_shared_memory.in/.gitignore @@ -0,0 +1,2 @@ +target/ +.mooncakes/ diff --git a/crates/moon/tests/test_cases/import_shared_memory.in/README.md b/crates/moon/tests/test_cases/import_shared_memory.in/README.md new file mode 100644 index 00000000..ae00983f --- /dev/null +++ b/crates/moon/tests/test_cases/import_shared_memory.in/README.md @@ -0,0 +1 @@ +# username/hello \ No newline at end of file diff --git a/crates/moon/tests/test_cases/import_shared_memory.in/lib/hello.mbt b/crates/moon/tests/test_cases/import_shared_memory.in/lib/hello.mbt new file mode 100644 index 00000000..9012592a --- /dev/null +++ b/crates/moon/tests/test_cases/import_shared_memory.in/lib/hello.mbt @@ -0,0 +1,3 @@ +pub fn hello() -> String { + "Hello, world!" +} diff --git a/crates/moon/tests/test_cases/import_shared_memory.in/lib/hello_test.mbt b/crates/moon/tests/test_cases/import_shared_memory.in/lib/hello_test.mbt new file mode 100644 index 00000000..e70f85d6 --- /dev/null +++ b/crates/moon/tests/test_cases/import_shared_memory.in/lib/hello_test.mbt @@ -0,0 +1,5 @@ +test "hello" { + if @lib.hello() != "Hello, world!" { + fail!("hello() != \"Hello, world!\"") + } +} diff --git a/crates/moon/tests/test_cases/import_shared_memory.in/lib/moon.pkg.json b/crates/moon/tests/test_cases/import_shared_memory.in/lib/moon.pkg.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/crates/moon/tests/test_cases/import_shared_memory.in/lib/moon.pkg.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/crates/moon/tests/test_cases/import_shared_memory.in/main/main.mbt b/crates/moon/tests/test_cases/import_shared_memory.in/main/main.mbt new file mode 100644 index 00000000..d25cb935 --- /dev/null +++ b/crates/moon/tests/test_cases/import_shared_memory.in/main/main.mbt @@ -0,0 +1,3 @@ +fn main { + println(@lib.hello()) +} diff --git a/crates/moon/tests/test_cases/import_shared_memory.in/main/moon.pkg.json b/crates/moon/tests/test_cases/import_shared_memory.in/main/moon.pkg.json new file mode 100644 index 00000000..8c2f2d88 --- /dev/null +++ b/crates/moon/tests/test_cases/import_shared_memory.in/main/moon.pkg.json @@ -0,0 +1,31 @@ +{ + "is-main": true, + "import": [ + "username/hello/lib" + ], + "link": { + "wasm": { + "heap-start-address": 65536, + "import-memory": { + "module": "xxx", + "name": "yyy" + }, + "memory-limits": { + "min": 1, + "max": 65536 + }, + "shared-memory": true + }, + "wasm-gc": { + "import-memory": { + "module": "xxx", + "name": "yyy" + }, + "memory-limits": { + "min": 1, + "max": 65536 + }, + "shared-memory": true + } + } +} \ No newline at end of file diff --git a/crates/moon/tests/test_cases/import_shared_memory.in/moon.mod.json b/crates/moon/tests/test_cases/import_shared_memory.in/moon.mod.json new file mode 100644 index 00000000..80554ae2 --- /dev/null +++ b/crates/moon/tests/test_cases/import_shared_memory.in/moon.mod.json @@ -0,0 +1,9 @@ +{ + "name": "username/hello", + "version": "0.1.0", + "readme": "README.md", + "repository": "", + "license": "", + "keywords": [], + "description": "" +} \ No newline at end of file diff --git a/crates/moon/tests/test_cases/mod.rs b/crates/moon/tests/test_cases/mod.rs index 9e1d2be9..19f10bbc 100644 --- a/crates/moon/tests/test_cases/mod.rs +++ b/crates/moon/tests/test_cases/mod.rs @@ -5467,6 +5467,49 @@ fn test_import_memory_and_heap_start() { ); } +#[test] +fn test_import_shared_memory() { + let dir = TestDir::new("import_shared_memory.in"); + check( + get_stdout( + &dir, + [ + "build", + "--target", + "wasm", + "--dry-run", + "--sort-input", + "--nostd", + ], + ), + expect![[r#" + moonc build-package ./lib/hello.mbt -o ./target/wasm/release/build/lib/lib.core -pkg username/hello/lib -pkg-sources username/hello/lib:./lib -target wasm + moonc build-package ./main/main.mbt -o ./target/wasm/release/build/main/main.core -pkg username/hello/main -is-main -i ./target/wasm/release/build/lib/lib.mi:lib -pkg-sources username/hello/main:./main -target wasm + moonc link-core ./target/wasm/release/build/lib/lib.core ./target/wasm/release/build/main/main.core -main username/hello/main -o ./target/wasm/release/build/main/main.wasm -pkg-config-path ./main/moon.pkg.json -pkg-sources username/hello/lib:./lib -pkg-sources username/hello/main:./main -target wasm -import-memory-module xxx -import-memory-name yyy -memory-limits-min 1 -memory-limits-max 65536 -shared-memory -heap-start-address 65536 + "#]], + ); + + let dir = TestDir::new("import_shared_memory.in"); + check( + get_stdout( + &dir, + [ + "build", + "--target", + "wasm-gc", + "--dry-run", + "--sort-input", + "--nostd", + ], + ), + expect![[r#" + moonc build-package ./lib/hello.mbt -o ./target/wasm-gc/release/build/lib/lib.core -pkg username/hello/lib -pkg-sources username/hello/lib:./lib -target wasm-gc + moonc build-package ./main/main.mbt -o ./target/wasm-gc/release/build/main/main.core -pkg username/hello/main -is-main -i ./target/wasm-gc/release/build/lib/lib.mi:lib -pkg-sources username/hello/main:./main -target wasm-gc + moonc link-core ./target/wasm-gc/release/build/lib/lib.core ./target/wasm-gc/release/build/main/main.core -main username/hello/main -o ./target/wasm-gc/release/build/main/main.wasm -pkg-config-path ./main/moon.pkg.json -pkg-sources username/hello/lib:./lib -pkg-sources username/hello/main:./main -target wasm-gc -import-memory-module xxx -import-memory-name yyy -memory-limits-min 1 -memory-limits-max 65536 -shared-memory + "#]], + ); +} + #[test] fn test_many_targets() { let dir = TestDir::new("test_many_targets.in"); diff --git a/crates/moonbuild/src/gen/gen_build.rs b/crates/moonbuild/src/gen/gen_build.rs index d1dd34dd..4324196d 100644 --- a/crates/moonbuild/src/gen/gen_build.rs +++ b/crates/moonbuild/src/gen/gen_build.rs @@ -346,6 +346,8 @@ pub fn gen_link_command( let export_memory_name = item.export_memory_name(moonc_opt.link_opt.target_backend); let heap_start_address = item.heap_start_address(moonc_opt.link_opt.target_backend); let import_memory = item.import_memory(moonc_opt.link_opt.target_backend); + let memory_limits = item.memory_limits(moonc_opt.link_opt.target_backend); + let shared_memory = item.shared_memory(moonc_opt.link_opt.target_backend); let link_flags = item.link_flags(moonc_opt.link_opt.target_backend); let native_cc = item.native_cc(moonc_opt.link_opt.target_backend); @@ -421,6 +423,23 @@ pub fn gen_link_command( im.name.clone(), ] }) + .lazy_args_with_cond(memory_limits.is_some(), || { + let ml = memory_limits.unwrap(); + vec![ + "-memory-limits-min".to_string(), + ml.min.to_string(), + "-memory-limits-max".to_string(), + ml.max.to_string(), + ] + }) + .lazy_args_with_cond(shared_memory.is_some(), || { + let sm = shared_memory.unwrap_or(false); + let mut args = vec![]; + if sm { + args.push("-shared-memory".to_string()) + } + args + }) .lazy_args_with_cond(heap_start_address.is_some(), || { vec![ "-heap-start-address".to_string(), diff --git a/crates/moonbuild/template/pkg.schema.json b/crates/moonbuild/template/pkg.schema.json index 582acd14..30a0fc65 100644 --- a/crates/moonbuild/template/pkg.schema.json +++ b/crates/moonbuild/template/pkg.schema.json @@ -353,6 +353,22 @@ "null" ] }, + "memory-limits": { + "anyOf": [ + { + "$ref": "#/definitions/memory-limits" + }, + { + "type": "null" + } + ] + }, + "shared-memory": { + "type": [ + "boolean", + "null" + ] + }, "use-js-builtin-string": { "type": [ "boolean", @@ -405,6 +421,22 @@ "type": "null" } ] + }, + "memory-limits": { + "anyOf": [ + { + "$ref": "#/definitions/memory-limits" + }, + { + "type": "null" + } + ] + }, + "shared-memory": { + "type": [ + "boolean", + "null" + ] } } }, @@ -422,6 +454,25 @@ "type": "string" } } + }, + "memory-limits": { + "type": "object", + "required": [ + "max", + "min" + ], + "properties": { + "max": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "min": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } } } } \ No newline at end of file diff --git a/crates/moonutil/src/package.rs b/crates/moonutil/src/package.rs index 0c26794f..3026c844 100644 --- a/crates/moonutil/src/package.rs +++ b/crates/moonutil/src/package.rs @@ -265,6 +265,13 @@ pub struct ImportMemory { pub name: String, } +#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] +#[schemars(rename = "memory-limits")] +pub struct MemoryLimits { + pub min: u32, + pub max: u32, +} + #[derive(Debug, Clone)] pub struct LinkDepItem { pub out: String, @@ -282,12 +289,16 @@ impl LinkDepItem { pub fn wasm_exports(&self) -> Option<&[String]> { self.link.as_ref()?.wasm.as_ref()?.exports.as_deref() } pub fn wasm_export_memory_name(&self) -> Option<&str> { self.link.as_ref()?.wasm.as_ref()?.export_memory_name.as_deref() } pub fn wasm_import_memory(&self) -> Option<&ImportMemory> { self.link.as_ref()?.wasm.as_ref()?.import_memory.as_ref() } + pub fn wasm_memory_limits(&self) -> Option<&MemoryLimits> { self.link.as_ref()?.wasm.as_ref()?.memory_limits.as_ref() } + pub fn wasm_shared_memory(&self) -> Option { self.link.as_ref()?.wasm.as_ref()?.shared_memory } pub fn wasm_heap_start_address(&self) -> Option { self.link.as_ref()?.wasm.as_ref()?.heap_start_address } pub fn wasm_link_flags(&self) -> Option<&[String]> { self.link.as_ref()?.wasm.as_ref()?.flags.as_deref() } pub fn wasm_gc_exports(&self) -> Option<&[String]> { self.link.as_ref()?.wasm_gc.as_ref()?.exports.as_deref() } pub fn wasm_gc_export_memory_name(&self) -> Option<&str> { self.link.as_ref()?.wasm_gc.as_ref()?.export_memory_name.as_deref() } pub fn wasm_gc_import_memory(&self) -> Option<&ImportMemory> { self.link.as_ref()?.wasm_gc.as_ref()?.import_memory.as_ref() } + pub fn wasm_gc_memory_limits(&self) -> Option<&MemoryLimits> { self.link.as_ref()?.wasm.as_ref()?.memory_limits.as_ref() } + pub fn wasm_gc_shared_memory(&self) -> Option { self.link.as_ref()?.wasm.as_ref()?.shared_memory } pub fn wasm_gc_link_flags(&self) -> Option<&[String]> { self.link.as_ref()?.wasm_gc.as_ref()?.flags.as_deref() } pub fn js_exports(&self) -> Option<&[String]> { self.link.as_ref()?.js.as_ref()?.exports.as_deref() } @@ -328,6 +339,24 @@ impl LinkDepItem { } } + pub fn memory_limits(&self, b:TargetBackend) -> Option<&MemoryLimits> { + match b { + Wasm => self.wasm_memory_limits(), + WasmGC => self.wasm_gc_memory_limits(), + Js => None, + Native => None, + } + } + + pub fn shared_memory(&self, b: TargetBackend) -> Option { + match b { + Wasm => self.wasm_shared_memory(), + WasmGC => self.wasm_gc_shared_memory(), + Js => None, + Native => None, + } + } + pub fn link_flags(&self, b: TargetBackend) -> Option<&[String]> { match b { Wasm => self.wasm_link_flags(), @@ -372,6 +401,14 @@ pub struct WasmLinkConfig { #[serde(rename = "import-memory")] pub import_memory: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(rename = "memory-limits")] + pub memory_limits: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(rename = "shared-memory")] + pub shared_memory: Option, + #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "export-memory-name")] pub export_memory_name: Option, @@ -400,6 +437,12 @@ pub struct WasmGcLinkConfig { #[serde(skip_serializing_if = "Option::is_none")] pub import_memory: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub memory_limits: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + pub shared_memory: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub export_memory_name: Option, diff --git a/docs/manual-zh/src/source/pkg_json_schema.html b/docs/manual-zh/src/source/pkg_json_schema.html index a3f603a8..251e996f 100644 --- a/docs/manual-zh/src/source/pkg_json_schema.html +++ b/docs/manual-zh/src/source/pkg_json_schema.html @@ -391,6 +391,22 @@ "null" ] }, + "memory-limits": { + "anyOf": [ + { + "$ref": "#/definitions/memory-limits" + }, + { + "type": "null" + } + ] + }, + "shared-memory": { + "type": [ + "boolean", + "null" + ] + }, "use-js-builtin-string": { "type": [ "boolean", @@ -443,6 +459,22 @@ "type": "null" } ] + }, + "memory-limits": { + "anyOf": [ + { + "$ref": "#/definitions/memory-limits" + }, + { + "type": "null" + } + ] + }, + "shared-memory": { + "type": [ + "boolean", + "null" + ] } } }, @@ -460,6 +492,25 @@ "type": "string" } } + }, + "memory-limits": { + "type": "object", + "required": [ + "max", + "min" + ], + "properties": { + "max": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "min": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } } } } diff --git a/docs/manual/src/source/pkg_json_schema.html b/docs/manual/src/source/pkg_json_schema.html index a3f603a8..251e996f 100644 --- a/docs/manual/src/source/pkg_json_schema.html +++ b/docs/manual/src/source/pkg_json_schema.html @@ -391,6 +391,22 @@ "null" ] }, + "memory-limits": { + "anyOf": [ + { + "$ref": "#/definitions/memory-limits" + }, + { + "type": "null" + } + ] + }, + "shared-memory": { + "type": [ + "boolean", + "null" + ] + }, "use-js-builtin-string": { "type": [ "boolean", @@ -443,6 +459,22 @@ "type": "null" } ] + }, + "memory-limits": { + "anyOf": [ + { + "$ref": "#/definitions/memory-limits" + }, + { + "type": "null" + } + ] + }, + "shared-memory": { + "type": [ + "boolean", + "null" + ] } } }, @@ -460,6 +492,25 @@ "type": "string" } } + }, + "memory-limits": { + "type": "object", + "required": [ + "max", + "min" + ], + "properties": { + "max": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "min": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } } } }