1use crate::{
2 components::{Blocktype, Funcidx, Functype, Importdesc, Localidx},
3 instance::FuncInst,
4 instructions::Instr,
5 Env, GlobalVal, HostFunc, Module, Val, Vector, VectorFactory, PAGE_SIZE,
6};
7use core::fmt::{Debug, Display, Formatter};
8
9#[derive(Debug, Clone, Copy)]
10pub enum ExecuteError {
11 NotExportedFunction,
12 UnresolvedImport { index: usize },
13 InvalidImportedMem,
14 InvalidImportedTable,
15 InvalidData { index: usize },
16 InvalidElem { index: usize },
17 InvalidGlobal { index: usize },
18 InvalidMemidx,
19 InvalidFuncidx,
20 InvalidTypeidx,
21 InvalidFuncArgs,
22 Trapped, }
24
25impl Display for ExecuteError {
26 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
27 match self {
28 Self::NotExportedFunction => write!(f, "Not exported function"),
29 Self::UnresolvedImport { index } => write!(f, "Unresolved import: {}", index),
30 Self::InvalidImportedMem => write!(f, "Invalid imported memory"),
31 Self::InvalidImportedTable => write!(f, "Invalid imported table"),
32 Self::InvalidData { index } => write!(f, "Invalid data: {}", index),
33 Self::InvalidElem { index } => write!(f, "Invalid elem: {}", index),
34 Self::InvalidGlobal { index } => write!(f, "Invalid global: {}", index),
35 Self::InvalidMemidx => write!(f, "Invalid memidx"),
36 Self::InvalidFuncidx => write!(f, "Invalid funcidx"),
37 Self::InvalidTypeidx => write!(f, "Invalid typeidx"),
38 Self::InvalidFuncArgs => write!(f, "Invalid function arguments"),
39 Self::Trapped => write!(f, "Trapped"),
40 }
41 }
42}
43
44#[cfg(feature = "std")]
45impl std::error::Error for ExecuteError {}
46
47pub struct Executor<V: VectorFactory> {
48 pub mem: V::Vector<u8>,
49 pub table: V::Vector<Option<Funcidx>>,
50 pub globals: V::Vector<GlobalVal>,
51 pub locals: V::Vector<Val>,
52 pub values: V::Vector<Val>,
53 pub current_frame: Frame,
54 pub current_block: Block,
55}
56
57impl<V: VectorFactory> Executor<V> {
58 pub fn new(
59 mem: V::Vector<u8>,
60 table: V::Vector<Option<Funcidx>>,
61 globals: V::Vector<GlobalVal>,
62 ) -> Self {
63 Self {
64 mem,
65 table,
66 globals,
67 locals: V::create_vector(None),
68 values: V::create_vector(None),
69 current_frame: Frame::default(),
70 current_block: Block::default(),
71 }
72 }
73
74 pub fn enter_frame(&mut self, ty: &Functype<V>) -> Frame {
75 let locals_start = self.locals.len();
76 for _ in 0..ty.params.len() {
77 let v = self.pop_value();
78 self.locals.push(v);
79 }
80 self.locals[locals_start..].reverse();
81 let values_start = self.values.len();
82
83 let prev = self.current_frame;
84 self.current_frame = Frame {
85 arity: ty.result.len(),
86 locals_start,
87 values_start,
88 };
89 prev
90 }
91
92 pub fn exit_frame(&mut self, _ty: &Functype<V>, prev: Frame) {
94 let frame = self.current_frame;
95
96 assert!(frame.locals_start <= self.locals.len());
97 self.locals.truncate(frame.locals_start);
98
99 self.values
100 .remove_range(frame.values_start..self.values.len() - frame.arity);
101
102 self.current_frame = prev;
103 }
104
105 pub fn enter_block(&mut self, ty: Blocktype) -> Block {
106 assert!(matches!(ty, Blocktype::Empty)); let prev = self.current_block;
109 self.current_block = Block {
110 arity: ty.arity(),
111 values_start: self.values.len(),
112 };
113 prev
114 }
115
116 pub fn exit_block(&mut self, ty: Blocktype, skipped: bool, prev: Block) {
118 assert!(matches!(ty, Blocktype::Empty)); let block = self.current_block;
121
122 if !skipped {
123 self.values
124 .remove_range(block.values_start..self.values.len() - block.arity);
125 }
126
127 self.current_block = prev;
128 }
129
130 pub fn set_local(&mut self, i: Localidx, v: Val) {
131 let i = self.current_frame.locals_start + i.get();
132 self.locals[i] = v;
133 }
134
135 pub fn get_local(&self, i: Localidx) -> Val {
136 let i = self.current_frame.locals_start + i.get();
137 self.locals[i]
138 }
139
140 pub fn push_value(&mut self, v: Val) {
141 self.values.push(v);
142 }
143
144 pub fn pop_value(&mut self) -> Val {
145 self.values.pop().expect("unreachable")
146 }
147
148 pub fn pop_value_i32(&mut self) -> i32 {
149 let Some(Val::I32(v)) = self.values.pop() else {
150 unreachable!();
151 };
152 v
153 }
154
155 pub fn pop_value_i64(&mut self) -> i64 {
156 let Some(Val::I64(v)) = self.values.pop() else {
157 unreachable!();
158 };
159 v
160 }
161
162 pub fn pop_value_u64(&mut self) -> u64 {
163 let Some(Val::I64(v)) = self.values.pop() else {
164 unreachable!();
165 };
166 v as u64
167 }
168
169 pub fn pop_value_u32(&mut self) -> u32 {
170 let Some(Val::I32(v)) = self.values.pop() else {
171 unreachable!();
172 };
173 v as u32
174 }
175
176 pub fn pop_value_f32(&mut self) -> f32 {
177 let Some(Val::F32(v)) = self.values.pop() else {
178 unreachable!();
179 };
180 v
181 }
182
183 pub fn pop_value_f64(&mut self) -> f64 {
184 let Some(Val::F64(v)) = self.values.pop() else {
185 unreachable!();
186 };
187 v
188 }
189
190 pub fn call_function<H: HostFunc>(
191 &mut self,
192 func_idx: Funcidx,
193 funcs: &mut [FuncInst<H>],
194 module: &Module<V>,
195 ) -> Result<(), ExecuteError> {
196 let func = funcs
198 .get_mut(func_idx.get())
199 .ok_or(ExecuteError::InvalidFuncidx)?;
200 let func_type = func.get_type(module).ok_or(ExecuteError::InvalidFuncidx)?; let prev_frame = self.enter_frame(func_type);
203 match func {
204 FuncInst::Imported {
205 imports_index,
206 host_func,
207 } => {
208 let Importdesc::Func(typeidx) = module.imports()[*imports_index].desc else {
209 unreachable!()
210 };
211 let func_type = &module.types()[typeidx.get()];
212 let args_end = self.locals.len();
213 let args_start = args_end - func_type.params.len();
214 let args = &self.locals[args_start..args_end];
215
216 let mut env = Env {
217 mem: &mut self.mem,
218 globals: &mut self.globals,
219 };
220 let value = host_func.invoke(args, &mut env);
221
222 if let Some(v) = value {
224 self.values.push(v);
225 }
226 }
227 FuncInst::Module { funcs_index } => {
228 let func = module
229 .funcs()
230 .get(*funcs_index)
231 .ok_or(ExecuteError::InvalidFuncidx)?;
232 for v in func.locals.iter().copied().map(Val::zero) {
233 self.locals.push(v);
234 }
235 self.execute_instrs(func.body.instrs(), 0, funcs, module)?;
236 }
237 };
238 self.exit_frame(func_type, prev_frame);
239 Ok(())
240 }
241
242 pub fn execute_instrs<H: HostFunc>(
243 &mut self,
244 instrs: &[Instr<V>],
245 level: usize, funcs: &mut [FuncInst<H>],
247 module: &Module<V>,
248 ) -> Result<Option<usize>, ExecuteError> {
249 for instr in instrs {
250 match instr {
251 Instr::Unreachable => return Err(ExecuteError::Trapped),
253 Instr::Nop => {}
254 Instr::Block(block) => {
255 let prev_block = self.enter_block(block.blocktype);
256 let return_level =
257 self.execute_instrs(&block.instrs, level + 1, funcs, module)?;
258 let skipped = return_level.map_or(false, |return_level| return_level <= level);
259 self.exit_block(block.blocktype, skipped, prev_block);
260 if skipped {
261 return Ok(return_level);
262 }
263 }
264 Instr::Loop(block) => {
265 let current_level = level + 1;
266 let blocktype = Blocktype::Empty;
267 let prev_block = self.enter_block(blocktype);
268 loop {
269 let return_level =
270 self.execute_instrs(&block.instrs, current_level, funcs, module)?;
271 if return_level == Some(current_level) {
272 continue;
273 }
274 let skipped =
275 return_level.map_or(false, |return_level| return_level <= level);
276 self.exit_block(blocktype, skipped, prev_block);
277 if skipped {
278 return Ok(return_level);
279 }
280 break;
281 }
282 }
283 Instr::If(block) => {
284 let c = self.pop_value_i32();
285 let prev_block = self.enter_block(block.blocktype);
286 let return_level = if c != 0 {
287 self.execute_instrs(&block.then_instrs, level + 1, funcs, module)?
288 } else {
289 self.execute_instrs(&block.else_instrs, level + 1, funcs, module)?
290 };
291 let skipped = return_level.map_or(false, |return_level| return_level <= level);
292 self.exit_block(block.blocktype, skipped, prev_block);
293 if skipped {
294 return Ok(return_level);
295 }
296 }
297 Instr::Br(label) => {
298 return Ok(Some(level - label.get()));
299 }
300 Instr::BrIf(label) => {
301 let c = self.pop_value_i32();
302 if c != 0 {
303 return Ok(Some(level - label.get()));
304 }
305 }
306 Instr::BrTable(table) => {
307 let i = self.pop_value_i32() as usize;
308 let label = table
309 .labels
310 .get(i)
311 .unwrap_or_else(|| table.labels.last().expect("unreachable"));
312 return Ok(Some(level - label.get()));
313 }
314 Instr::Return => {
315 return Ok(Some(0));
316 }
317 Instr::Call(funcidx) => {
318 self.call_function(*funcidx, funcs, module)?;
319 }
320 Instr::CallIndirect(typeidx) => {
321 let expect_type = module
322 .types()
323 .get(typeidx.get())
324 .ok_or(ExecuteError::InvalidTypeidx)?;
325
326 let i = self.pop_value_i32() as usize;
327 let funcidx = self
328 .table
329 .get(i)
330 .ok_or(ExecuteError::Trapped)?
331 .ok_or(ExecuteError::Trapped)?;
332 let func = funcs
333 .get(funcidx.get())
334 .ok_or(ExecuteError::InvalidFuncidx)?;
335 let actual_type = func.get_type(module).ok_or(ExecuteError::InvalidFuncidx)?; if expect_type != actual_type {
337 return Err(ExecuteError::Trapped);
338 }
339 self.call_function(funcidx, funcs, module)?;
340 }
341
342 Instr::Drop => {
344 self.pop_value();
345 }
346 Instr::Select => {
347 let c = self.pop_value_i32();
348 let v2 = self.pop_value();
349 let v1 = self.pop_value();
350 self.push_value(if c != 0 { v1 } else { v2 });
351 }
352
353 Instr::LocalTee(idx) => {
355 let v = self.pop_value();
356 self.set_local(*idx, v);
357 self.push_value(v);
358 }
359 Instr::LocalGet(idx) => {
360 let v = self.get_local(*idx);
361 self.push_value(v);
362 }
363 Instr::LocalSet(idx) => {
364 let v = self.pop_value();
365 self.set_local(*idx, v);
366 }
367 Instr::GlobalGet(idx) => {
368 let v = self.globals[idx.get()].get();
369 self.push_value(v);
370 }
371 Instr::GlobalSet(idx) => {
372 let v = self.pop_value();
373 self.globals[idx.get()].set(v);
374 }
375
376 Instr::I32Load(arg) => {
378 let i = self.pop_value_i32();
380 let start = (i + arg.offset as i32) as usize;
381 let end = start + 4;
382 if self.mem.len() < end {
383 return Err(ExecuteError::Trapped);
384 }
385 let v = i32::from_le_bytes(self.mem[start..end].try_into().unwrap()); self.values.push(Val::I32(v));
387 }
388 Instr::I64Load(arg) => {
389 let i = self.pop_value_i32();
391 let start = (i + arg.offset as i32) as usize;
392 let end = start + 8;
393 if self.mem.len() < end {
394 return Err(ExecuteError::Trapped);
395 }
396 let v = i64::from_le_bytes(self.mem[start..end].try_into().unwrap()); self.values.push(Val::I64(v));
398 }
399 Instr::F32Load(arg) => {
400 let i = self.pop_value_i32();
402 let start = (i + arg.offset as i32) as usize;
403 let end = start + 4;
404 if self.mem.len() < end {
405 return Err(ExecuteError::Trapped);
406 }
407 let v = f32::from_le_bytes(self.mem[start..end].try_into().unwrap()); self.values.push(Val::F32(v));
409 }
410 Instr::F64Load(arg) => {
411 let i = self.pop_value_i32();
413 let start = (i + arg.offset as i32) as usize;
414 let end = start + 8;
415 if self.mem.len() < end {
416 return Err(ExecuteError::Trapped);
417 }
418 let v = f64::from_le_bytes(self.mem[start..end].try_into().unwrap()); self.values.push(Val::F64(v));
420 }
421 Instr::I32Load8S(arg) => {
422 let i = self.pop_value_i32();
424 let i = (i + arg.offset as i32) as usize;
425 if self.mem.len() < i {
426 return Err(ExecuteError::Trapped);
427 }
428 let v = self.mem[i] as i8 as i32;
429 self.values.push(Val::I32(v));
430 }
431 Instr::I32Load8U(arg) => {
432 let i = self.pop_value_i32();
434 let i = (i + arg.offset as i32) as usize;
435 if self.mem.len() < i {
436 return Err(ExecuteError::Trapped);
437 }
438 let v = self.mem[i] as i32;
439 self.values.push(Val::I32(v));
440 }
441 Instr::I32Load16S(arg) => {
442 let i = self.pop_value_i32();
444 let start = (i + arg.offset as i32) as usize;
445 let end = start + 2;
446 if self.mem.len() < end {
447 return Err(ExecuteError::Trapped);
448 }
449 let v = i16::from_le_bytes(self.mem[start..end].try_into().unwrap()); self.values.push(Val::I32(v as i32));
451 }
452 Instr::I32Load16U(arg) => {
453 let i = self.pop_value_i32();
455 let start = (i + arg.offset as i32) as usize;
456 let end = start + 2;
457 if self.mem.len() < end {
458 return Err(ExecuteError::Trapped);
459 }
460 let v = u16::from_le_bytes(self.mem[start..end].try_into().unwrap()); self.values.push(Val::I32(v as i32));
462 }
463 Instr::I64Load8S(arg) => {
464 let i = self.pop_value_i32();
466 let i = (i + arg.offset as i32) as usize;
467 if self.mem.len() < i {
468 return Err(ExecuteError::Trapped);
469 }
470 let v = self.mem[i] as i8 as i64;
471 self.values.push(Val::I64(v));
472 }
473 Instr::I64Load8U(arg) => {
474 let i = self.pop_value_i32();
476 let i = (i + arg.offset as i32) as usize;
477 if self.mem.len() < i {
478 return Err(ExecuteError::Trapped);
479 }
480 let v = self.mem[i] as i64;
481 self.values.push(Val::I64(v));
482 }
483 Instr::I64Load16S(arg) => {
484 let i = self.pop_value_i32();
486 let start = (i + arg.offset as i32) as usize;
487 let end = start + 2;
488 if self.mem.len() < end {
489 return Err(ExecuteError::Trapped);
490 }
491 let v = i16::from_le_bytes(self.mem[start..end].try_into().unwrap()); self.values.push(Val::I64(v as i64));
493 }
494 Instr::I64Load16U(arg) => {
495 let i = self.pop_value_i32();
497 let start = (i + arg.offset as i32) as usize;
498 let end = start + 2;
499 if self.mem.len() < end {
500 return Err(ExecuteError::Trapped);
501 }
502 let v = u16::from_le_bytes(self.mem[start..end].try_into().unwrap()); self.values.push(Val::I64(v as i64));
504 }
505 Instr::I64Load32S(arg) => {
506 let i = self.pop_value_i32();
508 let start = (i + arg.offset as i32) as usize;
509 let end = start + 4;
510 if self.mem.len() < end {
511 return Err(ExecuteError::Trapped);
512 }
513 let v = i32::from_le_bytes(self.mem[start..end].try_into().unwrap()); self.values.push(Val::I64(v as i64));
515 }
516 Instr::I64Load32U(arg) => {
517 let i = self.pop_value_i32();
519 let start = (i + arg.offset as i32) as usize;
520 let end = start + 4;
521 if self.mem.len() < end {
522 return Err(ExecuteError::Trapped);
523 }
524 let v = u32::from_le_bytes(self.mem[start..end].try_into().unwrap()); self.values.push(Val::I64(v as i64));
526 }
527 Instr::I32Store(arg) => {
528 let v = self.pop_value();
530 let i = self.pop_value_i32();
531 let start = (i + arg.offset as i32) as usize;
532 let end = start + v.byte_size();
533 if self.mem.len() < end {
534 return Err(ExecuteError::Trapped);
535 }
536 v.copy_to(&mut self.mem[start..end]);
537 }
538 Instr::I64Store(arg) => {
539 let v = self.pop_value();
541 let i = self.pop_value_i32();
542 let start = (i + arg.offset as i32) as usize;
543 let end = start + v.byte_size();
544 if self.mem.len() < end {
545 return Err(ExecuteError::Trapped);
546 }
547 v.copy_to(&mut self.mem[start..end]);
548 }
549 Instr::F32Store(arg) => {
550 let v = self.pop_value();
552 let i = self.pop_value_i32();
553 let start = (i + arg.offset as i32) as usize;
554 let end = start + v.byte_size();
555 if self.mem.len() < end {
556 return Err(ExecuteError::Trapped);
557 }
558 v.copy_to(&mut self.mem[start..end]);
559 }
560 Instr::F64Store(arg) => {
561 let v = self.pop_value();
563 let i = self.pop_value_i32();
564 let start = (i + arg.offset as i32) as usize;
565 let end = start + v.byte_size();
566 if self.mem.len() < end {
567 return Err(ExecuteError::Trapped);
568 }
569 v.copy_to(&mut self.mem[start..end]);
570 }
571 Instr::I32Store8(arg) => {
572 let v = self.pop_value();
574 let i = self.pop_value_i32();
575 let i = (i + arg.offset as i32) as usize;
576 if self.mem.len() < i {
577 return Err(ExecuteError::Trapped);
578 }
579 let v = v.as_i32().ok_or(ExecuteError::Trapped)? as u8; self.mem[i] = v;
581 }
582 Instr::I32Store16(arg) => {
583 let v = self.pop_value();
585 let i = self.pop_value_i32();
586 let start = (i + arg.offset as i32) as usize;
587 let end = start + 2;
588 if self.mem.len() < end {
589 return Err(ExecuteError::Trapped);
590 }
591
592 let v = v.as_i32().ok_or(ExecuteError::Trapped)? as i16; self.mem[start..end].copy_from_slice(&v.to_le_bytes());
594 }
595 Instr::I64Store8(arg) => {
596 let v = self.pop_value();
598 let i = self.pop_value_i32();
599 let i = (i + arg.offset as i32) as usize;
600 if self.mem.len() < i {
601 return Err(ExecuteError::Trapped);
602 }
603 let v = v.as_i64().ok_or(ExecuteError::Trapped)? as u8; self.mem[i] = v;
605 }
606 Instr::I64Store16(arg) => {
607 let v = self.pop_value();
609 let i = self.pop_value_i32();
610 let start = (i + arg.offset as i32) as usize;
611 let end = start + 2;
612 if self.mem.len() < end {
613 return Err(ExecuteError::Trapped);
614 }
615
616 let v = v.as_i64().ok_or(ExecuteError::Trapped)? as i16; self.mem[start..end].copy_from_slice(&v.to_le_bytes());
618 }
619 Instr::I64Store32(arg) => {
620 let v = self.pop_value();
622 let i = self.pop_value_i32();
623 let start = (i + arg.offset as i32) as usize;
624 let end = start + 4;
625 if self.mem.len() < end {
626 return Err(ExecuteError::Trapped);
627 }
628
629 let v = v.as_i64().ok_or(ExecuteError::Trapped)? as i32; self.mem[start..end].copy_from_slice(&v.to_le_bytes());
631 }
632 Instr::MemorySize => {
633 let size = self.mem.len() / PAGE_SIZE;
634 self.push_value(Val::I32(size as i32));
635 }
636 Instr::MemoryGrow => {
637 let delta = self.pop_value_i32();
638 let max = module.mem().and_then(|m| m.limits.max).unwrap_or(u32::MAX);
639 let current = self.mem.len() / PAGE_SIZE;
640 let new = current + delta as usize;
641 if new <= max as usize {
642 for _ in 0..delta as usize * PAGE_SIZE {
644 self.mem.push(0);
645 }
646 self.push_value(Val::I32(current as i32));
647 } else {
648 self.push_value(Val::I32(-1));
649 };
650 }
651
652 Instr::I32Const(v) => self.push_value(Val::I32(*v)),
654 Instr::I64Const(v) => self.push_value(Val::I64(*v)),
655 Instr::F32Const(v) => self.push_value(Val::F32(*v)),
656 Instr::F64Const(v) => self.push_value(Val::F64(*v)),
657 Instr::I32Eqz => self.apply_unop_cmp_i32(|v| v == 0),
658 Instr::I32Eq => self.apply_binop_cmp_i32(|v0, v1| v0 == v1),
659 Instr::I32Ne => self.apply_binop_cmp_i32(|v0, v1| v0 != v1),
660 Instr::I32LtS => self.apply_binop_cmp_i32(|v0, v1| v0 < v1),
661 Instr::I32LtU => self.apply_binop_cmp_u32(|v0, v1| v0 < v1),
662 Instr::I32GtS => self.apply_binop_cmp_i32(|v0, v1| v0 > v1),
663 Instr::I32GtU => self.apply_binop_cmp_u32(|v0, v1| v0 > v1),
664 Instr::I32LeS => self.apply_binop_cmp_i32(|v0, v1| v0 <= v1),
665 Instr::I32LeU => self.apply_binop_cmp_u32(|v0, v1| v0 <= v1),
666 Instr::I32GeS => self.apply_binop_cmp_i32(|v0, v1| v0 >= v1),
667 Instr::I32GeU => self.apply_binop_cmp_u32(|v0, v1| v0 >= v1),
668 Instr::I64Eqz => self.apply_unop_cmp_i64(|v| v == 0),
669 Instr::I64Eq => self.apply_binop_cmp_i64(|v0, v1| v0 == v1),
670 Instr::I64Ne => self.apply_binop_cmp_i64(|v0, v1| v0 != v1),
671 Instr::I64LtS => self.apply_binop_cmp_i64(|v0, v1| v0 < v1),
672 Instr::I64LtU => self.apply_binop_cmp_u64(|v0, v1| v0 < v1),
673 Instr::I64GtS => self.apply_binop_cmp_i64(|v0, v1| v0 > v1),
674 Instr::I64GtU => self.apply_binop_cmp_u64(|v0, v1| v0 > v1),
675 Instr::I64LeS => self.apply_binop_cmp_i64(|v0, v1| v0 <= v1),
676 Instr::I64LeU => self.apply_binop_cmp_u64(|v0, v1| v0 <= v1),
677 Instr::I64GeS => self.apply_binop_cmp_i64(|v0, v1| v0 >= v1),
678 Instr::I64GeU => self.apply_binop_cmp_u64(|v0, v1| v0 >= v1),
679 Instr::F32Eq => self.apply_binop_cmp_f32(|v0, v1| v0 == v1),
680 Instr::F32Ne => self.apply_binop_cmp_f32(|v0, v1| v0 != v1),
681 Instr::F32Lt => self.apply_binop_cmp_f32(|v0, v1| v0 < v1),
682 Instr::F32Gt => self.apply_binop_cmp_f32(|v0, v1| v0 > v1),
683 Instr::F32Le => self.apply_binop_cmp_f32(|v0, v1| v0 <= v1),
684 Instr::F32Ge => self.apply_binop_cmp_f32(|v0, v1| v0 >= v1),
685 Instr::F64Eq => self.apply_binop_cmp_f64(|v0, v1| v0 == v1),
686 Instr::F64Ne => self.apply_binop_cmp_f64(|v0, v1| v0 != v1),
687 Instr::F64Lt => self.apply_binop_cmp_f64(|v0, v1| v0 < v1),
688 Instr::F64Gt => self.apply_binop_cmp_f64(|v0, v1| v0 > v1),
689 Instr::F64Le => self.apply_binop_cmp_f64(|v0, v1| v0 <= v1),
690 Instr::F64Ge => self.apply_binop_cmp_f64(|v0, v1| v0 >= v1),
691 Instr::I32Clz => self.apply_unop_i32(|v| v.leading_zeros() as i32),
692 Instr::I32Ctz => self.apply_unop_i32(|v| v.trailing_zeros() as i32),
693 Instr::I32Popcnt => self.apply_unop_i32(|v| v.count_ones() as i32),
694 Instr::I32Add => self.apply_binop_i32(|v0, v1| v0 + v1),
695 Instr::I32Sub => self.apply_binop_i32(|v0, v1| v0 - v1),
696 Instr::I32Mul => self.apply_binop_i32(|v0, v1| v0 * v1),
697 Instr::I32DivS => self.apply_binop_i32(|v0, v1| v0.wrapping_div(v1)), Instr::I32DivU => self.apply_binop_u32(|v0, v1| v0.wrapping_div(v1)), Instr::I32RemS => self.apply_binop_i32(|v0, v1| v0.wrapping_rem(v1)), Instr::I32RemU => self.apply_binop_u32(|v0, v1| v0.wrapping_rem(v1)), Instr::I32And => self.apply_binop_i32(|v0, v1| v0 & v1),
702 Instr::I32Or => self.apply_binop_i32(|v0, v1| v0 | v1),
703 Instr::I32Xor => self.apply_binop_i32(|v0, v1| v0 ^ v1),
704 Instr::I32Shl => self.apply_binop_i32(|v0, v1| v0.wrapping_shl(v1 as u32)), Instr::I32ShrS => self.apply_binop_i32(|v0, v1| v0.wrapping_shr(v1 as u32)), Instr::I32ShrU => self.apply_binop_u32(|v0, v1| v0.wrapping_shr(v1)), Instr::I32Rotl => self.apply_binop_i32(|v0, v1| v0.rotate_left(v1 as u32)),
708 Instr::I32Rotr => self.apply_binop_i32(|v0, v1| v0.rotate_right(v1 as u32)),
709 Instr::I64Clz => self.apply_unop_i64(|v| v.leading_zeros() as i64),
710 Instr::I64Ctz => self.apply_unop_i64(|v| v.trailing_zeros() as i64),
711 Instr::I64Popcnt => self.apply_unop_i64(|v| v.count_ones() as i64),
712 Instr::I64Add => self.apply_binop_i64(|v0, v1| v0 + v1),
713 Instr::I64Sub => self.apply_binop_i64(|v0, v1| v0 - v1),
714 Instr::I64Mul => self.apply_binop_i64(|v0, v1| v0 * v1),
715 Instr::I64DivS => self.apply_binop_i64(|v0, v1| v0.wrapping_div(v1)), Instr::I64DivU => self.apply_binop_u64(|v0, v1| v0.wrapping_div(v1)), Instr::I64RemS => self.apply_binop_i64(|v0, v1| v0.wrapping_rem(v1)), Instr::I64RemU => self.apply_binop_u64(|v0, v1| v0.wrapping_rem(v1)), Instr::I64And => self.apply_binop_i64(|v0, v1| v0 & v1),
720 Instr::I64Or => self.apply_binop_i64(|v0, v1| v0 | v1),
721 Instr::I64Xor => self.apply_binop_i64(|v0, v1| v0 ^ v1),
722 Instr::I64Shl => self.apply_binop_i64(|v0, v1| v0.wrapping_shl(v1 as u32)), Instr::I64ShrS => self.apply_binop_i64(|v0, v1| v0.wrapping_shr(v1 as u32)), Instr::I64ShrU => self.apply_binop_u64(|v0, v1| v0.wrapping_shr(v1 as u32)), Instr::I64Rotl => self.apply_binop_i64(|v0, v1| v0.rotate_left(v1 as u32)),
726 Instr::I64Rotr => self.apply_binop_i64(|v0, v1| v0.rotate_right(v1 as u32)),
727 Instr::F32Abs => self.apply_unop_f32(|v| v.abs()),
728 Instr::F32Neg => self.apply_unop_f32(|v| -v),
729 Instr::F32Ceil => self.apply_unop_f32(|v| v.ceil()),
730 Instr::F32Floor => self.apply_unop_f32(|v| v.floor()),
731 Instr::F32Trunc => self.apply_unop_f32(|v| v.trunc()),
732 Instr::F32Nearest => self.apply_unop_f32(|v| v.round()), Instr::F32Sqrt => self.apply_unop_f32(|v| v.sqrt()),
734 Instr::F32Add => self.apply_binop_f32(|v0, v1| v0 + v1),
735 Instr::F32Sub => self.apply_binop_f32(|v0, v1| v0 - v1),
736 Instr::F32Mul => self.apply_binop_f32(|v0, v1| v0 * v1),
737 Instr::F32Div => self.apply_binop_f32(|v0, v1| v0 / v1),
738 Instr::F32Min => self.apply_binop_f32(|v0, v1| v0.min(v1)),
739 Instr::F32Max => self.apply_binop_f32(|v0, v1| v0.max(v1)),
740 Instr::F32Copysign => self.apply_binop_f32(|v0, v1| v0.copysign(v1)),
741 Instr::F64Abs => self.apply_unop_f64(|v| v.abs()),
742 Instr::F64Neg => self.apply_unop_f64(|v| -v),
743 Instr::F64Ceil => self.apply_unop_f64(|v| v.ceil()),
744 Instr::F64Floor => self.apply_unop_f64(|v| v.floor()),
745 Instr::F64Trunc => self.apply_unop_f64(|v| v.trunc()),
746 Instr::F64Nearest => self.apply_unop_f64(|v| v.round()), Instr::F64Sqrt => self.apply_unop_f64(|v| v.sqrt()),
748 Instr::F64Add => self.apply_binop_f64(|v0, v1| v0 + v1),
749 Instr::F64Sub => self.apply_binop_f64(|v0, v1| v0 - v1),
750 Instr::F64Mul => self.apply_binop_f64(|v0, v1| v0 * v1),
751 Instr::F64Div => self.apply_binop_f64(|v0, v1| v0 / v1),
752 Instr::F64Min => self.apply_binop_f64(|v0, v1| v0.min(v1)),
753 Instr::F64Max => self.apply_binop_f64(|v0, v1| v0.max(v1)),
754 Instr::F64Copysign => self.apply_binop_f64(|v0, v1| v0.copysign(v1)),
755 Instr::I32WrapI64 => self.convert_from_i64(|v| Val::I32(v as i32)),
756 Instr::I32TruncF32S => self.convert_from_f32(|v| Val::I32(v.trunc() as i32)), Instr::I32TruncF32U => self.convert_from_f32(|v| Val::I32(v.trunc() as i32)), Instr::I32TruncF64S => self.convert_from_f64(|v| Val::I32(v.trunc() as i32)), Instr::I32TruncF64U => self.convert_from_f64(|v| Val::I32(v.trunc() as i32)), Instr::I64ExtendI32S => self.convert_from_i32(|v| Val::I64(v as i64)),
761 Instr::I64ExtendI32U => self.convert_from_i32(|v| Val::I64(v as u32 as i64)),
762 Instr::I64TruncF32S => self.convert_from_f32(|v| Val::I64(v.trunc() as i64)), Instr::I64TruncF32U => self.convert_from_f32(|v| Val::I64(v.trunc() as i64)), Instr::I64TruncF64S => self.convert_from_f64(|v| Val::I64(v.trunc() as i64)), Instr::I64TruncF64U => self.convert_from_f64(|v| Val::I64(v.trunc() as i64)), Instr::F32ConvertI32S => self.convert_from_i32(|v| Val::F32(v as f32)), Instr::F32ConvertI32U => self.convert_from_i32(|v| Val::F32(v as u32 as f32)), Instr::F32ConvertI64S => self.convert_from_i64(|v| Val::F32(v as f32)), Instr::F32ConvertI64U => self.convert_from_i64(|v| Val::F32(v as u64 as f32)), Instr::F32DemoteF64 => self.convert_from_f64(|v| Val::F32(v as f32)), Instr::F64ConvertI32S => self.convert_from_i32(|v| Val::F64(v as f64)), Instr::F64ConvertI32U => self.convert_from_i32(|v| Val::F64(v as u32 as f64)), Instr::F64ConvertI64S => self.convert_from_i64(|v| Val::F64(v as f64)), Instr::F64ConvertI64U => self.convert_from_i64(|v| Val::F64(v as u64 as f64)), Instr::F64PromoteF32 => self.convert_from_f32(|v| Val::F64(v as f64)),
776 Instr::I32ReinterpretF32 => self.convert_from_f32(|v| Val::I32(v.to_bits() as i32)),
777 Instr::I64ReinterpretF64 => self.convert_from_f64(|v| Val::I64(v.to_bits() as i64)),
778 Instr::F32ReinterpretI32 => {
779 self.convert_from_i32(|v| Val::F32(f32::from_bits(v as u32)))
780 }
781 Instr::F64ReinterpretI64 => {
782 self.convert_from_i64(|v| Val::F64(f64::from_bits(v as u64)))
783 }
784
785 #[cfg(feature = "sign_extension")]
787 Instr::SignExtension(instr) => match instr {
788 crate::sign_extension::SignExtensionInstr::I32Extend8S => {
789 self.convert_from_i32(|v| Val::I32(v as i8 as i32))
790 }
791 crate::sign_extension::SignExtensionInstr::I32Extend16S => {
792 self.convert_from_i32(|v| Val::I32(v as i16 as i32))
793 }
794 crate::sign_extension::SignExtensionInstr::I64Extend8S => {
795 self.convert_from_i64(|v| Val::I64(v as i8 as i64))
796 }
797 crate::sign_extension::SignExtensionInstr::I64Extend16S => {
798 self.convert_from_i64(|v| Val::I64(v as i16 as i64))
799 }
800 crate::sign_extension::SignExtensionInstr::I64Extend32S => {
801 self.convert_from_i64(|v| Val::I64(v as i32 as i64))
802 }
803 },
804 }
805 }
806 Ok(None)
807 }
808
809 fn convert_from_i32<F>(&mut self, f: F)
810 where
811 F: FnOnce(i32) -> Val,
812 {
813 let v = self.pop_value_i32();
814 self.push_value(f(v));
815 }
816
817 fn convert_from_i64<F>(&mut self, f: F)
818 where
819 F: FnOnce(i64) -> Val,
820 {
821 let v = self.pop_value_i64();
822 self.push_value(f(v));
823 }
824
825 fn convert_from_f32<F>(&mut self, f: F)
826 where
827 F: FnOnce(f32) -> Val,
828 {
829 let v = self.pop_value_f32();
830 self.push_value(f(v));
831 }
832
833 fn convert_from_f64<F>(&mut self, f: F)
834 where
835 F: FnOnce(f64) -> Val,
836 {
837 let v = self.pop_value_f64();
838 self.push_value(f(v));
839 }
840
841 fn apply_unop_f32<F>(&mut self, f: F)
842 where
843 F: FnOnce(f32) -> f32,
844 {
845 let v = self.pop_value_f32();
846 self.push_value(Val::F32(f(v)));
847 }
848
849 fn apply_binop_f32<F>(&mut self, f: F)
850 where
851 F: FnOnce(f32, f32) -> f32,
852 {
853 let v0 = self.pop_value_f32();
854 let v1 = self.pop_value_f32();
855 self.push_value(Val::F32(f(v1, v0)));
856 }
857
858 fn apply_unop_f64<F>(&mut self, f: F)
859 where
860 F: FnOnce(f64) -> f64,
861 {
862 let v = self.pop_value_f64();
863 self.push_value(Val::F64(f(v)));
864 }
865
866 fn apply_binop_f64<F>(&mut self, f: F)
867 where
868 F: FnOnce(f64, f64) -> f64,
869 {
870 let v0 = self.pop_value_f64();
871 let v1 = self.pop_value_f64();
872 self.push_value(Val::F64(f(v1, v0)));
873 }
874
875 fn apply_unop_i32<F>(&mut self, f: F)
876 where
877 F: FnOnce(i32) -> i32,
878 {
879 let v = self.pop_value_i32();
880 self.push_value(Val::I32(f(v)));
881 }
882
883 fn apply_binop_i32<F>(&mut self, f: F)
884 where
885 F: FnOnce(i32, i32) -> i32,
886 {
887 let v0 = self.pop_value_i32();
888 let v1 = self.pop_value_i32();
889 self.push_value(Val::I32(f(v1, v0)));
890 }
891
892 fn apply_binop_u32<F>(&mut self, f: F)
893 where
894 F: FnOnce(u32, u32) -> u32,
895 {
896 let v0 = self.pop_value_u32();
897 let v1 = self.pop_value_u32();
898 self.push_value(Val::I32(f(v1, v0) as i32));
899 }
900
901 fn apply_unop_i64<F>(&mut self, f: F)
902 where
903 F: FnOnce(i64) -> i64,
904 {
905 let v = self.pop_value_i64();
906 self.push_value(Val::I64(f(v)));
907 }
908
909 fn apply_binop_i64<F>(&mut self, f: F)
910 where
911 F: FnOnce(i64, i64) -> i64,
912 {
913 let v0 = self.pop_value_i64();
914 let v1 = self.pop_value_i64();
915 self.push_value(Val::I64(f(v1, v0)));
916 }
917
918 fn apply_binop_u64<F>(&mut self, f: F)
919 where
920 F: FnOnce(u64, u64) -> u64,
921 {
922 let v0 = self.pop_value_u64();
923 let v1 = self.pop_value_u64();
924 self.push_value(Val::I64(f(v1, v0) as i64));
925 }
926
927 fn apply_unop_cmp_i32<F>(&mut self, f: F)
928 where
929 F: FnOnce(i32) -> bool,
930 {
931 let v = self.pop_value_i32();
932 self.push_value(Val::I32(f(v) as i32));
933 }
934
935 fn apply_binop_cmp_i32<F>(&mut self, f: F)
936 where
937 F: FnOnce(i32, i32) -> bool,
938 {
939 let v0 = self.pop_value_i32();
940 let v1 = self.pop_value_i32();
941 self.push_value(Val::I32(f(v1, v0) as i32));
942 }
943
944 fn apply_binop_cmp_u32<F>(&mut self, f: F)
945 where
946 F: FnOnce(u32, u32) -> bool,
947 {
948 let v0 = self.pop_value_u32();
949 let v1 = self.pop_value_u32();
950 self.push_value(Val::I32(f(v1, v0) as i32));
951 }
952
953 fn apply_unop_cmp_i64<F>(&mut self, f: F)
954 where
955 F: FnOnce(i64) -> bool,
956 {
957 let v = self.pop_value_i64();
958 self.push_value(Val::I32(f(v) as i32));
959 }
960
961 fn apply_binop_cmp_i64<F>(&mut self, f: F)
962 where
963 F: FnOnce(i64, i64) -> bool,
964 {
965 let v0 = self.pop_value_i64();
966 let v1 = self.pop_value_i64();
967 self.push_value(Val::I32(f(v1, v0) as i32));
968 }
969
970 fn apply_binop_cmp_u64<F>(&mut self, f: F)
971 where
972 F: FnOnce(u64, u64) -> bool,
973 {
974 let v0 = self.pop_value_u64();
975 let v1 = self.pop_value_u64();
976 self.push_value(Val::I32(f(v1, v0) as i32));
977 }
978
979 fn apply_binop_cmp_f32<F>(&mut self, f: F)
980 where
981 F: FnOnce(f32, f32) -> bool,
982 {
983 let v0 = self.pop_value_f32();
984 let v1 = self.pop_value_f32();
985 self.push_value(Val::I32(f(v1, v0) as i32));
986 }
987
988 fn apply_binop_cmp_f64<F>(&mut self, f: F)
989 where
990 F: FnOnce(f64, f64) -> bool,
991 {
992 let v0 = self.pop_value_f64();
993 let v1 = self.pop_value_f64();
994 self.push_value(Val::I32(f(v1, v0) as i32));
995 }
996}
997
998impl<V: VectorFactory> Debug for Executor<V> {
999 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1000 f.debug_struct("Executor").finish_non_exhaustive()
1002 }
1003}
1004
1005#[derive(Debug, Default, Clone, Copy)]
1007pub struct Frame {
1008 pub arity: usize,
1009 pub locals_start: usize,
1010 pub values_start: usize,
1011}
1012
1013#[derive(Debug, Default, Clone, Copy)]
1014pub struct Block {
1015 pub arity: usize,
1016 pub values_start: usize,
1017}
1018
1019#[cfg(not(feature = "std"))]
1020trait FloatExt: Sized {
1021 fn abs(self) -> Self;
1022 fn ceil(self) -> Self;
1023 fn floor(self) -> Self;
1024 fn round(self) -> Self;
1025 fn trunc(self) -> Self;
1026 fn copysign(self, sign: Self) -> Self;
1027 fn sqrt(self) -> Self;
1028 fn signum(self) -> Self;
1029}
1030
1031#[cfg(not(feature = "std"))]
1032impl FloatExt for f32 {
1033 fn abs(self) -> Self {
1034 if self < 0.0 {
1035 -self
1036 } else {
1037 self
1038 }
1039 }
1040
1041 fn ceil(self) -> Self {
1042 let int = self as i32;
1043 if self - (int as f32) > 0.0 {
1044 int as f32 + 1.0
1045 } else {
1046 int as f32
1047 }
1048 }
1049
1050 fn floor(self) -> Self {
1051 let int = self as i32;
1052 if self - (int as f32) < 0.0 {
1053 int as f32 - 1.0
1054 } else {
1055 int as f32
1056 }
1057 }
1058
1059 fn round(self) -> Self {
1060 let int = self as i32;
1061 if self - (int as f32) >= 0.5 {
1062 int as f32 + 1.0
1063 } else {
1064 int as f32
1065 }
1066 }
1067
1068 fn trunc(self) -> Self {
1069 self as i32 as f32
1070 }
1071
1072 fn copysign(self, sign: Self) -> Self {
1073 if self.is_nan() {
1074 if sign.is_sign_positive() {
1075 f32::NAN
1076 } else {
1077 -f32::NAN
1078 }
1079 } else {
1080 self.abs() * sign.signum()
1081 }
1082 }
1083
1084 fn sqrt(self) -> Self {
1085 if self < 0.0 {
1086 panic!()
1087 }
1088 if self == 0.0 {
1089 return 0.0;
1090 }
1091
1092 let mut guess = self / 2.0;
1093 let mut previous_guess = 0.0;
1094
1095 while (guess - previous_guess).abs() > f32::EPSILON {
1096 previous_guess = guess;
1097 guess = (guess + self / guess) / 2.0;
1098 }
1099
1100 guess
1101 }
1102
1103 fn signum(self) -> Self {
1104 if self.is_nan() {
1105 f32::NAN
1106 } else if self == 0.0 {
1107 0.0
1108 } else if self > 0.0 {
1109 1.0
1110 } else {
1111 -1.0
1112 }
1113 }
1114}
1115
1116#[cfg(not(feature = "std"))]
1117impl FloatExt for f64 {
1118 fn abs(self) -> Self {
1119 if self < 0.0 {
1120 -self
1121 } else {
1122 self
1123 }
1124 }
1125
1126 fn ceil(self) -> Self {
1127 let int = self as i64;
1128 if self - int as f64 > 0.0 {
1129 int as f64 + 1.0
1130 } else {
1131 int as f64
1132 }
1133 }
1134
1135 fn floor(self) -> Self {
1136 let int = self as i64;
1137 if self - (int as f64) < 0.0 {
1138 int as f64 - 1.0
1139 } else {
1140 int as f64
1141 }
1142 }
1143
1144 fn round(self) -> Self {
1145 let int = self as i64;
1146 if self - (int as f64) >= 0.5 {
1147 int as f64 + 1.0
1148 } else {
1149 int as f64
1150 }
1151 }
1152
1153 fn trunc(self) -> Self {
1154 self as i64 as f64
1155 }
1156
1157 fn copysign(self, sign: Self) -> Self {
1158 if self.is_nan() {
1159 if sign.is_sign_positive() {
1160 f64::NAN
1161 } else {
1162 -f64::NAN
1163 }
1164 } else {
1165 self.abs() * sign.signum()
1166 }
1167 }
1168
1169 fn sqrt(self) -> Self {
1170 if self < 0.0 {
1171 panic!()
1172 }
1173 if self == 0.0 {
1174 return 0.0;
1175 }
1176
1177 let mut guess = self / 2.0;
1178 let mut previous_guess = 0.0;
1179
1180 while (guess - previous_guess).abs() > f64::EPSILON {
1181 previous_guess = guess;
1182 guess = (guess + self / guess) / 2.0;
1183 }
1184
1185 guess
1186 }
1187
1188 fn signum(self) -> Self {
1189 if self.is_nan() {
1190 f64::NAN
1191 } else if self == 0.0 {
1192 0.0
1193 } else if self > 0.0 {
1194 1.0
1195 } else {
1196 -1.0
1197 }
1198 }
1199}
1200
1201#[cfg(test)]
1202mod tests {
1203 use crate::{Env, FuncInst, HostFunc, Module, Resolve, StdVectorFactory, Val};
1204
1205 #[test]
1206 fn control_flow_br_test() {
1207 let input = [
1241 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 127, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1242 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 6, 6, 1, 127, 1, 65, 0,
1243 11, 8, 1, 1, 10, 25, 1, 23, 0, 3, 64, 35, 0, 65, 1, 106, 36, 0, 35, 0, 16, 0, 35, 0,
1244 65, 10, 72, 13, 0, 11, 11,
1245 ];
1246 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1247 let instance = module.instantiate(Resolver).expect("instantiate");
1248
1249 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1250 panic!()
1251 };
1252 assert_eq!(10, host_func.messages.len());
1253 for (i, m) in host_func.messages.iter().enumerate() {
1254 assert_eq!(Val::I32((i + 1) as i32), *m);
1255 }
1256 }
1257
1258 #[test]
1259 fn control_flow_drop_test() {
1260 let input = [
1277 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 127, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1278 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 8, 1, 1, 10, 11, 1, 9, 0,
1279 65, 10, 65, 20, 26, 16, 0, 11,
1280 ];
1281 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1282 let instance = module.instantiate(Resolver).expect("instantiate");
1283
1284 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1285 panic!()
1286 };
1287 assert_eq!(&[Val::I32(10)][..], &host_func.messages);
1288 }
1289
1290 #[test]
1291 fn control_flow_select_test() {
1292 let input = [
1313 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 127, 3, 2, 1, 0, 7, 17, 1, 13, 115,
1314 101, 108, 101, 99, 116, 95, 115, 105, 109, 112, 108, 101, 0, 0, 10, 11, 1, 9, 0, 65,
1315 10, 65, 20, 65, 0, 27, 11,
1316 ];
1317 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1318 let mut instance = module.instantiate(Resolver).expect("instantiate");
1319
1320 let val = instance
1321 .invoke("select_simple", &[])
1322 .expect("invoke")
1323 .expect("result");
1324 assert_eq!(Val::I32(20), val);
1325 }
1326
1327 #[test]
1328 fn control_flow_block_test() {
1329 let input = [
1362 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 1, 127, 0, 2, 15, 1, 7, 99, 111, 110, 115,
1363 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 0, 7, 18, 1, 14, 108, 111, 103, 95,
1364 105, 102, 95, 110, 111, 116, 95, 49, 48, 48, 0, 1, 10, 22, 1, 20, 0, 2, 64, 32, 0, 65,
1365 228, 0, 70, 4, 64, 12, 1, 11, 32, 0, 16, 0, 11, 11,
1366 ];
1367 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1368 let mut instance = module.instantiate(Resolver).expect("instantiate");
1369
1370 assert!(instance
1371 .invoke("log_if_not_100", &[Val::I32(99)])
1372 .expect("invoke")
1373 .is_none());
1374
1375 assert!(instance
1376 .invoke("log_if_not_100", &[Val::I32(100)])
1377 .expect("invoke")
1378 .is_none());
1379
1380 assert!(instance
1381 .invoke("log_if_not_100", &[Val::I32(101)])
1382 .expect("invoke")
1383 .is_none());
1384
1385 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1386 panic!()
1387 };
1388 assert_eq!(&[Val::I32(99), Val::I32(101)][..], &host_func.messages);
1389 }
1390
1391 #[test]
1392 fn memory_size_test() {
1393 let input = [
1407 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 127, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1408 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 5, 3, 1, 0, 2, 8, 1, 1,
1409 10, 8, 1, 6, 0, 63, 0, 16, 0, 11,
1410 ];
1411 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1412 let instance = module.instantiate(Resolver).expect("instantiate");
1413
1414 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1415 panic!()
1416 };
1417 assert_eq!(&[Val::I32(2)][..], &host_func.messages);
1418 }
1419
1420 #[test]
1421 fn memory_grow_test() {
1422 let input = [
1441 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 127, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1442 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 5, 4, 1, 1, 1, 2, 8, 1, 1,
1443 10, 16, 1, 14, 0, 65, 1, 64, 0, 16, 0, 65, 1, 64, 0, 16, 0, 11,
1444 ];
1445 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1446 let instance = module.instantiate(Resolver).expect("instantiate");
1447
1448 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1449 panic!()
1450 };
1451 assert_eq!(&[Val::I32(1), Val::I32(-1)][..], &host_func.messages);
1452 }
1453
1454 #[test]
1455 fn consts_test() {
1456 let input = [
1469 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 127, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1470 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 8, 1, 1, 10, 12, 1, 10, 0,
1471 65, 10, 16, 0, 65, 125, 16, 0, 11,
1472 ];
1473
1474 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1475 let instance = module.instantiate(Resolver).expect("instantiate");
1476
1477 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1478 panic!()
1479 };
1480 assert_eq!(&[Val::I32(10), Val::I32(-3)][..], &host_func.messages);
1481 }
1482
1483 #[test]
1484 fn numeric_reinterpret_test() {
1485 let input = [
1502 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 127, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1503 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 8, 1, 1, 10, 12, 1, 10, 0,
1504 67, 0, 0, 0, 128, 188, 16, 0, 11,
1505 ];
1506 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1507 let instance = module.instantiate(Resolver).expect("instantiate");
1508
1509 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1510 panic!()
1511 };
1512 assert_eq!(&[Val::I32(-2147483648)][..], &host_func.messages);
1513 }
1514
1515 #[test]
1516 fn numeric_truncate_float_to_int_test() {
1517 let input = [
1533 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 127, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1534 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 8, 1, 1, 10, 12, 1, 10, 0,
1535 67, 0, 0, 40, 65, 168, 16, 0, 11,
1536 ];
1537 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1538 let instance = module.instantiate(Resolver).expect("instantiate");
1539
1540 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1541 panic!()
1542 };
1543 assert_eq!(&[Val::I32(10)][..], &host_func.messages);
1544 }
1545
1546 #[test]
1547 fn numeric_convert_test() {
1548 let input = [
1563 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 125, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1564 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 8, 1, 1, 10, 9, 1, 7, 0,
1565 65, 10, 178, 16, 0, 11,
1566 ];
1567 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1568 let instance = module.instantiate(Resolver).expect("instantiate");
1569
1570 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1571 panic!()
1572 };
1573 assert_eq!(&[Val::F32(10.0)][..], &host_func.messages);
1574 }
1575
1576 #[test]
1577 fn numeric_demote_test() {
1578 let input = [
1594 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 125, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1595 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 8, 1, 1, 10, 16, 1, 14, 0,
1596 68, 0, 0, 0, 0, 0, 0, 37, 64, 182, 16, 0, 11,
1597 ];
1598 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1599 let instance = module.instantiate(Resolver).expect("instantiate");
1600
1601 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1602 panic!()
1603 };
1604 assert_eq!(&[Val::F32(10.5)][..], &host_func.messages);
1605 }
1606
1607 #[test]
1608 fn numeric_promote_test() {
1609 let input = [
1625 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 124, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1626 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 8, 1, 1, 10, 12, 1, 10, 0,
1627 67, 0, 0, 40, 65, 187, 16, 0, 11,
1628 ];
1629 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1630 let instance = module.instantiate(Resolver).expect("instantiate");
1631
1632 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1633 panic!()
1634 };
1635 assert_eq!(&[Val::F64(10.5)][..], &host_func.messages);
1636 }
1637
1638 #[test]
1639 fn numeric_wrap_test() {
1640 let input = [
1655 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 127, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1656 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 8, 1, 1, 10, 9, 1, 7, 0,
1657 66, 10, 167, 16, 0, 11,
1658 ];
1659 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1660 let instance = module.instantiate(Resolver).expect("instantiate");
1661
1662 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1663 panic!()
1664 };
1665 assert_eq!(&[Val::I32(10)][..], &host_func.messages);
1666 }
1667
1668 #[test]
1669 fn numeric_extend_test() {
1670 let input = [
1686 0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 126, 0, 96, 0, 0, 2, 15, 1, 7, 99, 111,
1687 110, 115, 111, 108, 101, 3, 108, 111, 103, 0, 0, 3, 2, 1, 1, 8, 1, 1, 10, 9, 1, 7, 0,
1688 65, 10, 172, 16, 0, 11,
1689 ];
1690 let module = Module::<StdVectorFactory>::decode(&input).expect("decode");
1691 let instance = module.instantiate(Resolver).expect("instantiate");
1692
1693 let FuncInst::Imported { host_func, .. } = &instance.funcs()[0] else {
1694 panic!()
1695 };
1696 assert_eq!(&[Val::I64(10)][..], &host_func.messages);
1697 }
1698
1699 #[derive(Debug)]
1700 struct Resolver;
1701
1702 impl Resolve for Resolver {
1703 type HostFunc = Log;
1704
1705 fn resolve_func(&self, module: &str, name: &str) -> Option<Self::HostFunc> {
1706 if module == "console" && name == "log" {
1707 Some(Log::default())
1708 } else {
1709 None
1710 }
1711 }
1712 }
1713
1714 #[derive(Debug, Default)]
1715 struct Log {
1716 messages: Vec<Val>,
1717 }
1718
1719 impl HostFunc for Log {
1720 fn invoke(&mut self, args: &[Val], _env: &mut Env) -> Option<Val> {
1721 self.messages.push(args[0]);
1722 None
1723 }
1724 }
1725}