mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-14 09:21:20 +00:00
Fix arithmetic NaN handling in f32.nearest and f64.nearest
This commit is contained in:
@ -26,7 +26,7 @@ pub extern "C" fn nearbyintf32(x: f32) -> f32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if x.is_nan() {
|
if x.is_nan() {
|
||||||
x
|
f32::from_bits(x.to_bits() | (1 << 22))
|
||||||
} else {
|
} else {
|
||||||
let k = f32::EPSILON.recip();
|
let k = f32::EPSILON.recip();
|
||||||
let a = x.abs();
|
let a = x.abs();
|
||||||
@ -64,7 +64,7 @@ pub extern "C" fn nearbyintf64(x: f64) -> f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if x.is_nan() {
|
if x.is_nan() {
|
||||||
x
|
f64::from_bits(x.to_bits() | (1 << 51))
|
||||||
} else {
|
} else {
|
||||||
let k = f64::EPSILON.recip();
|
let k = f64::EPSILON.recip();
|
||||||
let a = x.abs();
|
let a = x.abs();
|
||||||
|
@ -11,51 +11,8 @@ fn main() {
|
|||||||
|
|
||||||
fn create_module_1() -> Box<Instance> {
|
fn create_module_1() -> Box<Instance> {
|
||||||
let module_str = "(module
|
let module_str = "(module
|
||||||
(type (;0;) (func))
|
(import \"spectest\" \"memory\" (memory (;0;) 0))
|
||||||
(type (;1;) (func))
|
(data (;0;) (i32.const 0) \"\"))
|
||||||
(type (;2;) (func (param i64 i64 f64 i64 f64 i64 f32 i32)))
|
|
||||||
(type (;3;) (func (param f64 i64 f64 i64 f64 i64 f32 i32)))
|
|
||||||
(func (;0;) (type 0))
|
|
||||||
(func (;1;) (type 3) (param f64 i64 f64 i64 f64 i64 f32 i32))
|
|
||||||
(func (;2;) (type 0))
|
|
||||||
(func (;3;) (type 3) (param f64 i64 f64 i64 f64 i64 f32 i32))
|
|
||||||
(func (;4;) (type 3) (param f64 i64 f64 i64 f64 i64 f32 i32))
|
|
||||||
(func (;5;) (type 2) (param i64 i64 f64 i64 f64 i64 f32 i32))
|
|
||||||
(func (;6;) (type 2) (param i64 i64 f64 i64 f64 i64 f32 i32))
|
|
||||||
(func (;7;) (type 0)
|
|
||||||
f64.const 0x0p+0 (;=0;)
|
|
||||||
i64.const 0
|
|
||||||
f64.const 0x0p+0 (;=0;)
|
|
||||||
i64.const 0
|
|
||||||
f64.const 0x0p+0 (;=0;)
|
|
||||||
i64.const 0
|
|
||||||
f32.const 0x0p+0 (;=0;)
|
|
||||||
i32.const 0
|
|
||||||
i32.const 0
|
|
||||||
call_indirect (type 3)
|
|
||||||
f64.const 0x0p+0 (;=0;)
|
|
||||||
i64.const 0
|
|
||||||
f64.const 0x0p+0 (;=0;)
|
|
||||||
i64.const 0
|
|
||||||
f64.const 0x0p+0 (;=0;)
|
|
||||||
i64.const 0
|
|
||||||
f32.const 0x0p+0 (;=0;)
|
|
||||||
i32.const 0
|
|
||||||
i32.const 2
|
|
||||||
call_indirect (type 3)
|
|
||||||
f64.const 0x0p+0 (;=0;)
|
|
||||||
i64.const 0
|
|
||||||
f64.const 0x0p+0 (;=0;)
|
|
||||||
i64.const 0
|
|
||||||
f64.const 0x0p+0 (;=0;)
|
|
||||||
i64.const 0
|
|
||||||
f32.const 0x0p+0 (;=0;)
|
|
||||||
i32.const 0
|
|
||||||
i32.const 3
|
|
||||||
call_indirect (type 3))
|
|
||||||
(table (;0;) 7 7 anyfunc)
|
|
||||||
(export \"signature-implicit-reused\" (func 7))
|
|
||||||
(elem (;0;) (i32.const 0) 4 2 1 4 0 5 6))
|
|
||||||
";
|
";
|
||||||
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
let wasm_binary = wat2wasm(module_str.as_bytes()).expect("WAST not valid or malformed");
|
||||||
let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new()).expect("WASM can't be compiled");
|
let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new()).expect("WASM can't be compiled");
|
||||||
|
@ -179,94 +179,104 @@ impl ImportBacking {
|
|||||||
"imported tables not yet supported"
|
"imported tables not yet supported"
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut functions = Vec::with_capacity(module.imported_functions.len());
|
Ok(ImportBacking {
|
||||||
for (
|
functions: import_functions(module, imports)?,
|
||||||
index,
|
memories: vec![].into_boxed_slice(),
|
||||||
|
tables: vec![].into_boxed_slice(),
|
||||||
|
globals: import_globals(module, imports)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn import_memories(module: &Module, imports: &dyn ImportResolver) -> Result<Box<[vm::ImportedMemory]>, String> {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn import_functions(module: &Module, imports: &dyn ImportResolver) -> Result<Box<[vm::ImportedFunc]>, String> {
|
||||||
|
let mut functions = Vec::with_capacity(module.imported_functions.len());
|
||||||
|
for (
|
||||||
|
index,
|
||||||
|
ImportName {
|
||||||
|
module: mod_name,
|
||||||
|
name: item_name,
|
||||||
|
},
|
||||||
|
) in &module.imported_functions
|
||||||
|
{
|
||||||
|
let sig_index = module.func_assoc[index];
|
||||||
|
let expected_sig = module.sig_registry.lookup_func_sig(sig_index);
|
||||||
|
let import = imports.get(mod_name, item_name);
|
||||||
|
match import {
|
||||||
|
Some(&Import::Func(ref func, ref signature)) => {
|
||||||
|
if expected_sig == signature {
|
||||||
|
functions.push(vm::ImportedFunc {
|
||||||
|
func: func.inner(),
|
||||||
|
// vmctx: ptr::null_mut(),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Err(format!(
|
||||||
|
"unexpected signature for {:?}:{:?}",
|
||||||
|
mod_name, item_name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(_) => {
|
||||||
|
return Err(format!(
|
||||||
|
"incorrect import type for {}:{}",
|
||||||
|
mod_name, item_name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err(format!("import not found: {}:{}", mod_name, item_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(functions.into_boxed_slice())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn import_globals(module: &Module, imports: &dyn ImportResolver) -> Result<Box<[vm::ImportedGlobal]>, String> {
|
||||||
|
let mut globals = Vec::with_capacity(module.imported_globals.len());
|
||||||
|
for (
|
||||||
|
_,
|
||||||
|
(
|
||||||
ImportName {
|
ImportName {
|
||||||
module: mod_name,
|
module: mod_name,
|
||||||
name: item_name,
|
name: item_name,
|
||||||
},
|
},
|
||||||
) in &module.imported_functions
|
global_desc,
|
||||||
{
|
),
|
||||||
let sig_index = module.func_assoc[index];
|
) in &module.imported_globals
|
||||||
let expected_sig = module.sig_registry.lookup_func_sig(sig_index);
|
{
|
||||||
let import = imports.get(mod_name, item_name);
|
let import = imports.get(mod_name, item_name);
|
||||||
match import {
|
match import {
|
||||||
Some(&Import::Func(ref func, ref signature)) => {
|
Some(Import::Global(val)) => {
|
||||||
if expected_sig == signature {
|
if val.ty() == global_desc.ty {
|
||||||
functions.push(vm::ImportedFunc {
|
globals.push(vm::ImportedGlobal {
|
||||||
func: func.inner(),
|
global: vm::LocalGlobal {
|
||||||
// vmctx: ptr::null_mut(),
|
data: match val {
|
||||||
});
|
Value::I32(n) => *n as u64,
|
||||||
} else {
|
Value::I64(n) => *n as u64,
|
||||||
return Err(format!(
|
Value::F32(n) => (*n).to_bits() as u64,
|
||||||
"unexpected signature for {:?}:{:?}",
|
Value::F64(n) => (*n).to_bits(),
|
||||||
mod_name, item_name
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(_) => {
|
|
||||||
return Err(format!(
|
|
||||||
"incorrect import type for {}:{}",
|
|
||||||
mod_name, item_name
|
|
||||||
));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
return Err(format!("import not found: {}:{}", mod_name, item_name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut globals = Vec::with_capacity(module.imported_globals.len());
|
|
||||||
for (
|
|
||||||
_,
|
|
||||||
(
|
|
||||||
ImportName {
|
|
||||||
module: mod_name,
|
|
||||||
name: item_name,
|
|
||||||
},
|
|
||||||
global_desc,
|
|
||||||
),
|
|
||||||
) in &module.imported_globals
|
|
||||||
{
|
|
||||||
let import = imports.get(mod_name, item_name);
|
|
||||||
match import {
|
|
||||||
Some(Import::Global(val)) => {
|
|
||||||
if val.ty() == global_desc.ty {
|
|
||||||
globals.push(vm::ImportedGlobal {
|
|
||||||
global: vm::LocalGlobal {
|
|
||||||
data: match val {
|
|
||||||
Value::I32(n) => *n as u64,
|
|
||||||
Value::I64(n) => *n as u64,
|
|
||||||
Value::F32(n) => (*n).to_bits() as u64,
|
|
||||||
Value::F64(n) => (*n).to_bits(),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
} else {
|
});
|
||||||
return Err(format!(
|
} else {
|
||||||
"unexpected global type for {:?}:{:?}",
|
|
||||||
mod_name, item_name
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(_) => {
|
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"incorrect import type for {}:{}",
|
"unexpected global type for {:?}:{:?}",
|
||||||
mod_name, item_name
|
mod_name, item_name
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
None => {
|
}
|
||||||
return Err(format!("import not found: {}:{}", mod_name, item_name));
|
Some(_) => {
|
||||||
}
|
return Err(format!(
|
||||||
|
"incorrect import type for {}:{}",
|
||||||
|
mod_name, item_name
|
||||||
|
));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err(format!("import not found: {}:{}", mod_name, item_name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ImportBacking {
|
|
||||||
functions: functions.into_boxed_slice(),
|
|
||||||
memories: vec![].into_boxed_slice(),
|
|
||||||
tables: vec![].into_boxed_slice(),
|
|
||||||
globals: globals.into_boxed_slice(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
Ok(globals.into_boxed_slice())
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ impl NaNCheck for f32 {
|
|||||||
impl NaNCheck for f64 {
|
impl NaNCheck for f64 {
|
||||||
/// The MSB of the mantissa must be set for a NaN to be a quiet NaN.
|
/// The MSB of the mantissa must be set for a NaN to be a quiet NaN.
|
||||||
fn is_quiet_nan(&self) -> bool {
|
fn is_quiet_nan(&self) -> bool {
|
||||||
let bit_mask = 0b1 << 51; // Used to check if 51st bit is set, which is MSB of the mantissa
|
let bit_mask = 0b1 << 51; // Used to check if 52st bit is set, which is MSB of the mantissa
|
||||||
self.is_nan() && (self.to_bits() & bit_mask) == bit_mask
|
self.is_nan() && (self.to_bits() & bit_mask) == bit_mask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user