Add float equality
This commit is contained in:
28
README.md
28
README.md
@@ -165,55 +165,55 @@ Now obviously I'm not advocating for replacing FireFox's optimising compiler wit
|
|||||||
|
|
||||||
## Specification compliance
|
## Specification compliance
|
||||||
|
|
||||||
It's hard to judge, since each test in the spec testsuite covers a wide range of features (to check their interactions), but currently 40 out of 76 of the spec suite tests pass when run in Wasmtime with Lightbeam as a backend. Here's the full test output:
|
It's hard to judge, since each test in the spec testsuite covers a wide range of features (to check their interactions), but currently 42 out of 76 of the spec suite tests pass when run in Wasmtime with Lightbeam as a backend. Here's the full test output:
|
||||||
|
|
||||||
```
|
```
|
||||||
running 76 tests
|
running 76 tests
|
||||||
test misc_testsuite::stack_overflow ... ok
|
test misc_testsuite::stack_overflow ... ok
|
||||||
test spec_testsuite::binary ... ok
|
|
||||||
test misc_testsuite::misc_traps ... ok
|
test misc_testsuite::misc_traps ... ok
|
||||||
|
test spec_testsuite::binary ... ok
|
||||||
test spec_testsuite::align ... FAILED
|
test spec_testsuite::align ... FAILED
|
||||||
test spec_testsuite::address ... FAILED
|
test spec_testsuite::address ... FAILED
|
||||||
test spec_testsuite::block ... ok
|
test spec_testsuite::block ... ok
|
||||||
test spec_testsuite::break_drop ... ok
|
test spec_testsuite::break_drop ... ok
|
||||||
test spec_testsuite::call ... FAILED
|
|
||||||
test spec_testsuite::br ... ok
|
test spec_testsuite::br ... ok
|
||||||
test spec_testsuite::call_indirect ... FAILED
|
test spec_testsuite::call ... FAILED
|
||||||
test spec_testsuite::comments ... ok
|
test spec_testsuite::comments ... ok
|
||||||
|
test spec_testsuite::call_indirect ... FAILED
|
||||||
test spec_testsuite::const_ ... ok
|
test spec_testsuite::const_ ... ok
|
||||||
test spec_testsuite::custom ... ok
|
test spec_testsuite::custom ... ok
|
||||||
test spec_testsuite::custom_section ... ok
|
test spec_testsuite::custom_section ... ok
|
||||||
|
test spec_testsuite::br_if ... ok
|
||||||
test spec_testsuite::data ... ok
|
test spec_testsuite::data ... ok
|
||||||
test spec_testsuite::conversions ... FAILED
|
test spec_testsuite::conversions ... FAILED
|
||||||
test spec_testsuite::endianness ... FAILED
|
test spec_testsuite::endianness ... FAILED
|
||||||
test spec_testsuite::elem ... FAILED
|
|
||||||
test spec_testsuite::br_if ... ok
|
|
||||||
test spec_testsuite::exports ... ok
|
test spec_testsuite::exports ... ok
|
||||||
|
test spec_testsuite::elem ... FAILED
|
||||||
test spec_testsuite::f32_bitwise ... FAILED
|
test spec_testsuite::f32_bitwise ... FAILED
|
||||||
test spec_testsuite::br_table ... FAILED
|
test spec_testsuite::br_table ... FAILED
|
||||||
test spec_testsuite::f64_bitwise ... FAILED
|
test spec_testsuite::f64_bitwise ... FAILED
|
||||||
test spec_testsuite::f32 ... FAILED
|
test spec_testsuite::f32 ... FAILED
|
||||||
test spec_testsuite::f32_cmp ... FAILED
|
|
||||||
test spec_testsuite::fac ... ok
|
test spec_testsuite::fac ... ok
|
||||||
test spec_testsuite::f64 ... FAILED
|
test spec_testsuite::f64 ... FAILED
|
||||||
test spec_testsuite::f64_cmp ... FAILED
|
test spec_testsuite::f32_cmp ... ok
|
||||||
test spec_testsuite::float_memory ... ok
|
test spec_testsuite::float_memory ... ok
|
||||||
|
test spec_testsuite::f64_cmp ... ok
|
||||||
test spec_testsuite::forward ... ok
|
test spec_testsuite::forward ... ok
|
||||||
test spec_testsuite::float_misc ... FAILED
|
test spec_testsuite::float_misc ... FAILED
|
||||||
test spec_testsuite::func_ptrs ... FAILED
|
test spec_testsuite::func_ptrs ... FAILED
|
||||||
test spec_testsuite::get_local ... FAILED
|
test spec_testsuite::get_local ... FAILED
|
||||||
test spec_testsuite::float_exprs ... FAILED
|
|
||||||
test spec_testsuite::float_literals ... ok
|
test spec_testsuite::float_literals ... ok
|
||||||
|
test spec_testsuite::float_exprs ... FAILED
|
||||||
test spec_testsuite::globals ... ok
|
test spec_testsuite::globals ... ok
|
||||||
test spec_testsuite::if_ ... FAILED
|
|
||||||
test spec_testsuite::func ... ok
|
test spec_testsuite::func ... ok
|
||||||
|
test spec_testsuite::if_ ... FAILED
|
||||||
test spec_testsuite::inline_module ... ok
|
test spec_testsuite::inline_module ... ok
|
||||||
test spec_testsuite::imports ... FAILED
|
test spec_testsuite::imports ... FAILED
|
||||||
test spec_testsuite::i32 ... ok
|
test spec_testsuite::i32 ... ok
|
||||||
test spec_testsuite::i64 ... ok
|
|
||||||
test spec_testsuite::int_literals ... ok
|
test spec_testsuite::int_literals ... ok
|
||||||
test spec_testsuite::labels ... ok
|
test spec_testsuite::labels ... ok
|
||||||
test spec_testsuite::linking ... FAILED
|
test spec_testsuite::linking ... FAILED
|
||||||
|
test spec_testsuite::i64 ... ok
|
||||||
test spec_testsuite::left_to_right ... FAILED
|
test spec_testsuite::left_to_right ... FAILED
|
||||||
test spec_testsuite::loop_ ... FAILED
|
test spec_testsuite::loop_ ... FAILED
|
||||||
test spec_testsuite::memory ... FAILED
|
test spec_testsuite::memory ... FAILED
|
||||||
@@ -234,11 +234,11 @@ test spec_testsuite::tee_local ... FAILED
|
|||||||
test spec_testsuite::token ... ok
|
test spec_testsuite::token ... ok
|
||||||
test spec_testsuite::switch ... ok
|
test spec_testsuite::switch ... ok
|
||||||
test spec_testsuite::type_ ... ok
|
test spec_testsuite::type_ ... ok
|
||||||
test spec_testsuite::return_ ... ok
|
|
||||||
test spec_testsuite::typecheck ... ok
|
test spec_testsuite::typecheck ... ok
|
||||||
test spec_testsuite::traps ... FAILED
|
test spec_testsuite::traps ... FAILED
|
||||||
test spec_testsuite::unwind ... FAILED
|
test spec_testsuite::return_ ... ok
|
||||||
test spec_testsuite::unreached_invalid ... ok
|
test spec_testsuite::unreached_invalid ... ok
|
||||||
|
test spec_testsuite::unwind ... FAILED
|
||||||
test spec_testsuite::utf8_custom_section_id ... ok
|
test spec_testsuite::utf8_custom_section_id ... ok
|
||||||
test spec_testsuite::utf8_import_field ... ok
|
test spec_testsuite::utf8_import_field ... ok
|
||||||
test spec_testsuite::utf8_import_module ... ok
|
test spec_testsuite::utf8_import_module ... ok
|
||||||
@@ -246,7 +246,7 @@ test spec_testsuite::utf8_invalid_encoding ... ok
|
|||||||
test spec_testsuite::unreachable ... ok
|
test spec_testsuite::unreachable ... ok
|
||||||
test spec_testsuite::names ... FAILED
|
test spec_testsuite::names ... FAILED
|
||||||
|
|
||||||
test result: FAILED. 40 passed; 36 failed; 0 ignored; 0 measured; 0 filtered out
|
test result: FAILED. 42 passed; 34 failed; 0 ignored; 0 measured; 0 filtered out
|
||||||
```
|
```
|
||||||
|
|
||||||
## Getting involved
|
## Getting involved
|
||||||
|
|||||||
@@ -1245,6 +1245,48 @@ macro_rules! cmp_f32 {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! eq_float {
|
||||||
|
($name:ident, $instr:ident, $imm_fn:ident, $const_fallback:expr) => {
|
||||||
|
pub fn $name(&mut self) {
|
||||||
|
let right = self.pop();
|
||||||
|
let left = self.pop();
|
||||||
|
|
||||||
|
if let Some(right) = right.immediate() {
|
||||||
|
if let Some(left) = left.immediate() {
|
||||||
|
self.push(ValueLocation::Immediate(
|
||||||
|
if $const_fallback(left.$imm_fn().unwrap(), right.$imm_fn().unwrap()) {
|
||||||
|
1u32
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}.into()
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (left, right) = match left {
|
||||||
|
ValueLocation::Reg(r) if self.block_state.regs.num_usages(r) <= 1 => (left, right),
|
||||||
|
_ => (right, left)
|
||||||
|
};
|
||||||
|
|
||||||
|
let left = self.into_temp_reg(GPRType::Rx, left);
|
||||||
|
let right = self.into_reg(GPRType::Rx, right);
|
||||||
|
let out = self.block_state.regs.take(I32);
|
||||||
|
|
||||||
|
dynasm!(self.asm
|
||||||
|
; $instr Rx(left.rx().unwrap()), Rx(right.rx().unwrap())
|
||||||
|
; movd Rd(out.rq().unwrap()), Rx(left.rx().unwrap())
|
||||||
|
; and Rd(out.rq().unwrap()), 1
|
||||||
|
);
|
||||||
|
|
||||||
|
self.push(ValueLocation::Reg(out));
|
||||||
|
self.free_value(ValueLocation::Reg(left));
|
||||||
|
self.free_value(ValueLocation::Reg(right));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! cmp_f64 {
|
macro_rules! cmp_f64 {
|
||||||
($name:ident, $reverse_name:ident, $instr:ident, $const_fallback:expr) => {
|
($name:ident, $reverse_name:ident, $instr:ident, $const_fallback:expr) => {
|
||||||
cmp_float!(
|
cmp_float!(
|
||||||
@@ -1855,9 +1897,33 @@ impl<'module, M: ModuleContext> Context<'module, M> {
|
|||||||
|
|
||||||
cmp_f32!(f32_gt, f32_lt, seta, |a, b| a > b);
|
cmp_f32!(f32_gt, f32_lt, seta, |a, b| a > b);
|
||||||
cmp_f32!(f32_ge, f32_le, setnc, |a, b| a >= b);
|
cmp_f32!(f32_ge, f32_le, setnc, |a, b| a >= b);
|
||||||
|
eq_float!(
|
||||||
|
f32_eq,
|
||||||
|
cmpeqss,
|
||||||
|
as_f32,
|
||||||
|
|a: wasmparser::Ieee32, b: wasmparser::Ieee32| f32::from_bits(a.0) == f32::from_bits(b.0)
|
||||||
|
);
|
||||||
|
eq_float!(
|
||||||
|
f32_ne,
|
||||||
|
cmpneqss,
|
||||||
|
as_f32,
|
||||||
|
|a: wasmparser::Ieee32, b: wasmparser::Ieee32| f32::from_bits(a.0) != f32::from_bits(b.0)
|
||||||
|
);
|
||||||
|
|
||||||
cmp_f64!(f64_gt, f64_lt, seta, |a, b| a > b);
|
cmp_f64!(f64_gt, f64_lt, seta, |a, b| a > b);
|
||||||
cmp_f64!(f64_ge, f64_le, setnc, |a, b| a >= b);
|
cmp_f64!(f64_ge, f64_le, setnc, |a, b| a >= b);
|
||||||
|
eq_float!(
|
||||||
|
f64_eq,
|
||||||
|
cmpeqsd,
|
||||||
|
as_f64,
|
||||||
|
|a: wasmparser::Ieee64, b: wasmparser::Ieee64| f64::from_bits(a.0) == f64::from_bits(b.0)
|
||||||
|
);
|
||||||
|
eq_float!(
|
||||||
|
f64_ne,
|
||||||
|
cmpneqsd,
|
||||||
|
as_f64,
|
||||||
|
|a: wasmparser::Ieee64, b: wasmparser::Ieee64| f64::from_bits(a.0) != f64::from_bits(b.0)
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: Should we do this logic in `eq` and just have this delegate to `eq`?
|
// TODO: Should we do this logic in `eq` and just have this delegate to `eq`?
|
||||||
// That would mean that `eqz` and `eq` with a const 0 argument don't
|
// That would mean that `eqz` and `eq` with a const 0 argument don't
|
||||||
|
|||||||
@@ -459,6 +459,8 @@ where
|
|||||||
Operator::Div(SF32) => ctx.f32_div(),
|
Operator::Div(SF32) => ctx.f32_div(),
|
||||||
Operator::Neg(Size::_32) => ctx.f32_neg(),
|
Operator::Neg(Size::_32) => ctx.f32_neg(),
|
||||||
Operator::Abs(Size::_32) => ctx.f32_abs(),
|
Operator::Abs(Size::_32) => ctx.f32_abs(),
|
||||||
|
Operator::Eq(F32) => ctx.f32_eq(),
|
||||||
|
Operator::Ne(F32) => ctx.f32_ne(),
|
||||||
Operator::Gt(SF32) => ctx.f32_gt(),
|
Operator::Gt(SF32) => ctx.f32_gt(),
|
||||||
Operator::Ge(SF32) => ctx.f32_ge(),
|
Operator::Ge(SF32) => ctx.f32_ge(),
|
||||||
Operator::Lt(SF32) => ctx.f32_lt(),
|
Operator::Lt(SF32) => ctx.f32_lt(),
|
||||||
@@ -469,6 +471,8 @@ where
|
|||||||
Operator::Div(SF64) => ctx.f64_div(),
|
Operator::Div(SF64) => ctx.f64_div(),
|
||||||
Operator::Neg(Size::_64) => ctx.f64_neg(),
|
Operator::Neg(Size::_64) => ctx.f64_neg(),
|
||||||
Operator::Abs(Size::_64) => ctx.f64_abs(),
|
Operator::Abs(Size::_64) => ctx.f64_abs(),
|
||||||
|
Operator::Eq(F64) => ctx.f64_eq(),
|
||||||
|
Operator::Ne(F64) => ctx.f64_ne(),
|
||||||
Operator::Gt(SF64) => ctx.f64_gt(),
|
Operator::Gt(SF64) => ctx.f64_gt(),
|
||||||
Operator::Ge(SF64) => ctx.f64_ge(),
|
Operator::Ge(SF64) => ctx.f64_ge(),
|
||||||
Operator::Lt(SF64) => ctx.f64_lt(),
|
Operator::Lt(SF64) => ctx.f64_lt(),
|
||||||
|
|||||||
Reference in New Issue
Block a user