Skip to content

Commit bf8e227

Browse files
authored
Refactor WasmInteger trait (#1553)
* add NonZero support to UntypedVal conversions * refactor WasmInteger trait * refactor WasmInteger users * rename eq_zero -> is_zero
1 parent 88b0f41 commit bf8e227

File tree

5 files changed

+88
-41
lines changed

5 files changed

+88
-41
lines changed

crates/core/src/untyped.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ macro_rules! impl_write_as_for_int {
9292
self.write_lo64(value as $as as _)
9393
}
9494
}
95+
96+
impl WriteAs<::core::num::NonZero<$int>> for UntypedVal {
97+
fn write_as(&mut self, value: ::core::num::NonZero<$int>) {
98+
<UntypedVal as WriteAs<$int>>::write_as(self, value.get())
99+
}
100+
}
95101
)*
96102
};
97103
}
@@ -106,10 +112,23 @@ macro_rules! impl_write_as_for_uint {
106112
self.write_lo64(value as _)
107113
}
108114
}
115+
116+
impl WriteAs<::core::num::NonZero<$int>> for UntypedVal {
117+
fn write_as(&mut self, value: ::core::num::NonZero<$int>) {
118+
<UntypedVal as WriteAs<$int>>::write_as(self, value.get())
119+
}
120+
}
109121
)*
110122
};
111123
}
112-
impl_write_as_for_uint!(bool, u8, u16, u32, u64);
124+
impl_write_as_for_uint!(u8, u16, u32, u64);
125+
126+
impl WriteAs<bool> for UntypedVal {
127+
#[allow(clippy::cast_lossless)]
128+
fn write_as(&mut self, value: bool) {
129+
self.write_lo64(value as _)
130+
}
131+
}
113132

114133
macro_rules! impl_write_as_for_float {
115134
( $( $float:ty ),* $(,)? ) => {
@@ -224,14 +243,27 @@ macro_rules! impl_from_unsigned_prim {
224243
Self::from_bits64(value as _)
225244
}
226245
}
246+
247+
impl From<::core::num::NonZero<$prim>> for UntypedVal {
248+
fn from(value: ::core::num::NonZero<$prim>) -> Self {
249+
<_ as From<$prim>>::from(value.get())
250+
}
251+
}
227252
)*
228253
};
229254
}
230255
#[rustfmt::skip]
231256
impl_from_unsigned_prim!(
232-
bool, u8, u16, u32, u64,
257+
u8, u16, u32, u64,
233258
);
234259

260+
impl From<bool> for UntypedVal {
261+
#[allow(clippy::cast_lossless)]
262+
fn from(value: bool) -> Self {
263+
Self::from_bits64(value as _)
264+
}
265+
}
266+
235267
macro_rules! impl_from_signed_prim {
236268
( $( $prim:ty as $base:ty ),* $(,)? ) => {
237269
$(
@@ -241,6 +273,12 @@ macro_rules! impl_from_signed_prim {
241273
Self::from_bits64(u64::from(value as $base))
242274
}
243275
}
276+
277+
impl From<::core::num::NonZero<$prim>> for UntypedVal {
278+
fn from(value: ::core::num::NonZero<$prim>) -> Self {
279+
<_ as From<$prim>>::from(value.get())
280+
}
281+
}
244282
)*
245283
};
246284
}

