Skip to content
This repository was archived by the owner on Oct 3, 2025. It is now read-only.

Commit f5119e7

Browse files
chore: refactor executer macros
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
1 parent 93f9383 commit f5119e7

File tree

2 files changed

+162
-212
lines changed

2 files changed

+162
-212
lines changed

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

Lines changed: 61 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
//!
33
//! These macros are used to generate the actual instruction implementations.
44
5+
/// Load a value from memory
56
macro_rules! mem_load {
67
($type:ty, $arg:ident, $stack:ident, $store:ident, $module:ident) => {{
78
mem_load!($type, $type, $arg, $stack, $store, $module)
89
}};
910

1011
($load_type:ty, $target_type:ty, $arg:ident, $stack:ident, $store:ident, $module:ident) => {{
12+
// TODO: there could be a lot of performance improvements here
1113
let mem_idx = $module.resolve_mem_addr($arg.mem_addr);
1214
let mem = $store.get_mem(mem_idx as usize)?;
1315

@@ -28,14 +30,6 @@ macro_rules! mem_load {
2830
}};
2931
}
3032

31-
/// Convert the top value on the stack to a specific type
32-
macro_rules! conv_1 {
33-
($from:ty, $to:ty, $stack:ident) => {{
34-
let a: $from = $stack.values.pop()?.into();
35-
$stack.values.push((a as $to).into());
36-
}};
37-
}
38-
3933
/// Doing the actual conversion from float to int is a bit tricky, because
4034
/// we need to check for overflow. This macro generates the min/max values
4135
/// for a specific conversion, which are then used in the actual conversion.
@@ -71,75 +65,56 @@ macro_rules! float_min_max {
7165
};
7266
}
7367

