1use crate::{limits::*, *};
17use std::convert::TryInto;
18use std::error::Error;
19use std::fmt;
20use std::marker;
21use std::ops::Range;
22use std::str;
23
24const WASM_MAGIC_NUMBER: &[u8; 4] = b"\0asm";
25
26#[derive(Debug, Clone)]
28pub struct BinaryReaderError {
29 pub(crate) inner: Box<BinaryReaderErrorInner>,
33}
34
35#[derive(Debug, Clone)]
36pub(crate) struct BinaryReaderErrorInner {
37 pub(crate) message: String,
38 pub(crate) offset: usize,
39 pub(crate) needed_hint: Option<usize>,
40}
41
42pub type Result<T, E = BinaryReaderError> = std::result::Result<T, E>;
44
45impl Error for BinaryReaderError {}
46
47impl fmt::Display for BinaryReaderError {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 write!(
50 f,
51 "{} (at offset 0x{:x})",
52 self.inner.message, self.inner.offset
53 )
54 }
55}
56
57impl BinaryReaderError {
58 #[cold]
59 pub(crate) fn new(message: impl Into<String>, offset: usize) -> Self {
60 let message = message.into();
61 BinaryReaderError {
62 inner: Box::new(BinaryReaderErrorInner {
63 message,
64 offset,
65 needed_hint: None,
66 }),
67 }
68 }
69
70 #[cold]
71 pub(crate) fn fmt(args: fmt::Arguments<'_>, offset: usize) -> Self {
72 BinaryReaderError::new(args.to_string(), offset)
73 }
74
75 #[cold]
76 pub(crate) fn eof(offset: usize, needed_hint: usize) -> Self {
77 BinaryReaderError {
78 inner: Box::new(BinaryReaderErrorInner {
79 message: "unexpected end-of-file".to_string(),
80 offset,
81 needed_hint: Some(needed_hint),
82 }),
83 }
84 }
85
86 pub fn message(&self) -> &str {
88 &self.inner.message
89 }
90
91 pub fn offset(&self) -> usize {
93 self.inner.offset
94 }
95}
96
97#[derive(Clone, Debug, Hash)]
99pub struct BinaryReader<'a> {
100 pub(crate) buffer: &'a [u8],
101 pub(crate) position: usize,
102 original_offset: usize,
103 allow_memarg64: bool,
104}
105
106impl<'a> BinaryReader<'a> {
107 pub fn new(data: &[u8]) -> BinaryReader {
119 BinaryReader {
120 buffer: data,
121 position: 0,
122 original_offset: 0,
123 allow_memarg64: false,
124 }
125 }
126
127 pub fn new_with_offset(data: &[u8], original_offset: usize) -> BinaryReader {
129 BinaryReader {
130 buffer: data,
131 position: 0,
132 original_offset,
133 allow_memarg64: false,
134 }
135 }
136
137 #[inline]
139 pub fn original_position(&self) -> usize {
140 self.original_offset + self.position
141 }
142
143 pub fn allow_memarg64(&mut self, allow: bool) {
148 self.allow_memarg64 = allow;
149 }
150
151 pub fn range(&self) -> Range<usize> {
153 self.original_offset..self.original_offset + self.buffer.len()
154 }
155
156 pub(crate) fn remaining_buffer(&self) -> &'a [u8] {
157 &self.buffer[self.position..]
158 }
159
160 fn ensure_has_byte(&self) -> Result<()> {
161 if self.position < self.buffer.len() {
162 Ok(())
163 } else {
164 Err(BinaryReaderError::eof(self.original_position(), 1))
165 }
166 }
167
168 pub(crate) fn ensure_has_bytes(&self, len: usize) -> Result<()> {
169 if self.position + len <= self.buffer.len() {
170 Ok(())
171 } else {
172 let hint = self.position + len - self.buffer.len();
173 Err(BinaryReaderError::eof(self.original_position(), hint))
174 }
175 }
176
177 #[inline]
180 pub fn read<T>(&mut self) -> Result<T>
181 where
182 T: FromReader<'a>,
183 {
184 T::from_reader(self)
185 }
186
187 pub(crate) fn read_u7(&mut self) -> Result<u8> {
188 let b = self.read_u8()?;
189 if (b & 0x80) != 0 {
190 return Err(BinaryReaderError::new(
191 "invalid u7",
192 self.original_position() - 1,
193 ));
194 }
195 Ok(b)
196 }
197
198 pub(crate) fn external_kind_from_byte(byte: u8, offset: usize) -> Result<ExternalKind> {
199 match byte {
200 0x00 => Ok(ExternalKind::Func),
201 0x01 => Ok(ExternalKind::Table),
202 0x02 => Ok(ExternalKind::Memory),
203 0x03 => Ok(ExternalKind::Global),
204 0x04 => Ok(ExternalKind::Tag),
205 x => Err(Self::invalid_leading_byte_error(x, "external kind", offset)),
206 }
207 }
208
209 pub fn read_size(&mut self, limit: usize, desc: &str) -> Result<usize> {
212 let pos = self.original_position();
213 let size = self.read_var_u32()? as usize;
214 if size > limit {
215 bail!(pos, "{desc} size is out of bounds");
216 }
217 Ok(size)
218 }
219
220 pub fn read_iter<'me, T>(
228 &'me mut self,
229 limit: usize,
230 desc: &str,
231 ) -> Result<BinaryReaderIter<'a, 'me, T>>
232 where
233 T: FromReader<'a>,
234 {
235 let size = self.read_size(limit, desc)?;
236 Ok(BinaryReaderIter {
237 remaining: size,
238 reader: self,
239 _marker: marker::PhantomData,
240 })
241 }
242
243 fn read_first_byte_and_var_u32(&mut self) -> Result<(u8, u32)> {
244 let pos = self.position;
245 let val = self.read_var_u32()?;
246 Ok((self.buffer[pos], val))
247 }
248
249 fn read_memarg(&mut self, max_align: u8) -> Result<MemArg> {
250 let flags_pos = self.original_position();
251 let mut flags = self.read_var_u32()?;
252 let memory = if flags & (1 << 6) != 0 {
253 flags ^= 1 << 6;
254 self.read_var_u32()?
255 } else {
256 0
257 };
258 let align = if flags >= (1 << 6) {
259 return Err(BinaryReaderError::new("alignment too large", flags_pos));
260 } else {
261 flags as u8
262 };
263 let offset = if self.allow_memarg64 {
264 self.read_var_u64()?
265 } else {
266 u64::from(self.read_var_u32()?)
267 };
268 Ok(MemArg {
269 align,
270 max_align,
271 offset,
272 memory,
273 })
274 }
275
276 fn read_br_table(&mut self) -> Result<BrTable<'a>> {
277 let cnt = self.read_size(MAX_WASM_BR_TABLE_SIZE, "br_table")?;
278 let start = self.position;
279 for _ in 0..cnt {
280 self.read_var_u32()?;
281 }
282 let end = self.position;
283 let default = self.read_var_u32()?;
284 Ok(BrTable {
285 reader: BinaryReader::new_with_offset(&self.buffer[start..end], start),
286 cnt: cnt as u32,
287 default,
288 })
289 }
290
291 #[inline]
293 pub fn eof(&self) -> bool {
294 self.position >= self.buffer.len()
295 }
296
297 #[inline]
299 pub fn current_position(&self) -> usize {
300 self.position
301 }
302
303 #[inline]
305 pub fn bytes_remaining(&self) -> usize {
306 self.buffer.len() - self.position
307 }
308
309 pub fn read_bytes(&mut self, size: usize) -> Result<&'a [u8]> {
315 self.ensure_has_bytes(size)?;
316 let start = self.position;
317 self.position += size;
318 Ok(&self.buffer[start..self.position])
319 }
320
321 pub fn read_reader(&mut self, err: &str) -> Result<BinaryReader<'a>> {
326 let size = self.read_var_u32()? as usize;
327 let body_start = self.position;
328 let buffer = match self.buffer.get(self.position..).and_then(|s| s.get(..size)) {
329 Some(buf) => buf,
330 None => {
331 return Err(BinaryReaderError::new(
332 err,
333 self.original_offset + self.buffer.len(),
334 ))
335 }
336 };
337 self.position += size;
338 Ok(BinaryReader::new_with_offset(
339 buffer,
340 self.original_offset + body_start,
341 ))
342 }
343
344 pub fn read_u32(&mut self) -> Result<u32> {
348 self.ensure_has_bytes(4)?;
349 let word = u32::from_le_bytes(
350 self.buffer[self.position..self.position + 4]
351 .try_into()
352 .unwrap(),
353 );
354 self.position += 4;
355 Ok(word)
356 }
357
358 pub fn read_u64(&mut self) -> Result<u64> {
362 self.ensure_has_bytes(8)?;
363 let word = u64::from_le_bytes(
364 self.buffer[self.position..self.position + 8]
365 .try_into()
366 .unwrap(),
367 );
368 self.position += 8;
369 Ok(word)
370 }
371
372 #[inline]
378 pub fn read_u8(&mut self) -> Result<u8> {
379 let b = match self.buffer.get(self.position) {
380 Some(b) => *b,
381 None => return Err(self.eof_err()),
382 };
383 self.position += 1;
384 Ok(b)
385 }
386
387 #[cold]
388 fn eof_err(&self) -> BinaryReaderError {
389 BinaryReaderError::eof(self.original_position(), 1)
390 }
391
392 #[inline]
400 pub fn read_var_u32(&mut self) -> Result<u32> {
401 let byte = self.read_u8()?;
403 if (byte & 0x80) == 0 {
404 Ok(u32::from(byte))
405 } else {
406 self.read_var_u32_big(byte)
407 }
408 }
409
410 fn read_var_u32_big(&mut self, byte: u8) -> Result<u32> {
411 let mut result = (byte & 0x7F) as u32;
412 let mut shift = 7;
413 loop {
414 let byte = self.read_u8()?;
415 result |= ((byte & 0x7F) as u32) << shift;
416 if shift >= 25 && (byte >> (32 - shift)) != 0 {
417 let msg = if byte & 0x80 != 0 {
418 "invalid var_u32: integer representation too long"
419 } else {
420 "invalid var_u32: integer too large"
421 };
422 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
424 }
425 shift += 7;
426 if (byte & 0x80) == 0 {
427 break;
428 }
429 }
430 Ok(result)
431 }
432
433 #[inline]
441 pub fn read_var_u64(&mut self) -> Result<u64> {
442 let byte = u64::from(self.read_u8()?);
444 if (byte & 0x80) == 0 {
445 Ok(byte)
446 } else {
447 self.read_var_u64_big(byte)
448 }
449 }
450
451 fn read_var_u64_big(&mut self, byte: u64) -> Result<u64> {
452 let mut result = byte & 0x7F;
453 let mut shift = 7;
454 loop {
455 let byte = u64::from(self.read_u8()?);
456 result |= (byte & 0x7F) << shift;
457 if shift >= 57 && (byte >> (64 - shift)) != 0 {
458 let msg = if byte & 0x80 != 0 {
459 "invalid var_u64: integer representation too long"
460 } else {
461 "invalid var_u64: integer too large"
462 };
463 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
465 }
466 shift += 7;
467 if (byte & 0x80) == 0 {
468 break;
469 }
470 }
471 Ok(result)
472 }
473
474 pub fn skip(&mut self, f: impl FnOnce(&mut Self) -> Result<()>) -> Result<Self> {
477 let start = self.position;
478 f(self)?;
479 Ok(BinaryReader::new_with_offset(
480 &self.buffer[start..self.position],
481 self.original_offset + start,
482 ))
483 }
484
485 pub fn skip_string(&mut self) -> Result<()> {
492 let len = self.read_var_u32()? as usize;
493 if len > MAX_WASM_STRING_SIZE {
494 return Err(BinaryReaderError::new(
495 "string size out of bounds",
496 self.original_position() - 1,
497 ));
498 }
499 self.ensure_has_bytes(len)?;
500 self.position += len;
501 Ok(())
502 }
503
504 #[inline]
510 pub fn read_var_i32(&mut self) -> Result<i32> {
511 let byte = self.read_u8()?;
513 if (byte & 0x80) == 0 {
514 Ok(((byte as i32) << 25) >> 25)
515 } else {
516 self.read_var_i32_big(byte)
517 }
518 }
519
520 fn read_var_i32_big(&mut self, byte: u8) -> Result<i32> {
521 let mut result = (byte & 0x7F) as i32;
522 let mut shift = 7;
523 loop {
524 let byte = self.read_u8()?;
525 result |= ((byte & 0x7F) as i32) << shift;
526 if shift >= 25 {
527 let continuation_bit = (byte & 0x80) != 0;
528 let sign_and_unused_bit = (byte << 1) as i8 >> (32 - shift);
529 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
530 let msg = if continuation_bit {
531 "invalid var_i32: integer representation too long"
532 } else {
533 "invalid var_i32: integer too large"
534 };
535 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
536 }
537 return Ok(result);
538 }
539 shift += 7;
540 if (byte & 0x80) == 0 {
541 break;
542 }
543 }
544 let ashift = 32 - shift;
545 Ok((result << ashift) >> ashift)
546 }
547
548 pub fn read_var_s33(&mut self) -> Result<i64> {
554 let byte = self.read_u8()?;
556 if (byte & 0x80) == 0 {
557 return Ok(((byte as i8) << 1) as i64 >> 1);
558 }
559
560 let mut result = (byte & 0x7F) as i64;
561 let mut shift = 7;
562 loop {
563 let byte = self.read_u8()?;
564 result |= ((byte & 0x7F) as i64) << shift;
565 if shift >= 25 {
566 let continuation_bit = (byte & 0x80) != 0;
567 let sign_and_unused_bit = (byte << 1) as i8 >> (33 - shift);
568 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
569 return Err(BinaryReaderError::new(
570 "invalid var_s33: integer representation too long",
571 self.original_position() - 1,
572 ));
573 }
574 return Ok(result);
575 }
576 shift += 7;
577 if (byte & 0x80) == 0 {
578 break;
579 }
580 }
581 let ashift = 64 - shift;
582 Ok((result << ashift) >> ashift)
583 }
584
585 pub fn read_var_i64(&mut self) -> Result<i64> {
591 let mut result: i64 = 0;
592 let mut shift = 0;
593 loop {
594 let byte = self.read_u8()?;
595 result |= i64::from(byte & 0x7F) << shift;
596 if shift >= 57 {
597 let continuation_bit = (byte & 0x80) != 0;
598 let sign_and_unused_bit = ((byte << 1) as i8) >> (64 - shift);
599 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
600 let msg = if continuation_bit {
601 "invalid var_i64: integer representation too long"
602 } else {
603 "invalid var_i64: integer too large"
604 };
605 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
606 }
607 return Ok(result);
608 }
609 shift += 7;
610 if (byte & 0x80) == 0 {
611 break;
612 }
613 }
614 let ashift = 64 - shift;
615 Ok((result << ashift) >> ashift)
616 }
617
618 pub fn read_f32(&mut self) -> Result<Ieee32> {
624 let value = self.read_u32()?;
625 Ok(Ieee32(value))
626 }
627
628 pub fn read_f64(&mut self) -> Result<Ieee64> {
634 let value = self.read_u64()?;
635 Ok(Ieee64(value))
636 }
637
638 pub fn read_string(&mut self) -> Result<&'a str> {
644 let len = self.read_var_u32()? as usize;
645 if len > MAX_WASM_STRING_SIZE {
646 return Err(BinaryReaderError::new(
647 "string size out of bounds",
648 self.original_position() - 1,
649 ));
650 }
651 let bytes = self.read_bytes(len)?;
652 str::from_utf8(bytes).map_err(|_| {
653 BinaryReaderError::new("invalid UTF-8 encoding", self.original_position() - 1)
654 })
655 }
656
657 #[cold]
658 pub(crate) fn invalid_leading_byte<T>(&self, byte: u8, desc: &str) -> Result<T> {
659 Err(Self::invalid_leading_byte_error(
660 byte,
661 desc,
662 self.original_position() - 1,
663 ))
664 }
665
666 pub(crate) fn invalid_leading_byte_error(
667 byte: u8,
668 desc: &str,
669 offset: usize,
670 ) -> BinaryReaderError {
671 format_err!(offset, "invalid leading byte (0x{byte:x}) for {desc}")
672 }
673
674 pub(crate) fn peek(&self) -> Result<u8> {
675 self.ensure_has_byte()?;
676 Ok(self.buffer[self.position])
677 }
678
679 fn read_block_type(&mut self) -> Result<BlockType> {
680 let b = self.peek()?;
681
682 if b == 0x40 {
684 self.position += 1;
685 return Ok(BlockType::Empty);
686 }
687
688 if ValType::is_valtype_byte(b) {
690 return Ok(BlockType::Type(self.read()?));
691 }
692
693 let idx = self.read_var_s33()?;
695 match u32::try_from(idx) {
696 Ok(idx) => Ok(BlockType::FuncType(idx)),
697 Err(_) => {
698 return Err(BinaryReaderError::new(
699 "invalid function type",
700 self.original_position(),
701 ));
702 }
703 }
704 }
705
706 pub fn visit_operator<T>(&mut self, visitor: &mut T) -> Result<<T as VisitOperator<'a>>::Output>
752 where
753 T: VisitOperator<'a>,
754 {
755 let pos = self.original_position();
756 let code = self.read_u8()? as u8;
757 Ok(match code {
758 0x00 => visitor.visit_unreachable(),
759 0x01 => visitor.visit_nop(),
760 0x02 => visitor.visit_block(self.read_block_type()?),
761 0x03 => visitor.visit_loop(self.read_block_type()?),
762 0x04 => visitor.visit_if(self.read_block_type()?),
763 0x05 => visitor.visit_else(),
764 0x06 => visitor.visit_try(self.read_block_type()?),
765 0x07 => visitor.visit_catch(self.read_var_u32()?),
766 0x08 => visitor.visit_throw(self.read_var_u32()?),
767 0x09 => visitor.visit_rethrow(self.read_var_u32()?),
768 0x0b => visitor.visit_end(),
769 0x0c => visitor.visit_br(self.read_var_u32()?),
770 0x0d => visitor.visit_br_if(self.read_var_u32()?),
771 0x0e => visitor.visit_br_table(self.read_br_table()?),
772 0x0f => visitor.visit_return(),
773 0x10 => visitor.visit_call(self.read_var_u32()?),
774 0x11 => {
775 let index = self.read_var_u32()?;
776 let (table_byte, table_index) = self.read_first_byte_and_var_u32()?;
777 visitor.visit_call_indirect(index, table_index, table_byte)
778 }
779 0x12 => visitor.visit_return_call(self.read_var_u32()?),
780 0x13 => visitor.visit_return_call_indirect(self.read_var_u32()?, self.read_var_u32()?),
781 0x14 => visitor.visit_call_ref(self.read()?),
782 0x15 => visitor.visit_return_call_ref(self.read()?),
783 0x18 => visitor.visit_delegate(self.read_var_u32()?),
784 0x19 => visitor.visit_catch_all(),
785 0x1a => visitor.visit_drop(),
786 0x1b => visitor.visit_select(),
787 0x1c => {
788 let results = self.read_var_u32()?;
789 if results != 1 {
790 return Err(BinaryReaderError::new(
791 "invalid result arity",
792 self.position,
793 ));
794 }
795 visitor.visit_typed_select(self.read()?)
796 }
797
798 0x20 => visitor.visit_local_get(self.read_var_u32()?),
799 0x21 => visitor.visit_local_set(self.read_var_u32()?),
800 0x22 => visitor.visit_local_tee(self.read_var_u32()?),
801 0x23 => visitor.visit_global_get(self.read_var_u32()?),
802 0x24 => visitor.visit_global_set(self.read_var_u32()?),
803 0x25 => visitor.visit_table_get(self.read_var_u32()?),
804 0x26 => visitor.visit_table_set(self.read_var_u32()?),
805
806 0x28 => visitor.visit_i32_load(self.read_memarg(2)?),
807 0x29 => visitor.visit_i64_load(self.read_memarg(3)?),
808 0x2a => visitor.visit_f32_load(self.read_memarg(2)?),
809 0x2b => visitor.visit_f64_load(self.read_memarg(3)?),
810 0x2c => visitor.visit_i32_load8_s(self.read_memarg(0)?),
811 0x2d => visitor.visit_i32_load8_u(self.read_memarg(0)?),
812 0x2e => visitor.visit_i32_load16_s(self.read_memarg(1)?),
813 0x2f => visitor.visit_i32_load16_u(self.read_memarg(1)?),
814 0x30 => visitor.visit_i64_load8_s(self.read_memarg(0)?),
815 0x31 => visitor.visit_i64_load8_u(self.read_memarg(0)?),
816 0x32 => visitor.visit_i64_load16_s(self.read_memarg(1)?),
817 0x33 => visitor.visit_i64_load16_u(self.read_memarg(1)?),
818 0x34 => visitor.visit_i64_load32_s(self.read_memarg(2)?),
819 0x35 => visitor.visit_i64_load32_u(self.read_memarg(2)?),
820 0x36 => visitor.visit_i32_store(self.read_memarg(2)?),
821 0x37 => visitor.visit_i64_store(self.read_memarg(3)?),
822 0x38 => visitor.visit_f32_store(self.read_memarg(2)?),
823 0x39 => visitor.visit_f64_store(self.read_memarg(3)?),
824 0x3a => visitor.visit_i32_store8(self.read_memarg(0)?),
825 0x3b => visitor.visit_i32_store16(self.read_memarg(1)?),
826 0x3c => visitor.visit_i64_store8(self.read_memarg(0)?),
827 0x3d => visitor.visit_i64_store16(self.read_memarg(1)?),
828 0x3e => visitor.visit_i64_store32(self.read_memarg(2)?),
829 0x3f => {
830 let (mem_byte, mem) = self.read_first_byte_and_var_u32()?;
831 visitor.visit_memory_size(mem, mem_byte)
832 }
833 0x40 => {
834 let (mem_byte, mem) = self.read_first_byte_and_var_u32()?;
835 visitor.visit_memory_grow(mem, mem_byte)
836 }
837
838 0x41 => visitor.visit_i32_const(self.read_var_i32()?),
839 0x42 => visitor.visit_i64_const(self.read_var_i64()?),
840 0x43 => visitor.visit_f32_const(self.read_f32()?),
841 0x44 => visitor.visit_f64_const(self.read_f64()?),
842
843 0x45 => visitor.visit_i32_eqz(),
844 0x46 => visitor.visit_i32_eq(),
845 0x47 => visitor.visit_i32_ne(),
846 0x48 => visitor.visit_i32_lt_s(),
847 0x49 => visitor.visit_i32_lt_u(),
848 0x4a => visitor.visit_i32_gt_s(),
849 0x4b => visitor.visit_i32_gt_u(),
850 0x4c => visitor.visit_i32_le_s(),
851 0x4d => visitor.visit_i32_le_u(),
852 0x4e => visitor.visit_i32_ge_s(),
853 0x4f => visitor.visit_i32_ge_u(),
854 0x50 => visitor.visit_i64_eqz(),
855 0x51 => visitor.visit_i64_eq(),
856 0x52 => visitor.visit_i64_ne(),
857 0x53 => visitor.visit_i64_lt_s(),
858 0x54 => visitor.visit_i64_lt_u(),
859 0x55 => visitor.visit_i64_gt_s(),
860 0x56 => visitor.visit_i64_gt_u(),
861 0x57 => visitor.visit_i64_le_s(),
862 0x58 => visitor.visit_i64_le_u(),
863 0x59 => visitor.visit_i64_ge_s(),
864 0x5a => visitor.visit_i64_ge_u(),
865 0x5b => visitor.visit_f32_eq(),
866 0x5c => visitor.visit_f32_ne(),
867 0x5d => visitor.visit_f32_lt(),
868 0x5e => visitor.visit_f32_gt(),
869 0x5f => visitor.visit_f32_le(),
870 0x60 => visitor.visit_f32_ge(),
871 0x61 => visitor.visit_f64_eq(),
872 0x62 => visitor.visit_f64_ne(),
873 0x63 => visitor.visit_f64_lt(),
874 0x64 => visitor.visit_f64_gt(),
875 0x65 => visitor.visit_f64_le(),
876 0x66 => visitor.visit_f64_ge(),
877 0x67 => visitor.visit_i32_clz(),
878 0x68 => visitor.visit_i32_ctz(),
879 0x69 => visitor.visit_i32_popcnt(),
880 0x6a => visitor.visit_i32_add(),
881 0x6b => visitor.visit_i32_sub(),
882 0x6c => visitor.visit_i32_mul(),
883 0x6d => visitor.visit_i32_div_s(),
884 0x6e => visitor.visit_i32_div_u(),
885 0x6f => visitor.visit_i32_rem_s(),
886 0x70 => visitor.visit_i32_rem_u(),
887 0x71 => visitor.visit_i32_and(),
888 0x72 => visitor.visit_i32_or(),
889 0x73 => visitor.visit_i32_xor(),
890 0x74 => visitor.visit_i32_shl(),
891 0x75 => visitor.visit_i32_shr_s(),
892 0x76 => visitor.visit_i32_shr_u(),
893 0x77 => visitor.visit_i32_rotl(),
894 0x78 => visitor.visit_i32_rotr(),
895 0x79 => visitor.visit_i64_clz(),
896 0x7a => visitor.visit_i64_ctz(),
897 0x7b => visitor.visit_i64_popcnt(),
898 0x7c => visitor.visit_i64_add(),
899 0x7d => visitor.visit_i64_sub(),
900 0x7e => visitor.visit_i64_mul(),
901 0x7f => visitor.visit_i64_div_s(),
902 0x80 => visitor.visit_i64_div_u(),
903 0x81 => visitor.visit_i64_rem_s(),
904 0x82 => visitor.visit_i64_rem_u(),
905 0x83 => visitor.visit_i64_and(),
906 0x84 => visitor.visit_i64_or(),
907 0x85 => visitor.visit_i64_xor(),
908 0x86 => visitor.visit_i64_shl(),
909 0x87 => visitor.visit_i64_shr_s(),
910 0x88 => visitor.visit_i64_shr_u(),
911 0x89 => visitor.visit_i64_rotl(),
912 0x8a => visitor.visit_i64_rotr(),
913 0x8b => visitor.visit_f32_abs(),
914 0x8c => visitor.visit_f32_neg(),
915 0x8d => visitor.visit_f32_ceil(),
916 0x8e => visitor.visit_f32_floor(),
917 0x8f => visitor.visit_f32_trunc(),
918 0x90 => visitor.visit_f32_nearest(),
919 0x91 => visitor.visit_f32_sqrt(),
920 0x92 => visitor.visit_f32_add(),
921 0x93 => visitor.visit_f32_sub(),
922 0x94 => visitor.visit_f32_mul(),
923 0x95 => visitor.visit_f32_div(),
924 0x96 => visitor.visit_f32_min(),
925 0x97 => visitor.visit_f32_max(),
926 0x98 => visitor.visit_f32_copysign(),
927 0x99 => visitor.visit_f64_abs(),
928 0x9a => visitor.visit_f64_neg(),
929 0x9b => visitor.visit_f64_ceil(),
930 0x9c => visitor.visit_f64_floor(),
931 0x9d => visitor.visit_f64_trunc(),
932 0x9e => visitor.visit_f64_nearest(),
933 0x9f => visitor.visit_f64_sqrt(),
934 0xa0 => visitor.visit_f64_add(),
935 0xa1 => visitor.visit_f64_sub(),
936 0xa2 => visitor.visit_f64_mul(),
937 0xa3 => visitor.visit_f64_div(),
938 0xa4 => visitor.visit_f64_min(),
939 0xa5 => visitor.visit_f64_max(),
940 0xa6 => visitor.visit_f64_copysign(),
941 0xa7 => visitor.visit_i32_wrap_i64(),
942 0xa8 => visitor.visit_i32_trunc_f32_s(),
943 0xa9 => visitor.visit_i32_trunc_f32_u(),
944 0xaa => visitor.visit_i32_trunc_f64_s(),
945 0xab => visitor.visit_i32_trunc_f64_u(),
946 0xac => visitor.visit_i64_extend_i32_s(),
947 0xad => visitor.visit_i64_extend_i32_u(),
948 0xae => visitor.visit_i64_trunc_f32_s(),
949 0xaf => visitor.visit_i64_trunc_f32_u(),
950 0xb0 => visitor.visit_i64_trunc_f64_s(),
951 0xb1 => visitor.visit_i64_trunc_f64_u(),
952 0xb2 => visitor.visit_f32_convert_i32_s(),
953 0xb3 => visitor.visit_f32_convert_i32_u(),
954 0xb4 => visitor.visit_f32_convert_i64_s(),
955 0xb5 => visitor.visit_f32_convert_i64_u(),
956 0xb6 => visitor.visit_f32_demote_f64(),
957 0xb7 => visitor.visit_f64_convert_i32_s(),
958 0xb8 => visitor.visit_f64_convert_i32_u(),
959 0xb9 => visitor.visit_f64_convert_i64_s(),
960 0xba => visitor.visit_f64_convert_i64_u(),
961 0xbb => visitor.visit_f64_promote_f32(),
962 0xbc => visitor.visit_i32_reinterpret_f32(),
963 0xbd => visitor.visit_i64_reinterpret_f64(),
964 0xbe => visitor.visit_f32_reinterpret_i32(),
965 0xbf => visitor.visit_f64_reinterpret_i64(),
966
967 0xc0 => visitor.visit_i32_extend8_s(),
968 0xc1 => visitor.visit_i32_extend16_s(),
969 0xc2 => visitor.visit_i64_extend8_s(),
970 0xc3 => visitor.visit_i64_extend16_s(),
971 0xc4 => visitor.visit_i64_extend32_s(),
972
973 0xd0 => visitor.visit_ref_null(self.read()?),
974 0xd1 => visitor.visit_ref_is_null(),
975 0xd2 => visitor.visit_ref_func(self.read_var_u32()?),
976 0xd3 => visitor.visit_ref_as_non_null(),
977 0xd4 => visitor.visit_br_on_null(self.read_var_u32()?),
978 0xd6 => visitor.visit_br_on_non_null(self.read_var_u32()?),
979
980 0xfc => self.visit_0xfc_operator(pos, visitor)?,
981 0xfd => self.visit_0xfd_operator(pos, visitor)?,
982 0xfe => self.visit_0xfe_operator(pos, visitor)?,
983
984 _ => bail!(pos, "illegal opcode: 0x{code:x}"),
985 })
986 }
987
988 fn visit_0xfc_operator<T>(
989 &mut self,
990 pos: usize,
991 visitor: &mut T,
992 ) -> Result<<T as VisitOperator<'a>>::Output>
993 where
994 T: VisitOperator<'a>,
995 {
996 let code = self.read_var_u32()?;
997 Ok(match code {
998 0x00 => visitor.visit_i32_trunc_sat_f32_s(),
999 0x01 => visitor.visit_i32_trunc_sat_f32_u(),
1000 0x02 => visitor.visit_i32_trunc_sat_f64_s(),
1001 0x03 => visitor.visit_i32_trunc_sat_f64_u(),
1002 0x04 => visitor.visit_i64_trunc_sat_f32_s(),
1003 0x05 => visitor.visit_i64_trunc_sat_f32_u(),
1004 0x06 => visitor.visit_i64_trunc_sat_f64_s(),
1005 0x07 => visitor.visit_i64_trunc_sat_f64_u(),
1006
1007 0x08 => {
1008 let segment = self.read_var_u32()?;
1009 let mem = self.read_var_u32()?;
1010 visitor.visit_memory_init(segment, mem)
1011 }
1012 0x09 => {
1013 let segment = self.read_var_u32()?;
1014 visitor.visit_data_drop(segment)
1015 }
1016 0x0a => {
1017 let dst = self.read_var_u32()?;
1018 let src = self.read_var_u32()?;
1019 visitor.visit_memory_copy(dst, src)
1020 }
1021 0x0b => {
1022 let mem = self.read_var_u32()?;
1023 visitor.visit_memory_fill(mem)
1024 }
1025 0x0c => {
1026 let segment = self.read_var_u32()?;
1027 let table = self.read_var_u32()?;
1028 visitor.visit_table_init(segment, table)
1029 }
1030 0x0d => {
1031 let segment = self.read_var_u32()?;
1032 visitor.visit_elem_drop(segment)
1033 }
1034 0x0e => {
1035 let dst_table = self.read_var_u32()?;
1036 let src_table = self.read_var_u32()?;
1037 visitor.visit_table_copy(dst_table, src_table)
1038 }
1039
1040 0x0f => {
1041 let table = self.read_var_u32()?;
1042 visitor.visit_table_grow(table)
1043 }
1044 0x10 => {
1045 let table = self.read_var_u32()?;
1046 visitor.visit_table_size(table)
1047 }
1048
1049 0x11 => {
1050 let table = self.read_var_u32()?;
1051 visitor.visit_table_fill(table)
1052 }
1053
1054 0x12 => {
1055 let mem = self.read_var_u32()?;
1056 visitor.visit_memory_discard(mem)
1057 }
1058
1059 _ => bail!(pos, "unknown 0xfc subopcode: 0x{code:x}"),
1060 })
1061 }
1062
1063 fn visit_0xfd_operator<T>(
1064 &mut self,
1065 pos: usize,
1066 visitor: &mut T,
1067 ) -> Result<<T as VisitOperator<'a>>::Output>
1068 where
1069 T: VisitOperator<'a>,
1070 {
1071 let code = self.read_var_u32()?;
1072 Ok(match code {
1073 0x00 => visitor.visit_v128_load(self.read_memarg(4)?),
1074 0x01 => visitor.visit_v128_load8x8_s(self.read_memarg(3)?),
1075 0x02 => visitor.visit_v128_load8x8_u(self.read_memarg(3)?),
1076 0x03 => visitor.visit_v128_load16x4_s(self.read_memarg(3)?),
1077 0x04 => visitor.visit_v128_load16x4_u(self.read_memarg(3)?),
1078 0x05 => visitor.visit_v128_load32x2_s(self.read_memarg(3)?),
1079 0x06 => visitor.visit_v128_load32x2_u(self.read_memarg(3)?),
1080 0x07 => visitor.visit_v128_load8_splat(self.read_memarg(0)?),
1081 0x08 => visitor.visit_v128_load16_splat(self.read_memarg(1)?),
1082 0x09 => visitor.visit_v128_load32_splat(self.read_memarg(2)?),
1083 0x0a => visitor.visit_v128_load64_splat(self.read_memarg(3)?),
1084
1085 0x0b => visitor.visit_v128_store(self.read_memarg(4)?),
1086 0x0c => visitor.visit_v128_const(self.read_v128()?),
1087 0x0d => {
1088 let mut lanes: [u8; 16] = [0; 16];
1089 for lane in &mut lanes {
1090 *lane = self.read_lane_index(32)?
1091 }
1092 visitor.visit_i8x16_shuffle(lanes)
1093 }
1094
1095 0x0e => visitor.visit_i8x16_swizzle(),
1096 0x0f => visitor.visit_i8x16_splat(),
1097 0x10 => visitor.visit_i16x8_splat(),
1098 0x11 => visitor.visit_i32x4_splat(),
1099 0x12 => visitor.visit_i64x2_splat(),
1100 0x13 => visitor.visit_f32x4_splat(),
1101 0x14 => visitor.visit_f64x2_splat(),
1102
1103 0x15 => visitor.visit_i8x16_extract_lane_s(self.read_lane_index(16)?),
1104 0x16 => visitor.visit_i8x16_extract_lane_u(self.read_lane_index(16)?),
1105 0x17 => visitor.visit_i8x16_replace_lane(self.read_lane_index(16)?),
1106 0x18 => visitor.visit_i16x8_extract_lane_s(self.read_lane_index(8)?),
1107 0x19 => visitor.visit_i16x8_extract_lane_u(self.read_lane_index(8)?),
1108 0x1a => visitor.visit_i16x8_replace_lane(self.read_lane_index(8)?),
1109 0x1b => visitor.visit_i32x4_extract_lane(self.read_lane_index(4)?),
1110
1111 0x1c => visitor.visit_i32x4_replace_lane(self.read_lane_index(4)?),
1112 0x1d => visitor.visit_i64x2_extract_lane(self.read_lane_index(2)?),
1113 0x1e => visitor.visit_i64x2_replace_lane(self.read_lane_index(2)?),
1114 0x1f => visitor.visit_f32x4_extract_lane(self.read_lane_index(4)?),
1115 0x20 => visitor.visit_f32x4_replace_lane(self.read_lane_index(4)?),
1116 0x21 => visitor.visit_f64x2_extract_lane(self.read_lane_index(2)?),
1117 0x22 => visitor.visit_f64x2_replace_lane(self.read_lane_index(2)?),
1118
1119 0x23 => visitor.visit_i8x16_eq(),
1120 0x24 => visitor.visit_i8x16_ne(),
1121 0x25 => visitor.visit_i8x16_lt_s(),
1122 0x26 => visitor.visit_i8x16_lt_u(),
1123 0x27 => visitor.visit_i8x16_gt_s(),
1124 0x28 => visitor.visit_i8x16_gt_u(),
1125 0x29 => visitor.visit_i8x16_le_s(),
1126 0x2a => visitor.visit_i8x16_le_u(),
1127 0x2b => visitor.visit_i8x16_ge_s(),
1128 0x2c => visitor.visit_i8x16_ge_u(),
1129 0x2d => visitor.visit_i16x8_eq(),
1130 0x2e => visitor.visit_i16x8_ne(),
1131 0x2f => visitor.visit_i16x8_lt_s(),
1132 0x30 => visitor.visit_i16x8_lt_u(),
1133 0x31 => visitor.visit_i16x8_gt_s(),
1134 0x32 => visitor.visit_i16x8_gt_u(),
1135 0x33 => visitor.visit_i16x8_le_s(),
1136 0x34 => visitor.visit_i16x8_le_u(),
1137 0x35 => visitor.visit_i16x8_ge_s(),
1138 0x36 => visitor.visit_i16x8_ge_u(),
1139 0x37 => visitor.visit_i32x4_eq(),
1140 0x38 => visitor.visit_i32x4_ne(),
1141 0x39 => visitor.visit_i32x4_lt_s(),
1142 0x3a => visitor.visit_i32x4_lt_u(),
1143 0x3b => visitor.visit_i32x4_gt_s(),
1144 0x3c => visitor.visit_i32x4_gt_u(),
1145 0x3d => visitor.visit_i32x4_le_s(),
1146 0x3e => visitor.visit_i32x4_le_u(),
1147 0x3f => visitor.visit_i32x4_ge_s(),
1148 0x40 => visitor.visit_i32x4_ge_u(),
1149 0x41 => visitor.visit_f32x4_eq(),
1150 0x42 => visitor.visit_f32x4_ne(),
1151 0x43 => visitor.visit_f32x4_lt(),
1152 0x44 => visitor.visit_f32x4_gt(),
1153 0x45 => visitor.visit_f32x4_le(),
1154 0x46 => visitor.visit_f32x4_ge(),
1155 0x47 => visitor.visit_f64x2_eq(),
1156 0x48 => visitor.visit_f64x2_ne(),
1157 0x49 => visitor.visit_f64x2_lt(),
1158 0x4a => visitor.visit_f64x2_gt(),
1159 0x4b => visitor.visit_f64x2_le(),
1160 0x4c => visitor.visit_f64x2_ge(),
1161 0x4d => visitor.visit_v128_not(),
1162 0x4e => visitor.visit_v128_and(),
1163 0x4f => visitor.visit_v128_andnot(),
1164 0x50 => visitor.visit_v128_or(),
1165 0x51 => visitor.visit_v128_xor(),
1166 0x52 => visitor.visit_v128_bitselect(),
1167 0x53 => visitor.visit_v128_any_true(),
1168
1169 0x54 => {
1170 let memarg = self.read_memarg(0)?;
1171 let lane = self.read_lane_index(16)?;
1172 visitor.visit_v128_load8_lane(memarg, lane)
1173 }
1174 0x55 => {
1175 let memarg = self.read_memarg(1)?;
1176 let lane = self.read_lane_index(8)?;
1177 visitor.visit_v128_load16_lane(memarg, lane)
1178 }
1179 0x56 => {
1180 let memarg = self.read_memarg(2)?;
1181 let lane = self.read_lane_index(4)?;
1182 visitor.visit_v128_load32_lane(memarg, lane)
1183 }
1184 0x57 => {
1185 let memarg = self.read_memarg(3)?;
1186 let lane = self.read_lane_index(2)?;
1187 visitor.visit_v128_load64_lane(memarg, lane)
1188 }
1189 0x58 => {
1190 let memarg = self.read_memarg(0)?;
1191 let lane = self.read_lane_index(16)?;
1192 visitor.visit_v128_store8_lane(memarg, lane)
1193 }
1194 0x59 => {
1195 let memarg = self.read_memarg(1)?;
1196 let lane = self.read_lane_index(8)?;
1197 visitor.visit_v128_store16_lane(memarg, lane)
1198 }
1199 0x5a => {
1200 let memarg = self.read_memarg(2)?;
1201 let lane = self.read_lane_index(4)?;
1202 visitor.visit_v128_store32_lane(memarg, lane)
1203 }
1204 0x5b => {
1205 let memarg = self.read_memarg(3)?;
1206 let lane = self.read_lane_index(2)?;
1207 visitor.visit_v128_store64_lane(memarg, lane)
1208 }
1209
1210 0x5c => visitor.visit_v128_load32_zero(self.read_memarg(2)?),
1211 0x5d => visitor.visit_v128_load64_zero(self.read_memarg(3)?),
1212 0x5e => visitor.visit_f32x4_demote_f64x2_zero(),
1213 0x5f => visitor.visit_f64x2_promote_low_f32x4(),
1214 0x60 => visitor.visit_i8x16_abs(),
1215 0x61 => visitor.visit_i8x16_neg(),
1216 0x62 => visitor.visit_i8x16_popcnt(),
1217 0x63 => visitor.visit_i8x16_all_true(),
1218 0x64 => visitor.visit_i8x16_bitmask(),
1219 0x65 => visitor.visit_i8x16_narrow_i16x8_s(),
1220 0x66 => visitor.visit_i8x16_narrow_i16x8_u(),
1221 0x67 => visitor.visit_f32x4_ceil(),
1222 0x68 => visitor.visit_f32x4_floor(),
1223 0x69 => visitor.visit_f32x4_trunc(),
1224 0x6a => visitor.visit_f32x4_nearest(),
1225 0x6b => visitor.visit_i8x16_shl(),
1226 0x6c => visitor.visit_i8x16_shr_s(),
1227 0x6d => visitor.visit_i8x16_shr_u(),
1228 0x6e => visitor.visit_i8x16_add(),
1229 0x6f => visitor.visit_i8x16_add_sat_s(),
1230 0x70 => visitor.visit_i8x16_add_sat_u(),
1231 0x71 => visitor.visit_i8x16_sub(),
1232 0x72 => visitor.visit_i8x16_sub_sat_s(),
1233 0x73 => visitor.visit_i8x16_sub_sat_u(),
1234 0x74 => visitor.visit_f64x2_ceil(),
1235 0x75 => visitor.visit_f64x2_floor(),
1236 0x76 => visitor.visit_i8x16_min_s(),
1237 0x77 => visitor.visit_i8x16_min_u(),
1238 0x78 => visitor.visit_i8x16_max_s(),
1239 0x79 => visitor.visit_i8x16_max_u(),
1240 0x7a => visitor.visit_f64x2_trunc(),
1241 0x7b => visitor.visit_i8x16_avgr_u(),
1242 0x7c => visitor.visit_i16x8_extadd_pairwise_i8x16_s(),
1243 0x7d => visitor.visit_i16x8_extadd_pairwise_i8x16_u(),
1244 0x7e => visitor.visit_i32x4_extadd_pairwise_i16x8_s(),
1245 0x7f => visitor.visit_i32x4_extadd_pairwise_i16x8_u(),
1246 0x80 => visitor.visit_i16x8_abs(),
1247 0x81 => visitor.visit_i16x8_neg(),
1248 0x82 => visitor.visit_i16x8_q15mulr_sat_s(),
1249 0x83 => visitor.visit_i16x8_all_true(),
1250 0x84 => visitor.visit_i16x8_bitmask(),
1251 0x85 => visitor.visit_i16x8_narrow_i32x4_s(),
1252 0x86 => visitor.visit_i16x8_narrow_i32x4_u(),
1253 0x87 => visitor.visit_i16x8_extend_low_i8x16_s(),
1254 0x88 => visitor.visit_i16x8_extend_high_i8x16_s(),
1255 0x89 => visitor.visit_i16x8_extend_low_i8x16_u(),
1256 0x8a => visitor.visit_i16x8_extend_high_i8x16_u(),
1257 0x8b => visitor.visit_i16x8_shl(),
1258 0x8c => visitor.visit_i16x8_shr_s(),
1259 0x8d => visitor.visit_i16x8_shr_u(),
1260 0x8e => visitor.visit_i16x8_add(),
1261 0x8f => visitor.visit_i16x8_add_sat_s(),
1262 0x90 => visitor.visit_i16x8_add_sat_u(),
1263 0x91 => visitor.visit_i16x8_sub(),
1264 0x92 => visitor.visit_i16x8_sub_sat_s(),
1265 0x93 => visitor.visit_i16x8_sub_sat_u(),
1266 0x94 => visitor.visit_f64x2_nearest(),
1267 0x95 => visitor.visit_i16x8_mul(),
1268 0x96 => visitor.visit_i16x8_min_s(),
1269 0x97 => visitor.visit_i16x8_min_u(),
1270 0x98 => visitor.visit_i16x8_max_s(),
1271 0x99 => visitor.visit_i16x8_max_u(),
1272 0x9b => visitor.visit_i16x8_avgr_u(),
1273 0x9c => visitor.visit_i16x8_extmul_low_i8x16_s(),
1274 0x9d => visitor.visit_i16x8_extmul_high_i8x16_s(),
1275 0x9e => visitor.visit_i16x8_extmul_low_i8x16_u(),
1276 0x9f => visitor.visit_i16x8_extmul_high_i8x16_u(),
1277 0xa0 => visitor.visit_i32x4_abs(),
1278 0xa1 => visitor.visit_i32x4_neg(),
1279 0xa3 => visitor.visit_i32x4_all_true(),
1280 0xa4 => visitor.visit_i32x4_bitmask(),
1281 0xa7 => visitor.visit_i32x4_extend_low_i16x8_s(),
1282 0xa8 => visitor.visit_i32x4_extend_high_i16x8_s(),
1283 0xa9 => visitor.visit_i32x4_extend_low_i16x8_u(),
1284 0xaa => visitor.visit_i32x4_extend_high_i16x8_u(),
1285 0xab => visitor.visit_i32x4_shl(),
1286 0xac => visitor.visit_i32x4_shr_s(),
1287 0xad => visitor.visit_i32x4_shr_u(),
1288 0xae => visitor.visit_i32x4_add(),
1289 0xb1 => visitor.visit_i32x4_sub(),
1290 0xb5 => visitor.visit_i32x4_mul(),
1291 0xb6 => visitor.visit_i32x4_min_s(),
1292 0xb7 => visitor.visit_i32x4_min_u(),
1293 0xb8 => visitor.visit_i32x4_max_s(),
1294 0xb9 => visitor.visit_i32x4_max_u(),
1295 0xba => visitor.visit_i32x4_dot_i16x8_s(),
1296 0xbc => visitor.visit_i32x4_extmul_low_i16x8_s(),
1297 0xbd => visitor.visit_i32x4_extmul_high_i16x8_s(),
1298 0xbe => visitor.visit_i32x4_extmul_low_i16x8_u(),
1299 0xbf => visitor.visit_i32x4_extmul_high_i16x8_u(),
1300 0xc0 => visitor.visit_i64x2_abs(),
1301 0xc1 => visitor.visit_i64x2_neg(),
1302 0xc3 => visitor.visit_i64x2_all_true(),
1303 0xc4 => visitor.visit_i64x2_bitmask(),
1304 0xc7 => visitor.visit_i64x2_extend_low_i32x4_s(),
1305 0xc8 => visitor.visit_i64x2_extend_high_i32x4_s(),
1306 0xc9 => visitor.visit_i64x2_extend_low_i32x4_u(),
1307 0xca => visitor.visit_i64x2_extend_high_i32x4_u(),
1308 0xcb => visitor.visit_i64x2_shl(),
1309 0xcc => visitor.visit_i64x2_shr_s(),
1310 0xcd => visitor.visit_i64x2_shr_u(),
1311 0xce => visitor.visit_i64x2_add(),
1312 0xd1 => visitor.visit_i64x2_sub(),
1313 0xd5 => visitor.visit_i64x2_mul(),
1314 0xd6 => visitor.visit_i64x2_eq(),
1315 0xd7 => visitor.visit_i64x2_ne(),
1316 0xd8 => visitor.visit_i64x2_lt_s(),
1317 0xd9 => visitor.visit_i64x2_gt_s(),
1318 0xda => visitor.visit_i64x2_le_s(),
1319 0xdb => visitor.visit_i64x2_ge_s(),
1320 0xdc => visitor.visit_i64x2_extmul_low_i32x4_s(),
1321 0xdd => visitor.visit_i64x2_extmul_high_i32x4_s(),
1322 0xde => visitor.visit_i64x2_extmul_low_i32x4_u(),
1323 0xdf => visitor.visit_i64x2_extmul_high_i32x4_u(),
1324 0xe0 => visitor.visit_f32x4_abs(),
1325 0xe1 => visitor.visit_f32x4_neg(),
1326 0xe3 => visitor.visit_f32x4_sqrt(),
1327 0xe4 => visitor.visit_f32x4_add(),
1328 0xe5 => visitor.visit_f32x4_sub(),
1329 0xe6 => visitor.visit_f32x4_mul(),
1330 0xe7 => visitor.visit_f32x4_div(),
1331 0xe8 => visitor.visit_f32x4_min(),
1332 0xe9 => visitor.visit_f32x4_max(),
1333 0xea => visitor.visit_f32x4_pmin(),
1334 0xeb => visitor.visit_f32x4_pmax(),
1335 0xec => visitor.visit_f64x2_abs(),
1336 0xed => visitor.visit_f64x2_neg(),
1337 0xef => visitor.visit_f64x2_sqrt(),
1338 0xf0 => visitor.visit_f64x2_add(),
1339 0xf1 => visitor.visit_f64x2_sub(),
1340 0xf2 => visitor.visit_f64x2_mul(),
1341 0xf3 => visitor.visit_f64x2_div(),
1342 0xf4 => visitor.visit_f64x2_min(),
1343 0xf5 => visitor.visit_f64x2_max(),
1344 0xf6 => visitor.visit_f64x2_pmin(),
1345 0xf7 => visitor.visit_f64x2_pmax(),
1346 0xf8 => visitor.visit_i32x4_trunc_sat_f32x4_s(),
1347 0xf9 => visitor.visit_i32x4_trunc_sat_f32x4_u(),
1348 0xfa => visitor.visit_f32x4_convert_i32x4_s(),
1349 0xfb => visitor.visit_f32x4_convert_i32x4_u(),
1350 0xfc => visitor.visit_i32x4_trunc_sat_f64x2_s_zero(),
1351 0xfd => visitor.visit_i32x4_trunc_sat_f64x2_u_zero(),
1352 0xfe => visitor.visit_f64x2_convert_low_i32x4_s(),
1353 0xff => visitor.visit_f64x2_convert_low_i32x4_u(),
1354 0x100 => visitor.visit_i8x16_relaxed_swizzle(),
1355 0x101 => visitor.visit_i32x4_relaxed_trunc_f32x4_s(),
1356 0x102 => visitor.visit_i32x4_relaxed_trunc_f32x4_u(),
1357 0x103 => visitor.visit_i32x4_relaxed_trunc_f64x2_s_zero(),
1358 0x104 => visitor.visit_i32x4_relaxed_trunc_f64x2_u_zero(),
1359 0x105 => visitor.visit_f32x4_relaxed_madd(),
1360 0x106 => visitor.visit_f32x4_relaxed_nmadd(),
1361 0x107 => visitor.visit_f64x2_relaxed_madd(),
1362 0x108 => visitor.visit_f64x2_relaxed_nmadd(),
1363 0x109 => visitor.visit_i8x16_relaxed_laneselect(),
1364 0x10a => visitor.visit_i16x8_relaxed_laneselect(),
1365 0x10b => visitor.visit_i32x4_relaxed_laneselect(),
1366 0x10c => visitor.visit_i64x2_relaxed_laneselect(),
1367 0x10d => visitor.visit_f32x4_relaxed_min(),
1368 0x10e => visitor.visit_f32x4_relaxed_max(),
1369 0x10f => visitor.visit_f64x2_relaxed_min(),
1370 0x110 => visitor.visit_f64x2_relaxed_max(),
1371 0x111 => visitor.visit_i16x8_relaxed_q15mulr_s(),
1372 0x112 => visitor.visit_i16x8_relaxed_dot_i8x16_i7x16_s(),
1373 0x113 => visitor.visit_i32x4_relaxed_dot_i8x16_i7x16_add_s(),
1374
1375 _ => bail!(pos, "unknown 0xfd subopcode: 0x{code:x}"),
1376 })
1377 }
1378
1379 fn visit_0xfe_operator<T>(
1380 &mut self,
1381 pos: usize,
1382 visitor: &mut T,
1383 ) -> Result<<T as VisitOperator<'a>>::Output>
1384 where
1385 T: VisitOperator<'a>,
1386 {
1387 let code = self.read_var_u32()?;
1388 Ok(match code {
1389 0x00 => visitor.visit_memory_atomic_notify(self.read_memarg(2)?),
1390 0x01 => visitor.visit_memory_atomic_wait32(self.read_memarg(2)?),
1391 0x02 => visitor.visit_memory_atomic_wait64(self.read_memarg(3)?),
1392 0x03 => {
1393 if self.read_u8()? != 0 {
1394 bail!(pos, "nonzero byte after `atomic.fence`");
1395 }
1396 visitor.visit_atomic_fence()
1397 }
1398 0x10 => visitor.visit_i32_atomic_load(self.read_memarg(2)?),
1399 0x11 => visitor.visit_i64_atomic_load(self.read_memarg(3)?),
1400 0x12 => visitor.visit_i32_atomic_load8_u(self.read_memarg(0)?),
1401 0x13 => visitor.visit_i32_atomic_load16_u(self.read_memarg(1)?),
1402 0x14 => visitor.visit_i64_atomic_load8_u(self.read_memarg(0)?),
1403 0x15 => visitor.visit_i64_atomic_load16_u(self.read_memarg(1)?),
1404 0x16 => visitor.visit_i64_atomic_load32_u(self.read_memarg(2)?),
1405 0x17 => visitor.visit_i32_atomic_store(self.read_memarg(2)?),
1406 0x18 => visitor.visit_i64_atomic_store(self.read_memarg(3)?),
1407 0x19 => visitor.visit_i32_atomic_store8(self.read_memarg(0)?),
1408 0x1a => visitor.visit_i32_atomic_store16(self.read_memarg(1)?),
1409 0x1b => visitor.visit_i64_atomic_store8(self.read_memarg(0)?),
1410 0x1c => visitor.visit_i64_atomic_store16(self.read_memarg(1)?),
1411 0x1d => visitor.visit_i64_atomic_store32(self.read_memarg(2)?),
1412 0x1e => visitor.visit_i32_atomic_rmw_add(self.read_memarg(2)?),
1413 0x1f => visitor.visit_i64_atomic_rmw_add(self.read_memarg(3)?),
1414 0x20 => visitor.visit_i32_atomic_rmw8_add_u(self.read_memarg(0)?),
1415 0x21 => visitor.visit_i32_atomic_rmw16_add_u(self.read_memarg(1)?),
1416 0x22 => visitor.visit_i64_atomic_rmw8_add_u(self.read_memarg(0)?),
1417 0x23 => visitor.visit_i64_atomic_rmw16_add_u(self.read_memarg(1)?),
1418 0x24 => visitor.visit_i64_atomic_rmw32_add_u(self.read_memarg(2)?),
1419 0x25 => visitor.visit_i32_atomic_rmw_sub(self.read_memarg(2)?),
1420 0x26 => visitor.visit_i64_atomic_rmw_sub(self.read_memarg(3)?),
1421 0x27 => visitor.visit_i32_atomic_rmw8_sub_u(self.read_memarg(0)?),
1422 0x28 => visitor.visit_i32_atomic_rmw16_sub_u(self.read_memarg(1)?),
1423 0x29 => visitor.visit_i64_atomic_rmw8_sub_u(self.read_memarg(0)?),
1424 0x2a => visitor.visit_i64_atomic_rmw16_sub_u(self.read_memarg(1)?),
1425 0x2b => visitor.visit_i64_atomic_rmw32_sub_u(self.read_memarg(2)?),
1426 0x2c => visitor.visit_i32_atomic_rmw_and(self.read_memarg(2)?),
1427 0x2d => visitor.visit_i64_atomic_rmw_and(self.read_memarg(3)?),
1428 0x2e => visitor.visit_i32_atomic_rmw8_and_u(self.read_memarg(0)?),
1429 0x2f => visitor.visit_i32_atomic_rmw16_and_u(self.read_memarg(1)?),
1430 0x30 => visitor.visit_i64_atomic_rmw8_and_u(self.read_memarg(0)?),
1431 0x31 => visitor.visit_i64_atomic_rmw16_and_u(self.read_memarg(1)?),
1432 0x32 => visitor.visit_i64_atomic_rmw32_and_u(self.read_memarg(2)?),
1433 0x33 => visitor.visit_i32_atomic_rmw_or(self.read_memarg(2)?),
1434 0x34 => visitor.visit_i64_atomic_rmw_or(self.read_memarg(3)?),
1435 0x35 => visitor.visit_i32_atomic_rmw8_or_u(self.read_memarg(0)?),
1436 0x36 => visitor.visit_i32_atomic_rmw16_or_u(self.read_memarg(1)?),
1437 0x37 => visitor.visit_i64_atomic_rmw8_or_u(self.read_memarg(0)?),
1438 0x38 => visitor.visit_i64_atomic_rmw16_or_u(self.read_memarg(1)?),
1439 0x39 => visitor.visit_i64_atomic_rmw32_or_u(self.read_memarg(2)?),
1440 0x3a => visitor.visit_i32_atomic_rmw_xor(self.read_memarg(2)?),
1441 0x3b => visitor.visit_i64_atomic_rmw_xor(self.read_memarg(3)?),
1442 0x3c => visitor.visit_i32_atomic_rmw8_xor_u(self.read_memarg(0)?),
1443 0x3d => visitor.visit_i32_atomic_rmw16_xor_u(self.read_memarg(1)?),
1444 0x3e => visitor.visit_i64_atomic_rmw8_xor_u(self.read_memarg(0)?),
1445 0x3f => visitor.visit_i64_atomic_rmw16_xor_u(self.read_memarg(1)?),
1446 0x40 => visitor.visit_i64_atomic_rmw32_xor_u(self.read_memarg(2)?),
1447 0x41 => visitor.visit_i32_atomic_rmw_xchg(self.read_memarg(2)?),
1448 0x42 => visitor.visit_i64_atomic_rmw_xchg(self.read_memarg(3)?),
1449 0x43 => visitor.visit_i32_atomic_rmw8_xchg_u(self.read_memarg(0)?),
1450 0x44 => visitor.visit_i32_atomic_rmw16_xchg_u(self.read_memarg(1)?),
1451 0x45 => visitor.visit_i64_atomic_rmw8_xchg_u(self.read_memarg(0)?),
1452 0x46 => visitor.visit_i64_atomic_rmw16_xchg_u(self.read_memarg(1)?),
1453 0x47 => visitor.visit_i64_atomic_rmw32_xchg_u(self.read_memarg(2)?),
1454 0x48 => visitor.visit_i32_atomic_rmw_cmpxchg(self.read_memarg(2)?),
1455 0x49 => visitor.visit_i64_atomic_rmw_cmpxchg(self.read_memarg(3)?),
1456 0x4a => visitor.visit_i32_atomic_rmw8_cmpxchg_u(self.read_memarg(0)?),
1457 0x4b => visitor.visit_i32_atomic_rmw16_cmpxchg_u(self.read_memarg(1)?),
1458 0x4c => visitor.visit_i64_atomic_rmw8_cmpxchg_u(self.read_memarg(0)?),
1459 0x4d => visitor.visit_i64_atomic_rmw16_cmpxchg_u(self.read_memarg(1)?),
1460 0x4e => visitor.visit_i64_atomic_rmw32_cmpxchg_u(self.read_memarg(2)?),
1461
1462 _ => bail!(pos, "unknown 0xfe subopcode: 0x{code:x}"),
1463 })
1464 }
1465
1466 pub fn read_operator(&mut self) -> Result<Operator<'a>> {
1473 self.visit_operator(&mut OperatorFactory::new())
1474 }
1475
1476 fn read_lane_index(&mut self, max: u8) -> Result<u8> {
1477 let index = self.read_u8()?;
1478 if index >= max {
1479 return Err(BinaryReaderError::new(
1480 "invalid lane index",
1481 self.original_position() - 1,
1482 ));
1483 }
1484 Ok(index)
1485 }
1486
1487 fn read_v128(&mut self) -> Result<V128> {
1488 let mut bytes = [0; 16];
1489 bytes.clone_from_slice(self.read_bytes(16)?);
1490 Ok(V128(bytes))
1491 }
1492
1493 pub(crate) fn read_header_version(&mut self) -> Result<u32> {
1494 let magic_number = self.read_bytes(4)?;
1495 if magic_number != WASM_MAGIC_NUMBER {
1496 return Err(BinaryReaderError::new(
1497 "magic header not detected: bad magic number",
1498 self.original_position() - 4,
1499 ));
1500 }
1501 self.read_u32()
1502 }
1503
1504 pub(crate) fn skip_const_expr(&mut self) -> Result<()> {
1505 loop {
1507 if let Operator::End = self.read_operator()? {
1508 return Ok(());
1509 }
1510 }
1511 }
1512}
1513
1514impl<'a> BrTable<'a> {
1515 pub fn len(&self) -> u32 {
1518 self.cnt
1519 }
1520
1521 pub fn is_empty(&self) -> bool {
1523 self.len() == 0
1524 }
1525
1526 pub fn default(&self) -> u32 {
1528 self.default
1529 }
1530
1531 pub fn targets(&self) -> BrTableTargets {
1550 BrTableTargets {
1551 reader: self.reader.clone(),
1552 remaining: self.cnt,
1553 }
1554 }
1555}
1556
1557pub struct BrTableTargets<'a> {
1565 reader: crate::BinaryReader<'a>,
1566 remaining: u32,
1567}
1568
1569impl<'a> Iterator for BrTableTargets<'a> {
1570 type Item = Result<u32>;
1571
1572 fn size_hint(&self) -> (usize, Option<usize>) {
1573 let remaining = usize::try_from(self.remaining).unwrap_or_else(|error| {
1574 panic!("could not convert remaining `u32` into `usize`: {}", error)
1575 });
1576 (remaining, Some(remaining))
1577 }
1578
1579 fn next(&mut self) -> Option<Self::Item> {
1580 if self.remaining == 0 {
1581 if !self.reader.eof() {
1582 return Some(Err(BinaryReaderError::new(
1583 "trailing data in br_table",
1584 self.reader.original_position(),
1585 )));
1586 }
1587 return None;
1588 }
1589 self.remaining -= 1;
1590 Some(self.reader.read_var_u32())
1591 }
1592}
1593
1594impl fmt::Debug for BrTable<'_> {
1595 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1596 let mut f = f.debug_struct("BrTable");
1597 f.field("count", &self.cnt);
1598 f.field("default", &self.default);
1599 match self.targets().collect::<Result<Vec<_>>>() {
1600 Ok(targets) => {
1601 f.field("targets", &targets);
1602 }
1603 Err(_) => {
1604 f.field("reader", &self.reader);
1605 }
1606 }
1607 f.finish()
1608 }
1609}
1610
1611struct OperatorFactory<'a> {
1613 marker: core::marker::PhantomData<fn() -> &'a ()>,
1614}
1615
1616impl<'a> OperatorFactory<'a> {
1617 fn new() -> Self {
1619 Self {
1620 marker: core::marker::PhantomData,
1621 }
1622 }
1623}
1624
1625macro_rules! define_visit_operator {
1626 ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => {
1627 $(
1628 fn $visit(&mut self $($(,$arg: $argty)*)?) -> Operator<'a> {
1629 Operator::$op $({ $($arg),* })?
1630 }
1631 )*
1632 }
1633}
1634
1635impl<'a> VisitOperator<'a> for OperatorFactory<'a> {
1636 type Output = Operator<'a>;
1637
1638 for_each_operator!(define_visit_operator);
1639}
1640
1641pub struct BinaryReaderIter<'a, 'me, T: FromReader<'a>> {
1643 remaining: usize,
1644 reader: &'me mut BinaryReader<'a>,
1645 _marker: marker::PhantomData<T>,
1646}
1647
1648impl<'a, T> Iterator for BinaryReaderIter<'a, '_, T>
1649where
1650 T: FromReader<'a>,
1651{
1652 type Item = Result<T>;
1653
1654 fn next(&mut self) -> Option<Result<T>> {
1655 if self.remaining == 0 {
1656 None
1657 } else {
1658 let ret = self.reader.read::<T>();
1659 if ret.is_err() {
1660 self.remaining = 0;
1661 } else {
1662 self.remaining -= 1;
1663 }
1664 Some(ret)
1665 }
1666 }
1667
1668 fn size_hint(&self) -> (usize, Option<usize>) {
1669 (self.remaining, Some(self.remaining))
1670 }
1671}
1672
1673impl<'a, T> Drop for BinaryReaderIter<'a, '_, T>
1674where
1675 T: FromReader<'a>,
1676{
1677 fn drop(&mut self) {
1678 while self.next().is_some() {
1679 }
1681 }
1682}