crates/wasmi/src/engine/translator/func/instr_encoder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ impl InstrEncoder {
840840
lhs: Reg,
841841
rhs: T,
842842
) -> Result<bool, Error> {
843-
if !rhs.eq_zero() {
843+
if !rhs.is_zero() {
844844
// Case: `rhs` needs to be zero to apply this optimization.
845845
return Ok(false);
846846
}
@@ -885,7 +885,7 @@ impl InstrEncoder {
885885
lhs: Reg,
886886
rhs: T,
887887
) -> Result<bool, Error> {
888-
if !rhs.eq_zero() {
888+
if !rhs.is_zero() {
889889
// Case: `rhs` needs to be zero to apply this optimization.
890890
return Ok(false);
891891
}

crates/wasmi/src/engine/translator/func/mod.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,7 +1328,7 @@ impl FuncTranslator {
13281328
// Custom optimization was applied: return early
13291329
return Ok(());
13301330
}
1331-
if T::from(lhs).eq_zero() {
1331+
if T::from(lhs).is_zero() {
13321332
// Optimization: Shifting or rotating a zero value is a no-op.
13331333
self.stack.push_const(lhs);
13341334
return Ok(());
@@ -1362,18 +1362,17 @@ impl FuncTranslator {
13621362
///
13631363
/// - `{i32, i64}.{div_u, div_s, rem_u, rem_s}`
13641364
#[allow(clippy::too_many_arguments)]
1365-
fn translate_divrem<T, NonZeroT>(
1365+
fn translate_divrem<T>(
13661366
&mut self,
13671367
make_instr: fn(result: Reg, lhs: Reg, rhs: Reg) -> Instruction,
1368-
make_instr_imm16: fn(result: Reg, lhs: Reg, rhs: Const16<NonZeroT>) -> Instruction,
1368+
make_instr_imm16: fn(result: Reg, lhs: Reg, rhs: Const16<T::NonZero>) -> Instruction,
13691369
make_instr_imm16_rev: fn(result: Reg, lhs: Const16<T>, rhs: Reg) -> Instruction,
13701370
consteval: fn(T, T) -> Result<T, TrapCode>,
13711371
make_instr_opt: fn(&mut Self, lhs: Reg, rhs: Reg) -> Result<bool, Error>,
13721372
make_instr_reg_imm_opt: fn(&mut Self, lhs: Reg, rhs: T) -> Result<bool, Error>,
13731373
) -> Result<(), Error>
13741374
where
13751375
T: WasmInteger,
1376-
NonZeroT: Copy + TryFrom<T> + TryInto<Const16<NonZeroT>>,
13771376
{
13781377
bail_unreachable!(self);
13791378
match self.stack.pop2() {
@@ -1385,7 +1384,7 @@ impl FuncTranslator {
13851384
self.push_binary_instr(lhs, rhs, make_instr)
13861385
}
13871386
(TypedProvider::Register(lhs), TypedProvider::Const(rhs)) => {
1388-
let Some(non_zero_rhs) = NonZeroT::try_from(T::from(rhs)).ok() else {
1387+
let Some(non_zero_rhs) = <T as WasmInteger>::non_zero(T::from(rhs)) else {
13891388
// Optimization: division by zero always traps
13901389
self.translate_trap(TrapCode::IntegerDivisionByZero)?;
13911390
return Ok(());

crates/wasmi/src/engine/translator/func/visit.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ use crate::{
3333
FuncRef,
3434
Mutability,
3535
};
36-
use core::num::{NonZeroI32, NonZeroI64, NonZeroU32, NonZeroU64};
3736
use wasmparser::VisitOperator;
3837

3938
/// Used to swap operands of binary [`Instruction`] constructor.
@@ -2037,7 +2036,7 @@ impl<'a> VisitOperator<'a> for FuncTranslator {
20372036
}
20382037

20392038
fn visit_i32_div_s(&mut self) -> Self::Output {
2040-
self.translate_divrem::<i32, NonZeroI32>(
2039+
self.translate_divrem::<i32>(
20412040
Instruction::i32_div_s,
20422041
Instruction::i32_div_s_imm16_rhs,
20432042
Instruction::i32_div_s_imm16_lhs,
@@ -2055,7 +2054,7 @@ impl<'a> VisitOperator<'a> for FuncTranslator {
20552054
}
20562055

20572056
fn visit_i32_div_u(&mut self) -> Self::Output {
2058-
self.translate_divrem::<u32, NonZeroU32>(
2057+
self.translate_divrem::<u32>(
20592058
Instruction::i32_div_u,
20602059
Instruction::i32_div_u_imm16_rhs,
20612060
Instruction::i32_div_u_imm16_lhs,
@@ -2073,7 +2072,7 @@ impl<'a> VisitOperator<'a> for FuncTranslator {
20732072
}
20742073

20752074
fn visit_i32_rem_s(&mut self) -> Self::Output {
2076-
self.translate_divrem::<i32, NonZeroI32>(
2075+
self.translate_divrem::<i32>(
20772076
Instruction::i32_rem_s,
20782077
Instruction::i32_rem_s_imm16_rhs,
20792078
Instruction::i32_rem_s_imm16_lhs,
@@ -2091,7 +2090,7 @@ impl<'a> VisitOperator<'a> for FuncTranslator {
20912090
}
20922091

20932092
fn visit_i32_rem_u(&mut self) -> Self::Output {
2094-
self.translate_divrem::<u32, NonZeroU32>(
2093+
self.translate_divrem::<u32>(
20952094
Instruction::i32_rem_u,
20962095
Instruction::i32_rem_u_imm16_rhs,
20972096
Instruction::i32_rem_u_imm16_lhs,
@@ -2354,7 +2353,7 @@ impl<'a> VisitOperator<'a> for FuncTranslator {
23542353
}
23552354

23562355
fn visit_i64_div_s(&mut self) -> Self::Output {
2357-
self.translate_divrem::<i64, NonZeroI64>(
2356+
self.translate_divrem::<i64>(
23582357
Instruction::i64_div_s,
23592358
Instruction::i64_div_s_imm16_rhs,
23602359
Instruction::i64_div_s_imm16_lhs,
@@ -2372,7 +2371,7 @@ impl<'a> VisitOperator<'a> for FuncTranslator {
23722371
}
23732372

23742373
fn visit_i64_div_u(&mut self) -> Self::Output {
2375-
self.translate_divrem::<u64, NonZeroU64>(
2374+
self.translate_divrem::<u64>(
23762375
Instruction::i64_div_u,
23772376
Instruction::i64_div_u_imm16_rhs,
23782377
Instruction::i64_div_u_imm16_lhs,
@@ -2390,7 +2389,7 @@ impl<'a> VisitOperator<'a> for FuncTranslator {
23902389
}
23912390

23922391
fn visit_i64_rem_s(&mut self) -> Self::Output {
2393-
self.translate_divrem::<i64, NonZeroI64>(
2392+
self.translate_divrem::<i64>(
23942393
Instruction::i64_rem_s,
23952394
Instruction::i64_rem_s_imm16_rhs,
23962395
Instruction::i64_rem_s_imm16_lhs,
@@ -2408,7 +2407,7 @@ impl<'a> VisitOperator<'a> for FuncTranslator {
24082407
}
24092408

24102409
fn visit_i64_rem_u(&mut self) -> Self::Output {
2411-
self.translate_divrem::<u64, NonZeroU64>(
2410+
self.translate_divrem::<u64>(
24122411
Instruction::i64_rem_u,
24132412
Instruction::i64_rem_u_imm16_rhs,
24142413
Instruction::i64_rem_u_imm16_lhs,

crates/wasmi/src/engine/translator/utils.rs

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use crate::{
2-
core::{FuelCostsProvider, Typed, TypedVal, ValType},
2+
core::{FuelCostsProvider, Typed, TypedVal, UntypedVal, ValType},
33
ir::{Const16, Instruction, Sign},
44
Error,
55
ExternRef,
66
FuncRef,
77
};
8+
use core::num::NonZero;
89

910
macro_rules! impl_typed_for {
1011
( $( $ty:ident ),* $(,)? ) => {
@@ -39,35 +40,45 @@ impl_typed_for! {
3940
///
4041
/// This trait provides some utility methods useful for translation.
4142
pub trait WasmInteger:
42-
Copy + Eq + From<TypedVal> + Into<TypedVal> + TryInto<Const16<Self>>
43+
Copy
44+
+ Eq
45+
+ Typed
46+
+ From<TypedVal>
47+
+ Into<TypedVal>
48+
+ From<UntypedVal>
49+
+ Into<UntypedVal>
50+
+ TryInto<Const16<Self>>
4351
{
44-
/// Returns `true` if `self` is equal to zero (0).
45-
fn eq_zero(self) -> bool;
46-
}
52+
/// The non-zero type of the [`WasmInteger`].
53+
type NonZero: Copy + Into<Self> + TryInto<Const16<Self::NonZero>> + Into<UntypedVal>;
4754

48-
impl WasmInteger for i32 {
49-
fn eq_zero(self) -> bool {
50-
self == 0
51-
}
52-
}
55+
/// Returns `self` as [`Self::NonZero`] if possible.
56+
///
57+
/// Returns `None` if `self` is zero.
58+
fn non_zero(self) -> Option<Self::NonZero>;
5359

54-
impl WasmInteger for u32 {
55-
fn eq_zero(self) -> bool {
56-
self == 0
57-
}
60+
/// Returns `true` if `self` is equal to zero (0).
61+
fn is_zero(self) -> bool;
5862
}
5963

60-
impl WasmInteger for i64 {
61-
fn eq_zero(self) -> bool {
62-
self == 0
63-
}
64-
}
64+
macro_rules! impl_wasm_integer {
65+
($($ty:ty),*) => {
66+
$(
67+
impl WasmInteger for $ty {
68+
type NonZero = NonZero<Self>;
6569

66-
impl WasmInteger for u64 {
67-
fn eq_zero(self) -> bool {
68-
self == 0
69-
}
70+
fn non_zero(self) -> Option<Self::NonZero> {
71+
Self::NonZero::new(self)
72+
}
73+
74+
fn is_zero(self) -> bool {
75+
self == 0
76+
}
77+
}
78+
)*
79+
};
7080
}
81+
impl_wasm_integer!(i32, u32, i64, u64);
7182

7283
/// A WebAssembly float. Either `f32` or `f64`.
7384
///

0 commit comments

Comments
 (0)