diff --git a/crates/wasmparser/src/validator/component_types.rs b/crates/wasmparser/src/validator/component_types.rs index 789f9b2c97..53d0f820e6 100644 --- a/crates/wasmparser/src/validator/component_types.rs +++ b/crates/wasmparser/src/validator/component_types.rs @@ -25,6 +25,9 @@ use core::{ /// Functions that exceed this limit will instead pass parameters indirectly from /// linear memory via a single pointer parameter. const MAX_FLAT_FUNC_PARAMS: usize = 16; +/// The maximum number of parameters in the canonical ABI that can be passed by +/// value in async function imports/exports. +const MAX_FLAT_ASYNC_PARAMS: usize = 4; /// The maximum number of results in the canonical ABI that can be returned by a function. /// /// Functions that exceed this limit have their results written to linear memory via an @@ -931,15 +934,7 @@ impl ComponentFuncType { let mut sig = LoweredSignature::default(); if abi == Abi::Lower && options.concurrency.is_async() { - for _ in 0..2 { - sig.params.assert_push(ValType::I32); - } - sig.results.assert_push(ValType::I32); - options.require_memory(offset)?; - if self.result.is_some_and(|ty| ty.contains_ptr(types)) { - options.require_realloc(offset)?; - } - return Ok(sig.into_func_type()); + sig.params.max = MAX_FLAT_ASYNC_PARAMS; } for (_, ty) in self.params.iter() { @@ -975,9 +970,6 @@ impl ComponentFuncType { } match (abi, options.concurrency) { - (Abi::Lower, Concurrency::Async { .. }) => { - unreachable!("special-cased at the start of the function") - } (Abi::Lower | Abi::Lift, Concurrency::Sync) => { if let Some(ty) = &self.result { // Results of lowered functions that contains pointers must be @@ -1006,10 +998,19 @@ impl ComponentFuncType { } } } - (Abi::Lift, Concurrency::Async { callback: Some(_) }) => { + (Abi::Lower, Concurrency::Async { callback: _ }) => { + if self.result.is_some() { + sig.params.max = MAX_LOWERED_TYPES; + sig.params.assert_push(ValType::I32); + options.require_memory(offset)?; + } sig.results.assert_push(ValType::I32); } - (Abi::Lift, Concurrency::Async { callback: None }) => {} + (Abi::Lift, Concurrency::Async { callback }) => { + if callback.is_some() { + sig.results.assert_push(ValType::I32); + } + } } Ok(sig.into_func_type()) diff --git a/crates/wit-component/tests/components/async-import/component.wat b/crates/wit-component/tests/components/async-import/component.wat index 4036fab673..af47790d81 100644 --- a/crates/wit-component/tests/components/async-import/component.wat +++ b/crates/wit-component/tests/components/async-import/component.wat @@ -9,7 +9,7 @@ (type (;1;) (func (param "s" string) (result string))) (import "foo" (func (;0;) (type 1))) (core module (;0;) - (type (;0;) (func (param i32 i32) (result i32))) + (type (;0;) (func (param i32 i32 i32) (result i32))) (type (;1;) (func (param i32 i32 i32))) (type (;2;) (func (param i32 i32 i32 i32) (result i32))) (import "$root" "[async-lower]foo" (func (;0;) (type 0))) @@ -28,7 +28,7 @@ ) ) (core module (;1;) - (type (;0;) (func (param i32 i32) (result i32))) + (type (;0;) (func (param i32 i32 i32) (result i32))) (type (;1;) (func (param i32 i32 i32))) (table (;0;) 4 4 funcref) (export "0" (func $"indirect-$root-[async-lower]foo")) @@ -36,9 +36,10 @@ (export "2" (func $"indirect-foo:foo/bar-[async-lower]foo")) (export "3" (func $indirect-foo:foo/bar-foo)) (export "$imports" (table 0)) - (func $"indirect-$root-[async-lower]foo" (;0;) (type 0) (param i32 i32) (result i32) + (func $"indirect-$root-[async-lower]foo" (;0;) (type 0) (param i32 i32 i32) (result i32) local.get 0 local.get 1 + local.get 2 i32.const 0 call_indirect (type 0) ) @@ -49,9 +50,10 @@ i32.const 1 call_indirect (type 1) ) - (func $"indirect-foo:foo/bar-[async-lower]foo" (;2;) (type 0) (param i32 i32) (result i32) + (func $"indirect-foo:foo/bar-[async-lower]foo" (;2;) (type 0) (param i32 i32 i32) (result i32) local.get 0 local.get 1 + local.get 2 i32.const 2 call_indirect (type 0) ) @@ -67,7 +69,7 @@ ) ) (core module (;2;) - (type (;0;) (func (param i32 i32) (result i32))) + (type (;0;) (func (param i32 i32 i32) (result i32))) (type (;1;) (func (param i32 i32 i32))) (import "" "0" (func (;0;) (type 0))) (import "" "1" (func (;1;) (type 1))) diff --git a/crates/wit-component/tests/components/async-import/module.wat b/crates/wit-component/tests/components/async-import/module.wat index 723fea947c..df10e1cc4e 100644 --- a/crates/wit-component/tests/components/async-import/module.wat +++ b/crates/wit-component/tests/components/async-import/module.wat @@ -1,6 +1,6 @@ (module - (func (import "$root" "[async-lower]foo") (param i32 i32) (result i32)) - (func (import "foo:foo/bar" "[async-lower]foo") (param i32 i32) (result i32)) + (func (import "$root" "[async-lower]foo") (param i32 i32 i32) (result i32)) + (func (import "foo:foo/bar" "[async-lower]foo") (param i32 i32 i32) (result i32)) (func (import "$root" "foo") (param i32 i32 i32)) (func (import "foo:foo/bar" "foo") (param i32 i32 i32)) (memory (export "memory") 1) diff --git a/crates/wit-component/tests/components/async-streams-and-futures/component.wat b/crates/wit-component/tests/components/async-streams-and-futures/component.wat index 6e1a263019..c377fea50d 100644 --- a/crates/wit-component/tests/components/async-streams-and-futures/component.wat +++ b/crates/wit-component/tests/components/async-streams-and-futures/component.wat @@ -15,99 +15,99 @@ (type (;4;) (func (param "x" 2) (param "y" u32) (result 3))) (import "foo" (func (;0;) (type 4))) (core module (;0;) - (type (;0;) (func (param i32 i32) (result i32))) + (type (;0;) (func (param i32 i32 i32) (result i32))) (type (;1;) (func (result i64))) - (type (;2;) (func (param i32 i32 i32) (result i32))) - (type (;3;) (func (param i32) (result i32))) - (type (;4;) (func (param i32))) + (type (;2;) (func (param i32) (result i32))) + (type (;3;) (func (param i32))) + (type (;4;) (func (param i32 i32) (result i32))) (type (;5;) (func (param i32 i32))) (type (;6;) (func (param i32 i32 i32 i32) (result i32))) (import "$root" "[async-lower]foo" (func (;0;) (type 0))) (import "foo:foo/bar" "[async-lower]foo" (func (;1;) (type 0))) (import "$root" "[stream-new-2]foo" (func (;2;) (type 1))) - (import "$root" "[stream-read-2]foo" (func (;3;) (type 2))) - (import "$root" "[stream-write-2]foo" (func (;4;) (type 2))) - (import "$root" "[stream-cancel-read-2]foo" (func (;5;) (type 3))) - (import "$root" "[stream-cancel-write-2]foo" (func (;6;) (type 3))) - (import "$root" "[stream-close-readable-2]foo" (func (;7;) (type 4))) - (import "$root" "[stream-close-writable-2]foo" (func (;8;) (type 4))) + (import "$root" "[stream-read-2]foo" (func (;3;) (type 0))) + (import "$root" "[stream-write-2]foo" (func (;4;) (type 0))) + (import "$root" "[stream-cancel-read-2]foo" (func (;5;) (type 2))) + (import "$root" "[stream-cancel-write-2]foo" (func (;6;) (type 2))) + (import "$root" "[stream-close-readable-2]foo" (func (;7;) (type 3))) + (import "$root" "[stream-close-writable-2]foo" (func (;8;) (type 3))) (import "foo:foo/bar" "[stream-new-2]foo" (func (;9;) (type 1))) - (import "foo:foo/bar" "[stream-read-2]foo" (func (;10;) (type 2))) - (import "foo:foo/bar" "[stream-write-2]foo" (func (;11;) (type 2))) - (import "foo:foo/bar" "[stream-cancel-read-2]foo" (func (;12;) (type 3))) - (import "foo:foo/bar" "[stream-cancel-write-2]foo" (func (;13;) (type 3))) - (import "foo:foo/bar" "[stream-close-readable-2]foo" (func (;14;) (type 4))) - (import "foo:foo/bar" "[stream-close-writable-2]foo" (func (;15;) (type 4))) + (import "foo:foo/bar" "[stream-read-2]foo" (func (;10;) (type 0))) + (import "foo:foo/bar" "[stream-write-2]foo" (func (;11;) (type 0))) + (import "foo:foo/bar" "[stream-cancel-read-2]foo" (func (;12;) (type 2))) + (import "foo:foo/bar" "[stream-cancel-write-2]foo" (func (;13;) (type 2))) + (import "foo:foo/bar" "[stream-close-readable-2]foo" (func (;14;) (type 3))) + (import "foo:foo/bar" "[stream-close-writable-2]foo" (func (;15;) (type 3))) (import "$root" "[future-new-0]foo" (func (;16;) (type 1))) - (import "$root" "[future-read-0]foo" (func (;17;) (type 0))) - (import "$root" "[future-write-0]foo" (func (;18;) (type 0))) - (import "$root" "[future-cancel-read-0]foo" (func (;19;) (type 3))) - (import "$root" "[future-cancel-write-0]foo" (func (;20;) (type 3))) - (import "$root" "[future-close-readable-0]foo" (func (;21;) (type 4))) - (import "$root" "[future-close-writable-0]foo" (func (;22;) (type 4))) + (import "$root" "[future-read-0]foo" (func (;17;) (type 4))) + (import "$root" "[future-write-0]foo" (func (;18;) (type 4))) + (import "$root" "[future-cancel-read-0]foo" (func (;19;) (type 2))) + (import "$root" "[future-cancel-write-0]foo" (func (;20;) (type 2))) + (import "$root" "[future-close-readable-0]foo" (func (;21;) (type 3))) + (import "$root" "[future-close-writable-0]foo" (func (;22;) (type 3))) (import "foo:foo/bar" "[future-new-0]foo" (func (;23;) (type 1))) - (import "foo:foo/bar" "[future-read-0]foo" (func (;24;) (type 0))) - (import "foo:foo/bar" "[future-write-0]foo" (func (;25;) (type 0))) - (import "foo:foo/bar" "[future-cancel-read-0]foo" (func (;26;) (type 3))) - (import "foo:foo/bar" "[future-cancel-write-0]foo" (func (;27;) (type 3))) - (import "foo:foo/bar" "[future-close-readable-0]foo" (func (;28;) (type 4))) - (import "foo:foo/bar" "[future-close-writable-0]foo" (func (;29;) (type 4))) + (import "foo:foo/bar" "[future-read-0]foo" (func (;24;) (type 4))) + (import "foo:foo/bar" "[future-write-0]foo" (func (;25;) (type 4))) + (import "foo:foo/bar" "[future-cancel-read-0]foo" (func (;26;) (type 2))) + (import "foo:foo/bar" "[future-cancel-write-0]foo" (func (;27;) (type 2))) + (import "foo:foo/bar" "[future-close-readable-0]foo" (func (;28;) (type 3))) + (import "foo:foo/bar" "[future-close-writable-0]foo" (func (;29;) (type 3))) (import "$root" "[future-new-1]foo" (func (;30;) (type 1))) - (import "$root" "[future-read-1]foo" (func (;31;) (type 0))) - (import "$root" "[future-write-1]foo" (func (;32;) (type 0))) - (import "$root" "[future-cancel-read-1]foo" (func (;33;) (type 3))) - (import "$root" "[future-cancel-write-1]foo" (func (;34;) (type 3))) - (import "$root" "[future-close-readable-1]foo" (func (;35;) (type 4))) - (import "$root" "[future-close-writable-1]foo" (func (;36;) (type 4))) + (import "$root" "[future-read-1]foo" (func (;31;) (type 4))) + (import "$root" "[future-write-1]foo" (func (;32;) (type 4))) + (import "$root" "[future-cancel-read-1]foo" (func (;33;) (type 2))) + (import "$root" "[future-cancel-write-1]foo" (func (;34;) (type 2))) + (import "$root" "[future-close-readable-1]foo" (func (;35;) (type 3))) + (import "$root" "[future-close-writable-1]foo" (func (;36;) (type 3))) (import "foo:foo/bar" "[future-new-1]foo" (func (;37;) (type 1))) - (import "foo:foo/bar" "[future-read-1]foo" (func (;38;) (type 0))) - (import "foo:foo/bar" "[future-write-1]foo" (func (;39;) (type 0))) - (import "foo:foo/bar" "[future-cancel-read-1]foo" (func (;40;) (type 3))) - (import "foo:foo/bar" "[future-cancel-write-1]foo" (func (;41;) (type 3))) - (import "foo:foo/bar" "[future-close-readable-1]foo" (func (;42;) (type 4))) - (import "foo:foo/bar" "[future-close-writable-1]foo" (func (;43;) (type 4))) + (import "foo:foo/bar" "[future-read-1]foo" (func (;38;) (type 4))) + (import "foo:foo/bar" "[future-write-1]foo" (func (;39;) (type 4))) + (import "foo:foo/bar" "[future-cancel-read-1]foo" (func (;40;) (type 2))) + (import "foo:foo/bar" "[future-cancel-write-1]foo" (func (;41;) (type 2))) + (import "foo:foo/bar" "[future-close-readable-1]foo" (func (;42;) (type 3))) + (import "foo:foo/bar" "[future-close-writable-1]foo" (func (;43;) (type 3))) (import "[export]$root" "[stream-new-2]foo" (func (;44;) (type 1))) - (import "[export]$root" "[stream-read-2]foo" (func (;45;) (type 2))) - (import "[export]$root" "[stream-write-2]foo" (func (;46;) (type 2))) - (import "[export]$root" "[stream-cancel-read-2]foo" (func (;47;) (type 3))) - (import "[export]$root" "[stream-cancel-write-2]foo" (func (;48;) (type 3))) - (import "[export]$root" "[stream-close-readable-2]foo" (func (;49;) (type 4))) - (import "[export]$root" "[stream-close-writable-2]foo" (func (;50;) (type 4))) + (import "[export]$root" "[stream-read-2]foo" (func (;45;) (type 0))) + (import "[export]$root" "[stream-write-2]foo" (func (;46;) (type 0))) + (import "[export]$root" "[stream-cancel-read-2]foo" (func (;47;) (type 2))) + (import "[export]$root" "[stream-cancel-write-2]foo" (func (;48;) (type 2))) + (import "[export]$root" "[stream-close-readable-2]foo" (func (;49;) (type 3))) + (import "[export]$root" "[stream-close-writable-2]foo" (func (;50;) (type 3))) (import "[export]foo:foo/bar" "[stream-new-2]foo" (func (;51;) (type 1))) - (import "[export]foo:foo/bar" "[stream-read-2]foo" (func (;52;) (type 2))) - (import "[export]foo:foo/bar" "[stream-write-2]foo" (func (;53;) (type 2))) - (import "[export]foo:foo/bar" "[stream-cancel-read-2]foo" (func (;54;) (type 3))) - (import "[export]foo:foo/bar" "[stream-cancel-write-2]foo" (func (;55;) (type 3))) - (import "[export]foo:foo/bar" "[stream-close-readable-2]foo" (func (;56;) (type 4))) - (import "[export]foo:foo/bar" "[stream-close-writable-2]foo" (func (;57;) (type 4))) + (import "[export]foo:foo/bar" "[stream-read-2]foo" (func (;52;) (type 0))) + (import "[export]foo:foo/bar" "[stream-write-2]foo" (func (;53;) (type 0))) + (import "[export]foo:foo/bar" "[stream-cancel-read-2]foo" (func (;54;) (type 2))) + (import "[export]foo:foo/bar" "[stream-cancel-write-2]foo" (func (;55;) (type 2))) + (import "[export]foo:foo/bar" "[stream-close-readable-2]foo" (func (;56;) (type 3))) + (import "[export]foo:foo/bar" "[stream-close-writable-2]foo" (func (;57;) (type 3))) (import "[export]$root" "[future-new-0]foo" (func (;58;) (type 1))) - (import "[export]$root" "[future-read-0]foo" (func (;59;) (type 0))) - (import "[export]$root" "[future-write-0]foo" (func (;60;) (type 0))) - (import "[export]$root" "[future-cancel-read-0]foo" (func (;61;) (type 3))) - (import "[export]$root" "[future-cancel-write-0]foo" (func (;62;) (type 3))) - (import "[export]$root" "[future-close-readable-0]foo" (func (;63;) (type 4))) - (import "[export]$root" "[future-close-writable-0]foo" (func (;64;) (type 4))) + (import "[export]$root" "[future-read-0]foo" (func (;59;) (type 4))) + (import "[export]$root" "[future-write-0]foo" (func (;60;) (type 4))) + (import "[export]$root" "[future-cancel-read-0]foo" (func (;61;) (type 2))) + (import "[export]$root" "[future-cancel-write-0]foo" (func (;62;) (type 2))) + (import "[export]$root" "[future-close-readable-0]foo" (func (;63;) (type 3))) + (import "[export]$root" "[future-close-writable-0]foo" (func (;64;) (type 3))) (import "[export]foo:foo/bar" "[future-new-0]foo" (func (;65;) (type 1))) - (import "[export]foo:foo/bar" "[future-read-0]foo" (func (;66;) (type 0))) - (import "[export]foo:foo/bar" "[future-write-0]foo" (func (;67;) (type 0))) - (import "[export]foo:foo/bar" "[future-cancel-read-0]foo" (func (;68;) (type 3))) - (import "[export]foo:foo/bar" "[future-cancel-write-0]foo" (func (;69;) (type 3))) - (import "[export]foo:foo/bar" "[future-close-readable-0]foo" (func (;70;) (type 4))) - (import "[export]foo:foo/bar" "[future-close-writable-0]foo" (func (;71;) (type 4))) + (import "[export]foo:foo/bar" "[future-read-0]foo" (func (;66;) (type 4))) + (import "[export]foo:foo/bar" "[future-write-0]foo" (func (;67;) (type 4))) + (import "[export]foo:foo/bar" "[future-cancel-read-0]foo" (func (;68;) (type 2))) + (import "[export]foo:foo/bar" "[future-cancel-write-0]foo" (func (;69;) (type 2))) + (import "[export]foo:foo/bar" "[future-close-readable-0]foo" (func (;70;) (type 3))) + (import "[export]foo:foo/bar" "[future-close-writable-0]foo" (func (;71;) (type 3))) (import "[export]$root" "[future-new-1]foo" (func (;72;) (type 1))) - (import "[export]$root" "[future-read-1]foo" (func (;73;) (type 0))) - (import "[export]$root" "[future-write-1]foo" (func (;74;) (type 0))) - (import "[export]$root" "[future-cancel-read-1]foo" (func (;75;) (type 3))) - (import "[export]$root" "[future-cancel-write-1]foo" (func (;76;) (type 3))) - (import "[export]$root" "[future-close-readable-1]foo" (func (;77;) (type 4))) - (import "[export]$root" "[future-close-writable-1]foo" (func (;78;) (type 4))) + (import "[export]$root" "[future-read-1]foo" (func (;73;) (type 4))) + (import "[export]$root" "[future-write-1]foo" (func (;74;) (type 4))) + (import "[export]$root" "[future-cancel-read-1]foo" (func (;75;) (type 2))) + (import "[export]$root" "[future-cancel-write-1]foo" (func (;76;) (type 2))) + (import "[export]$root" "[future-close-readable-1]foo" (func (;77;) (type 3))) + (import "[export]$root" "[future-close-writable-1]foo" (func (;78;) (type 3))) (import "[export]foo:foo/bar" "[future-new-1]foo" (func (;79;) (type 1))) - (import "[export]foo:foo/bar" "[future-read-1]foo" (func (;80;) (type 0))) - (import "[export]foo:foo/bar" "[future-write-1]foo" (func (;81;) (type 0))) - (import "[export]foo:foo/bar" "[future-cancel-read-1]foo" (func (;82;) (type 3))) - (import "[export]foo:foo/bar" "[future-cancel-write-1]foo" (func (;83;) (type 3))) - (import "[export]foo:foo/bar" "[future-close-readable-1]foo" (func (;84;) (type 4))) - (import "[export]foo:foo/bar" "[future-close-writable-1]foo" (func (;85;) (type 4))) + (import "[export]foo:foo/bar" "[future-read-1]foo" (func (;80;) (type 4))) + (import "[export]foo:foo/bar" "[future-write-1]foo" (func (;81;) (type 4))) + (import "[export]foo:foo/bar" "[future-cancel-read-1]foo" (func (;82;) (type 2))) + (import "[export]foo:foo/bar" "[future-cancel-write-1]foo" (func (;83;) (type 2))) + (import "[export]foo:foo/bar" "[future-close-readable-1]foo" (func (;84;) (type 3))) + (import "[export]foo:foo/bar" "[future-close-writable-1]foo" (func (;85;) (type 3))) (memory (;0;) 1) (export "[async-lift-stackful]foo" (func 86)) (export "[async-lift-stackful]foo:foo/bar#foo" (func 87)) @@ -128,7 +128,7 @@ ) ) (core module (;1;) - (type (;0;) (func (param i32 i32) (result i32))) + (type (;0;) (func (param i32 i32 i32) (result i32))) (type (;1;) (func (param i32 i32 i32) (result i32))) (type (;2;) (func (param i32 i32) (result i32))) (table (;0;) 26 26 funcref) @@ -159,9 +159,10 @@ (export "24" (func $"[export]foo:foo/bar-[future-read-1]foo")) (export "25" (func $"[export]foo:foo/bar-[future-write-1]foo")) (export "$imports" (table 0)) - (func $"indirect-$root-[async-lower]foo" (;0;) (type 0) (param i32 i32) (result i32) + (func $"indirect-$root-[async-lower]foo" (;0;) (type 0) (param i32 i32 i32) (result i32) local.get 0 local.get 1 + local.get 2 i32.const 0 call_indirect (type 0) ) @@ -203,9 +204,10 @@ i32.const 6 call_indirect (type 2) ) - (func $"indirect-foo:foo/bar-[async-lower]foo" (;7;) (type 0) (param i32 i32) (result i32) + (func $"indirect-foo:foo/bar-[async-lower]foo" (;7;) (type 0) (param i32 i32 i32) (result i32) local.get 0 local.get 1 + local.get 2 i32.const 7 call_indirect (type 0) ) @@ -328,7 +330,7 @@ ) ) (core module (;2;) - (type (;0;) (func (param i32 i32) (result i32))) + (type (;0;) (func (param i32 i32 i32) (result i32))) (type (;1;) (func (param i32 i32 i32) (result i32))) (type (;2;) (func (param i32 i32) (result i32))) (import "" "0" (func (;0;) (type 0))) diff --git a/crates/wit-component/tests/components/async-streams-and-futures/module.wat b/crates/wit-component/tests/components/async-streams-and-futures/module.wat index 2f2603e656..60fe1bf35d 100644 --- a/crates/wit-component/tests/components/async-streams-and-futures/module.wat +++ b/crates/wit-component/tests/components/async-streams-and-futures/module.wat @@ -1,6 +1,6 @@ (module - (func (import "$root" "[async-lower]foo") (param i32 i32) (result i32)) - (func (import "foo:foo/bar" "[async-lower]foo") (param i32 i32) (result i32)) + (func (import "$root" "[async-lower]foo") (param i32 i32 i32) (result i32)) + (func (import "foo:foo/bar" "[async-lower]foo") (param i32 i32 i32) (result i32)) (func (import "$root" "[stream-new-2]foo") (result i64)) (func (import "$root" "[stream-read-2]foo") (param i32 i32 i32) (result i32)) (func (import "$root" "[stream-write-2]foo") (param i32 i32 i32) (result i32)) diff --git a/crates/wit-parser/src/abi.rs b/crates/wit-parser/src/abi.rs index 9dc0920387..8c69db34d8 100644 --- a/crates/wit-parser/src/abi.rs +++ b/crates/wit-parser/src/abi.rs @@ -168,6 +168,7 @@ impl<'a> FlatTypes<'a> { impl Resolve { const MAX_FLAT_PARAMS: usize = 16; + const MAX_FLAT_ASYNC_PARAMS: usize = 4; const MAX_FLAT_RESULTS: usize = 1; /// Get the WebAssembly type signature for this interface function @@ -175,15 +176,6 @@ impl Resolve { /// The first entry returned is the list of parameters and the second entry /// is the list of results for the wasm function signature. pub fn wasm_signature(&self, variant: AbiVariant, func: &Function) -> WasmSignature { - if let AbiVariant::GuestImportAsync = variant { - return WasmSignature { - params: vec![WasmType::Pointer; 2], - indirect_params: true, - results: vec![WasmType::I32], - retptr: true, - }; - } - // Note that one extra parameter is allocated in case a return pointer // is needed down below for imports. let mut storage = [WasmType::I32; Self::MAX_FLAT_PARAMS + 1]; @@ -191,7 +183,15 @@ impl Resolve { let ok = self.push_flat_list(func.params.iter().map(|(_, param)| param), &mut params); assert_eq!(ok, !params.overflow); - let indirect_params = !ok || params.cur > Self::MAX_FLAT_PARAMS; + let max = match variant { + AbiVariant::GuestImport + | AbiVariant::GuestExport + | AbiVariant::GuestExportAsync + | AbiVariant::GuestExportAsyncStackful => Self::MAX_FLAT_PARAMS, + AbiVariant::GuestImportAsync => Self::MAX_FLAT_ASYNC_PARAMS, + }; + + let indirect_params = !ok || params.cur > max; if indirect_params { params.types[0] = WasmType::Pointer; params.cur = 1; @@ -216,48 +216,53 @@ impl Resolve { } } - match variant { - AbiVariant::GuestExportAsync => { - return WasmSignature { - params: params.to_vec(), - indirect_params, - results: vec![WasmType::Pointer], - retptr: false, - }; - } - AbiVariant::GuestExportAsyncStackful => { - return WasmSignature { - params: params.to_vec(), - indirect_params, - results: Vec::new(), - retptr: false, - }; - } - _ => {} - } - let mut storage = [WasmType::I32; Self::MAX_FLAT_RESULTS]; let mut results = FlatTypes::new(&mut storage); - if let Some(ty) = &func.result { - self.push_flat(ty, &mut results); - } - - let retptr = results.overflow; - - // Rust/C don't support multi-value well right now, so if a function - // would have multiple results then instead truncate it. Imports take a - // return pointer to write into and exports return a pointer they wrote - // into. - if retptr { - results.cur = 0; - match variant { - AbiVariant::GuestImport => { - assert!(params.push(WasmType::Pointer)); + let mut retptr = false; + match variant { + AbiVariant::GuestImport | AbiVariant::GuestExport => { + if let Some(ty) = &func.result { + self.push_flat(ty, &mut results); } - AbiVariant::GuestExport => { - assert!(results.push(WasmType::Pointer)); + retptr = results.overflow; + + // Rust/C don't support multi-value well right now, so if a + // function would have multiple results then instead truncate + // it. Imports take a return pointer to write into and exports + // return a pointer they wrote into. + if retptr { + results.cur = 0; + match variant { + AbiVariant::GuestImport => { + assert!(params.push(WasmType::Pointer)); + } + AbiVariant::GuestExport => { + assert!(results.push(WasmType::Pointer)); + } + _ => unreachable!(), + } + } + } + AbiVariant::GuestImportAsync => { + // If this function has a result, a pointer must be passed to + // get filled in by the async runtime. + if func.result.is_some() { + assert!(params.push(WasmType::Pointer)); + retptr = true; } - _ => unreachable!(), + + // The result of this function is a status code. + assert!(results.push(WasmType::I32)); + } + AbiVariant::GuestExportAsync => { + // The result of this function is a status code. Note that the + // function results are entirely ignored here as they aren't + // part of the ABI and are handled in the `task.return` + // intrinsic. + assert!(results.push(WasmType::I32)); + } + AbiVariant::GuestExportAsyncStackful => { + // No status code, and like async exports no result handling. } } diff --git a/tests/cli/component-model-async/abi.wast b/tests/cli/component-model-async/abi.wast new file mode 100644 index 0000000000..e684da4c94 --- /dev/null +++ b/tests/cli/component-model-async/abi.wast @@ -0,0 +1,172 @@ +;; RUN: wast --assert default --snapshot tests/snapshots % -f cm-async,cm-fixed-size-list,cm-async-stackful + +;; async lower +(component + (core module $libc (memory (export "memory") 1)) + (core instance $libc (instantiate $libc)) + + ;; func() + (import "f1" (func $f1)) + (core func $f1 (canon lower (func $f1) async)) + (core module $m1 (func (import "" "f") (result i32))) + (core instance (instantiate $m1 (with "" (instance (export "f" (func $f1)))))) + + ;; func(x: u32) + (import "f2" (func $f2 (param "x" u32))) + (core func $f2 (canon lower (func $f2) async)) + (core module $m2 (func (import "" "f") (param i32) (result i32))) + (core instance (instantiate $m2 (with "" (instance (export "f" (func $f2)))))) + + ;; func() -> u32 + (import "f3" (func $f3 (result u32))) + (core func $f3 (canon lower (func $f3) async (memory $libc "memory"))) + (core module $m3 (func (import "" "f") (param i32) (result i32))) + (core instance (instantiate $m3 (with "" (instance (export "f" (func $f3)))))) + + ;; func(x: u32, y: f32, z: string) + (import "f4" (func $f4 (param "x" u32) (param "y" f32) (param "z" string))) + (core func $f4 (canon lower (func $f4) async (memory $libc "memory"))) + (core module $m4 (func (import "" "f") (param i32 f32 i32 i32) (result i32))) + (core instance (instantiate $m4 (with "" (instance (export "f" (func $f4)))))) + + ;; func() -> f32 + (import "f5" (func $f5 (result f32))) + (core func $f5 (canon lower (func $f5) async (memory $libc "memory"))) + (core module $m5 (func (import "" "f") (param i32) (result i32))) + (core instance (instantiate $m5 (with "" (instance (export "f" (func $f5)))))) + + ;; func(x: list) -> f32 + (import "f6" (func $f6 (param "x" (list string 6)) (result f32))) + (core func $f6 (canon lower (func $f6) async (memory $libc "memory"))) + (core module $m6 (func (import "" "f") (param i32 i32) (result i32))) + (core instance (instantiate $m6 (with "" (instance (export "f" (func $f6)))))) +) + +;; async lift, callback abi +(component + ;; func() + (core module $m1 + (func (export "cb") (param i32 i32 i32) (result i32) unreachable) + (func (export "f") (result i32) unreachable)) + (core instance $m1 (instantiate $m1)) + (func + (canon lift (core func $m1 "f") async (callback (func $m1 "cb")))) + + ;; func(x: u32) + (core module $m2 + (func (export "cb") (param i32 i32 i32) (result i32) unreachable) + (func (export "f") (param i32) (result i32) unreachable)) + (core instance $m2 (instantiate $m2)) + (func (param "x" u32) + (canon lift (core func $m2 "f") async (callback (func $m2 "cb")))) + + ;; func() -> u32 + (core module $m3 + (func (export "cb") (param i32 i32 i32) (result i32) unreachable) + (func (export "f") (result i32) unreachable)) + (core instance $m3 (instantiate $m3)) + (func (result u32) + (canon lift (core func $m3 "f") async (callback (func $m3 "cb")))) + + ;; func(x: f32) + (core module $m4 + (func (export "cb") (param i32 i32 i32) (result i32) unreachable) + (func (export "f") (param f32) (result i32) unreachable)) + (core instance $m4 (instantiate $m4)) + (func (param "x" f32) + (canon lift (core func $m4 "f") async (callback (func $m4 "cb")))) + + ;; func(x: f32, y: string) + (core module $m5 + (memory (export "memory") 1) + (func (export "cb") (param i32 i32 i32) (result i32) unreachable) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable) + (func (export "f") (param f32 i32 i32) (result i32) unreachable)) + (core instance $m5 (instantiate $m5)) + (func (param "x" f32) (param "y" string) + (canon lift (core func $m5 "f") async (callback (func $m5 "cb")) + (memory $m5 "memory") (realloc (func $m5 "realloc")))) + + ;; func(x: list) + (core module $m6 + (memory (export "memory") 1) + (func (export "cb") (param i32 i32 i32) (result i32) unreachable) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable) + (func (export "f") (param i32 i32 i32 i32 i32 i32 i32 i32) (result i32) unreachable)) + (core instance $m6 (instantiate $m6)) + (func (param "x" (list string 4)) + (canon lift (core func $m6 "f") async (callback (func $m6 "cb")) + (memory $m6 "memory") (realloc (func $m6 "realloc")))) + + ;; func(x: list) + (core module $m7 + (memory (export "memory") 1) + (func (export "cb") (param i32 i32 i32) (result i32) unreachable) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable) + (func (export "f") (param i32) (result i32) unreachable)) + (core instance $m7 (instantiate $m7)) + (func (param "x" (list string 10)) + (canon lift (core func $m7 "f") async (callback (func $m7 "cb")) + (memory $m7 "memory") (realloc (func $m7 "realloc")))) +) + +;; async lift, stackful abi +(component + ;; func() + (core module $m1 + (func (export "f") unreachable)) + (core instance $m1 (instantiate $m1)) + (func + (canon lift (core func $m1 "f") async)) + + ;; func(x: u32) + (core module $m2 + (func (export "f") (param i32) unreachable)) + (core instance $m2 (instantiate $m2)) + (func (param "x" u32) + (canon lift (core func $m2 "f") async)) + + ;; func() -> u32 + (core module $m3 + (func (export "f") unreachable)) + (core instance $m3 (instantiate $m3)) + (func (result u32) + (canon lift (core func $m3 "f") async)) + + ;; func(x: f32) + (core module $m4 + (func (export "f") (param f32) unreachable)) + (core instance $m4 (instantiate $m4)) + (func (param "x" f32) + (canon lift (core func $m4 "f") async)) + + ;; func(x: f32, y: string) + (core module $m5 + (memory (export "memory") 1) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable) + (func (export "f") (param f32 i32 i32) unreachable)) + (core instance $m5 (instantiate $m5)) + (func (param "x" f32) (param "y" string) + (canon lift (core func $m5 "f") async + (memory $m5 "memory") (realloc (func $m5 "realloc")))) + + ;; func(x: list) + (core module $m6 + (memory (export "memory") 1) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable) + (func (export "f") (param i32 i32 i32 i32 i32 i32 i32 i32) unreachable)) + (core instance $m6 (instantiate $m6)) + (func (param "x" (list string 4)) + (canon lift (core func $m6 "f") async + (memory $m6 "memory") (realloc (func $m6 "realloc")))) + + ;; func(x: list) + (core module $m7 + (memory (export "memory") 1) + (func (export "realloc") (param i32 i32 i32 i32) (result i32) unreachable) + (func (export "f") (param i32) unreachable)) + (core instance $m7 (instantiate $m7)) + (func (param "x" (list string 10)) + (canon lift (core func $m7 "f") async + (memory $m7 "memory") (realloc (func $m7 "realloc")))) +) diff --git a/tests/snapshots/cli/component-model-async/abi.wast.json b/tests/snapshots/cli/component-model-async/abi.wast.json new file mode 100644 index 0000000000..b6a59dbeba --- /dev/null +++ b/tests/snapshots/cli/component-model-async/abi.wast.json @@ -0,0 +1,23 @@ +{ + "source_filename": "tests/cli/component-model-async/abi.wast", + "commands": [ + { + "type": "module", + "line": 4, + "filename": "abi.0.wasm", + "module_type": "binary" + }, + { + "type": "module", + "line": 46, + "filename": "abi.1.wasm", + "module_type": "binary" + }, + { + "type": "module", + "line": 114, + "filename": "abi.2.wasm", + "module_type": "binary" + } + ] +} \ No newline at end of file diff --git a/tests/snapshots/cli/component-model-async/abi.wast/0.print b/tests/snapshots/cli/component-model-async/abi.wast/0.print new file mode 100644 index 0000000000..1f2caa6b3e --- /dev/null +++ b/tests/snapshots/cli/component-model-async/abi.wast/0.print @@ -0,0 +1,96 @@ +(component + (core module $libc (;0;) + (memory (;0;) 1) + (export "memory" (memory 0)) + ) + (core instance $libc (;0;) (instantiate $libc)) + (type (;0;) (func)) + (import "f1" (func $f1 (;0;) (type 0))) + (core func $f1 (;0;) (canon lower (func $f1) async)) + (core module $m1 (;1;) + (type (;0;) (func (result i32))) + (import "" "f" (func (;0;) (type 0))) + ) + (core instance (;1;) + (export "f" (func $f1)) + ) + (core instance (;2;) (instantiate $m1 + (with "" (instance 1)) + ) + ) + (type (;1;) (func (param "x" u32))) + (import "f2" (func $f2 (;1;) (type 1))) + (core func $f2 (;1;) (canon lower (func $f2) async)) + (core module $m2 (;2;) + (type (;0;) (func (param i32) (result i32))) + (import "" "f" (func (;0;) (type 0))) + ) + (core instance (;3;) + (export "f" (func $f2)) + ) + (core instance (;4;) (instantiate $m2 + (with "" (instance 3)) + ) + ) + (type (;2;) (func (result u32))) + (import "f3" (func $f3 (;2;) (type 2))) + (alias core export $libc "memory" (core memory (;0;))) + (core func $f3 (;2;) (canon lower (func $f3) async (memory 0))) + (core module $m3 (;3;) + (type (;0;) (func (param i32) (result i32))) + (import "" "f" (func (;0;) (type 0))) + ) + (core instance (;5;) + (export "f" (func $f3)) + ) + (core instance (;6;) (instantiate $m3 + (with "" (instance 5)) + ) + ) + (type (;3;) (func (param "x" u32) (param "y" f32) (param "z" string))) + (import "f4" (func $f4 (;3;) (type 3))) + (alias core export $libc "memory" (core memory (;1;))) + (core func $f4 (;3;) (canon lower (func $f4) async (memory 1))) + (core module $m4 (;4;) + (type (;0;) (func (param i32 f32 i32 i32) (result i32))) + (import "" "f" (func (;0;) (type 0))) + ) + (core instance (;7;) + (export "f" (func $f4)) + ) + (core instance (;8;) (instantiate $m4 + (with "" (instance 7)) + ) + ) + (type (;4;) (func (result f32))) + (import "f5" (func $f5 (;4;) (type 4))) + (alias core export $libc "memory" (core memory (;2;))) + (core func $f5 (;4;) (canon lower (func $f5) async (memory 2))) + (core module $m5 (;5;) + (type (;0;) (func (param i32) (result i32))) + (import "" "f" (func (;0;) (type 0))) + ) + (core instance (;9;) + (export "f" (func $f5)) + ) + (core instance (;10;) (instantiate $m5 + (with "" (instance 9)) + ) + ) + (type (;5;) (list string 6)) + (type (;6;) (func (param "x" 5) (result f32))) + (import "f6" (func $f6 (;5;) (type 6))) + (alias core export $libc "memory" (core memory (;3;))) + (core func $f6 (;5;) (canon lower (func $f6) async (memory 3))) + (core module $m6 (;6;) + (type (;0;) (func (param i32 i32) (result i32))) + (import "" "f" (func (;0;) (type 0))) + ) + (core instance (;11;) + (export "f" (func $f6)) + ) + (core instance (;12;) (instantiate $m6 + (with "" (instance 11)) + ) + ) +) diff --git a/tests/snapshots/cli/component-model-async/abi.wast/1.print b/tests/snapshots/cli/component-model-async/abi.wast/1.print new file mode 100644 index 0000000000..08815a75a2 --- /dev/null +++ b/tests/snapshots/cli/component-model-async/abi.wast/1.print @@ -0,0 +1,150 @@ +(component + (core module $m1 (;0;) + (type (;0;) (func (param i32 i32 i32) (result i32))) + (type (;1;) (func (result i32))) + (export "cb" (func 0)) + (export "f" (func 1)) + (func (;0;) (type 0) (param i32 i32 i32) (result i32) + unreachable + ) + (func (;1;) (type 1) (result i32) + unreachable + ) + ) + (core instance $m1 (;0;) (instantiate $m1)) + (type (;0;) (func)) + (alias core export $m1 "f" (core func (;0;))) + (alias core export $m1 "cb" (core func (;1;))) + (func (;0;) (type 0) (canon lift (core func 0) async (callback 1))) + (core module $m2 (;1;) + (type (;0;) (func (param i32 i32 i32) (result i32))) + (type (;1;) (func (param i32) (result i32))) + (export "cb" (func 0)) + (export "f" (func 1)) + (func (;0;) (type 0) (param i32 i32 i32) (result i32) + unreachable + ) + (func (;1;) (type 1) (param i32) (result i32) + unreachable + ) + ) + (core instance $m2 (;1;) (instantiate $m2)) + (type (;1;) (func (param "x" u32))) + (alias core export $m2 "f" (core func (;2;))) + (alias core export $m2 "cb" (core func (;3;))) + (func (;1;) (type 1) (canon lift (core func 2) async (callback 3))) + (core module $m3 (;2;) + (type (;0;) (func (param i32 i32 i32) (result i32))) + (type (;1;) (func (result i32))) + (export "cb" (func 0)) + (export "f" (func 1)) + (func (;0;) (type 0) (param i32 i32 i32) (result i32) + unreachable + ) + (func (;1;) (type 1) (result i32) + unreachable + ) + ) + (core instance $m3 (;2;) (instantiate $m3)) + (type (;2;) (func (result u32))) + (alias core export $m3 "f" (core func (;4;))) + (alias core export $m3 "cb" (core func (;5;))) + (func (;2;) (type 2) (canon lift (core func 4) async (callback 5))) + (core module $m4 (;3;) + (type (;0;) (func (param i32 i32 i32) (result i32))) + (type (;1;) (func (param f32) (result i32))) + (export "cb" (func 0)) + (export "f" (func 1)) + (func (;0;) (type 0) (param i32 i32 i32) (result i32) + unreachable + ) + (func (;1;) (type 1) (param f32) (result i32) + unreachable + ) + ) + (core instance $m4 (;3;) (instantiate $m4)) + (type (;3;) (func (param "x" f32))) + (alias core export $m4 "f" (core func (;6;))) + (alias core export $m4 "cb" (core func (;7;))) + (func (;3;) (type 3) (canon lift (core func 6) async (callback 7))) + (core module $m5 (;4;) + (type (;0;) (func (param i32 i32 i32) (result i32))) + (type (;1;) (func (param i32 i32 i32 i32) (result i32))) + (type (;2;) (func (param f32 i32 i32) (result i32))) + (memory (;0;) 1) + (export "memory" (memory 0)) + (export "cb" (func 0)) + (export "realloc" (func 1)) + (export "f" (func 2)) + (func (;0;) (type 0) (param i32 i32 i32) (result i32) + unreachable + ) + (func (;1;) (type 1) (param i32 i32 i32 i32) (result i32) + unreachable + ) + (func (;2;) (type 2) (param f32 i32 i32) (result i32) + unreachable + ) + ) + (core instance $m5 (;4;) (instantiate $m5)) + (type (;4;) (func (param "x" f32) (param "y" string))) + (alias core export $m5 "f" (core func (;8;))) + (alias core export $m5 "cb" (core func (;9;))) + (alias core export $m5 "memory" (core memory (;0;))) + (alias core export $m5 "realloc" (core func (;10;))) + (func (;4;) (type 4) (canon lift (core func 8) async (callback 9) (memory 0) (realloc 10))) + (core module $m6 (;5;) + (type (;0;) (func (param i32 i32 i32) (result i32))) + (type (;1;) (func (param i32 i32 i32 i32) (result i32))) + (type (;2;) (func (param i32 i32 i32 i32 i32 i32 i32 i32) (result i32))) + (memory (;0;) 1) + (export "memory" (memory 0)) + (export "cb" (func 0)) + (export "realloc" (func 1)) + (export "f" (func 2)) + (func (;0;) (type 0) (param i32 i32 i32) (result i32) + unreachable + ) + (func (;1;) (type 1) (param i32 i32 i32 i32) (result i32) + unreachable + ) + (func (;2;) (type 2) (param i32 i32 i32 i32 i32 i32 i32 i32) (result i32) + unreachable + ) + ) + (core instance $m6 (;5;) (instantiate $m6)) + (type (;5;) (list string 4)) + (type (;6;) (func (param "x" 5))) + (alias core export $m6 "f" (core func (;11;))) + (alias core export $m6 "cb" (core func (;12;))) + (alias core export $m6 "memory" (core memory (;1;))) + (alias core export $m6 "realloc" (core func (;13;))) + (func (;5;) (type 6) (canon lift (core func 11) async (callback 12) (memory 1) (realloc 13))) + (core module $m7 (;6;) + (type (;0;) (func (param i32 i32 i32) (result i32))) + (type (;1;) (func (param i32 i32 i32 i32) (result i32))) + (type (;2;) (func (param i32) (result i32))) + (memory (;0;) 1) + (export "memory" (memory 0)) + (export "cb" (func 0)) + (export "realloc" (func 1)) + (export "f" (func 2)) + (func (;0;) (type 0) (param i32 i32 i32) (result i32) + unreachable + ) + (func (;1;) (type 1) (param i32 i32 i32 i32) (result i32) + unreachable + ) + (func (;2;) (type 2) (param i32) (result i32) + unreachable + ) + ) + (core instance $m7 (;6;) (instantiate $m7)) + (type (;7;) (list string 10)) + (type (;8;) (func (param "x" 7))) + (alias core export $m7 "f" (core func (;14;))) + (alias core export $m7 "cb" (core func (;15;))) + (alias core export $m7 "memory" (core memory (;2;))) + (alias core export $m7 "realloc" (core func (;16;))) + (func (;6;) (type 8) (canon lift (core func 14) async (callback 15) (memory 2) (realloc 16))) +) diff --git a/tests/snapshots/cli/component-model-async/abi.wast/2.print b/tests/snapshots/cli/component-model-async/abi.wast/2.print new file mode 100644 index 0000000000..83f4c93847 --- /dev/null +++ b/tests/snapshots/cli/component-model-async/abi.wast/2.print @@ -0,0 +1,108 @@ +(component + (core module $m1 (;0;) + (type (;0;) (func)) + (export "f" (func 0)) + (func (;0;) (type 0) + unreachable + ) + ) + (core instance $m1 (;0;) (instantiate $m1)) + (type (;0;) (func)) + (alias core export $m1 "f" (core func (;0;))) + (func (;0;) (type 0) (canon lift (core func 0) async)) + (core module $m2 (;1;) + (type (;0;) (func (param i32))) + (export "f" (func 0)) + (func (;0;) (type 0) (param i32) + unreachable + ) + ) + (core instance $m2 (;1;) (instantiate $m2)) + (type (;1;) (func (param "x" u32))) + (alias core export $m2 "f" (core func (;1;))) + (func (;1;) (type 1) (canon lift (core func 1) async)) + (core module $m3 (;2;) + (type (;0;) (func)) + (export "f" (func 0)) + (func (;0;) (type 0) + unreachable + ) + ) + (core instance $m3 (;2;) (instantiate $m3)) + (type (;2;) (func (result u32))) + (alias core export $m3 "f" (core func (;2;))) + (func (;2;) (type 2) (canon lift (core func 2) async)) + (core module $m4 (;3;) + (type (;0;) (func (param f32))) + (export "f" (func 0)) + (func (;0;) (type 0) (param f32) + unreachable + ) + ) + (core instance $m4 (;3;) (instantiate $m4)) + (type (;3;) (func (param "x" f32))) + (alias core export $m4 "f" (core func (;3;))) + (func (;3;) (type 3) (canon lift (core func 3) async)) + (core module $m5 (;4;) + (type (;0;) (func (param i32 i32 i32 i32) (result i32))) + (type (;1;) (func (param f32 i32 i32))) + (memory (;0;) 1) + (export "memory" (memory 0)) + (export "realloc" (func 0)) + (export "f" (func 1)) + (func (;0;) (type 0) (param i32 i32 i32 i32) (result i32) + unreachable + ) + (func (;1;) (type 1) (param f32 i32 i32) + unreachable + ) + ) + (core instance $m5 (;4;) (instantiate $m5)) + (type (;4;) (func (param "x" f32) (param "y" string))) + (alias core export $m5 "f" (core func (;4;))) + (alias core export $m5 "memory" (core memory (;0;))) + (alias core export $m5 "realloc" (core func (;5;))) + (func (;4;) (type 4) (canon lift (core func 4) async (memory 0) (realloc 5))) + (core module $m6 (;5;) + (type (;0;) (func (param i32 i32 i32 i32) (result i32))) + (type (;1;) (func (param i32 i32 i32 i32 i32 i32 i32 i32))) + (memory (;0;) 1) + (export "memory" (memory 0)) + (export "realloc" (func 0)) + (export "f" (func 1)) + (func (;0;) (type 0) (param i32 i32 i32 i32) (result i32) + unreachable + ) + (func (;1;) (type 1) (param i32 i32 i32 i32 i32 i32 i32 i32) + unreachable + ) + ) + (core instance $m6 (;5;) (instantiate $m6)) + (type (;5;) (list string 4)) + (type (;6;) (func (param "x" 5))) + (alias core export $m6 "f" (core func (;6;))) + (alias core export $m6 "memory" (core memory (;1;))) + (alias core export $m6 "realloc" (core func (;7;))) + (func (;5;) (type 6) (canon lift (core func 6) async (memory 1) (realloc 7))) + (core module $m7 (;6;) + (type (;0;) (func (param i32 i32 i32 i32) (result i32))) + (type (;1;) (func (param i32))) + (memory (;0;) 1) + (export "memory" (memory 0)) + (export "realloc" (func 0)) + (export "f" (func 1)) + (func (;0;) (type 0) (param i32 i32 i32 i32) (result i32) + unreachable + ) + (func (;1;) (type 1) (param i32) + unreachable + ) + ) + (core instance $m7 (;6;) (instantiate $m7)) + (type (;7;) (list string 10)) + (type (;8;) (func (param "x" 7))) + (alias core export $m7 "f" (core func (;8;))) + (alias core export $m7 "memory" (core memory (;2;))) + (alias core export $m7 "realloc" (core func (;9;))) + (func (;6;) (type 8) (canon lift (core func 8) async (memory 2) (realloc 9))) +)