Skip to content

Commit 85f5a38

Browse files
feat: more float conversions
Signed-off-by: Henry <[email protected]>
1 parent 03ff413 commit 85f5a38

File tree

10 files changed

+121
-30
lines changed

10 files changed

+121
-30
lines changed

CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@
2626
- **`cargo workspaces version`**\
2727
Bump the version of all crates in the workspace and push changes to git. This is used for releasing new versions on github.
2828

29-
- **`cargo workspaces publish --from-git`**\
29+
- **`cargo workspaces publish --publish-as-is`**\
3030
Publish all crates in the workspace to crates.io. This should be used a new version has been released on github. After publishing, the version should be bumped to the next dev version.

Cargo.lock

+6-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/tinywasm/src/error.rs

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ pub enum Trap {
1717

1818
/// A division by zero occurred
1919
DivisionByZero,
20+
21+
/// Invalid Integer Conversion
22+
InvalidConversionToInt,
23+
24+
/// Integer Overflow
25+
IntegerOverflow,
2026
}
2127

2228
#[derive(Debug)]

crates/tinywasm/src/runtime/executor/macros.rs

+74
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,77 @@ macro_rules! conv_1 {
1010
}};
1111
}
1212

13+
macro_rules! float_min_max {
14+
(f32, i32) => {
15+
(-2147483904.0_f32, 2147483648.0_f32)
16+
};
17+
(f64, i32) => {
18+
(-2147483649.0_f64, 2147483648.0_f64)
19+
};
20+
(f32, u32) => {
21+
(-1.0_f32, 4294967296.0_f32)
22+
};
23+
(f64, u32) => {
24+
(-1.0_f64, 4294967296.0_f64)
25+
};
26+
(f32, i64) => {
27+
(-9223373136366403584.0_f32, 9223372036854775808.0_f32)
28+
};
29+
(f64, i64) => {
30+
(-9223372036854777856.0_f64, 9223372036854775808.0_f64)
31+
};
32+
(f32, u64) => {
33+
(-1.0_f32, 18446744073709551616.0_f32)
34+
};
35+
(f64, u64) => {
36+
(-1.0_f64, 18446744073709551616.0_f64)
37+
};
38+
// other conversions are not allowed
39+
($from:ty, $to:ty) => {
40+
compile_error!("invalid float conversion");
41+
};
42+
}
43+
44+
// Convert a float to an int, checking for overflow
45+
macro_rules! checked_float_conv_1 {
46+
($from:tt, $to:tt, $stack:ident) => {{
47+
let (min, max) = float_min_max!($from, $to);
48+
let a: $from = $stack.values.pop()?.into();
49+
50+
if a.is_nan() {
51+
return Err(Error::Trap(crate::Trap::InvalidConversionToInt));
52+
}
53+
54+
if a <= min || a >= max {
55+
return Err(Error::Trap(crate::Trap::IntegerOverflow));
56+
}
57+
58+
$stack.values.push((a as $to).into());
59+
}};
60+
}
61+
62+
// Convert a float to an int, checking for overflow
63+
macro_rules! checked_float_conv_2 {
64+
($from:tt, $uty:tt, $to:tt, $stack:ident) => {{
65+
let (min, max) = float_min_max!($from, $uty);
66+
let a: $from = $stack.values.pop()?.into();
67+
68+
if a.is_nan() {
69+
return Err(Error::Trap(crate::Trap::InvalidConversionToInt));
70+
}
71+
72+
log::info!("a: {}", a);
73+
log::info!("min: {}", min);
74+
log::info!("max: {}", max);
75+
76+
if a <= min || a >= max {
77+
return Err(Error::Trap(crate::Trap::IntegerOverflow));
78+
}
79+
80+
$stack.values.push((a as $uty as $to).into());
81+
}};
82+
}
83+
1384
/// Convert the unsigned value on the top of the stack to a specific type
1485
macro_rules! conv_2 {
1586
($ty:ty, $uty:ty, $to:ty, $stack:ident) => {{
@@ -133,8 +204,11 @@ pub(super) use arithmetic_method_self;
133204
pub(super) use arithmetic_op;
134205
pub(super) use checked_arithmetic_method;
135206
pub(super) use checked_arithmetic_method_cast;
207+
pub(super) use checked_float_conv_1;
208+
pub(super) use checked_float_conv_2;
136209
pub(super) use comp;
137210
pub(super) use comp_cast;
138211
pub(super) use comp_zero;
139212
pub(super) use conv_1;
140213
pub(super) use conv_2;
214+
pub(super) use float_min_max;

crates/tinywasm/src/runtime/executor/mod.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ fn exec_one(
172172
}
173173

174174
Block(args, end_offset) => {
175-
// let params = stack.values.pop_block_params(*args, &module)?;
176175
cf.enter_label(
177176
LabelFrame {
178177
instr_ptr: cf.instr_ptr,
@@ -394,7 +393,20 @@ fn exec_one(
394393
F32ReinterpretI32 => {}
395394
F64ReinterpretI64 => {}
396395

397-
i => todo!("{:?}", i),
396+
// unsigned versions of these are a bit broken atm
397+
I32TruncF32S => checked_float_conv_1!(f32, i32, stack),
398+
I32TruncF64S => checked_float_conv_1!(f64, i32, stack),
399+
I32TruncF32U => checked_float_conv_2!(f32, u32, i32, stack),
400+
I32TruncF64U => checked_float_conv_2!(f64, u32, i32, stack),
401+
I64TruncF32S => checked_float_conv_1!(f32, i64, stack),
402+
I64TruncF64S => checked_float_conv_1!(f64, i64, stack),
403+
I64TruncF32U => checked_float_conv_2!(f32, u64, i64, stack),
404+
I64TruncF64U => checked_float_conv_2!(f64, u64, i64, stack),
405+
406+
i => {
407+
log::error!("unimplemented instruction: {:?}", i);
408+
panic!("Unimplemented instruction: {:?}", i)
409+
}
398410
};
399411

400412
Ok(ExecResult::Ok)

crates/tinywasm/src/runtime/executor/traits.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ macro_rules! impl_wasm_float_ops {
2020
match self {
2121
x if x.is_nan() => x,
2222
x if x.is_infinite() || x == 0.0 => x,
23-
x if x > 0.0 && x <= 0.5 => 0.0,
24-
x if x < 0.0 && x >= -0.5 => -0.0,
23+
x if (0.0..=0.5).contains(&x) => 0.0,
24+
x if (-0.5..0.0).contains(&x) => -0.0,
2525
x => x.round(),
2626
}
2727
}

crates/tinywasm/tests/generated/mvp.csv

+1-1
Large diffs are not rendered by default.

crates/tinywasm/tests/generated/progress-mvp.svg

+3-3
Loading

crates/tinywasm/tests/testsuite/run.rs

+14-13
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::borrow::Cow;
33

44
use super::TestSuite;
55
use eyre::{eyre, Result};
6-
use log::{debug, error};
6+
use log::{debug, error, info};
77
use tinywasm_types::TinyWasmModule;
88
use wast::{lexer::Lexer, parser::ParseBuffer, Wast};
99

@@ -135,23 +135,30 @@ impl TestSuite {
135135
Err(err) => test_group.add_result(
136136
&format!("{}-trap", name),
137137
span,
138-
Err(eyre!("test panicked: {:?}", err)),
138+
Err(eyre!("test panicked: {:?}, span: {:?}", err, span.linecol_in(&wast))),
139139
),
140140
Ok(Err(tinywasm::Error::Trap(_))) => {
141141
test_group.add_result(&format!("{}-trap", name), span, Ok(()))
142142
}
143143
Ok(Err(err)) => test_group.add_result(
144144
&format!("{}-trap", name),
145145
span,
146-
Err(eyre!("expected trap, got error: {:?}", err)),
146+
Err(eyre!(
147+
"expected trap, got error: {:?}, span: {:?}",
148+
err,
149+
span.linecol_in(&wast)
150+
)),
151+
),
152+
Ok(Ok(())) => test_group.add_result(
153+
&format!("{}-trap", name),
154+
span,
155+
Err(eyre!("expected trap, got ok, span: {:?}", span.linecol_in(&wast))),
147156
),
148-
Ok(Ok(())) => {
149-
test_group.add_result(&format!("{}-trap", name), span, Err(eyre!("expected trap, got ok")))
150-
}
151157
}
152158
}
153159

154160
AssertReturn { span, exec, results } => {
161+
info!("AssertReturn: {:?}", exec);
155162
let res: Result<Result<()>, _> = catch_unwind_silent(|| {
156163
let invoke = match exec {
157164
wast::WastExecute::Wat(_) => {
@@ -200,9 +207,6 @@ impl TestSuite {
200207
));
201208
}
202209

203-
println!("expected: {:?}", expected);
204-
println!("outcomes: {:?}", outcomes);
205-
206210
outcomes
207211
.iter()
208212
.zip(expected)
@@ -221,10 +225,7 @@ impl TestSuite {
221225
});
222226

223227
let res = res
224-
.map_err(|e| {
225-
error!("test panicked: {:?}", e);
226-
eyre!("test panicked: {:?}", e.downcast_ref::<&str>())
227-
})
228+
.map_err(|e| eyre!("test panicked: {:?}", e.downcast_ref::<&str>()))
228229
.and_then(|r| r);
229230

230231
test_group.add_result(&format!("{}-return", name), span, res);

crates/tinywasm/tests/testsuite/util.rs

-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ pub fn wastarg2tinywasmvalue(arg: wast::WastArg) -> Result<tinywasm_types::WasmV
3636
return Err(eyre!("unsupported arg type"));
3737
};
3838

39-
use tinywasm_types::WasmValue;
4039
use wast::core::WastArgCore::*;
4140
Ok(match arg {
4241
F32(f) => WasmValue::F32(f32::from_bits(f.bits)),
@@ -52,7 +51,6 @@ pub fn wastret2tinywasmvalue(arg: wast::WastRet) -> Result<tinywasm_types::WasmV
5251
return Err(eyre!("unsupported arg type"));
5352
};
5453

55-
use tinywasm_types::WasmValue;
5654
use wast::core::WastRetCore::*;
5755
Ok(match arg {
5856
F32(f) => nanpattern2tinywasmvalue(f)?,

0 commit comments

Comments
 (0)