From 66395fcd1cc69e0e45653adc0cd8c42088761473 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Thu, 18 Mar 2021 15:21:40 +0100 Subject: [PATCH] cranelift: add support for the Mac aarch64 calling convention This bumps target-lexicon and adds support for the AppleAarch64 calling convention. Specifically for WebAssembly support, we only have to worry about the new stack slots convention. Stack slots don't need to be at least 8-bytes, they can be as small as the data type's size. For instance, if we need stack slots for (i32, i32), they can be located at offsets (+0, +4). Note that they still need to be properly aligned on the data type they're containing, though, so if we need stack slots for (i32, i64), we can't start the i64 slot at the +4 offset (it must start at the +8 offset). Added one test that was failing on the Mac M1, as well as other tests stressing different yet similar situations. --- Cargo.lock | 4 +- Cargo.toml | 2 +- cranelift/Cargo.toml | 2 +- cranelift/codegen/Cargo.toml | 2 +- cranelift/codegen/meta/src/shared/settings.rs | 1 + cranelift/codegen/src/isa/aarch64/abi.rs | 34 ++++- cranelift/codegen/src/isa/call_conv.rs | 20 ++- cranelift/codegen/src/isa/x64/abi.rs | 3 + cranelift/codegen/src/isa/x86/abi.rs | 1 + cranelift/codegen/src/machinst/abi_impl.rs | 3 +- cranelift/filetests/Cargo.toml | 2 +- cranelift/frontend/Cargo.toml | 2 +- cranelift/jit/Cargo.toml | 2 +- cranelift/native/Cargo.toml | 2 +- cranelift/object/Cargo.toml | 2 +- cranelift/reader/Cargo.toml | 2 +- cranelift/wasm/Cargo.toml | 2 +- crates/debug/Cargo.toml | 2 +- crates/jit/Cargo.toml | 2 +- crates/obj/Cargo.toml | 2 +- crates/profiling/Cargo.toml | 2 +- crates/test-programs/Cargo.toml | 2 +- crates/wasmtime/Cargo.toml | 2 +- fuzz/Cargo.toml | 2 +- tests/all/func.rs | 3 - tests/all/host_funcs.rs | 138 +++++++++++++++++- 26 files changed, 204 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 574c97a2f20c..e5cd71f323ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2705,9 +2705,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.11.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422045212ea98508ae3d28025bc5aaa2bd4a9cdaecd442a08da2ee620ee9ea95" +checksum = "64ae3b39281e4b14b8123bdbaddd472b7dfe215e444181f2f9d2443c2444f834" [[package]] name = "tempfile" diff --git a/Cargo.toml b/Cargo.toml index ab98691b700a..5cc273d1f30f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ wasi-cap-std-sync = { path = "crates/wasi-common/cap-std-sync", version = "0.25. structopt = { version = "0.3.5", features = ["color", "suggestions"] } object = { version = "0.23.0", default-features = false, features = ["write"] } anyhow = "1.0.19" -target-lexicon = { version = "0.11.0", default-features = false } +target-lexicon = { version = "0.12.0", default-features = false } pretty_env_logger = "0.4.0" file-per-thread-logger = "0.1.1" wat = "1.0.36" diff --git a/cranelift/Cargo.toml b/cranelift/Cargo.toml index a5fe3acd3a4e..80a083250ed9 100644 --- a/cranelift/Cargo.toml +++ b/cranelift/Cargo.toml @@ -34,7 +34,7 @@ log = "0.4.8" termcolor = "1.1.2" capstone = { version = "0.7.0", optional = true } wat = { version = "1.0.36", optional = true } -target-lexicon = { version = "0.11", features = ["std"] } +target-lexicon = { version = "0.12", features = ["std"] } peepmatic-souper = { path = "./peepmatic/crates/souper", version = "0.72.0", optional = true } pretty_env_logger = "0.4.0" rayon = { version = "1", optional = true } diff --git a/cranelift/codegen/Cargo.toml b/cranelift/codegen/Cargo.toml index 068c7847a48a..835a92ae64c6 100644 --- a/cranelift/codegen/Cargo.toml +++ b/cranelift/codegen/Cargo.toml @@ -17,7 +17,7 @@ cranelift-codegen-shared = { path = "./shared", version = "0.72.0" } cranelift-entity = { path = "../entity", version = "0.72.0" } cranelift-bforest = { path = "../bforest", version = "0.72.0" } hashbrown = { version = "0.9.1", optional = true } -target-lexicon = "0.11" +target-lexicon = "0.12" log = { version = "0.4.6", default-features = false } serde = { version = "1.0.94", features = ["derive"], optional = true } bincode = { version = "1.2.1", optional = true } diff --git a/cranelift/codegen/meta/src/shared/settings.rs b/cranelift/codegen/meta/src/shared/settings.rs index 2d3cfc6f389d..2acc34118dd7 100644 --- a/cranelift/codegen/meta/src/shared/settings.rs +++ b/cranelift/codegen/meta/src/shared/settings.rs @@ -192,6 +192,7 @@ pub(crate) fn define() -> SettingGroup { "cold", "system_v", "windows_fastcall", + "apple_aarch64", "baldrdash_system_v", "baldrdash_windows", "baldrdash_2020", diff --git a/cranelift/codegen/src/isa/aarch64/abi.rs b/cranelift/codegen/src/isa/aarch64/abi.rs index 2c3776fbf7bb..8f3b2e6f1eb1 100644 --- a/cranelift/codegen/src/isa/aarch64/abi.rs +++ b/cranelift/codegen/src/isa/aarch64/abi.rs @@ -171,6 +171,21 @@ impl ABIMachineSpec for AArch64MachineDeps { let has_baldrdash_tls = call_conv == isa::CallConv::Baldrdash2020; // See AArch64 ABI (https://c9x.me/compile/bib/abi-arm64.pdf), sections 5.4. + // + // MacOS aarch64 is slightly different, see also + // https://developer.apple.com/documentation/xcode/writing_arm64_code_for_apple_platforms. + // We are diverging from the MacOS aarch64 implementation in the + // following ways: + // - sign- and zero- extensions of data types less than 32 bits are not + // implemented yet. + // - i128 arguments passing isn't implemented yet in the standard (non + // MacOS) aarch64 ABI. + // - we align the arguments stack space to a 16-bytes boundary, while + // the MacOS allows aligning only on 8 bytes. In practice it means we're + // slightly overallocating when calling, which is fine, and doesn't + // break our other invariants that the stack is always allocated in + // 16-bytes chunks. + let mut next_xreg = 0; let mut next_vreg = 0; let mut next_stack: u64 = 0; @@ -264,13 +279,24 @@ impl ABIMachineSpec for AArch64MachineDeps { *next_reg += 1; remaining_reg_vals -= 1; } else { - // Compute size. Every arg takes a minimum slot of 8 bytes. (16-byte - // stack alignment happens separately after all args.) + // Compute the stack slot's size. let size = (ty_bits(param.value_type) / 8) as u64; - let size = std::cmp::max(size, 8); - // Align. + + let size = if call_conv != isa::CallConv::AppleAarch64 { + // Every arg takes a minimum slot of 8 bytes. (16-byte stack + // alignment happens separately after all args.) + std::cmp::max(size, 8) + } else { + // MacOS aarch64 allows stack slots with sizes less than 8 + // bytes. They still need to be properly aligned on their + // natural data alignment, though. + size + }; + + // Align the stack slot. debug_assert!(size.is_power_of_two()); next_stack = align_to(next_stack, size); + ret.push(ABIArg::stack( next_stack as i64, param.value_type, diff --git a/cranelift/codegen/src/isa/call_conv.rs b/cranelift/codegen/src/isa/call_conv.rs index 61a94e5a43b0..e764f33c6e37 100644 --- a/cranelift/codegen/src/isa/call_conv.rs +++ b/cranelift/codegen/src/isa/call_conv.rs @@ -10,22 +10,24 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub enum CallConv { - /// Best performance, not ABI-stable + /// Best performance, not ABI-stable. Fast, - /// Smallest caller code size, not ABI-stable + /// Smallest caller code size, not ABI-stable. Cold, - /// System V-style convention used on many platforms + /// System V-style convention used on many platforms. SystemV, - /// Windows "fastcall" convention, also used for x64 and ARM + /// Windows "fastcall" convention, also used for x64 and ARM. WindowsFastcall, - /// SpiderMonkey WebAssembly convention on systems using natively SystemV + /// Mac aarch64 calling convention, which is a tweak aarch64 ABI. + AppleAarch64, + /// SpiderMonkey WebAssembly convention on systems using natively SystemV. BaldrdashSystemV, - /// SpiderMonkey WebAssembly convention on Windows + /// SpiderMonkey WebAssembly convention on Windows. BaldrdashWindows, /// SpiderMonkey WebAssembly convention for "ABI-2020", with extra TLS /// register slots in the frame. Baldrdash2020, - /// Specialized convention for the probestack function + /// Specialized convention for the probestack function. Probestack, } @@ -36,6 +38,7 @@ impl CallConv { // Default to System V for unknown targets because most everything // uses System V. Ok(CallingConvention::SystemV) | Err(()) => Self::SystemV, + Ok(CallingConvention::AppleAarch64) => Self::AppleAarch64, Ok(CallingConvention::WindowsFastcall) => Self::WindowsFastcall, Ok(unimp) => unimplemented!("calling convention: {:?}", unimp), } @@ -49,6 +52,7 @@ impl CallConv { LibcallCallConv::Cold => Self::Cold, LibcallCallConv::SystemV => Self::SystemV, LibcallCallConv::WindowsFastcall => Self::WindowsFastcall, + LibcallCallConv::AppleAarch64 => Self::AppleAarch64, LibcallCallConv::BaldrdashSystemV => Self::BaldrdashSystemV, LibcallCallConv::BaldrdashWindows => Self::BaldrdashWindows, LibcallCallConv::Baldrdash2020 => Self::Baldrdash2020, @@ -80,6 +84,7 @@ impl fmt::Display for CallConv { Self::Cold => "cold", Self::SystemV => "system_v", Self::WindowsFastcall => "windows_fastcall", + Self::AppleAarch64 => "apple_aarch64", Self::BaldrdashSystemV => "baldrdash_system_v", Self::BaldrdashWindows => "baldrdash_windows", Self::Baldrdash2020 => "baldrdash_2020", @@ -96,6 +101,7 @@ impl str::FromStr for CallConv { "cold" => Ok(Self::Cold), "system_v" => Ok(Self::SystemV), "windows_fastcall" => Ok(Self::WindowsFastcall), + "apple_aarch64" => Ok(Self::AppleAarch64), "baldrdash_system_v" => Ok(Self::BaldrdashSystemV), "baldrdash_windows" => Ok(Self::BaldrdashWindows), "baldrdash_2020" => Ok(Self::Baldrdash2020), diff --git a/cranelift/codegen/src/isa/x64/abi.rs b/cranelift/codegen/src/isa/x64/abi.rs index 4ae639568d07..f55478a1c8d3 100644 --- a/cranelift/codegen/src/isa/x64/abi.rs +++ b/cranelift/codegen/src/isa/x64/abi.rs @@ -907,6 +907,7 @@ fn get_intreg_for_retval( _ => None, }, CallConv::BaldrdashWindows | CallConv::Probestack => todo!(), + CallConv::AppleAarch64 => unreachable!(), } } @@ -933,6 +934,7 @@ fn get_fltreg_for_retval( _ => None, }, CallConv::BaldrdashWindows | CallConv::Probestack => todo!(), + CallConv::AppleAarch64 => unreachable!(), } } @@ -1001,6 +1003,7 @@ fn get_callee_saves(call_conv: &CallConv, regs: &Set>) -> Vec< .filter(|r| is_callee_save_fastcall(r.to_reg())) .collect(), CallConv::Probestack => todo!("probestack?"), + CallConv::AppleAarch64 => unreachable!(), }; // Sort registers for deterministic code output. We can do an unstable sort because the // registers will be unique (there are no dups). diff --git a/cranelift/codegen/src/isa/x86/abi.rs b/cranelift/codegen/src/isa/x86/abi.rs index 0117b8918b4e..c6df87ae2203 100644 --- a/cranelift/codegen/src/isa/x86/abi.rs +++ b/cranelift/codegen/src/isa/x86/abi.rs @@ -512,6 +512,7 @@ pub fn prologue_epilogue(func: &mut ir::Function, isa: &dyn TargetIsa) -> Codege } CallConv::Probestack => unimplemented!("probestack calling convention"), CallConv::Baldrdash2020 => unimplemented!("Baldrdash ABI 2020"), + CallConv::AppleAarch64 => unreachable!(), } } diff --git a/cranelift/codegen/src/machinst/abi_impl.rs b/cranelift/codegen/src/machinst/abi_impl.rs index f240c9a238e1..c17406b334d4 100644 --- a/cranelift/codegen/src/machinst/abi_impl.rs +++ b/cranelift/codegen/src/machinst/abi_impl.rs @@ -646,7 +646,8 @@ impl ABICalleeImpl { || call_conv == isa::CallConv::Fast || call_conv == isa::CallConv::Cold || call_conv.extends_baldrdash() - || call_conv.extends_windows_fastcall(), + || call_conv.extends_windows_fastcall() + || call_conv == isa::CallConv::AppleAarch64, "Unsupported calling convention: {:?}", call_conv ); diff --git a/cranelift/filetests/Cargo.toml b/cranelift/filetests/Cargo.toml index 40d643a70831..ccfae3ec1a0c 100644 --- a/cranelift/filetests/Cargo.toml +++ b/cranelift/filetests/Cargo.toml @@ -23,7 +23,7 @@ gimli = { version = "0.23.0", default-features = false, features = ["read"] } log = "0.4.6" memmap2 = "0.2.1" num_cpus = "1.8.0" -target-lexicon = "0.11" +target-lexicon = "0.12" thiserror = "1.0.15" anyhow = "1.0.32" diff --git a/cranelift/frontend/Cargo.toml b/cranelift/frontend/Cargo.toml index 0b70573955e2..68635eeff5ff 100644 --- a/cranelift/frontend/Cargo.toml +++ b/cranelift/frontend/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" [dependencies] cranelift-codegen = { path = "../codegen", version = "0.72.0", default-features = false } -target-lexicon = "0.11" +target-lexicon = "0.12" log = { version = "0.4.6", default-features = false } hashbrown = { version = "0.9.1", optional = true } smallvec = { version = "1.6.1" } diff --git a/cranelift/jit/Cargo.toml b/cranelift/jit/Cargo.toml index c55655aed587..e64da54bcf34 100644 --- a/cranelift/jit/Cargo.toml +++ b/cranelift/jit/Cargo.toml @@ -18,7 +18,7 @@ anyhow = "1.0" region = "2.2.0" libc = { version = "0.2.42" } errno = "0.2.4" -target-lexicon = "0.11" +target-lexicon = "0.12" memmap2 = { version = "0.2.1", optional = true } log = { version = "0.4.6", default-features = false } diff --git a/cranelift/native/Cargo.toml b/cranelift/native/Cargo.toml index c1dcf7153fa0..42c458a03c6e 100644 --- a/cranelift/native/Cargo.toml +++ b/cranelift/native/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" [dependencies] cranelift-codegen = { path = "../codegen", version = "0.72.0", default-features = false } -target-lexicon = "0.11" +target-lexicon = "0.12" [features] default = ["std"] diff --git a/cranelift/object/Cargo.toml b/cranelift/object/Cargo.toml index d26840ad753b..b6799e24c19a 100644 --- a/cranelift/object/Cargo.toml +++ b/cranelift/object/Cargo.toml @@ -13,7 +13,7 @@ edition = "2018" cranelift-module = { path = "../module", version = "0.72.0" } cranelift-codegen = { path = "../codegen", version = "0.72.0", default-features = false, features = ["std"] } object = { version = "0.23.0", default-features = false, features = ["write"] } -target-lexicon = "0.11" +target-lexicon = "0.12" anyhow = "1.0" log = { version = "0.4.6", default-features = false } diff --git a/cranelift/reader/Cargo.toml b/cranelift/reader/Cargo.toml index 8316b592d249..c8d0ae99f960 100644 --- a/cranelift/reader/Cargo.toml +++ b/cranelift/reader/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" [dependencies] cranelift-codegen = { path = "../codegen", version = "0.72.0" } smallvec = "1.6.1" -target-lexicon = "0.11" +target-lexicon = "0.12" thiserror = "1.0.15" [badges] diff --git a/cranelift/wasm/Cargo.toml b/cranelift/wasm/Cargo.toml index 25ed63339fbf..87a1f8c15a6f 100644 --- a/cranelift/wasm/Cargo.toml +++ b/cranelift/wasm/Cargo.toml @@ -25,7 +25,7 @@ thiserror = "1.0.4" [dev-dependencies] wat = "1.0.36" -target-lexicon = "0.11" +target-lexicon = "0.12" # Enable the riscv feature for cranelift-codegen, as some tests require it cranelift-codegen = { path = "../codegen", version = "0.72.0", default-features = false, features = ["riscv"] } diff --git a/crates/debug/Cargo.toml b/crates/debug/Cargo.toml index 0e69efd8fb8d..68ec71297042 100644 --- a/crates/debug/Cargo.toml +++ b/crates/debug/Cargo.toml @@ -16,7 +16,7 @@ gimli = "0.23.0" wasmparser = "0.76" object = { version = "0.23.0", default-features = false, features = ["read_core", "elf", "write"] } wasmtime-environ = { path = "../environ", version = "0.25.0" } -target-lexicon = { version = "0.11.0", default-features = false } +target-lexicon = { version = "0.12.0", default-features = false } anyhow = "1.0" thiserror = "1.0.4" more-asserts = "0.2.1" diff --git a/crates/jit/Cargo.toml b/crates/jit/Cargo.toml index 4ddb6508cd7e..e96466883fde 100644 --- a/crates/jit/Cargo.toml +++ b/crates/jit/Cargo.toml @@ -27,7 +27,7 @@ wasmtime-obj = { path = "../obj", version = "0.25.0" } rayon = { version = "1.0", optional = true } region = "2.2.0" thiserror = "1.0.4" -target-lexicon = { version = "0.11.0", default-features = false } +target-lexicon = { version = "0.12.0", default-features = false } wasmparser = "0.76" more-asserts = "0.2.1" anyhow = "1.0" diff --git a/crates/obj/Cargo.toml b/crates/obj/Cargo.toml index 6748b1d8ecc1..f9dba6e11b63 100644 --- a/crates/obj/Cargo.toml +++ b/crates/obj/Cargo.toml @@ -15,7 +15,7 @@ anyhow = "1.0" wasmtime-environ = { path = "../environ", version = "0.25.0" } object = { version = "0.23.0", default-features = false, features = ["write"] } more-asserts = "0.2.1" -target-lexicon = { version = "0.11.0", default-features = false } +target-lexicon = { version = "0.12.0", default-features = false } wasmtime-debug = { path = "../debug", version = "0.25.0" } [badges] diff --git a/crates/profiling/Cargo.toml b/crates/profiling/Cargo.toml index 712a6e447029..fc22b6f0129a 100644 --- a/crates/profiling/Cargo.toml +++ b/crates/profiling/Cargo.toml @@ -18,7 +18,7 @@ lazy_static = "1.4" libc = { version = "0.2.60", default-features = false } scroll = { version = "0.10.1", features = ["derive"], optional = true } serde = { version = "1.0.99", features = ["derive"] } -target-lexicon = "0.11.0" +target-lexicon = "0.12.0" wasmtime-environ = { path = "../environ", version = "0.25.0" } wasmtime-runtime = { path = "../runtime", version = "0.25.0" } ittapi-rs = { version = "0.1.5", optional = true } diff --git a/crates/test-programs/Cargo.toml b/crates/test-programs/Cargo.toml index 660abc0a47fc..74e16cbd9c8f 100644 --- a/crates/test-programs/Cargo.toml +++ b/crates/test-programs/Cargo.toml @@ -15,7 +15,7 @@ wasi-common = { path = "../wasi-common", version = "0.25.0" } wasi-cap-std-sync = { path = "../wasi-common/cap-std-sync", version = "0.25.0" } wasmtime = { path = "../wasmtime", version = "0.25.0" } wasmtime-wasi = { path = "../wasi", version = "0.25.0" } -target-lexicon = "0.11.0" +target-lexicon = "0.12.0" pretty_env_logger = "0.4.0" tempfile = "3.1.0" os_pipe = "0.9" diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml index c99f37001e3a..39feb1777ab7 100644 --- a/crates/wasmtime/Cargo.toml +++ b/crates/wasmtime/Cargo.toml @@ -19,7 +19,7 @@ wasmtime-jit = { path = "../jit", version = "0.25.0" } wasmtime-cache = { path = "../cache", version = "0.25.0", optional = true } wasmtime-profiling = { path = "../profiling", version = "0.25.0" } wasmtime-fiber = { path = "../fiber", version = "0.25.0", optional = true } -target-lexicon = { version = "0.11.0", default-features = false } +target-lexicon = { version = "0.12.0", default-features = false } wasmparser = "0.76" anyhow = "1.0.19" region = "2.2.0" diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 2b40128d2582..4376f7f20d47 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -13,7 +13,7 @@ cranelift-codegen = { path = "../cranelift/codegen" } cranelift-reader = { path = "../cranelift/reader" } cranelift-wasm = { path = "../cranelift/wasm" } libfuzzer-sys = "0.4.0" -target-lexicon = "0.11" +target-lexicon = "0.12" peepmatic-fuzzing = { path = "../cranelift/peepmatic/crates/fuzzing", optional = true } wasmtime = { path = "../crates/wasmtime" } wasmtime-fuzzing = { path = "../crates/fuzzing" } diff --git a/tests/all/func.rs b/tests/all/func.rs index 73166cc8918a..b334056893ae 100644 --- a/tests/all/func.rs +++ b/tests/all/func.rs @@ -121,9 +121,6 @@ fn signatures_match() { } #[test] -// Note: Cranelift only supports refrerence types (used in the wasm in this -// test) on x64. -#[cfg(target_arch = "x86_64")] fn import_works() -> Result<()> { static HITS: AtomicUsize = AtomicUsize::new(0); diff --git a/tests/all/host_funcs.rs b/tests/all/host_funcs.rs index de9470114418..26d43299417d 100644 --- a/tests/all/host_funcs.rs +++ b/tests/all/host_funcs.rs @@ -219,9 +219,6 @@ fn signatures_match() -> Result<()> { } #[test] -// Note: Cranelift only supports refrerence types (used in the wasm in this -// test) on x64. -#[cfg(target_arch = "x86_64")] fn import_works() -> Result<()> { static HITS: AtomicUsize = AtomicUsize::new(0); @@ -328,6 +325,141 @@ fn import_works() -> Result<()> { Ok(()) } +#[test] +fn call_import_many_args() -> Result<()> { + let wasm = wat::parse_str( + r#" + (import "" "host" (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32))) + (func (export "run") + i32.const 1 + i32.const 2 + i32.const 3 + i32.const 4 + i32.const 5 + i32.const 6 + i32.const 7 + i32.const 8 + i32.const 9 + i32.const 10 + call 0 + ) + "#, + )?; + + let mut config = Config::new(); + + config.wrap_host_func( + "", + "host", + |x1: i32, + x2: i32, + x3: i32, + x4: i32, + x5: i32, + x6: i32, + x7: i32, + x8: i32, + x9: i32, + x10: i32| { + assert_eq!(x1, 1); + assert_eq!(x2, 2); + assert_eq!(x3, 3); + assert_eq!(x4, 4); + assert_eq!(x5, 5); + assert_eq!(x6, 6); + assert_eq!(x7, 7); + assert_eq!(x8, 8); + assert_eq!(x9, 9); + assert_eq!(x10, 10); + }, + ); + + let engine = Engine::new(&config)?; + let module = Module::new(&engine, &wasm)?; + + let store = Store::new(&engine); + let instance = Instance::new( + &store, + &module, + &[store + .get_host_func("", "host") + .expect("should be defined") + .into()], + )?; + + let run = instance.get_func("run").unwrap(); + run.call(&[])?; + + Ok(()) +} + +#[test] +fn call_wasm_many_args() -> Result<()> { + let wasm = wat::parse_str( + r#" + (func (export "run") (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) + i32.const 1 + get_local 0 + i32.ne + if + unreachable + end + + i32.const 10 + get_local 9 + i32.ne + if + unreachable + end + ) + + (func (export "test") + i32.const 1 + i32.const 2 + i32.const 3 + i32.const 4 + i32.const 5 + i32.const 6 + i32.const 7 + i32.const 8 + i32.const 9 + i32.const 10 + call 0 + ) + "#, + )?; + + let config = Config::new(); + let engine = Engine::new(&config)?; + let module = Module::new(&engine, &wasm)?; + + let store = Store::new(&engine); + let instance = Instance::new(&store, &module, &[])?; + + let run = instance.get_func("run").unwrap(); + run.call(&[ + 1.into(), + 2.into(), + 3.into(), + 4.into(), + 5.into(), + 6.into(), + 7.into(), + 8.into(), + 9.into(), + 10.into(), + ])?; + + let typed_run = + instance.get_typed_func::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32), ()>("run")?; + typed_run.call((1, 2, 3, 4, 5, 6, 7, 8, 9, 10))?; + + let test = instance.get_func("test").unwrap(); + test.call(&[])?; + + Ok(()) +} + #[test] fn trap_smoke() -> Result<()> { let mut config = Config::default();