1#[allow(dead_code)]
7#[derive(Debug, Clone, PartialEq)]
8pub enum WasmValueType {
9 I32,
10 I64,
11 F32,
12 F64,
13 FuncRef,
14 ExternRef,
15}
16
17#[allow(dead_code)]
19#[derive(Debug, Clone, PartialEq)]
20pub enum WasmValue {
21 I32(i32),
22 I64(i64),
23 F32(f32),
24 F64(f64),
25}
26
27#[derive(Debug, thiserror::Error)]
29pub enum WasmError {
30 #[error("Function not found: {0}")]
31 FunctionNotFound(String),
32 #[error("Type mismatch: {0}")]
33 TypeMismatch(String),
34 #[error("Runtime trap: {0}")]
35 Trap(String),
36 #[error("Memory out of bounds at offset {0}")]
37 MemoryOutOfBounds(usize),
38 #[error("Division by zero")]
39 DivisionByZero,
40 #[error("Stack overflow")]
41 StackOverflow,
42 #[error("Unimplemented opcode: 0x{0:02X}")]
43 UnimplementedOpcode(u8),
44}
45
46#[allow(dead_code)]
47#[derive(Debug, Clone)]
48pub struct WasmBridgeConfig {
49 pub memory_pages: u32,
50 pub max_functions: usize,
51 pub debug_mode: bool,
52}
53
54#[allow(dead_code)]
55#[derive(Debug, Clone)]
56pub struct WasmMemory {
57 pub data: Vec<u8>,
58 pub size_bytes: usize,
59}
60
61#[allow(dead_code)]
66#[derive(Debug, Clone)]
67pub struct WasmFunction {
68 pub name: String,
69 pub param_types: Vec<WasmValueType>,
70 pub return_types: Vec<WasmValueType>,
71 pub bytecode: Vec<u8>,
72 pub local_types: Vec<WasmValueType>,
73}
74
75#[allow(dead_code)]
76#[derive(Debug, Clone)]
77pub struct WasmBridge {
78 pub config: WasmBridgeConfig,
79 pub memory: WasmMemory,
80 pub functions: Vec<WasmFunction>,
81 pub call_count: u64,
82}
83
84#[derive(Debug, Clone, PartialEq)]
87enum BlockKind {
88 Block,
89 Loop,
90 If,
91}
92
93#[derive(Debug, Clone)]
94struct BlockFrame {
95 kind: BlockKind,
96 arity: usize,
97 height: usize,
98 else_or_end_pc: usize,
100}
101
102fn read_leb128_u32(code: &[u8], pc: &mut usize) -> u32 {
105 let (mut r, mut s) = (0u32, 0u32);
106 loop {
107 let b = code[*pc];
108 *pc += 1;
109 r |= ((b & 0x7F) as u32) << s;
110 if b & 0x80 == 0 {
111 break;
112 }
113 s += 7;
114 }
115 r
116}
117
118#[allow(dead_code)]
119fn read_leb128_u64(code: &[u8], pc: &mut usize) -> u64 {
120 let (mut r, mut s) = (0u64, 0u32);
121 loop {
122 let b = code[*pc];
123 *pc += 1;
124 r |= ((b & 0x7F) as u64) << s;
125 if b & 0x80 == 0 {
126 break;
127 }
128 s += 7;
129 }
130 r
131}
132
133fn read_leb128_i32(code: &[u8], pc: &mut usize) -> i32 {
134 let (mut r, mut s) = (0i32, 0u32);
135 let last = loop {
136 let b = code[*pc];
137 *pc += 1;
138 r |= ((b & 0x7F) as i32) << s;
139 s += 7;
140 if b & 0x80 == 0 {
141 break b;
142 }
143 };
144 if s < 32 && (last & 0x40) != 0 {
145 r |= -1i32 << s;
146 }
147 r
148}
149
150fn read_leb128_i64(code: &[u8], pc: &mut usize) -> i64 {
151 let (mut r, mut s) = (0i64, 0u32);
152 let last = loop {
153 let b = code[*pc];
154 *pc += 1;
155 r |= ((b & 0x7F) as i64) << s;
156 s += 7;
157 if b & 0x80 == 0 {
158 break b;
159 }
160 };
161 if s < 64 && (last & 0x40) != 0 {
162 r |= -1i64 << s;
163 }
164 r
165}
166
167fn skip_leb128(code: &[u8], pc: &mut usize) {
168 while *pc < code.len() {
169 let b = code[*pc];
170 *pc += 1;
171 if b & 0x80 == 0 {
172 break;
173 }
174 }
175}
176
177const MAX_CALL_DEPTH: usize = 512;
180const MAX_STACK_DEPTH: usize = 65536;
181
182struct Interpreter<'a> {
183 stack: Vec<WasmValue>,
184 locals: Vec<WasmValue>,
185 memory: &'a mut WasmMemory,
186 code: &'a [u8],
187 pc: usize,
188 blocks: Vec<BlockFrame>,
189 call_depth: usize,
190}
191
192impl<'a> Interpreter<'a> {
193 fn new(
194 memory: &'a mut WasmMemory,
195 code: &'a [u8],
196 locals: Vec<WasmValue>,
197 call_depth: usize,
198 ) -> Self {
199 Interpreter {
200 stack: Vec::new(),
201 locals,
202 memory,
203 code,
204 pc: 0,
205 blocks: Vec::new(),
206 call_depth,
207 }
208 }
209
210 fn push(&mut self, v: WasmValue) -> Result<(), WasmError> {
213 if self.stack.len() >= MAX_STACK_DEPTH {
214 return Err(WasmError::StackOverflow);
215 }
216 self.stack.push(v);
217 Ok(())
218 }
219 fn pop(&mut self) -> Result<WasmValue, WasmError> {
220 self.stack
221 .pop()
222 .ok_or_else(|| WasmError::Trap("value stack underflow".into()))
223 }
224 fn pop_i32(&mut self) -> Result<i32, WasmError> {
225 match self.pop()? {
226 WasmValue::I32(v) => Ok(v),
227 o => Err(WasmError::TypeMismatch(format!(
228 "expected i32, got {:?}",
229 o
230 ))),
231 }
232 }
233 fn pop_i64(&mut self) -> Result<i64, WasmError> {
234 match self.pop()? {
235 WasmValue::I64(v) => Ok(v),
236 o => Err(WasmError::TypeMismatch(format!(
237 "expected i64, got {:?}",
238 o
239 ))),
240 }
241 }
242 fn pop_f32(&mut self) -> Result<f32, WasmError> {
243 match self.pop()? {
244 WasmValue::F32(v) => Ok(v),
245 o => Err(WasmError::TypeMismatch(format!(
246 "expected f32, got {:?}",
247 o
248 ))),
249 }
250 }
251 fn pop_f64(&mut self) -> Result<f64, WasmError> {
252 match self.pop()? {
253 WasmValue::F64(v) => Ok(v),
254 o => Err(WasmError::TypeMismatch(format!(
255 "expected f64, got {:?}",
256 o
257 ))),
258 }
259 }
260 #[allow(dead_code)]
261 fn peek_byte(&self) -> Option<u8> {
262 self.code.get(self.pc).copied()
263 }
264
265 fn read_byte(&mut self) -> Result<u8, WasmError> {
268 if self.pc >= self.code.len() {
269 return Err(WasmError::Trap("unexpected end of bytecode".into()));
270 }
271 let b = self.code[self.pc];
272 self.pc += 1;
273 Ok(b)
274 }
275 fn read_u32_leb(&mut self) -> Result<u32, WasmError> {
276 if self.pc >= self.code.len() {
277 return Err(WasmError::Trap("unexpected end (LEB128 u32)".into()));
278 }
279 Ok(read_leb128_u32(self.code, &mut self.pc))
280 }
281 fn read_i32_leb(&mut self) -> Result<i32, WasmError> {
282 if self.pc >= self.code.len() {
283 return Err(WasmError::Trap("unexpected end (LEB128 i32)".into()));
284 }
285 Ok(read_leb128_i32(self.code, &mut self.pc))
286 }
287 fn read_i64_leb(&mut self) -> Result<i64, WasmError> {
288 if self.pc >= self.code.len() {
289 return Err(WasmError::Trap("unexpected end (LEB128 i64)".into()));
290 }
291 Ok(read_leb128_i64(self.code, &mut self.pc))
292 }
293 fn read_f32(&mut self) -> Result<f32, WasmError> {
294 if self.pc + 4 > self.code.len() {
295 return Err(WasmError::Trap("unexpected end (f32)".into()));
296 }
297 let b = [
298 self.code[self.pc],
299 self.code[self.pc + 1],
300 self.code[self.pc + 2],
301 self.code[self.pc + 3],
302 ];
303 self.pc += 4;
304 Ok(f32::from_le_bytes(b))
305 }
306 fn read_f64(&mut self) -> Result<f64, WasmError> {
307 if self.pc + 8 > self.code.len() {
308 return Err(WasmError::Trap("unexpected end (f64)".into()));
309 }
310 let b: [u8; 8] = self.code[self.pc..self.pc + 8].try_into().unwrap_or([0; 8]);
311 self.pc += 8;
312 Ok(f64::from_le_bytes(b))
313 }
314
315 fn effective_addr(&self, base: u32, offset: u32) -> usize {
318 (base as usize).wrapping_add(offset as usize)
319 }
320
321 fn mload_i32(&self, a: usize) -> Result<i32, WasmError> {
323 if a + 4 > self.memory.data.len() {
324 return Err(WasmError::MemoryOutOfBounds(a));
325 }
326 Ok(i32::from_le_bytes(
327 self.memory.data[a..a + 4].try_into().unwrap_or([0; 4]),
328 ))
329 }
330 fn mload_i64(&self, a: usize) -> Result<i64, WasmError> {
331 if a + 8 > self.memory.data.len() {
332 return Err(WasmError::MemoryOutOfBounds(a));
333 }
334 Ok(i64::from_le_bytes(
335 self.memory.data[a..a + 8].try_into().unwrap_or([0; 8]),
336 ))
337 }
338 fn mload_f32(&self, a: usize) -> Result<f32, WasmError> {
339 if a + 4 > self.memory.data.len() {
340 return Err(WasmError::MemoryOutOfBounds(a));
341 }
342 Ok(f32::from_le_bytes(
343 self.memory.data[a..a + 4].try_into().unwrap_or([0; 4]),
344 ))
345 }
346 fn mload_f64(&self, a: usize) -> Result<f64, WasmError> {
347 if a + 8 > self.memory.data.len() {
348 return Err(WasmError::MemoryOutOfBounds(a));
349 }
350 Ok(f64::from_le_bytes(
351 self.memory.data[a..a + 8].try_into().unwrap_or([0; 8]),
352 ))
353 }
354 fn mload_i32_ext(&self, a: usize, bytes: usize, signed: bool) -> Result<i32, WasmError> {
355 if a + bytes > self.memory.data.len() {
356 return Err(WasmError::MemoryOutOfBounds(a));
357 }
358 let mut buf = [0u8; 4];
359 buf[..bytes].copy_from_slice(&self.memory.data[a..a + bytes]);
360 let raw = u32::from_le_bytes(buf);
361 Ok(if signed {
362 sign_extend_u32(raw, bytes * 8)
363 } else {
364 raw as i32
365 })
366 }
367 fn mload_i64_ext(&self, a: usize, bytes: usize, signed: bool) -> Result<i64, WasmError> {
368 if a + bytes > self.memory.data.len() {
369 return Err(WasmError::MemoryOutOfBounds(a));
370 }
371 let mut buf = [0u8; 8];
372 buf[..bytes].copy_from_slice(&self.memory.data[a..a + bytes]);
373 let raw = u64::from_le_bytes(buf);
374 Ok(if signed {
375 sign_extend_u64(raw, bytes * 8)
376 } else {
377 raw as i64
378 })
379 }
380
381 fn mstore_i32(&mut self, a: usize, v: i32) -> Result<(), WasmError> {
383 if a + 4 > self.memory.data.len() {
384 return Err(WasmError::MemoryOutOfBounds(a));
385 }
386 self.memory.data[a..a + 4].copy_from_slice(&v.to_le_bytes());
387 Ok(())
388 }
389 fn mstore_i64(&mut self, a: usize, v: i64) -> Result<(), WasmError> {
390 if a + 8 > self.memory.data.len() {
391 return Err(WasmError::MemoryOutOfBounds(a));
392 }
393 self.memory.data[a..a + 8].copy_from_slice(&v.to_le_bytes());
394 Ok(())
395 }
396 fn mstore_f32(&mut self, a: usize, v: f32) -> Result<(), WasmError> {
397 if a + 4 > self.memory.data.len() {
398 return Err(WasmError::MemoryOutOfBounds(a));
399 }
400 self.memory.data[a..a + 4].copy_from_slice(&v.to_le_bytes());
401 Ok(())
402 }
403 fn mstore_f64(&mut self, a: usize, v: f64) -> Result<(), WasmError> {
404 if a + 8 > self.memory.data.len() {
405 return Err(WasmError::MemoryOutOfBounds(a));
406 }
407 self.memory.data[a..a + 8].copy_from_slice(&v.to_le_bytes());
408 Ok(())
409 }
410 fn mstore_trunc(&mut self, a: usize, bytes: usize, v: u64) -> Result<(), WasmError> {
411 if a + bytes > self.memory.data.len() {
412 return Err(WasmError::MemoryOutOfBounds(a));
413 }
414 let src = v.to_le_bytes();
415 self.memory.data[a..a + bytes].copy_from_slice(&src[..bytes]);
416 Ok(())
417 }
418
419 fn read_mem_arg(&mut self) -> Result<u32, WasmError> {
422 let _align = self.read_u32_leb()?;
423 self.read_u32_leb()
424 }
425
426 fn pop_addr_offset(&mut self, offset: u32) -> Result<usize, WasmError> {
427 let base = self.pop_i32()? as u32;
428 Ok(self.effective_addr(base, offset))
429 }
430
431 fn scan_to_else_or_end(&self, start_pc: usize) -> Result<(usize, usize), WasmError> {
436 let (mut depth, mut pc) = (1usize, start_pc);
437 let mut first_else: Option<usize> = None;
438 while pc < self.code.len() {
439 let op = self.code[pc];
440 pc += 1;
441 match op {
442 0x02..=0x04 => {
443 depth += 1;
444 pc += 1;
445 } 0x05 if depth == 1 && first_else.is_none() => {
447 first_else = Some(pc - 1);
448 }
449 0x0B => {
450 depth -= 1;
451 if depth == 0 {
452 let end_pc = pc - 1;
453 return Ok((first_else.unwrap_or(end_pc), end_pc));
454 }
455 }
456 0x20..=0x24 => {
457 skip_leb128(self.code, &mut pc);
458 }
459 0x28..=0x3E => {
460 skip_leb128(self.code, &mut pc);
461 skip_leb128(self.code, &mut pc);
462 }
463 0x3F | 0x40 => {
464 pc += 1;
465 }
466 0x41 => {
467 skip_leb128(self.code, &mut pc);
468 }
469 0x42 => {
470 skip_leb128(self.code, &mut pc);
471 }
472 0x43 => {
473 pc += 4;
474 }
475 0x44 => {
476 pc += 8;
477 }
478 0x0C | 0x0D => {
479 skip_leb128(self.code, &mut pc);
480 }
481 0x0E => {
482 let n = read_leb128_u32(self.code, &mut pc) as usize;
483 for _ in 0..=n {
484 skip_leb128(self.code, &mut pc);
485 }
486 }
487 0x10 | 0x11 => {
488 skip_leb128(self.code, &mut pc);
489 if op == 0x11 {
490 skip_leb128(self.code, &mut pc);
491 }
492 }
493 _ => {}
494 }
495 }
496 Err(WasmError::Trap("unmatched block (no end found)".into()))
497 }
498
499 fn do_branch(&mut self, depth: u32) -> Result<Option<usize>, WasmError> {
502 let depth = depth as usize;
503 if depth >= self.blocks.len() {
504 return Ok(None);
505 }
506 let idx = self.blocks.len() - 1 - depth;
507 let frame = self.blocks[idx].clone();
508 let slen = self.stack.len();
509 if slen < frame.arity {
510 return Err(WasmError::Trap("branch: stack underflow".into()));
511 }
512 let results: Vec<WasmValue> = self.stack[slen - frame.arity..].to_vec();
513 self.stack.truncate(frame.height);
514 for v in results {
515 self.push(v)?;
516 }
517 self.blocks.truncate(idx);
518 let new_pc = match frame.kind {
519 BlockKind::Loop => frame.else_or_end_pc,
520 _ => {
521 let end = frame.else_or_end_pc;
522 if end < self.code.len() && self.code[end] == 0x0B {
523 end + 1
524 } else {
525 end
526 }
527 }
528 };
529 Ok(Some(new_pc))
530 }
531
532 fn run(&mut self, n_results: usize) -> Result<Vec<WasmValue>, WasmError> {
535 if self.call_depth > MAX_CALL_DEPTH {
536 return Err(WasmError::StackOverflow);
537 }
538
539 while self.pc < self.code.len() {
540 let op = self.read_byte()?;
541 match op {
542 0x00 => return Err(WasmError::Trap("unreachable".into())),
544 0x01 => { }
545 0x02 => {
546 let _ = self.read_byte()?;
548 let scan = self.pc;
549 let (_ep, end) = self.scan_to_else_or_end(scan)?;
550 self.blocks.push(BlockFrame {
551 kind: BlockKind::Block,
552 arity: 0,
553 height: self.stack.len(),
554 else_or_end_pc: end,
555 });
556 }
557 0x03 => {
558 let _ = self.read_byte()?;
560 let hdr = self.pc;
561 let scan = self.pc;
562 let _ = self.scan_to_else_or_end(scan)?;
563 self.blocks.push(BlockFrame {
564 kind: BlockKind::Loop,
565 arity: 0,
566 height: self.stack.len(),
567 else_or_end_pc: hdr,
568 });
569 }
570 0x04 => {
571 let _ = self.read_byte()?;
573 let cond = self.pop_i32()?;
574 let scan = self.pc;
575 let (ep, end) = self.scan_to_else_or_end(scan)?;
576 self.blocks.push(BlockFrame {
577 kind: BlockKind::If,
578 arity: 0,
579 height: self.stack.len(),
580 else_or_end_pc: end,
581 });
582 if cond == 0 {
583 if ep < end {
584 self.pc = ep + 1;
585 } else {
586 self.pc = end + 1;
587 self.blocks.pop();
588 }
589 }
590 }
591 0x05 => {
592 let end = self
594 .blocks
595 .last()
596 .map(|f| f.else_or_end_pc)
597 .ok_or_else(|| WasmError::Trap("else without if".into()))?;
598 self.pc = end + 1;
599 self.blocks.pop();
600 }
601 0x0B => {
602 if self.blocks.is_empty() {
604 break;
605 }
606 let frame = self.blocks.pop().expect("block frame");
607 let slen = self.stack.len();
608 if slen < frame.arity {
609 return Err(WasmError::Trap("end: stack underflow".into()));
610 }
611 let res: Vec<WasmValue> = self.stack[slen - frame.arity..].to_vec();
612 self.stack.truncate(frame.height);
613 for v in res {
614 self.push(v)?;
615 }
616 }
617 0x0C => {
618 let d = self.read_u32_leb()?;
619 match self.do_branch(d)? {
620 Some(p) => self.pc = p,
621 None => break,
622 }
623 }
624 0x0D => {
625 let d = self.read_u32_leb()?;
626 let c = self.pop_i32()?;
627 if c != 0 {
628 match self.do_branch(d)? {
629 Some(p) => self.pc = p,
630 None => break,
631 }
632 }
633 }
634 0x0E => {
635 let n = self.read_u32_leb()? as usize;
637 let mut lbs = Vec::with_capacity(n + 1);
638 for _ in 0..=n {
639 lbs.push(self.read_u32_leb()?);
640 }
641 let idx = self.pop_i32()? as usize;
642 let d = if idx < n { lbs[idx] } else { lbs[n] };
643 match self.do_branch(d)? {
644 Some(p) => self.pc = p,
645 None => break,
646 }
647 }
648 0x0F => break, 0x10 => {
650 let _ = self.read_u32_leb()?;
651 return Err(WasmError::Trap("call not supported".into()));
652 }
653 0x11 => {
654 let _ = self.read_u32_leb()?;
655 let _ = self.read_u32_leb()?;
656 return Err(WasmError::Trap("call_indirect not supported".into()));
657 }
658
659 0x1A => {
661 self.pop()?;
662 }
663 0x1B => {
664 let c = self.pop_i32()?;
665 let b = self.pop()?;
666 let a = self.pop()?;
667 self.push(if c != 0 { a } else { b })?;
668 }
669
670 0x20 => {
672 let i = self.read_u32_leb()? as usize;
673 let v = self
674 .locals
675 .get(i)
676 .cloned()
677 .ok_or_else(|| WasmError::Trap(format!("local.get: {} oob", i)))?;
678 self.push(v)?;
679 }
680 0x21 => {
681 let i = self.read_u32_leb()? as usize;
682 let v = self.pop()?;
683 *self
684 .locals
685 .get_mut(i)
686 .ok_or_else(|| WasmError::Trap(format!("local.set: {} oob", i)))? = v;
687 }
688 0x22 => {
689 let i = self.read_u32_leb()? as usize;
690 let v = self
691 .stack
692 .last()
693 .cloned()
694 .ok_or_else(|| WasmError::Trap("local.tee: underflow".into()))?;
695 *self
696 .locals
697 .get_mut(i)
698 .ok_or_else(|| WasmError::Trap(format!("local.tee: {} oob", i)))? = v;
699 }
700 0x23 => {
701 let _ = self.read_u32_leb()?;
702 return Err(WasmError::Trap("global.get not supported".into()));
703 }
704 0x24 => {
705 let _ = self.read_u32_leb()?;
706 return Err(WasmError::Trap("global.set not supported".into()));
707 }
708
709 0x28 => {
711 let off = self.read_mem_arg()?;
712 let a = self.pop_addr_offset(off)?;
713 let v = self.mload_i32(a)?;
714 self.push(WasmValue::I32(v))?;
715 }
716 0x29 => {
717 let off = self.read_mem_arg()?;
718 let a = self.pop_addr_offset(off)?;
719 let v = self.mload_i64(a)?;
720 self.push(WasmValue::I64(v))?;
721 }
722 0x2A => {
723 let off = self.read_mem_arg()?;
724 let a = self.pop_addr_offset(off)?;
725 let v = self.mload_f32(a)?;
726 self.push(WasmValue::F32(v))?;
727 }
728 0x2B => {
729 let off = self.read_mem_arg()?;
730 let a = self.pop_addr_offset(off)?;
731 let v = self.mload_f64(a)?;
732 self.push(WasmValue::F64(v))?;
733 }
734 0x2C => {
735 let off = self.read_mem_arg()?;
736 let a = self.pop_addr_offset(off)?;
737 let v = self.mload_i32_ext(a, 1, true)?;
738 self.push(WasmValue::I32(v))?;
739 }
740 0x2D => {
741 let off = self.read_mem_arg()?;
742 let a = self.pop_addr_offset(off)?;
743 let v = self.mload_i32_ext(a, 1, false)?;
744 self.push(WasmValue::I32(v))?;
745 }
746 0x2E => {
747 let off = self.read_mem_arg()?;
748 let a = self.pop_addr_offset(off)?;
749 let v = self.mload_i32_ext(a, 2, true)?;
750 self.push(WasmValue::I32(v))?;
751 }
752 0x2F => {
753 let off = self.read_mem_arg()?;
754 let a = self.pop_addr_offset(off)?;
755 let v = self.mload_i32_ext(a, 2, false)?;
756 self.push(WasmValue::I32(v))?;
757 }
758 0x30 => {
759 let off = self.read_mem_arg()?;
760 let a = self.pop_addr_offset(off)?;
761 let v = self.mload_i64_ext(a, 1, true)?;
762 self.push(WasmValue::I64(v))?;
763 }
764 0x31 => {
765 let off = self.read_mem_arg()?;
766 let a = self.pop_addr_offset(off)?;
767 let v = self.mload_i64_ext(a, 1, false)?;
768 self.push(WasmValue::I64(v))?;
769 }
770 0x32 => {
771 let off = self.read_mem_arg()?;
772 let a = self.pop_addr_offset(off)?;
773 let v = self.mload_i64_ext(a, 2, true)?;
774 self.push(WasmValue::I64(v))?;
775 }
776 0x33 => {
777 let off = self.read_mem_arg()?;
778 let a = self.pop_addr_offset(off)?;
779 let v = self.mload_i64_ext(a, 2, false)?;
780 self.push(WasmValue::I64(v))?;
781 }
782 0x34 => {
783 let off = self.read_mem_arg()?;
784 let a = self.pop_addr_offset(off)?;
785 let v = self.mload_i64_ext(a, 4, true)?;
786 self.push(WasmValue::I64(v))?;
787 }
788 0x35 => {
789 let off = self.read_mem_arg()?;
790 let a = self.pop_addr_offset(off)?;
791 let v = self.mload_i64_ext(a, 4, false)?;
792 self.push(WasmValue::I64(v))?;
793 }
794
795 0x36 => {
797 let off = self.read_mem_arg()?;
798 let v = self.pop_i32()?;
799 let a = self.pop_addr_offset(off)?;
800 self.mstore_i32(a, v)?;
801 }
802 0x37 => {
803 let off = self.read_mem_arg()?;
804 let v = self.pop_i64()?;
805 let a = self.pop_addr_offset(off)?;
806 self.mstore_i64(a, v)?;
807 }
808 0x38 => {
809 let off = self.read_mem_arg()?;
810 let v = self.pop_f32()?;
811 let a = self.pop_addr_offset(off)?;
812 self.mstore_f32(a, v)?;
813 }
814 0x39 => {
815 let off = self.read_mem_arg()?;
816 let v = self.pop_f64()?;
817 let a = self.pop_addr_offset(off)?;
818 self.mstore_f64(a, v)?;
819 }
820 0x3A => {
821 let off = self.read_mem_arg()?;
822 let v = self.pop_i32()? as u64;
823 let a = self.pop_addr_offset(off)?;
824 self.mstore_trunc(a, 1, v)?;
825 }
826 0x3B => {
827 let off = self.read_mem_arg()?;
828 let v = self.pop_i32()? as u64;
829 let a = self.pop_addr_offset(off)?;
830 self.mstore_trunc(a, 2, v)?;
831 }
832 0x3C => {
833 let off = self.read_mem_arg()?;
834 let v = self.pop_i64()? as u64;
835 let a = self.pop_addr_offset(off)?;
836 self.mstore_trunc(a, 1, v)?;
837 }
838 0x3D => {
839 let off = self.read_mem_arg()?;
840 let v = self.pop_i64()? as u64;
841 let a = self.pop_addr_offset(off)?;
842 self.mstore_trunc(a, 2, v)?;
843 }
844 0x3E => {
845 let off = self.read_mem_arg()?;
846 let v = self.pop_i64()? as u64;
847 let a = self.pop_addr_offset(off)?;
848 self.mstore_trunc(a, 4, v)?;
849 }
850
851 0x3F => {
853 let _ = self.read_byte()?;
854 self.push(WasmValue::I32((self.memory.data.len() / 65536) as i32))?;
855 }
856 0x40 => {
857 let _ = self.read_byte()?;
858 let n = self.pop_i32()?;
859 let cur = (self.memory.data.len() / 65536) as i32;
860 if n >= 0 {
861 let nb = self.memory.data.len() + (n as usize * 65536);
862 self.memory.data.resize(nb, 0);
863 self.memory.size_bytes = nb;
864 self.push(WasmValue::I32(cur))?;
865 } else {
866 self.push(WasmValue::I32(-1))?;
867 }
868 }
869
870 0x41 => {
872 let v = self.read_i32_leb()?;
873 self.push(WasmValue::I32(v))?;
874 }
875 0x42 => {
876 let v = self.read_i64_leb()?;
877 self.push(WasmValue::I64(v))?;
878 }
879 0x43 => {
880 let v = self.read_f32()?;
881 self.push(WasmValue::F32(v))?;
882 }
883 0x44 => {
884 let v = self.read_f64()?;
885 self.push(WasmValue::F64(v))?;
886 }
887
888 0x45 => {
890 let a = self.pop_i32()?;
891 self.push(WasmValue::I32(bool_to_i32(a == 0)))?;
892 }
893 0x46 => {
894 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
895 self.push(WasmValue::I32(bool_to_i32(a == b)))?;
896 }
897 0x47 => {
898 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
899 self.push(WasmValue::I32(bool_to_i32(a != b)))?;
900 }
901 0x48 => {
902 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
903 self.push(WasmValue::I32(bool_to_i32(a < b)))?;
904 }
905 0x49 => {
906 let (b, a) = (self.pop_i32()? as u32, self.pop_i32()? as u32);
907 self.push(WasmValue::I32(bool_to_i32(a < b)))?;
908 }
909 0x4A => {
910 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
911 self.push(WasmValue::I32(bool_to_i32(a > b)))?;
912 }
913 0x4B => {
914 let (b, a) = (self.pop_i32()? as u32, self.pop_i32()? as u32);
915 self.push(WasmValue::I32(bool_to_i32(a > b)))?;
916 }
917 0x4C => {
918 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
919 self.push(WasmValue::I32(bool_to_i32(a <= b)))?;
920 }
921 0x4D => {
922 let (b, a) = (self.pop_i32()? as u32, self.pop_i32()? as u32);
923 self.push(WasmValue::I32(bool_to_i32(a <= b)))?;
924 }
925 0x4E => {
926 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
927 self.push(WasmValue::I32(bool_to_i32(a >= b)))?;
928 }
929 0x4F => {
930 let (b, a) = (self.pop_i32()? as u32, self.pop_i32()? as u32);
931 self.push(WasmValue::I32(bool_to_i32(a >= b)))?;
932 }
933
934 0x50 => {
936 let a = self.pop_i64()?;
937 self.push(WasmValue::I32(bool_to_i32(a == 0)))?;
938 }
939 0x51 => {
940 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
941 self.push(WasmValue::I32(bool_to_i32(a == b)))?;
942 }
943 0x52 => {
944 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
945 self.push(WasmValue::I32(bool_to_i32(a != b)))?;
946 }
947 0x53 => {
948 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
949 self.push(WasmValue::I32(bool_to_i32(a < b)))?;
950 }
951 0x54 => {
952 let (b, a) = (self.pop_i64()? as u64, self.pop_i64()? as u64);
953 self.push(WasmValue::I32(bool_to_i32(a < b)))?;
954 }
955 0x55 => {
956 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
957 self.push(WasmValue::I32(bool_to_i32(a > b)))?;
958 }
959 0x56 => {
960 let (b, a) = (self.pop_i64()? as u64, self.pop_i64()? as u64);
961 self.push(WasmValue::I32(bool_to_i32(a > b)))?;
962 }
963 0x57 => {
964 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
965 self.push(WasmValue::I32(bool_to_i32(a <= b)))?;
966 }
967 0x58 => {
968 let (b, a) = (self.pop_i64()? as u64, self.pop_i64()? as u64);
969 self.push(WasmValue::I32(bool_to_i32(a <= b)))?;
970 }
971 0x59 => {
972 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
973 self.push(WasmValue::I32(bool_to_i32(a >= b)))?;
974 }
975 0x5A => {
976 let (b, a) = (self.pop_i64()? as u64, self.pop_i64()? as u64);
977 self.push(WasmValue::I32(bool_to_i32(a >= b)))?;
978 }
979
980 0x5B => {
982 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
983 self.push(WasmValue::I32(bool_to_i32(a == b)))?;
984 }
985 0x5C => {
986 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
987 self.push(WasmValue::I32(bool_to_i32(a != b)))?;
988 }
989 0x5D => {
990 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
991 self.push(WasmValue::I32(bool_to_i32(a < b)))?;
992 }
993 0x5E => {
994 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
995 self.push(WasmValue::I32(bool_to_i32(a > b)))?;
996 }
997 0x5F => {
998 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
999 self.push(WasmValue::I32(bool_to_i32(a <= b)))?;
1000 }
1001 0x60 => {
1002 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
1003 self.push(WasmValue::I32(bool_to_i32(a >= b)))?;
1004 }
1005
1006 0x61 => {
1008 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1009 self.push(WasmValue::I32(bool_to_i32(a == b)))?;
1010 }
1011 0x62 => {
1012 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1013 self.push(WasmValue::I32(bool_to_i32(a != b)))?;
1014 }
1015 0x63 => {
1016 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1017 self.push(WasmValue::I32(bool_to_i32(a < b)))?;
1018 }
1019 0x64 => {
1020 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1021 self.push(WasmValue::I32(bool_to_i32(a > b)))?;
1022 }
1023 0x65 => {
1024 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1025 self.push(WasmValue::I32(bool_to_i32(a <= b)))?;
1026 }
1027 0x66 => {
1028 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1029 self.push(WasmValue::I32(bool_to_i32(a >= b)))?;
1030 }
1031
1032 0x67 => {
1034 let a = self.pop_i32()? as u32;
1035 self.push(WasmValue::I32(a.leading_zeros() as i32))?;
1036 }
1037 0x68 => {
1038 let a = self.pop_i32()? as u32;
1039 self.push(WasmValue::I32(a.trailing_zeros() as i32))?;
1040 }
1041 0x69 => {
1042 let a = self.pop_i32()? as u32;
1043 self.push(WasmValue::I32(a.count_ones() as i32))?;
1044 }
1045
1046 0x6A => {
1048 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
1049 self.push(WasmValue::I32(a.wrapping_add(b)))?;
1050 }
1051 0x6B => {
1052 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
1053 self.push(WasmValue::I32(a.wrapping_sub(b)))?;
1054 }
1055 0x6C => {
1056 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
1057 self.push(WasmValue::I32(a.wrapping_mul(b)))?;
1058 }
1059 0x6D => {
1060 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
1062 if b == 0 {
1063 return Err(WasmError::DivisionByZero);
1064 }
1065 if a == i32::MIN && b == -1 {
1066 return Err(WasmError::Trap("i32 div overflow".into()));
1067 }
1068 self.push(WasmValue::I32(a / b))?;
1069 }
1070 0x6E => {
1071 let (b, a) = (self.pop_i32()? as u32, self.pop_i32()? as u32);
1073 if b == 0 {
1074 return Err(WasmError::DivisionByZero);
1075 }
1076 self.push(WasmValue::I32((a / b) as i32))?;
1077 }
1078 0x6F => {
1079 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
1081 if b == 0 {
1082 return Err(WasmError::DivisionByZero);
1083 }
1084 self.push(WasmValue::I32(a.wrapping_rem(b)))?;
1085 }
1086 0x70 => {
1087 let (b, a) = (self.pop_i32()? as u32, self.pop_i32()? as u32);
1089 if b == 0 {
1090 return Err(WasmError::DivisionByZero);
1091 }
1092 self.push(WasmValue::I32((a % b) as i32))?;
1093 }
1094 0x71 => {
1095 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
1096 self.push(WasmValue::I32(a & b))?;
1097 }
1098 0x72 => {
1099 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
1100 self.push(WasmValue::I32(a | b))?;
1101 }
1102 0x73 => {
1103 let (b, a) = (self.pop_i32()?, self.pop_i32()?);
1104 self.push(WasmValue::I32(a ^ b))?;
1105 }
1106 0x74 => {
1107 let (b, a) = (self.pop_i32()? as u32 & 31, self.pop_i32()?);
1108 self.push(WasmValue::I32(a.wrapping_shl(b)))?;
1109 }
1110 0x75 => {
1111 let (b, a) = (self.pop_i32()? as u32 & 31, self.pop_i32()?);
1112 self.push(WasmValue::I32(a.wrapping_shr(b)))?;
1113 }
1114 0x76 => {
1115 let (b, a) = (self.pop_i32()? as u32 & 31, self.pop_i32()? as u32);
1116 self.push(WasmValue::I32(a.wrapping_shr(b) as i32))?;
1117 }
1118 0x77 => {
1119 let (b, a) = (self.pop_i32()? as u32 & 31, self.pop_i32()? as u32);
1120 self.push(WasmValue::I32(a.rotate_left(b) as i32))?;
1121 }
1122 0x78 => {
1123 let (b, a) = (self.pop_i32()? as u32 & 31, self.pop_i32()? as u32);
1124 self.push(WasmValue::I32(a.rotate_right(b) as i32))?;
1125 }
1126
1127 0x79 => {
1129 let a = self.pop_i64()? as u64;
1130 self.push(WasmValue::I64(a.leading_zeros() as i64))?;
1131 }
1132 0x7A => {
1133 let a = self.pop_i64()? as u64;
1134 self.push(WasmValue::I64(a.trailing_zeros() as i64))?;
1135 }
1136 0x7B => {
1137 let a = self.pop_i64()? as u64;
1138 self.push(WasmValue::I64(a.count_ones() as i64))?;
1139 }
1140
1141 0x7C => {
1143 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
1144 self.push(WasmValue::I64(a.wrapping_add(b)))?;
1145 }
1146 0x7D => {
1147 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
1148 self.push(WasmValue::I64(a.wrapping_sub(b)))?;
1149 }
1150 0x7E => {
1151 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
1152 self.push(WasmValue::I64(a.wrapping_mul(b)))?;
1153 }
1154 0x7F => {
1155 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
1157 if b == 0 {
1158 return Err(WasmError::DivisionByZero);
1159 }
1160 if a == i64::MIN && b == -1 {
1161 return Err(WasmError::Trap("i64 div overflow".into()));
1162 }
1163 self.push(WasmValue::I64(a / b))?;
1164 }
1165 0x80 => {
1166 let (b, a) = (self.pop_i64()? as u64, self.pop_i64()? as u64);
1167 if b == 0 {
1168 return Err(WasmError::DivisionByZero);
1169 }
1170 self.push(WasmValue::I64((a / b) as i64))?;
1171 }
1172 0x81 => {
1173 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
1174 if b == 0 {
1175 return Err(WasmError::DivisionByZero);
1176 }
1177 self.push(WasmValue::I64(a.wrapping_rem(b)))?;
1178 }
1179 0x82 => {
1180 let (b, a) = (self.pop_i64()? as u64, self.pop_i64()? as u64);
1181 if b == 0 {
1182 return Err(WasmError::DivisionByZero);
1183 }
1184 self.push(WasmValue::I64((a % b) as i64))?;
1185 }
1186 0x83 => {
1187 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
1188 self.push(WasmValue::I64(a & b))?;
1189 }
1190 0x84 => {
1191 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
1192 self.push(WasmValue::I64(a | b))?;
1193 }
1194 0x85 => {
1195 let (b, a) = (self.pop_i64()?, self.pop_i64()?);
1196 self.push(WasmValue::I64(a ^ b))?;
1197 }
1198 0x86 => {
1199 let (b, a) = (self.pop_i64()? as u32 & 63, self.pop_i64()?);
1200 self.push(WasmValue::I64(a.wrapping_shl(b)))?;
1201 }
1202 0x87 => {
1203 let (b, a) = (self.pop_i64()? as u32 & 63, self.pop_i64()?);
1204 self.push(WasmValue::I64(a.wrapping_shr(b)))?;
1205 }
1206 0x88 => {
1207 let (b, a) = (self.pop_i64()? as u32 & 63, self.pop_i64()? as u64);
1208 self.push(WasmValue::I64(a.wrapping_shr(b) as i64))?;
1209 }
1210 0x89 => {
1211 let (b, a) = (self.pop_i64()? as u32 & 63, self.pop_i64()? as u64);
1212 self.push(WasmValue::I64(a.rotate_left(b) as i64))?;
1213 }
1214 0x8A => {
1215 let (b, a) = (self.pop_i64()? as u32 & 63, self.pop_i64()? as u64);
1216 self.push(WasmValue::I64(a.rotate_right(b) as i64))?;
1217 }
1218
1219 0x8B => {
1221 let a = self.pop_f32()?;
1222 self.push(WasmValue::F32(a.abs()))?;
1223 }
1224 0x8C => {
1225 let a = self.pop_f32()?;
1226 self.push(WasmValue::F32(-a))?;
1227 }
1228 0x8D => {
1229 let a = self.pop_f32()?;
1230 self.push(WasmValue::F32(a.ceil()))?;
1231 }
1232 0x8E => {
1233 let a = self.pop_f32()?;
1234 self.push(WasmValue::F32(a.floor()))?;
1235 }
1236 0x8F => {
1237 let a = self.pop_f32()?;
1238 self.push(WasmValue::F32(a.trunc()))?;
1239 }
1240 0x90 => {
1241 let a = self.pop_f32()?;
1242 self.push(WasmValue::F32(a.round()))?;
1243 }
1244 0x91 => {
1245 let a = self.pop_f32()?;
1246 self.push(WasmValue::F32(a.sqrt()))?;
1247 }
1248 0x92 => {
1249 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
1250 self.push(WasmValue::F32(a + b))?;
1251 }
1252 0x93 => {
1253 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
1254 self.push(WasmValue::F32(a - b))?;
1255 }
1256 0x94 => {
1257 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
1258 self.push(WasmValue::F32(a * b))?;
1259 }
1260 0x95 => {
1261 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
1262 self.push(WasmValue::F32(a / b))?;
1263 }
1264 0x96 => {
1265 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
1266 self.push(WasmValue::F32(a.min(b)))?;
1267 }
1268 0x97 => {
1269 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
1270 self.push(WasmValue::F32(a.max(b)))?;
1271 }
1272 0x98 => {
1273 let (b, a) = (self.pop_f32()?, self.pop_f32()?);
1274 self.push(WasmValue::F32(a.copysign(b)))?;
1275 }
1276
1277 0x99 => {
1279 let a = self.pop_f64()?;
1280 self.push(WasmValue::F64(a.abs()))?;
1281 }
1282 0x9A => {
1283 let a = self.pop_f64()?;
1284 self.push(WasmValue::F64(-a))?;
1285 }
1286 0x9B => {
1287 let a = self.pop_f64()?;
1288 self.push(WasmValue::F64(a.ceil()))?;
1289 }
1290 0x9C => {
1291 let a = self.pop_f64()?;
1292 self.push(WasmValue::F64(a.floor()))?;
1293 }
1294 0x9D => {
1295 let a = self.pop_f64()?;
1296 self.push(WasmValue::F64(a.trunc()))?;
1297 }
1298 0x9E => {
1299 let a = self.pop_f64()?;
1300 self.push(WasmValue::F64(a.round()))?;
1301 }
1302 0x9F => {
1303 let a = self.pop_f64()?;
1304 self.push(WasmValue::F64(a.sqrt()))?;
1305 }
1306 0xA0 => {
1307 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1308 self.push(WasmValue::F64(a + b))?;
1309 }
1310 0xA1 => {
1311 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1312 self.push(WasmValue::F64(a - b))?;
1313 }
1314 0xA2 => {
1315 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1316 self.push(WasmValue::F64(a * b))?;
1317 }
1318 0xA3 => {
1319 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1320 self.push(WasmValue::F64(a / b))?;
1321 }
1322 0xA4 => {
1323 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1324 self.push(WasmValue::F64(a.min(b)))?;
1325 }
1326 0xA5 => {
1327 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1328 self.push(WasmValue::F64(a.max(b)))?;
1329 }
1330 0xA6 => {
1331 let (b, a) = (self.pop_f64()?, self.pop_f64()?);
1332 self.push(WasmValue::F64(a.copysign(b)))?;
1333 }
1334
1335 0xA7 => {
1337 let a = self.pop_i64()?;
1338 self.push(WasmValue::I32(a as i32))?;
1339 }
1340 0xA8 => {
1341 let a = self.pop_f32()?;
1342 check_float_f32(a)?;
1343 self.push(WasmValue::I32(a as i32))?;
1344 }
1345 0xA9 => {
1346 let a = self.pop_f32()?;
1347 check_float_f32(a)?;
1348 self.push(WasmValue::I32(a as u32 as i32))?;
1349 }
1350 0xAA => {
1351 let a = self.pop_f64()?;
1352 check_float_f64(a)?;
1353 self.push(WasmValue::I32(a as i32))?;
1354 }
1355 0xAB => {
1356 let a = self.pop_f64()?;
1357 check_float_f64(a)?;
1358 self.push(WasmValue::I32(a as u32 as i32))?;
1359 }
1360 0xAC => {
1361 let a = self.pop_i32()?;
1362 self.push(WasmValue::I64(a as i64))?;
1363 }
1364 0xAD => {
1365 let a = self.pop_i32()? as u32;
1366 self.push(WasmValue::I64(a as i64))?;
1367 }
1368 0xAE => {
1369 let a = self.pop_f32()?;
1370 check_float_f32(a)?;
1371 self.push(WasmValue::I64(a as i64))?;
1372 }
1373 0xAF => {
1374 let a = self.pop_f32()?;
1375 check_float_f32(a)?;
1376 self.push(WasmValue::I64(a as u64 as i64))?;
1377 }
1378 0xB0 => {
1379 let a = self.pop_f64()?;
1380 check_float_f64(a)?;
1381 self.push(WasmValue::I64(a as i64))?;
1382 }
1383 0xB1 => {
1384 let a = self.pop_f64()?;
1385 check_float_f64(a)?;
1386 self.push(WasmValue::I64(a as u64 as i64))?;
1387 }
1388 0xB2 => {
1389 let a = self.pop_i32()?;
1390 self.push(WasmValue::F32(a as f32))?;
1391 }
1392 0xB3 => {
1393 let a = self.pop_i32()? as u32;
1394 self.push(WasmValue::F32(a as f32))?;
1395 }
1396 0xB4 => {
1397 let a = self.pop_i64()?;
1398 self.push(WasmValue::F32(a as f32))?;
1399 }
1400 0xB5 => {
1401 let a = self.pop_i64()? as u64;
1402 self.push(WasmValue::F32(a as f32))?;
1403 }
1404 0xB6 => {
1405 let a = self.pop_f64()?;
1406 self.push(WasmValue::F32(a as f32))?;
1407 }
1408 0xB7 => {
1409 let a = self.pop_i32()?;
1410 self.push(WasmValue::F64(a as f64))?;
1411 }
1412 0xB8 => {
1413 let a = self.pop_i32()? as u32;
1414 self.push(WasmValue::F64(a as f64))?;
1415 }
1416 0xB9 => {
1417 let a = self.pop_i64()?;
1418 self.push(WasmValue::F64(a as f64))?;
1419 }
1420 0xBA => {
1421 let a = self.pop_i64()? as u64;
1422 self.push(WasmValue::F64(a as f64))?;
1423 }
1424 0xBB => {
1425 let a = self.pop_f32()?;
1426 self.push(WasmValue::F64(a as f64))?;
1427 }
1428 0xBC => {
1429 let a = self.pop_f32()?;
1430 self.push(WasmValue::I32(i32::from_le_bytes(a.to_le_bytes())))?;
1431 }
1432 0xBD => {
1433 let a = self.pop_f64()?;
1434 self.push(WasmValue::I64(i64::from_le_bytes(a.to_le_bytes())))?;
1435 }
1436 0xBE => {
1437 let a = self.pop_i32()?;
1438 self.push(WasmValue::F32(f32::from_le_bytes(a.to_le_bytes())))?;
1439 }
1440 0xBF => {
1441 let a = self.pop_i64()?;
1442 self.push(WasmValue::F64(f64::from_le_bytes(a.to_le_bytes())))?;
1443 }
1444
1445 other => return Err(WasmError::UnimplementedOpcode(other)),
1446 }
1447 }
1448
1449 let slen = self.stack.len();
1451 Ok(if n_results <= slen {
1452 self.stack[slen - n_results..].to_vec()
1453 } else {
1454 self.stack.clone()
1455 })
1456 }
1457}
1458
1459#[inline]
1462fn bool_to_i32(b: bool) -> i32 {
1463 if b {
1464 1
1465 } else {
1466 0
1467 }
1468}
1469
1470fn check_float_f32(v: f32) -> Result<(), WasmError> {
1471 if v.is_nan() || v.is_infinite() {
1472 Err(WasmError::Trap("float conversion: invalid value".into()))
1473 } else {
1474 Ok(())
1475 }
1476}
1477fn check_float_f64(v: f64) -> Result<(), WasmError> {
1478 if v.is_nan() || v.is_infinite() {
1479 Err(WasmError::Trap("float conversion: invalid value".into()))
1480 } else {
1481 Ok(())
1482 }
1483}
1484
1485fn sign_extend_u32(raw: u32, bits: usize) -> i32 {
1486 let shift = 32 - bits;
1487 ((raw << shift) as i32) >> shift
1488}
1489fn sign_extend_u64(raw: u64, bits: usize) -> i64 {
1490 let shift = 64 - bits;
1491 ((raw << shift) as i64) >> shift
1492}
1493
1494#[allow(dead_code)]
1497pub fn default_wasm_bridge_config() -> WasmBridgeConfig {
1498 WasmBridgeConfig {
1499 memory_pages: 1,
1500 max_functions: 256,
1501 debug_mode: false,
1502 }
1503}
1504
1505#[allow(dead_code)]
1506pub fn new_wasm_bridge(cfg: WasmBridgeConfig) -> WasmBridge {
1507 let size_bytes = cfg.memory_pages as usize * 65536;
1508 WasmBridge {
1509 config: cfg,
1510 memory: WasmMemory {
1511 data: vec![0u8; size_bytes],
1512 size_bytes,
1513 },
1514 functions: Vec::new(),
1515 call_count: 0,
1516 }
1517}
1518
1519#[allow(dead_code)]
1520pub fn wasm_memory_size(bridge: &WasmBridge) -> usize {
1521 bridge.memory.size_bytes
1522}
1523
1524#[allow(dead_code)]
1525pub fn wasm_read_u32(bridge: &WasmBridge, offset: usize) -> Option<u32> {
1526 if offset + 4 > bridge.memory.data.len() {
1527 return None;
1528 }
1529 Some(u32::from_le_bytes([
1530 bridge.memory.data[offset],
1531 bridge.memory.data[offset + 1],
1532 bridge.memory.data[offset + 2],
1533 bridge.memory.data[offset + 3],
1534 ]))
1535}
1536
1537#[allow(dead_code)]
1538pub fn wasm_write_u32(bridge: &mut WasmBridge, offset: usize, val: u32) -> bool {
1539 if offset + 4 > bridge.memory.data.len() {
1540 return false;
1541 }
1542 let b = val.to_le_bytes();
1543 bridge.memory.data[offset..offset + 4].copy_from_slice(&b);
1544 true
1545}
1546
1547#[allow(dead_code)]
1548pub fn register_wasm_function(bridge: &mut WasmBridge, func: WasmFunction) {
1549 if bridge.functions.len() < bridge.config.max_functions {
1550 bridge.functions.push(func);
1551 }
1552}
1553
1554#[allow(dead_code)]
1555pub fn wasm_function_count(bridge: &WasmBridge) -> usize {
1556 bridge.functions.len()
1557}
1558
1559#[allow(dead_code)]
1564pub fn wasm_call(
1565 bridge: &mut WasmBridge,
1566 name: &str,
1567 args: &[WasmValue],
1568) -> Result<Vec<WasmValue>, WasmError> {
1569 let func = bridge
1570 .functions
1571 .iter()
1572 .find(|f| f.name == name)
1573 .cloned()
1574 .ok_or_else(|| WasmError::FunctionNotFound(name.to_string()))?;
1575
1576 bridge.call_count += 1;
1577 if func.bytecode.is_empty() {
1578 return Ok(Vec::new());
1579 }
1580
1581 let mut pc = 0usize;
1583 let n_decls = read_leb128_u32(&func.bytecode, &mut pc) as usize;
1584 let mut extra_locals: Vec<WasmValue> = Vec::new();
1585 for _ in 0..n_decls {
1586 let count = read_leb128_u32(&func.bytecode, &mut pc) as usize;
1587 let type_byte = func.bytecode[pc];
1588 pc += 1;
1589 let default = match type_byte {
1590 0x7F => WasmValue::I32(0),
1591 0x7E => WasmValue::I64(0),
1592 0x7D => WasmValue::F32(0.0),
1593 0x7C => WasmValue::F64(0.0),
1594 _ => WasmValue::I32(0),
1595 };
1596 for _ in 0..count {
1597 extra_locals.push(default.clone());
1598 }
1599 }
1600
1601 let mut locals: Vec<WasmValue> = args.to_vec();
1602 locals.extend(extra_locals);
1603
1604 let expr_code = &func.bytecode[pc..];
1605 let n_results = func.return_types.len();
1606 let mut interp = Interpreter::new(&mut bridge.memory, expr_code, locals, 0);
1607 interp.run(n_results)
1608}
1609
1610#[allow(dead_code)]
1613pub fn wasm_call_stub(bridge: &mut WasmBridge, name: &str) -> bool {
1614 wasm_call(bridge, name, &[]).is_ok()
1615}
1616
1617#[allow(dead_code)]
1618pub fn value_type_name(t: &WasmValueType) -> &'static str {
1619 match t {
1620 WasmValueType::I32 => "i32",
1621 WasmValueType::I64 => "i64",
1622 WasmValueType::F32 => "f32",
1623 WasmValueType::F64 => "f64",
1624 WasmValueType::FuncRef => "funcref",
1625 WasmValueType::ExternRef => "externref",
1626 }
1627}
1628
1629#[allow(dead_code)]
1630pub fn wasm_bridge_to_json(bridge: &WasmBridge) -> String {
1631 format!(
1632 "{{\"memory_pages\":{},\"function_count\":{},\"call_count\":{},\"debug_mode\":{}}}",
1633 bridge.config.memory_pages,
1634 bridge.functions.len(),
1635 bridge.call_count,
1636 bridge.config.debug_mode
1637 )
1638}
1639
1640#[cfg(test)]
1643mod tests {
1644 use super::*;
1645
1646 #[test]
1649 fn test_default_config() {
1650 let cfg = default_wasm_bridge_config();
1651 assert_eq!(cfg.memory_pages, 1);
1652 assert_eq!(cfg.max_functions, 256);
1653 assert!(!cfg.debug_mode);
1654 }
1655
1656 #[test]
1657 fn test_new_bridge_memory_size() {
1658 let bridge = new_wasm_bridge(default_wasm_bridge_config());
1659 assert_eq!(wasm_memory_size(&bridge), 65536);
1660 }
1661
1662 #[test]
1663 fn test_write_read_u32() {
1664 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1665 assert!(wasm_write_u32(&mut bridge, 0, 0xDEAD_BEEF));
1666 assert_eq!(wasm_read_u32(&bridge, 0), Some(0xDEAD_BEEF));
1667 }
1668
1669 #[test]
1670 fn test_out_of_bounds_returns_none() {
1671 let bridge = new_wasm_bridge(default_wasm_bridge_config());
1672 assert!(wasm_read_u32(&bridge, 65534).is_none());
1673 }
1674
1675 #[test]
1676 fn test_register_and_call_function() {
1677 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1678 let func = WasmFunction {
1679 name: "add".to_string(),
1680 param_types: vec![WasmValueType::I32, WasmValueType::I32],
1681 return_types: vec![WasmValueType::I32],
1682 bytecode: Vec::new(),
1683 local_types: Vec::new(),
1684 };
1685 register_wasm_function(&mut bridge, func);
1686 assert_eq!(wasm_function_count(&bridge), 1);
1687 assert!(wasm_call_stub(&mut bridge, "add"));
1688 assert_eq!(bridge.call_count, 1);
1689 }
1690
1691 #[test]
1692 fn test_call_unknown_function() {
1693 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1694 assert!(!wasm_call_stub(&mut bridge, "nonexistent"));
1695 assert_eq!(bridge.call_count, 0);
1696 }
1697
1698 #[test]
1699 fn test_value_type_names() {
1700 assert_eq!(value_type_name(&WasmValueType::I32), "i32");
1701 assert_eq!(value_type_name(&WasmValueType::I64), "i64");
1702 assert_eq!(value_type_name(&WasmValueType::F32), "f32");
1703 assert_eq!(value_type_name(&WasmValueType::F64), "f64");
1704 assert_eq!(value_type_name(&WasmValueType::FuncRef), "funcref");
1705 assert_eq!(value_type_name(&WasmValueType::ExternRef), "externref");
1706 }
1707
1708 #[test]
1709 fn test_bridge_to_json() {
1710 let bridge = new_wasm_bridge(default_wasm_bridge_config());
1711 let json = wasm_bridge_to_json(&bridge);
1712 assert!(json.contains("memory_pages"));
1713 assert!(json.contains("call_count"));
1714 }
1715
1716 fn make_func(
1719 name: &str,
1720 params: Vec<WasmValueType>,
1721 rets: Vec<WasmValueType>,
1722 bytecode: Vec<u8>,
1723 ) -> WasmFunction {
1724 WasmFunction {
1725 name: name.to_string(),
1726 param_types: params,
1727 return_types: rets,
1728 bytecode,
1729 local_types: Vec::new(),
1730 }
1731 }
1732
1733 #[test]
1736 fn test_wasm_call_add_function() {
1737 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1738 let f = make_func(
1739 "add",
1740 vec![WasmValueType::I32, WasmValueType::I32],
1741 vec![WasmValueType::I32],
1742 vec![0x00, 0x20, 0x00, 0x20, 0x01, 0x6A, 0x0B],
1743 );
1744 register_wasm_function(&mut bridge, f);
1745 let r = wasm_call(&mut bridge, "add", &[WasmValue::I32(3), WasmValue::I32(4)]).unwrap();
1746 assert_eq!(r, vec![WasmValue::I32(7)]);
1747 }
1748
1749 #[test]
1751 fn test_wasm_call_constant() {
1752 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1753 let f = make_func(
1754 "c42",
1755 vec![],
1756 vec![WasmValueType::I32],
1757 vec![0x00, 0x41, 0x2A, 0x0B],
1758 );
1759 register_wasm_function(&mut bridge, f);
1760 assert_eq!(
1761 wasm_call(&mut bridge, "c42", &[]).unwrap(),
1762 vec![WasmValue::I32(42)]
1763 );
1764 }
1765
1766 #[test]
1770 fn test_wasm_call_memory_write_read() {
1771 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1772 let bytecode = vec![
1773 0x00, 0x41, 0x00, 0x41, 0xE3, 0x00, 0x36, 0x02, 0x00, 0x0B, ];
1779 let f = make_func("write_99", vec![], vec![], bytecode);
1780 register_wasm_function(&mut bridge, f);
1781 let result = wasm_call(&mut bridge, "write_99", &[]);
1782 assert!(result.is_ok(), "Expected Ok but got: {:?}", result);
1783 assert_eq!(wasm_read_u32(&bridge, 0), Some(99));
1784 }
1785
1786 #[test]
1787 fn test_wasm_call_unknown_function_error() {
1788 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1789 let r = wasm_call(&mut bridge, "no_such_function", &[]);
1790 assert!(matches!(r, Err(WasmError::FunctionNotFound(_))));
1791 }
1792
1793 #[test]
1795 fn test_wasm_call_no_bytecode_succeeds() {
1796 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1797 let f = make_func("empty", vec![], vec![], vec![0x00, 0x0B]);
1798 register_wasm_function(&mut bridge, f);
1799 assert_eq!(wasm_call(&mut bridge, "empty", &[]).unwrap(), vec![]);
1800 }
1801
1802 #[test]
1805 fn test_wasm_call_i32_sub() {
1806 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1807 let f = make_func(
1808 "sub",
1809 vec![WasmValueType::I32, WasmValueType::I32],
1810 vec![WasmValueType::I32],
1811 vec![0x00, 0x20, 0x00, 0x20, 0x01, 0x6B, 0x0B],
1812 );
1813 register_wasm_function(&mut bridge, f);
1814 assert_eq!(
1815 wasm_call(&mut bridge, "sub", &[WasmValue::I32(10), WasmValue::I32(3)]).unwrap(),
1816 vec![WasmValue::I32(7)]
1817 );
1818 }
1819
1820 #[test]
1821 fn test_wasm_call_i32_mul() {
1822 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1823 let f = make_func(
1824 "mul",
1825 vec![WasmValueType::I32, WasmValueType::I32],
1826 vec![WasmValueType::I32],
1827 vec![0x00, 0x20, 0x00, 0x20, 0x01, 0x6C, 0x0B],
1828 );
1829 register_wasm_function(&mut bridge, f);
1830 assert_eq!(
1831 wasm_call(&mut bridge, "mul", &[WasmValue::I32(6), WasmValue::I32(7)]).unwrap(),
1832 vec![WasmValue::I32(42)]
1833 );
1834 }
1835
1836 #[test]
1837 fn test_wasm_call_div_by_zero_error() {
1838 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1839 let f = make_func(
1840 "div",
1841 vec![WasmValueType::I32, WasmValueType::I32],
1842 vec![WasmValueType::I32],
1843 vec![0x00, 0x20, 0x00, 0x20, 0x01, 0x6D, 0x0B],
1844 );
1845 register_wasm_function(&mut bridge, f);
1846 let r = wasm_call(&mut bridge, "div", &[WasmValue::I32(10), WasmValue::I32(0)]);
1847 assert!(matches!(r, Err(WasmError::DivisionByZero)));
1848 }
1849
1850 #[test]
1851 fn test_wasm_call_i32_eqz() {
1852 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1853 let f = make_func(
1854 "eqz",
1855 vec![WasmValueType::I32],
1856 vec![WasmValueType::I32],
1857 vec![0x00, 0x20, 0x00, 0x45, 0x0B],
1858 );
1859 register_wasm_function(&mut bridge, f);
1860 assert_eq!(
1861 wasm_call(&mut bridge, "eqz", &[WasmValue::I32(0)]).unwrap(),
1862 vec![WasmValue::I32(1)]
1863 );
1864 assert_eq!(
1865 wasm_call(&mut bridge, "eqz", &[WasmValue::I32(5)]).unwrap(),
1866 vec![WasmValue::I32(0)]
1867 );
1868 }
1869
1870 #[test]
1871 fn test_wasm_call_local_tee() {
1872 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1873 let f = make_func(
1875 "tee",
1876 vec![WasmValueType::I32],
1877 vec![WasmValueType::I32],
1878 vec![0x00, 0x20, 0x00, 0x22, 0x00, 0x1A, 0x20, 0x00, 0x0B],
1879 );
1880 register_wasm_function(&mut bridge, f);
1881 assert_eq!(
1882 wasm_call(&mut bridge, "tee", &[WasmValue::I32(77)]).unwrap(),
1883 vec![WasmValue::I32(77)]
1884 );
1885 }
1886
1887 #[test]
1888 fn test_wasm_call_select() {
1889 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1890 let f = make_func(
1892 "sel",
1893 vec![],
1894 vec![WasmValueType::I32],
1895 vec![0x00, 0x41, 0x0A, 0x41, 0x14, 0x41, 0x01, 0x1B, 0x0B],
1896 );
1897 register_wasm_function(&mut bridge, f);
1898 assert_eq!(
1899 wasm_call(&mut bridge, "sel", &[]).unwrap(),
1900 vec![WasmValue::I32(10)]
1901 );
1902 }
1903
1904 #[test]
1905 fn test_wasm_call_f32_add() {
1906 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1907 let mut bc = vec![0x00u8]; bc.push(0x43);
1909 bc.extend_from_slice(&1.5f32.to_le_bytes());
1910 bc.push(0x43);
1911 bc.extend_from_slice(&2.5f32.to_le_bytes());
1912 bc.push(0x92);
1913 bc.push(0x0B); let f = make_func("f32a", vec![], vec![WasmValueType::F32], bc);
1915 register_wasm_function(&mut bridge, f);
1916 assert_eq!(
1917 wasm_call(&mut bridge, "f32a", &[]).unwrap(),
1918 vec![WasmValue::F32(4.0)]
1919 );
1920 }
1921
1922 #[test]
1923 fn test_wasm_call_i32_conversion() {
1924 let mut bridge = new_wasm_bridge(default_wasm_bridge_config());
1925 let f = make_func(
1927 "rt",
1928 vec![],
1929 vec![WasmValueType::I32],
1930 vec![0x00, 0x41, 0xAC, 0x02, 0xAC, 0xA7, 0x0B],
1931 );
1932 register_wasm_function(&mut bridge, f);
1933 assert_eq!(
1934 wasm_call(&mut bridge, "rt", &[]).unwrap(),
1935 vec![WasmValue::I32(300)]
1936 );
1937 }
1938}