Open
Description
Describe the bug
Wasmer with llvm compiler gives wrong execution result for extmul
instructions. The PoC code is as the following:
use wasmer::sys::{EngineBuilder, Features};
use wasmer::{imports, Cranelift, CraneliftOptLevel, Instance, Memory, MemoryType, Module, Store, CompilerConfig};
use wasmer_compiler_llvm::{LLVM, LLVMOptLevel};
use anyhow::Error;
fn main() -> Result<(), Error> {
let diff = 0; // CHANGE HERE!!! (0 and 1)
let mut features = Features::new();
features.multi_value(true);
features.simd(true);
features.threads(true);
let engine = if diff == 0 {
let mut compiler = Cranelift::default();
compiler.canonicalize_nans(true);
compiler.opt_level(CraneliftOptLevel::None);
let engine = EngineBuilder::new(compiler).set_features(Some(features));
engine
} else {
let mut compiler = LLVM::default();
compiler.canonicalize_nans(true);
compiler.opt_level(LLVMOptLevel::None);
let engine = EngineBuilder::new(compiler).set_features(Some(features));
engine
};
let module_wat = r#"
(module
(type (;0;) (func (result v128)))
(import "mem" "mem" (memory (;0;) 1))
(func (;0;) (type 0)
v128.const i32x4 0x40404040 0x40404040 0x40404040 0x40404040
v128.const i32x4 0x00010203 0x807f7e7d 0xcccdcecf 0xfffefdfc
i16x8.extmul_low_i8x16_s)
(export "main" (func 0)))
"#;
let mut store = Store::new(engine);
let module = Module::new(&store, &module_wat)?;
let memory_ty = MemoryType::new(1, None, false);
let memory = Memory::new(&mut store, memory_ty)?;
let imports = imports!{
"mem" => {
"mem" => memory.clone()
}
};
let instance = Instance::new(&mut store, &module, &imports)?;
let main = instance.exports.get_function("main")
.expect("`main` was not an exported function");
let result = main.call(&mut store, vec![].as_slice());
println!("{:?}", result);
Ok(())
}
[package]
name = "wasmer-wrapper"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
wasmer = { version = "4.2.8", features = ["cranelift", "singlepass", "compiler"] }
wasmer-compiler-llvm = "4.2.8"
anyhow = "1.0"
Steps to reproduce
You can change the value of the variable diff
on line 7. (with 0 and 1) It will choose the compiler between Cranelift and llvm.
cargo run --release
Expected behavior
The output should be the one below as Cranelift gives. (0xe0001fc0_1f801f40_00000040_008000c0
) This value is checked to be correct with the WebAssembly interpreter.
Ok([V128(297747715032074996854313701444155343040)])
Actual behavior
Execution with the llvm compiler gives the following result: (0xff80ff00_f340f3c0_1fc01f40_004000c0
)
Ok([V128(339622925012778316421041060864476577984)])
Additional context
- llvm version: 15.0.7