74-
// Convert a float to an int, checking for overflow
75-
macro_rules! checked_float_conv_1 {
76-
($from:tt, $to:tt, $stack:ident) => {{
77-
let (min, max) = float_min_max!($from, $to);
68+
/// Convert a value on the stack
69+
macro_rules! conv {
70+
($from:ty, $intermediate:ty, $to:ty, $stack:ident) => {{
71+
let a: $from = $stack.values.pop()?.into();
72+
$stack.values.push((a as $intermediate as $to).into());
73+
}};
74+
($from:ty, $to:ty, $stack:ident) => {{
7875
let a: $from = $stack.values.pop()?.into();
79-
80-
if a.is_nan() {
81-
return Err(Error::Trap(crate::Trap::InvalidConversionToInt));
82-
}
83-
84-
if a <= min || a >= max {
85-
return Err(Error::Trap(crate::Trap::IntegerOverflow));
86-
}
87-
8876
$stack.values.push((a as $to).into());
8977
}};
9078
}
9179

92-
// Convert a float to an int, checking for overflow
93-
macro_rules! checked_float_conv_2 {
94-
($from:tt, $uty:tt, $to:tt, $stack:ident) => {{
95-
let (min, max) = float_min_max!($from, $uty);
80+
/// Convert a value on the stack with error checking
81+
macro_rules! checked_conv_float {
82+
// Direct conversion with error checking (two types)
83+
($from:tt, $to:tt, $stack:ident) => {{
84+
checked_conv_float!($from, $to, $to, $stack)
85+
}};
86+
// Conversion with an intermediate unsigned type and error checking (three types)
87+
($from:tt, $intermediate:tt, $to:tt, $stack:ident) => {{
88+
let (min, max) = float_min_max!($from, $intermediate);
9689
let a: $from = $stack.values.pop()?.into();
9790

9891
if a.is_nan() {
9992
return Err(Error::Trap(crate::Trap::InvalidConversionToInt));
10093
}
10194

102-
log::info!("a: {}", a);
103-
log::info!("min: {}", min);
104-
log::info!("max: {}", max);
105-
10695
if a <= min || a >= max {
10796
return Err(Error::Trap(crate::Trap::IntegerOverflow));
10897
}
10998

110-
$stack.values.push((a as $uty as $to).into());
111-
}};
112-
}
113-
114-
/// Convert the unsigned value on the top of the stack to a specific type
115-
macro_rules! conv_2 {
116-
($ty:ty, $uty:ty, $to:ty, $stack:ident) => {{
117-
let a: $ty = $stack.values.pop()?.into();
118-
$stack.values.push((a as $uty as $to).into());
99+
$stack.values.push((a as $intermediate as $to).into());
119100
}};
120101
}
121102

122103
/// Compare two values on the stack
123104
macro_rules! comp {
124105
($op:tt, $ty:ty, $stack:ident) => {{
125-
let [a, b] = $stack.values.pop_n_const::<2>()?;
126-
let a: $ty = a.into();
127-
let b: $ty = b.into();
128-
$stack.values.push(((a $op b) as i32).into());
106+
comp!($op, $ty, $ty, $stack)
129107
}};
130-
}
131108

132-
/// Compare two values on the stack (cast to ty2 before comparison)
133-
macro_rules! comp_cast {
134-
($op:tt, $ty:ty, $ty2:ty, $stack:ident) => {{
109+
($op:tt, $intermediate:ty, $to:ty, $stack:ident) => {{
135110
let [a, b] = $stack.values.pop_n_const::<2>()?;
136-
let a: $ty = a.into();
137-
let b: $ty = b.into();
111+
let a: $intermediate = a.into();
112+
let b: $intermediate = b.into();
138113

139114
// Cast to unsigned type before comparison
140-
let a_unsigned: $ty2 = a as $ty2;
141-
let b_unsigned: $ty2 = b as $ty2;
142-
$stack.values.push(((a_unsigned $op b_unsigned) as i32).into());
115+
let a = a as $to;
116+
let b = b as $to;
117+
$stack.values.push(((a $op b) as i32).into());
143118
}};
144119
}
145120

@@ -151,95 +126,70 @@ macro_rules! comp_zero {
151126
}};
152127
}
153128

154-
/// Apply an arithmetic operation to two values on the stack
155-
macro_rules! arithmetic_op {
129+
/// Apply an arithmetic method to two values on the stack
130+
macro_rules! arithmetic {
131+
($op:ident, $ty:ty, $stack:ident) => {{
132+
arithmetic!($op, $ty, $ty, $stack)
133+
}};
134+
135+
// also allow operators such as +, -
156136
($op:tt, $ty:ty, $stack:ident) => {{
157137
let [a, b] = $stack.values.pop_n_const::<2>()?;
158138
let a: $ty = a.into();
159139
let b: $ty = b.into();
160140
$stack.values.push((a $op b).into());
161141
}};
162-
}
163142

164-
macro_rules! arithmetic_method {
165-
($op:ident, $ty:ty, $stack:ident) => {{
143+
($op:ident, $intermediate:ty, $to:ty, $stack:ident) => {{
166144
let [a, b] = $stack.values.pop_n_const::<2>()?;
167-
let a: $ty = a.into();
168-
let b: $ty = b.into();
145+
let a: $to = a.into();
146+
let b: $to = b.into();
147+
148+
let a = a as $intermediate;
149+
let b = b as $intermediate;
150+
169151
let result = a.$op(b);
170-
$stack.values.push(result.into());
152+
$stack.values.push((result as $to).into());
171153
}};
172154
}
173155

174-
macro_rules! arithmetic_method_self {
156+
/// Apply an arithmetic method to a single value on the stack
157+
macro_rules! arithmetic_single {
175158
($op:ident, $ty:ty, $stack:ident) => {{
176159
let a: $ty = $stack.values.pop()?.into();
177160
let result = a.$op();
178161
$stack.values.push((result as $ty).into());
179162
}};
180163
}
181164

182-
macro_rules! arithmetic_method_cast {
183-
($op:ident, $ty:ty, $ty2:ty, $stack:ident) => {{
184-
let [a, b] = $stack.values.pop_n_const::<2>()?;
185-
let a: $ty = a.into();
186-
let b: $ty = b.into();
187-
188-
// Cast to unsigned type before operation
189-
let a_unsigned: $ty2 = a as $ty2;
190-
let b_unsigned: $ty2 = b as $ty2;
191-
192-
let result = a_unsigned.$op(b_unsigned);
193-
$stack.values.push((result as $ty).into());
165+
/// Apply an arithmetic operation to two values on the stack with error checking
166+
macro_rules! checked_arithmetic {
167+
// Direct conversion with error checking (two types)
168+
($from:tt, $to:tt, $stack:ident, $trap:expr) => {{
169+
checked_arithmetic!($from, $to, $to, $stack, $trap)
194170
}};
195-
}
196171

197-
/// Apply an arithmetic operation to two values on the stack
198-
macro_rules! checked_arithmetic_method {
199-
($op:ident, $ty:ty, $stack:ident, $trap:expr) => {{
172+
($op:ident, $from:ty, $to:ty, $stack:ident, $trap:expr) => {{
200173
let [a, b] = $stack.values.pop_n_const::<2>()?;
201-
let a: $ty = a.into();
202-
let b: $ty = b.into();
203-
let result = a.$op(b).ok_or_else(|| Error::Trap($trap))?;
204-
debug!(
205-
"checked_arithmetic_method: {}, a: {}, b: {}, res: {}",
206-
stringify!($op),
207-
a,
208-
b,
209-
result
210-
);
211-
$stack.values.push(result.into());
212-
}};
213-
}
174+
let a: $from = a.into();
175+
let b: $from = b.into();
214176

215-
/// Apply an arithmetic operation to two values on the stack (cast to ty2 before operation)
216-
macro_rules! checked_arithmetic_method_cast {
217-
($op:ident, $ty:ty, $ty2:ty, $stack:ident, $trap:expr) => {{
218-
let [a, b] = $stack.values.pop_n_const::<2>()?;
219-
let a: $ty = a.into();
220-
let b: $ty = b.into();
177+
let a_casted: $to = a as $to;
178+
let b_casted: $to = b as $to;
221179

222-
// Cast to unsigned type before operation
223-
let a_unsigned: $ty2 = a as $ty2;
224-
let b_unsigned: $ty2 = b as $ty2;
180+
let result = a_casted.$op(b_casted).ok_or_else(|| Error::Trap($trap))?;
225181

226-
let result = a_unsigned.$op(b_unsigned).ok_or_else(|| Error::Trap($trap))?;
227-
$stack.values.push((result as $ty).into());
182+
// Cast back to original type if different
183+
$stack.values.push((result as $from).into());
228184
}};
229185
}
230186

231-
pub(super) use arithmetic_method;
232-
pub(super) use arithmetic_method_cast;
233-
pub(super) use arithmetic_method_self;
234-
pub(super) use arithmetic_op;
235-
pub(super) use checked_arithmetic_method;
236-
pub(super) use checked_arithmetic_method_cast;
237-
pub(super) use checked_float_conv_1;
238-
pub(super) use checked_float_conv_2;
187+
pub(super) use arithmetic;
188+
pub(super) use arithmetic_single;
189+
pub(super) use checked_arithmetic;
190+
pub(super) use checked_conv_float;
239191
pub(super) use comp;
240-
pub(super) use comp_cast;
241192
pub(super) use comp_zero;
242-
pub(super) use conv_1;
243-
pub(super) use conv_2;
193+
pub(super) use conv;
244194
pub(super) use float_min_max;
245195
pub(super) use mem_load;

0 commit comments

Comments
 (0)