bnjbvr labeled Issue #2734:
Repro:
<details>
use wasmtime::*; fn main() -> Result<(), anyhow::Error> { //pretty_env_logger::init(); // All wasm objects operate within the context of a "store" let engine = Engine::new(Config::new().interruptable(true).cranelift_debug_verifier(true))?; let store = Store::new(&engine); // Modules can be compiled through either the text or binary format let wat = r#" (module (import "" "" (func $host_hello (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32)) ) (func (export "hello") 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 $host_hello) ) "#; let module = Module::new(store.engine(), wat)?; // Host functions can be defined which take/return wasm values and // execute arbitrary code on the host. let host_hello = Func::wrap( &store, |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); }, ); // Instantiation of a module requires specifying its imports and then // afterwards we can fetch exports by name, as well as asserting the // type signature of the function with `get_typed_func`. let instance = Instance::new(&store, &module, &[host_hello.into()])?; let hello = instance.get_typed_func::<(), ()>("hello")?; // And finally we can call the wasm as if it were a Rust function! hello.call(())?; Ok(()) }
</details>
This causes a panic for the 8th argument:
thread 'main' panicked at 'assertion failed: `(left == right)` left: `1`, right: `8`', src/main.rs:54:13
A wasm function calls an import that takes more than 8 arguments. 8 is the cutoff value for "in registers" vs "on the stack" for argument passing in the aarch64 ABI, so this might be related. I have looked at the codegen and what Cranelift generates seems sensible (?), so it's unclear what's going on. Will investigate a bit more tomorrow.
bnjbvr labeled Issue #2734:
Repro:
<details>
use wasmtime::*; fn main() -> Result<(), anyhow::Error> { //pretty_env_logger::init(); // All wasm objects operate within the context of a "store" let engine = Engine::new(Config::new().interruptable(true).cranelift_debug_verifier(true))?; let store = Store::new(&engine); // Modules can be compiled through either the text or binary format let wat = r#" (module (import "" "" (func $host_hello (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32)) ) (func (export "hello") 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 $host_hello) ) "#; let module = Module::new(store.engine(), wat)?; // Host functions can be defined which take/return wasm values and // execute arbitrary code on the host. let host_hello = Func::wrap( &store, |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); }, ); // Instantiation of a module requires specifying its imports and then // afterwards we can fetch exports by name, as well as asserting the // type signature of the function with `get_typed_func`. let instance = Instance::new(&store, &module, &[host_hello.into()])?; let hello = instance.get_typed_func::<(), ()>("hello")?; // And finally we can call the wasm as if it were a Rust function! hello.call(())?; Ok(()) }
</details>
This causes a panic for the 8th argument:
thread 'main' panicked at 'assertion failed: `(left == right)` left: `1`, right: `8`', src/main.rs:54:13
A wasm function calls an import that takes more than 8 arguments. 8 is the cutoff value for "in registers" vs "on the stack" for argument passing in the aarch64 ABI, so this might be related. I have looked at the codegen and what Cranelift generates seems sensible (?), so it's unclear what's going on. Will investigate a bit more tomorrow.
bnjbvr opened Issue #2734:
Repro:
<details>
use wasmtime::*; fn main() -> Result<(), anyhow::Error> { //pretty_env_logger::init(); // All wasm objects operate within the context of a "store" let engine = Engine::new(Config::new().interruptable(true).cranelift_debug_verifier(true))?; let store = Store::new(&engine); // Modules can be compiled through either the text or binary format let wat = r#" (module (import "" "" (func $host_hello (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32)) ) (func (export "hello") 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 $host_hello) ) "#; let module = Module::new(store.engine(), wat)?; // Host functions can be defined which take/return wasm values and // execute arbitrary code on the host. let host_hello = Func::wrap( &store, |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); }, ); // Instantiation of a module requires specifying its imports and then // afterwards we can fetch exports by name, as well as asserting the // type signature of the function with `get_typed_func`. let instance = Instance::new(&store, &module, &[host_hello.into()])?; let hello = instance.get_typed_func::<(), ()>("hello")?; // And finally we can call the wasm as if it were a Rust function! hello.call(())?; Ok(()) }
</details>
This causes a panic for the 8th argument:
thread 'main' panicked at 'assertion failed: `(left == right)` left: `1`, right: `8`', src/main.rs:54:13
A wasm function calls an import that takes more than 8 arguments. 8 is the cutoff value for "in registers" vs "on the stack" for argument passing in the aarch64 ABI, so this might be related. I have looked at the codegen and what Cranelift generates seems sensible (?), so it's unclear what's going on. Will investigate a bit more tomorrow.
cfallin commented on Issue #2734:
It appears that there may be some relevant differences in Apple's aarch64 ABI compared to the standard AAPCS. From this link, there is the statement "Apple platforms diverge from the ARM64 standard ABI in the following ways" followed by a list. I wonder if this is relevant -- I haven't fully digested the details there yet...
cfallin commented on Issue #2734:
Specifically, it seems that for args < 8 bytes that are on the stack, we need to not pad up to 8 bytes -- so args x9 and x10 should be at
[sp]
and[sp+4]
on macOS/aarch64, vs.[sp]
and[sp+8]
on e.g. Linux/aarch64. That doesn't explain the issue with x8, however.
Last updated: Nov 22 2024 at 17:03 UTC