1use crate::prelude::*;
17use crate::{limits::*, *};
18use core::fmt;
19use core::marker;
20use core::ops::Range;
21use core::str;
22
23pub(crate) const WASM_MAGIC_NUMBER: &[u8; 4] = b"\0asm";
24
25#[derive(Debug, Clone)]
27pub struct BinaryReaderError {
28 pub(crate) inner: Box<BinaryReaderErrorInner>,
32}
33
34#[derive(Debug, Clone)]
35pub(crate) struct BinaryReaderErrorInner {
36 pub(crate) message: String,
37 pub(crate) kind: BinaryReaderErrorKind,
38 pub(crate) offset: usize,
39 pub(crate) needed_hint: Option<usize>,
40}
41
42#[derive(Debug, Clone, Copy)]
43pub(crate) enum BinaryReaderErrorKind {
44 Custom,
45 Invalid,
46}
47
48pub type Result<T, E = BinaryReaderError> = core::result::Result<T, E>;
50
51#[cfg(feature = "std")]
52impl std::error::Error for BinaryReaderError {}
53
54#[cfg(all(not(feature = "std"), core_error))]
55impl core::error::Error for BinaryReaderError {}
56
57impl fmt::Display for BinaryReaderError {
58 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59 write!(
60 f,
61 "{} (at offset 0x{:x})",
62 self.inner.message, self.inner.offset
63 )
64 }
65}
66
67impl BinaryReaderError {
68 #[cold]
69 pub(crate) fn _new(kind: BinaryReaderErrorKind, message: String, offset: usize) -> Self {
70 BinaryReaderError {
71 inner: Box::new(BinaryReaderErrorInner {
72 kind,
73 message,
74 offset,
75 needed_hint: None,
76 }),
77 }
78 }
79
80 #[cold]
81 pub(crate) fn new(message: impl Into<String>, offset: usize) -> Self {
82 Self::_new(BinaryReaderErrorKind::Custom, message.into(), offset)
83 }
84
85 #[cold]
86 pub(crate) fn invalid(msg: &'static str, offset: usize) -> Self {
87 Self::_new(BinaryReaderErrorKind::Invalid, msg.into(), offset)
88 }
89
90 #[cold]
91 pub(crate) fn fmt(args: fmt::Arguments<'_>, offset: usize) -> Self {
92 BinaryReaderError::new(args.to_string(), offset)
93 }
94
95 #[cold]
96 pub(crate) fn eof(offset: usize, needed_hint: usize) -> Self {
97 let mut err = BinaryReaderError::new("unexpected end-of-file", offset);
98 err.inner.needed_hint = Some(needed_hint);
99 err
100 }
101
102 pub(crate) fn kind(&mut self) -> BinaryReaderErrorKind {
103 self.inner.kind
104 }
105
106 pub fn message(&self) -> &str {
108 &self.inner.message
109 }
110
111 pub fn offset(&self) -> usize {
113 self.inner.offset
114 }
115
116 #[cfg(all(feature = "validate", feature = "component-model"))]
117 pub(crate) fn add_context(&mut self, context: String) {
118 self.inner.message = format!("{context}\n{}", self.inner.message);
119 }
120
121 pub(crate) fn set_message(&mut self, message: &str) {
122 self.inner.message = message.to_string();
123 }
124}
125
126#[derive(Clone, Debug, Hash)]
128pub struct BinaryReader<'a> {
129 buffer: &'a [u8],
130 position: usize,
131 original_offset: usize,
132
133 #[cfg(feature = "features")]
145 features: WasmFeatures,
146}
147
148impl<'a> BinaryReader<'a> {
149 pub fn new(data: &[u8], original_offset: usize) -> BinaryReader<'_> {
160 BinaryReader {
161 buffer: data,
162 position: 0,
163 original_offset,
164 #[cfg(feature = "features")]
165 features: WasmFeatures::all(),
166 }
167 }
168
169 #[cfg(feature = "features")]
200 pub fn new_features(
201 data: &[u8],
202 original_offset: usize,
203 features: WasmFeatures,
204 ) -> BinaryReader<'_> {
205 BinaryReader {
206 buffer: data,
207 position: 0,
208 original_offset,
209 features,
210 }
211 }
212
213 pub(crate) fn shrink(&self) -> BinaryReader<'a> {
224 BinaryReader {
225 buffer: &self.buffer[self.position..],
226 position: 0,
227 original_offset: self.original_offset + self.position,
228 #[cfg(feature = "features")]
229 features: self.features,
230 }
231 }
232
233 #[inline]
235 pub fn original_position(&self) -> usize {
236 self.original_offset + self.position
237 }
238
239 #[cfg(feature = "features")]
244 pub fn features(&self) -> WasmFeatures {
245 self.features
246 }
247
248 #[cfg(feature = "features")]
252 pub fn set_features(&mut self, features: WasmFeatures) {
253 self.features = features;
254 }
255
256 pub fn range(&self) -> Range<usize> {
258 self.original_offset..self.original_offset + self.buffer.len()
259 }
260
261 pub(crate) fn remaining_buffer(&self) -> &'a [u8] {
262 &self.buffer[self.position..]
263 }
264
265 fn ensure_has_byte(&self) -> Result<()> {
266 if self.position < self.buffer.len() {
267 Ok(())
268 } else {
269 Err(BinaryReaderError::eof(self.original_position(), 1))
270 }
271 }
272
273 pub(crate) fn ensure_has_bytes(&self, len: usize) -> Result<()> {
274 if self.position + len <= self.buffer.len() {
275 Ok(())
276 } else {
277 let hint = self.position + len - self.buffer.len();
278 Err(BinaryReaderError::eof(self.original_position(), hint))
279 }
280 }
281
282 #[inline]
285 pub fn read<T>(&mut self) -> Result<T>
286 where
287 T: FromReader<'a>,
288 {
289 T::from_reader(self)
290 }
291
292 pub(crate) fn read_u7(&mut self) -> Result<u8> {
293 let b = self.read_u8()?;
294 if (b & 0x80) != 0 {
295 return Err(BinaryReaderError::new(
296 "invalid u7",
297 self.original_position() - 1,
298 ));
299 }
300 Ok(b)
301 }
302
303 pub(crate) fn external_kind_from_byte(byte: u8, offset: usize) -> Result<ExternalKind> {
304 match byte {
305 0x00 => Ok(ExternalKind::Func),
306 0x01 => Ok(ExternalKind::Table),
307 0x02 => Ok(ExternalKind::Memory),
308 0x03 => Ok(ExternalKind::Global),
309 0x04 => Ok(ExternalKind::Tag),
310 0x20 => Ok(ExternalKind::FuncExact),
311 x => Err(Self::invalid_leading_byte_error(x, "external kind", offset)),
312 }
313 }
314
315 pub fn read_size(&mut self, limit: usize, desc: &str) -> Result<usize> {
318 let pos = self.original_position();
319 let size = self.read_var_u32()? as usize;
320 if size > limit {
321 bail!(pos, "{desc} size is out of bounds");
322 }
323 Ok(size)
324 }
325
326 pub fn read_iter<'me, T>(
334 &'me mut self,
335 limit: usize,
336 desc: &str,
337 ) -> Result<BinaryReaderIter<'a, 'me, T>>
338 where
339 T: FromReader<'a>,
340 {
341 let size = self.read_size(limit, desc)?;
342 Ok(BinaryReaderIter {
343 remaining: size,
344 reader: self,
345 _marker: marker::PhantomData,
346 })
347 }
348
349 #[inline]
351 pub fn eof(&self) -> bool {
352 self.position >= self.buffer.len()
353 }
354
355 #[inline]
357 pub fn current_position(&self) -> usize {
358 self.position
359 }
360
361 #[inline]
363 pub fn bytes_remaining(&self) -> usize {
364 self.buffer.len() - self.position
365 }
366
367 pub fn read_bytes(&mut self, size: usize) -> Result<&'a [u8]> {
373 self.ensure_has_bytes(size)?;
374 let start = self.position;
375 self.position += size;
376 Ok(&self.buffer[start..self.position])
377 }
378
379 pub fn read_reader(&mut self) -> Result<BinaryReader<'a>> {
382 let size = self.read_var_u32()? as usize;
383 self.skip(|reader| {
384 reader.read_bytes(size)?;
385 Ok(())
386 })
387 }
388
389 pub fn read_u32(&mut self) -> Result<u32> {
393 self.ensure_has_bytes(4)?;
394 let word = u32::from_le_bytes(
395 self.buffer[self.position..self.position + 4]
396 .try_into()
397 .unwrap(),
398 );
399 self.position += 4;
400 Ok(word)
401 }
402
403 pub fn read_u64(&mut self) -> Result<u64> {
407 self.ensure_has_bytes(8)?;
408 let word = u64::from_le_bytes(
409 self.buffer[self.position..self.position + 8]
410 .try_into()
411 .unwrap(),
412 );
413 self.position += 8;
414 Ok(word)
415 }
416
417 #[inline]
423 pub fn read_u8(&mut self) -> Result<u8> {
424 let b = match self.buffer.get(self.position) {
425 Some(b) => *b,
426 None => return Err(self.eof_err()),
427 };
428 self.position += 1;
429 Ok(b)
430 }
431
432 #[cold]
433 fn eof_err(&self) -> BinaryReaderError {
434 BinaryReaderError::eof(self.original_position(), 1)
435 }
436
437 #[inline]
445 pub fn read_var_u32(&mut self) -> Result<u32> {
446 let byte = self.read_u8()?;
448 if (byte & 0x80) == 0 {
449 Ok(u32::from(byte))
450 } else {
451 self.read_var_u32_big(byte)
452 }
453 }
454
455 fn read_var_u32_big(&mut self, byte: u8) -> Result<u32> {
456 let mut result = (byte & 0x7F) as u32;
457 let mut shift = 7;
458 loop {
459 let byte = self.read_u8()?;
460 result |= ((byte & 0x7F) as u32) << shift;
461 if shift >= 25 && (byte >> (32 - shift)) != 0 {
462 let msg = if byte & 0x80 != 0 {
463 "invalid var_u32: integer representation too long"
464 } else {
465 "invalid var_u32: integer too large"
466 };
467 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
469 }
470 shift += 7;
471 if (byte & 0x80) == 0 {
472 break;
473 }
474 }
475 Ok(result)
476 }
477
478 #[inline]
486 pub fn read_var_u64(&mut self) -> Result<u64> {
487 let byte = u64::from(self.read_u8()?);
489 if (byte & 0x80) == 0 {
490 Ok(byte)
491 } else {
492 self.read_var_u64_big(byte)
493 }
494 }
495
496 fn read_var_u64_big(&mut self, byte: u64) -> Result<u64> {
497 let mut result = byte & 0x7F;
498 let mut shift = 7;
499 loop {
500 let byte = u64::from(self.read_u8()?);
501 result |= (byte & 0x7F) << shift;
502 if shift >= 57 && (byte >> (64 - shift)) != 0 {
503 let msg = if byte & 0x80 != 0 {
504 "invalid var_u64: integer representation too long"
505 } else {
506 "invalid var_u64: integer too large"
507 };
508 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
510 }
511 shift += 7;
512 if (byte & 0x80) == 0 {
513 break;
514 }
515 }
516 Ok(result)
517 }
518
519 pub fn skip(&mut self, f: impl FnOnce(&mut Self) -> Result<()>) -> Result<Self> {
522 let start = self.position;
523 f(self)?;
524 let mut ret = self.clone();
525 ret.buffer = &self.buffer[start..self.position];
526 ret.position = 0;
527 ret.original_offset = self.original_offset + start;
528 Ok(ret)
529 }
530
531 pub fn skip_string(&mut self) -> Result<()> {
538 let len = self.read_var_u32()? as usize;
539 if len > MAX_WASM_STRING_SIZE {
540 return Err(BinaryReaderError::new(
541 "string size out of bounds",
542 self.original_position() - 1,
543 ));
544 }
545 self.ensure_has_bytes(len)?;
546 self.position += len;
547 Ok(())
548 }
549
550 #[inline]
556 pub fn read_var_i32(&mut self) -> Result<i32> {
557 let byte = self.read_u8()?;
559 if (byte & 0x80) == 0 {
560 Ok(((byte as i32) << 25) >> 25)
561 } else {
562 self.read_var_i32_big(byte)
563 }
564 }
565
566 fn read_var_i32_big(&mut self, byte: u8) -> Result<i32> {
567 let mut result = (byte & 0x7F) as i32;
568 let mut shift = 7;
569 loop {
570 let byte = self.read_u8()?;
571 result |= ((byte & 0x7F) as i32) << shift;
572 if shift >= 25 {
573 let continuation_bit = (byte & 0x80) != 0;
574 let sign_and_unused_bit = (byte << 1) as i8 >> (32 - shift);
575 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
576 let msg = if continuation_bit {
577 "invalid var_i32: integer representation too long"
578 } else {
579 "invalid var_i32: integer too large"
580 };
581 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
582 }
583 return Ok(result);
584 }
585 shift += 7;
586 if (byte & 0x80) == 0 {
587 break;
588 }
589 }
590 let ashift = 32 - shift;
591 Ok((result << ashift) >> ashift)
592 }
593
594 pub fn read_var_s33(&mut self) -> Result<i64> {
600 let byte = self.read_u8()?;
602 if (byte & 0x80) == 0 {
603 return Ok(((byte as i8) << 1) as i64 >> 1);
604 }
605
606 let mut result = (byte & 0x7F) as i64;
607 let mut shift = 7;
608 loop {
609 let byte = self.read_u8()?;
610 result |= ((byte & 0x7F) as i64) << shift;
611 if shift >= 25 {
612 let continuation_bit = (byte & 0x80) != 0;
613 let sign_and_unused_bit = (byte << 1) as i8 >> (33 - shift);
614 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
615 return Err(BinaryReaderError::new(
616 "invalid var_s33: integer representation too long",
617 self.original_position() - 1,
618 ));
619 }
620 return Ok(result);
621 }
622 shift += 7;
623 if (byte & 0x80) == 0 {
624 break;
625 }
626 }
627 let ashift = 64 - shift;
628 Ok((result << ashift) >> ashift)
629 }
630
631 pub fn read_var_i64(&mut self) -> Result<i64> {
637 let mut result: i64 = 0;
638 let mut shift = 0;
639 loop {
640 let byte = self.read_u8()?;
641 result |= i64::from(byte & 0x7F) << shift;
642 if shift >= 57 {
643 let continuation_bit = (byte & 0x80) != 0;
644 let sign_and_unused_bit = ((byte << 1) as i8) >> (64 - shift);
645 if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
646 let msg = if continuation_bit {
647 "invalid var_i64: integer representation too long"
648 } else {
649 "invalid var_i64: integer too large"
650 };
651 return Err(BinaryReaderError::new(msg, self.original_position() - 1));
652 }
653 return Ok(result);
654 }
655 shift += 7;
656 if (byte & 0x80) == 0 {
657 break;
658 }
659 }
660 let ashift = 64 - shift;
661 Ok((result << ashift) >> ashift)
662 }
663
664 pub fn read_f32(&mut self) -> Result<Ieee32> {
669 let value = self.read_u32()?;
670 Ok(Ieee32(value))
671 }
672
673 pub fn read_f64(&mut self) -> Result<Ieee64> {
678 let value = self.read_u64()?;
679 Ok(Ieee64(value))
680 }
681
682 fn internal_read_string(&mut self, len: usize) -> Result<&'a str> {
684 let bytes = self.read_bytes(len)?;
685 str::from_utf8(bytes).map_err(|_| {
686 BinaryReaderError::new("malformed UTF-8 encoding", self.original_position() - 1)
687 })
688 }
689
690 pub fn read_string(&mut self) -> Result<&'a str> {
698 let len = self.read_var_u32()? as usize;
699 if len > MAX_WASM_STRING_SIZE {
700 return Err(BinaryReaderError::new(
701 "string size out of bounds",
702 self.original_position() - 1,
703 ));
704 }
705 return self.internal_read_string(len);
706 }
707
708 pub fn read_unlimited_string(&mut self) -> Result<&'a str> {
714 let len = self.read_var_u32()? as usize;
715 return self.internal_read_string(len);
716 }
717
718 #[cold]
719 pub(crate) fn invalid_leading_byte<T>(&self, byte: u8, desc: &str) -> Result<T> {
720 Err(Self::invalid_leading_byte_error(
721 byte,
722 desc,
723 self.original_position() - 1,
724 ))
725 }
726
727 pub(crate) fn invalid_leading_byte_error(
728 byte: u8,
729 desc: &str,
730 offset: usize,
731 ) -> BinaryReaderError {
732 format_err!(offset, "invalid leading byte (0x{byte:x}) for {desc}")
733 }
734
735 pub(crate) fn peek(&self) -> Result<u8> {
736 self.ensure_has_byte()?;
737 Ok(self.buffer[self.position])
738 }
739
740 pub(crate) fn peek_bytes(&self, len: usize) -> Result<&[u8]> {
741 self.ensure_has_bytes(len)?;
742 Ok(&self.buffer[self.position..(self.position + len)])
743 }
744
745 pub(crate) fn read_block_type(&mut self) -> Result<BlockType> {
746 let b = self.peek()?;
747
748 if b & 0x80 == 0 && b & 0x40 != 0 {
765 if b == 0x40 {
766 self.position += 1;
767 return Ok(BlockType::Empty);
768 }
769 return Ok(BlockType::Type(self.read()?));
770 }
771
772 let idx = self.read_var_s33()?;
774 match u32::try_from(idx) {
775 Ok(idx) => Ok(BlockType::FuncType(idx)),
776 Err(_) => {
777 return Err(BinaryReaderError::new(
778 "invalid function type",
779 self.original_position(),
780 ));
781 }
782 }
783 }
784
785 pub fn is_end_then_eof(&self) -> bool {
788 self.remaining_buffer() == &[0x0b]
789 }
790
791 pub(crate) fn read_header_version(&mut self) -> Result<u32> {
792 let magic_number = self.read_bytes(4)?;
793 if magic_number != WASM_MAGIC_NUMBER {
794 return Err(BinaryReaderError::new(
795 format!(
796 "magic header not detected: bad magic number - expected={WASM_MAGIC_NUMBER:#x?} actual={magic_number:#x?}"
797 ),
798 self.original_position() - 4,
799 ));
800 }
801 self.read_u32()
802 }
803}
804
805macro_rules! define_feature_accessor {
808 ($feature:ident = $default:expr) => {
809 impl BinaryReader<'_> {
810 #[inline]
811 #[allow(dead_code)]
812 pub(crate) fn $feature(&self) -> bool {
813 #[cfg(feature = "features")]
814 {
815 self.features.$feature()
816 }
817 #[cfg(not(feature = "features"))]
818 {
819 true
820 }
821 }
822 }
823 };
824}
825
826super::features::foreach_wasm_feature!(define_feature_accessor);
827
828pub struct BinaryReaderIter<'a, 'me, T: FromReader<'a>> {
830 remaining: usize,
831 pub(crate) reader: &'me mut BinaryReader<'a>,
832 _marker: marker::PhantomData<T>,
833}
834
835impl<'a, T> Iterator for BinaryReaderIter<'a, '_, T>
836where
837 T: FromReader<'a>,
838{
839 type Item = Result<T>;
840
841 fn next(&mut self) -> Option<Result<T>> {
842 if self.remaining == 0 {
843 None
844 } else {
845 let ret = self.reader.read::<T>();
846 if ret.is_err() {
847 self.remaining = 0;
848 } else {
849 self.remaining -= 1;
850 }
851 Some(ret)
852 }
853 }
854
855 fn size_hint(&self) -> (usize, Option<usize>) {
856 (self.remaining, Some(self.remaining))
857 }
858}
859
860impl<'a, T> Drop for BinaryReaderIter<'a, '_, T>
861where
862 T: FromReader<'a>,
863{
864 fn drop(&mut self) {
865 while self.next().is_some() {
866 }
868 }
869}
870
871impl<'a> BinaryReader<'a> {
872 pub fn finish_expression(&self, stack: &impl FrameStack) -> Result<()> {
875 if stack.current_frame().is_some() {
876 bail!(
877 self.original_position(),
878 "control frames remain at end of function body or expression"
879 );
880 }
881 if !self.eof() {
882 bail!(
883 self.original_position(),
884 "unexpected data at the end of operators"
885 );
886 }
887 Ok(())
888 }
889
890 #[inline]
891 fn expect_frame(&mut self, stack: &impl FrameStack, k: FrameKind, found: &str) -> Result<()> {
892 if stack.current_frame() == Some(k) {
893 return Ok(());
894 }
895 bail!(
896 self.original_position(),
897 "`{}` found outside `{:?}` block",
898 found,
899 k
900 );
901 }
902
903 pub fn visit_operator<T>(&mut self, visitor: &mut T) -> Result<<T as VisitOperator<'a>>::Output>
909 where
910 T: VisitOperator<'a> + FrameStack,
911 {
912 if visitor.current_frame().is_none() {
913 bail!(
914 self.original_position(),
915 "operators remaining after end of function body or expression"
916 );
917 }
918 let pos = self.original_position();
919 let code = self.read_u8()?;
920 Ok(match code {
921 0x00 => visitor.visit_unreachable(),
922 0x01 => visitor.visit_nop(),
923 0x02 => visitor.visit_block(self.read_block_type()?),
924 0x03 => visitor.visit_loop(self.read_block_type()?),
925 0x04 => visitor.visit_if(self.read_block_type()?),
926 0x05 => {
927 self.expect_frame(visitor, FrameKind::If, "else")?;
928 visitor.visit_else()
929 }
930 0x06 => {
931 if !self.legacy_exceptions() {
932 bail!(
933 pos,
934 "legacy_exceptions feature required for try instruction"
935 );
936 }
937 visitor.visit_try(self.read_block_type()?)
938 }
939 0x07 => {
940 if !self.legacy_exceptions() {
941 bail!(
942 pos,
943 "legacy_exceptions feature required for catch instruction"
944 );
945 }
946 match self.expect_frame(visitor, FrameKind::LegacyCatch, "catch") {
947 Ok(()) => (),
948 Err(_) => self.expect_frame(visitor, FrameKind::LegacyTry, "catch")?,
949 }
950 visitor.visit_catch(self.read_var_u32()?)
951 }
952 0x08 => visitor.visit_throw(self.read_var_u32()?),
953 0x09 => visitor.visit_rethrow(self.read_var_u32()?),
954 0x0a => visitor.visit_throw_ref(),
955 0x0b => visitor.visit_end(),
956 0x0c => visitor.visit_br(self.read_var_u32()?),
957 0x0d => visitor.visit_br_if(self.read_var_u32()?),
958 0x0e => visitor.visit_br_table(self.read_br_table()?),
959 0x0f => visitor.visit_return(),
960 0x10 => visitor.visit_call(self.read_var_u32()?),
961 0x11 => {
962 let index = self.read_var_u32()?;
963 let table = self.read_call_indirect_table_immediate()?;
964 visitor.visit_call_indirect(index, table)
965 }
966 0x12 => visitor.visit_return_call(self.read_var_u32()?),
967 0x13 => visitor.visit_return_call_indirect(self.read_var_u32()?, self.read_var_u32()?),
968 0x14 => visitor.visit_call_ref(self.read()?),
969 0x15 => visitor.visit_return_call_ref(self.read()?),
970 0x18 => {
971 self.expect_frame(visitor, FrameKind::LegacyTry, "delegate")?;
972 visitor.visit_delegate(self.read_var_u32()?)
973 }
974 0x19 => {
975 if !self.legacy_exceptions() {
976 bail!(
977 pos,
978 "legacy_exceptions feature required for catch_all instruction"
979 );
980 }
981 match self.expect_frame(visitor, FrameKind::LegacyCatch, "catch_all") {
982 Ok(()) => (),
983 Err(_) => self.expect_frame(visitor, FrameKind::LegacyTry, "catch_all")?,
984 }
985 visitor.visit_catch_all()
986 }
987 0x1a => visitor.visit_drop(),
988 0x1b => visitor.visit_select(),
989 0x1c => {
990 let result_count = self.read_size(MAX_WASM_SELECT_RESULT_SIZE, "select types")?;
991 if result_count == 1 {
992 visitor.visit_typed_select(self.read()?)
993 } else {
994 let mut results = Vec::new();
995 results.reserve_exact(result_count);
996 for _ in 0..result_count {
997 results.push(self.read()?);
998 }
999 visitor.visit_typed_select_multi(results)
1000 }
1001 }
1002 0x1f => visitor.visit_try_table(self.read()?),
1003
1004 0x20 => visitor.visit_local_get(self.read_var_u32()?),
1005 0x21 => visitor.visit_local_set(self.read_var_u32()?),
1006 0x22 => visitor.visit_local_tee(self.read_var_u32()?),
1007 0x23 => visitor.visit_global_get(self.read_var_u32()?),
1008 0x24 => visitor.visit_global_set(self.read_var_u32()?),
1009 0x25 => visitor.visit_table_get(self.read_var_u32()?),
1010 0x26 => visitor.visit_table_set(self.read_var_u32()?),
1011
1012 0x28 => visitor.visit_i32_load(self.read_memarg(2)?),
1013 0x29 => visitor.visit_i64_load(self.read_memarg(3)?),
1014 0x2a => visitor.visit_f32_load(self.read_memarg(2)?),
1015 0x2b => visitor.visit_f64_load(self.read_memarg(3)?),
1016 0x2c => visitor.visit_i32_load8_s(self.read_memarg(0)?),
1017 0x2d => visitor.visit_i32_load8_u(self.read_memarg(0)?),
1018 0x2e => visitor.visit_i32_load16_s(self.read_memarg(1)?),
1019 0x2f => visitor.visit_i32_load16_u(self.read_memarg(1)?),
1020 0x30 => visitor.visit_i64_load8_s(self.read_memarg(0)?),
1021 0x31 => visitor.visit_i64_load8_u(self.read_memarg(0)?),
1022 0x32 => visitor.visit_i64_load16_s(self.read_memarg(1)?),
1023 0x33 => visitor.visit_i64_load16_u(self.read_memarg(1)?),
1024 0x34 => visitor.visit_i64_load32_s(self.read_memarg(2)?),
1025 0x35 => visitor.visit_i64_load32_u(self.read_memarg(2)?),
1026 0x36 => visitor.visit_i32_store(self.read_memarg(2)?),
1027 0x37 => visitor.visit_i64_store(self.read_memarg(3)?),
1028 0x38 => visitor.visit_f32_store(self.read_memarg(2)?),
1029 0x39 => visitor.visit_f64_store(self.read_memarg(3)?),
1030 0x3a => visitor.visit_i32_store8(self.read_memarg(0)?),
1031 0x3b => visitor.visit_i32_store16(self.read_memarg(1)?),
1032 0x3c => visitor.visit_i64_store8(self.read_memarg(0)?),
1033 0x3d => visitor.visit_i64_store16(self.read_memarg(1)?),
1034 0x3e => visitor.visit_i64_store32(self.read_memarg(2)?),
1035 0x3f => {
1036 let mem = self.read_memory_index_or_zero_if_not_multi_memory()?;
1037 visitor.visit_memory_size(mem)
1038 }
1039 0x40 => {
1040 let mem = self.read_memory_index_or_zero_if_not_multi_memory()?;
1041 visitor.visit_memory_grow(mem)
1042 }
1043
1044 0x41 => visitor.visit_i32_const(self.read_var_i32()?),
1045 0x42 => visitor.visit_i64_const(self.read_var_i64()?),
1046 0x43 => visitor.visit_f32_const(self.read_f32()?),
1047 0x44 => visitor.visit_f64_const(self.read_f64()?),
1048
1049 0x45 => visitor.visit_i32_eqz(),
1050 0x46 => visitor.visit_i32_eq(),
1051 0x47 => visitor.visit_i32_ne(),
1052 0x48 => visitor.visit_i32_lt_s(),
1053 0x49 => visitor.visit_i32_lt_u(),
1054 0x4a => visitor.visit_i32_gt_s(),
1055 0x4b => visitor.visit_i32_gt_u(),
1056 0x4c => visitor.visit_i32_le_s(),
1057 0x4d => visitor.visit_i32_le_u(),
1058 0x4e => visitor.visit_i32_ge_s(),
1059 0x4f => visitor.visit_i32_ge_u(),
1060 0x50 => visitor.visit_i64_eqz(),
1061 0x51 => visitor.visit_i64_eq(),
1062 0x52 => visitor.visit_i64_ne(),
1063 0x53 => visitor.visit_i64_lt_s(),
1064 0x54 => visitor.visit_i64_lt_u(),
1065 0x55 => visitor.visit_i64_gt_s(),
1066 0x56 => visitor.visit_i64_gt_u(),
1067 0x57 => visitor.visit_i64_le_s(),
1068 0x58 => visitor.visit_i64_le_u(),
1069 0x59 => visitor.visit_i64_ge_s(),
1070 0x5a => visitor.visit_i64_ge_u(),
1071 0x5b => visitor.visit_f32_eq(),
1072 0x5c => visitor.visit_f32_ne(),
1073 0x5d => visitor.visit_f32_lt(),
1074 0x5e => visitor.visit_f32_gt(),
1075 0x5f => visitor.visit_f32_le(),
1076 0x60 => visitor.visit_f32_ge(),
1077 0x61 => visitor.visit_f64_eq(),
1078 0x62 => visitor.visit_f64_ne(),
1079 0x63 => visitor.visit_f64_lt(),
1080 0x64 => visitor.visit_f64_gt(),
1081 0x65 => visitor.visit_f64_le(),
1082 0x66 => visitor.visit_f64_ge(),
1083 0x67 => visitor.visit_i32_clz(),
1084 0x68 => visitor.visit_i32_ctz(),
1085 0x69 => visitor.visit_i32_popcnt(),
1086 0x6a => visitor.visit_i32_add(),
1087 0x6b => visitor.visit_i32_sub(),
1088 0x6c => visitor.visit_i32_mul(),
1089 0x6d => visitor.visit_i32_div_s(),
1090 0x6e => visitor.visit_i32_div_u(),
1091 0x6f => visitor.visit_i32_rem_s(),
1092 0x70 => visitor.visit_i32_rem_u(),
1093 0x71 => visitor.visit_i32_and(),
1094 0x72 => visitor.visit_i32_or(),
1095 0x73 => visitor.visit_i32_xor(),
1096 0x74 => visitor.visit_i32_shl(),
1097 0x75 => visitor.visit_i32_shr_s(),
1098 0x76 => visitor.visit_i32_shr_u(),
1099 0x77 => visitor.visit_i32_rotl(),
1100 0x78 => visitor.visit_i32_rotr(),
1101 0x79 => visitor.visit_i64_clz(),
1102 0x7a => visitor.visit_i64_ctz(),
1103 0x7b => visitor.visit_i64_popcnt(),
1104 0x7c => visitor.visit_i64_add(),
1105 0x7d => visitor.visit_i64_sub(),
1106 0x7e => visitor.visit_i64_mul(),
1107 0x7f => visitor.visit_i64_div_s(),
1108 0x80 => visitor.visit_i64_div_u(),
1109 0x81 => visitor.visit_i64_rem_s(),
1110 0x82 => visitor.visit_i64_rem_u(),
1111 0x83 => visitor.visit_i64_and(),
1112 0x84 => visitor.visit_i64_or(),
1113 0x85 => visitor.visit_i64_xor(),
1114 0x86 => visitor.visit_i64_shl(),
1115 0x87 => visitor.visit_i64_shr_s(),
1116 0x88 => visitor.visit_i64_shr_u(),
1117 0x89 => visitor.visit_i64_rotl(),
1118 0x8a => visitor.visit_i64_rotr(),
1119 0x8b => visitor.visit_f32_abs(),
1120 0x8c => visitor.visit_f32_neg(),
1121 0x8d => visitor.visit_f32_ceil(),
1122 0x8e => visitor.visit_f32_floor(),
1123 0x8f => visitor.visit_f32_trunc(),
1124 0x90 => visitor.visit_f32_nearest(),
1125 0x91 => visitor.visit_f32_sqrt(),
1126 0x92 => visitor.visit_f32_add(),
1127 0x93 => visitor.visit_f32_sub(),
1128 0x94 => visitor.visit_f32_mul(),
1129 0x95 => visitor.visit_f32_div(),
1130 0x96 => visitor.visit_f32_min(),
1131 0x97 => visitor.visit_f32_max(),
1132 0x98 => visitor.visit_f32_copysign(),
1133 0x99 => visitor.visit_f64_abs(),
1134 0x9a => visitor.visit_f64_neg(),
1135 0x9b => visitor.visit_f64_ceil(),
1136 0x9c => visitor.visit_f64_floor(),
1137 0x9d => visitor.visit_f64_trunc(),
1138 0x9e => visitor.visit_f64_nearest(),
1139 0x9f => visitor.visit_f64_sqrt(),
1140 0xa0 => visitor.visit_f64_add(),
1141 0xa1 => visitor.visit_f64_sub(),
1142 0xa2 => visitor.visit_f64_mul(),
1143 0xa3 => visitor.visit_f64_div(),
1144 0xa4 => visitor.visit_f64_min(),
1145 0xa5 => visitor.visit_f64_max(),
1146 0xa6 => visitor.visit_f64_copysign(),
1147 0xa7 => visitor.visit_i32_wrap_i64(),
1148 0xa8 => visitor.visit_i32_trunc_f32_s(),
1149 0xa9 => visitor.visit_i32_trunc_f32_u(),
1150 0xaa => visitor.visit_i32_trunc_f64_s(),
1151 0xab => visitor.visit_i32_trunc_f64_u(),
1152 0xac => visitor.visit_i64_extend_i32_s(),
1153 0xad => visitor.visit_i64_extend_i32_u(),
1154 0xae => visitor.visit_i64_trunc_f32_s(),
1155 0xaf => visitor.visit_i64_trunc_f32_u(),
1156 0xb0 => visitor.visit_i64_trunc_f64_s(),
1157 0xb1 => visitor.visit_i64_trunc_f64_u(),
1158 0xb2 => visitor.visit_f32_convert_i32_s(),
1159 0xb3 => visitor.visit_f32_convert_i32_u(),
1160 0xb4 => visitor.visit_f32_convert_i64_s(),
1161 0xb5 => visitor.visit_f32_convert_i64_u(),
1162 0xb6 => visitor.visit_f32_demote_f64(),
1163 0xb7 => visitor.visit_f64_convert_i32_s(),
1164 0xb8 => visitor.visit_f64_convert_i32_u(),
1165 0xb9 => visitor.visit_f64_convert_i64_s(),
1166 0xba => visitor.visit_f64_convert_i64_u(),
1167 0xbb => visitor.visit_f64_promote_f32(),
1168 0xbc => visitor.visit_i32_reinterpret_f32(),
1169 0xbd => visitor.visit_i64_reinterpret_f64(),
1170 0xbe => visitor.visit_f32_reinterpret_i32(),
1171 0xbf => visitor.visit_f64_reinterpret_i64(),
1172
1173 0xc0 => visitor.visit_i32_extend8_s(),
1174 0xc1 => visitor.visit_i32_extend16_s(),
1175 0xc2 => visitor.visit_i64_extend8_s(),
1176 0xc3 => visitor.visit_i64_extend16_s(),
1177 0xc4 => visitor.visit_i64_extend32_s(),
1178
1179 0xd0 => visitor.visit_ref_null(self.read()?),
1180 0xd1 => visitor.visit_ref_is_null(),
1181 0xd2 => visitor.visit_ref_func(self.read_var_u32()?),
1182 0xd3 => visitor.visit_ref_eq(),
1183 0xd4 => visitor.visit_ref_as_non_null(),
1184 0xd5 => visitor.visit_br_on_null(self.read_var_u32()?),
1185 0xd6 => visitor.visit_br_on_non_null(self.read_var_u32()?),
1186
1187 0xe0 => visitor.visit_cont_new(self.read_var_u32()?),
1188 0xe1 => visitor.visit_cont_bind(self.read_var_u32()?, self.read_var_u32()?),
1189 0xe2 => visitor.visit_suspend(self.read_var_u32()?),
1190 0xe3 => visitor.visit_resume(self.read_var_u32()?, self.read()?),
1191 0xe4 => {
1192 visitor.visit_resume_throw(self.read_var_u32()?, self.read_var_u32()?, self.read()?)
1193 }
1194 0xe5 => visitor.visit_switch(self.read_var_u32()?, self.read_var_u32()?),
1195
1196 0xfb => self.visit_0xfb_operator(pos, visitor)?,
1197 0xfc => self.visit_0xfc_operator(pos, visitor)?,
1198 0xfd => {
1199 #[cfg(feature = "simd")]
1200 if let Some(mut visitor) = visitor.simd_visitor() {
1201 return self.visit_0xfd_operator(pos, &mut visitor);
1202 }
1203 bail!(pos, "unexpected SIMD opcode: 0x{code:x}")
1204 }
1205 0xfe => self.visit_0xfe_operator(pos, visitor)?,
1206
1207 _ => bail!(pos, "illegal opcode: 0x{code:x}"),
1208 })
1209 }
1210
1211 fn visit_0xfb_operator<T>(
1212 &mut self,
1213 pos: usize,
1214 visitor: &mut T,
1215 ) -> Result<<T as VisitOperator<'a>>::Output>
1216 where
1217 T: VisitOperator<'a>,
1218 {
1219 let code = self.read_var_u32()?;
1220 Ok(match code {
1221 0x0 => {
1222 let type_index = self.read_var_u32()?;
1223 visitor.visit_struct_new(type_index)
1224 }
1225 0x01 => {
1226 let type_index = self.read_var_u32()?;
1227 visitor.visit_struct_new_default(type_index)
1228 }
1229 0x02 => {
1230 let type_index = self.read_var_u32()?;
1231 let field_index = self.read_var_u32()?;
1232 visitor.visit_struct_get(type_index, field_index)
1233 }
1234 0x03 => {
1235 let type_index = self.read_var_u32()?;
1236 let field_index = self.read_var_u32()?;
1237 visitor.visit_struct_get_s(type_index, field_index)
1238 }
1239 0x04 => {
1240 let type_index = self.read_var_u32()?;
1241 let field_index = self.read_var_u32()?;
1242 visitor.visit_struct_get_u(type_index, field_index)
1243 }
1244 0x05 => {
1245 let type_index = self.read_var_u32()?;
1246 let field_index = self.read_var_u32()?;
1247 visitor.visit_struct_set(type_index, field_index)
1248 }
1249 0x06 => {
1250 let type_index = self.read_var_u32()?;
1251 visitor.visit_array_new(type_index)
1252 }
1253 0x07 => {
1254 let type_index = self.read_var_u32()?;
1255 visitor.visit_array_new_default(type_index)
1256 }
1257 0x08 => {
1258 let type_index = self.read_var_u32()?;
1259 let n = self.read_var_u32()?;
1260 visitor.visit_array_new_fixed(type_index, n)
1261 }
1262 0x09 => {
1263 let type_index = self.read_var_u32()?;
1264 let data_index = self.read_var_u32()?;
1265 visitor.visit_array_new_data(type_index, data_index)
1266 }
1267 0x0a => {
1268 let type_index = self.read_var_u32()?;
1269 let elem_index = self.read_var_u32()?;
1270 visitor.visit_array_new_elem(type_index, elem_index)
1271 }
1272 0x0b => {
1273 let type_index = self.read_var_u32()?;
1274 visitor.visit_array_get(type_index)
1275 }
1276 0x0c => {
1277 let type_index = self.read_var_u32()?;
1278 visitor.visit_array_get_s(type_index)
1279 }
1280 0x0d => {
1281 let type_index = self.read_var_u32()?;
1282 visitor.visit_array_get_u(type_index)
1283 }
1284 0x0e => {
1285 let type_index = self.read_var_u32()?;
1286 visitor.visit_array_set(type_index)
1287 }
1288 0x0f => visitor.visit_array_len(),
1289 0x10 => {
1290 let type_index = self.read_var_u32()?;
1291 visitor.visit_array_fill(type_index)
1292 }
1293 0x11 => {
1294 let type_index_dst = self.read_var_u32()?;
1295 let type_index_src = self.read_var_u32()?;
1296 visitor.visit_array_copy(type_index_dst, type_index_src)
1297 }
1298 0x12 => {
1299 let type_index = self.read_var_u32()?;
1300 let data_index = self.read_var_u32()?;
1301 visitor.visit_array_init_data(type_index, data_index)
1302 }
1303 0x13 => {
1304 let type_index = self.read_var_u32()?;
1305 let elem_index = self.read_var_u32()?;
1306 visitor.visit_array_init_elem(type_index, elem_index)
1307 }
1308 0x14 => visitor.visit_ref_test_non_null(self.read()?),
1309 0x15 => visitor.visit_ref_test_nullable(self.read()?),
1310 0x16 => visitor.visit_ref_cast_non_null(self.read()?),
1311 0x17 => visitor.visit_ref_cast_nullable(self.read()?),
1312 0x18 => {
1313 let pos = self.original_position();
1314 let cast_flags = self.read_u8()?;
1315 let relative_depth = self.read_var_u32()?;
1316 let (from_type_nullable, to_type_nullable) = match cast_flags {
1317 0b00 => (false, false),
1318 0b01 => (true, false),
1319 0b10 => (false, true),
1320 0b11 => (true, true),
1321 _ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
1322 };
1323 let from_heap_type = self.read()?;
1324 let from_ref_type =
1325 RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
1326 format_err!(pos, "implementation error: type index too large")
1327 })?;
1328 let to_heap_type = self.read()?;
1329 let to_ref_type =
1330 RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
1331 format_err!(pos, "implementation error: type index too large")
1332 })?;
1333 visitor.visit_br_on_cast(relative_depth, from_ref_type, to_ref_type)
1334 }
1335 0x19 => {
1336 let pos = self.original_position();
1337 let cast_flags = self.read_u8()?;
1338 let relative_depth = self.read_var_u32()?;
1339 let (from_type_nullable, to_type_nullable) = match cast_flags {
1340 0 => (false, false),
1341 1 => (true, false),
1342 2 => (false, true),
1343 3 => (true, true),
1344 _ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
1345 };
1346 let from_heap_type = self.read()?;
1347 let from_ref_type =
1348 RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
1349 format_err!(pos, "implementation error: type index too large")
1350 })?;
1351 let to_heap_type = self.read()?;
1352 let to_ref_type =
1353 RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
1354 format_err!(pos, "implementation error: type index too large")
1355 })?;
1356 visitor.visit_br_on_cast_fail(relative_depth, from_ref_type, to_ref_type)
1357 }
1358
1359 0x1a => visitor.visit_any_convert_extern(),
1360 0x1b => visitor.visit_extern_convert_any(),
1361
1362 0x1c => visitor.visit_ref_i31(),
1363 0x1d => visitor.visit_i31_get_s(),
1364 0x1e => visitor.visit_i31_get_u(),
1365
1366 0x20 => {
1367 let type_index = self.read_var_u32()?;
1368 visitor.visit_struct_new_desc(type_index)
1369 }
1370 0x21 => {
1371 let type_index = self.read_var_u32()?;
1372 visitor.visit_struct_new_default_desc(type_index)
1373 }
1374 0x22 => visitor.visit_ref_get_desc(self.read()?),
1375 0x23 => visitor.visit_ref_cast_desc_non_null(self.read()?),
1376 0x24 => visitor.visit_ref_cast_desc_nullable(self.read()?),
1377 0x25 => {
1378 let pos = self.original_position();
1379 let cast_flags = self.read_u8()?;
1380 let relative_depth = self.read_var_u32()?;
1381 let (from_type_nullable, to_type_nullable) = match cast_flags {
1382 0b00 => (false, false),
1383 0b01 => (true, false),
1384 0b10 => (false, true),
1385 0b11 => (true, true),
1386 _ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
1387 };
1388 let from_heap_type = self.read()?;
1389 let from_ref_type =
1390 RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
1391 format_err!(pos, "implementation error: type index too large")
1392 })?;
1393 let to_heap_type = self.read()?;
1394 let to_ref_type =
1395 RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
1396 format_err!(pos, "implementation error: type index too large")
1397 })?;
1398 visitor.visit_br_on_cast_desc(relative_depth, from_ref_type, to_ref_type)
1399 }
1400 0x26 => {
1401 let pos = self.original_position();
1402 let cast_flags = self.read_u8()?;
1403 let relative_depth = self.read_var_u32()?;
1404 let (from_type_nullable, to_type_nullable) = match cast_flags {
1405 0 => (false, false),
1406 1 => (true, false),
1407 2 => (false, true),
1408 3 => (true, true),
1409 _ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
1410 };
1411 let from_heap_type = self.read()?;
1412 let from_ref_type =
1413 RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
1414 format_err!(pos, "implementation error: type index too large")
1415 })?;
1416 let to_heap_type = self.read()?;
1417 let to_ref_type =
1418 RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
1419 format_err!(pos, "implementation error: type index too large")
1420 })?;
1421 visitor.visit_br_on_cast_desc_fail(relative_depth, from_ref_type, to_ref_type)
1422 }
1423
1424 _ => bail!(pos, "unknown 0xfb subopcode: 0x{code:x}"),
1425 })
1426 }
1427
1428 fn visit_0xfc_operator<T>(
1429 &mut self,
1430 pos: usize,
1431 visitor: &mut T,
1432 ) -> Result<<T as VisitOperator<'a>>::Output>
1433 where
1434 T: VisitOperator<'a>,
1435 {
1436 let code = self.read_var_u32()?;
1437 Ok(match code {
1438 0x00 => visitor.visit_i32_trunc_sat_f32_s(),
1439 0x01 => visitor.visit_i32_trunc_sat_f32_u(),
1440 0x02 => visitor.visit_i32_trunc_sat_f64_s(),
1441 0x03 => visitor.visit_i32_trunc_sat_f64_u(),
1442 0x04 => visitor.visit_i64_trunc_sat_f32_s(),
1443 0x05 => visitor.visit_i64_trunc_sat_f32_u(),
1444 0x06 => visitor.visit_i64_trunc_sat_f64_s(),
1445 0x07 => visitor.visit_i64_trunc_sat_f64_u(),
1446
1447 0x08 => {
1448 let segment = self.read_var_u32()?;
1449 let mem = self.read_var_u32()?;
1450 visitor.visit_memory_init(segment, mem)
1451 }
1452 0x09 => {
1453 let segment = self.read_var_u32()?;
1454 visitor.visit_data_drop(segment)
1455 }
1456 0x0a => {
1457 let dst = self.read_var_u32()?;
1458 let src = self.read_var_u32()?;
1459 visitor.visit_memory_copy(dst, src)
1460 }
1461 0x0b => {
1462 let mem = self.read_var_u32()?;
1463 visitor.visit_memory_fill(mem)
1464 }
1465 0x0c => {
1466 let segment = self.read_var_u32()?;
1467 let table = self.read_var_u32()?;
1468 visitor.visit_table_init(segment, table)
1469 }
1470 0x0d => {
1471 let segment = self.read_var_u32()?;
1472 visitor.visit_elem_drop(segment)
1473 }
1474 0x0e => {
1475 let dst_table = self.read_var_u32()?;
1476 let src_table = self.read_var_u32()?;
1477 visitor.visit_table_copy(dst_table, src_table)
1478 }
1479
1480 0x0f => {
1481 let table = self.read_var_u32()?;
1482 visitor.visit_table_grow(table)
1483 }
1484 0x10 => {
1485 let table = self.read_var_u32()?;
1486 visitor.visit_table_size(table)
1487 }
1488
1489 0x11 => {
1490 let table = self.read_var_u32()?;
1491 visitor.visit_table_fill(table)
1492 }
1493
1494 0x12 => {
1495 let mem = self.read_var_u32()?;
1496 visitor.visit_memory_discard(mem)
1497 }
1498
1499 0x13 => visitor.visit_i64_add128(),
1500 0x14 => visitor.visit_i64_sub128(),
1501 0x15 => visitor.visit_i64_mul_wide_s(),
1502 0x16 => visitor.visit_i64_mul_wide_u(),
1503
1504 _ => bail!(pos, "unknown 0xfc subopcode: 0x{code:x}"),
1505 })
1506 }
1507
1508 #[cfg(feature = "simd")]
1509 pub(super) fn visit_0xfd_operator<T>(
1510 &mut self,
1511 pos: usize,
1512 visitor: &mut T,
1513 ) -> Result<<T as VisitOperator<'a>>::Output>
1514 where
1515 T: VisitSimdOperator<'a>,
1516 {
1517 let code = self.read_var_u32()?;
1518 Ok(match code {
1519 0x00 => visitor.visit_v128_load(self.read_memarg(4)?),
1520 0x01 => visitor.visit_v128_load8x8_s(self.read_memarg(3)?),
1521 0x02 => visitor.visit_v128_load8x8_u(self.read_memarg(3)?),
1522 0x03 => visitor.visit_v128_load16x4_s(self.read_memarg(3)?),
1523 0x04 => visitor.visit_v128_load16x4_u(self.read_memarg(3)?),
1524 0x05 => visitor.visit_v128_load32x2_s(self.read_memarg(3)?),
1525 0x06 => visitor.visit_v128_load32x2_u(self.read_memarg(3)?),
1526 0x07 => visitor.visit_v128_load8_splat(self.read_memarg(0)?),
1527 0x08 => visitor.visit_v128_load16_splat(self.read_memarg(1)?),
1528 0x09 => visitor.visit_v128_load32_splat(self.read_memarg(2)?),
1529 0x0a => visitor.visit_v128_load64_splat(self.read_memarg(3)?),
1530
1531 0x0b => visitor.visit_v128_store(self.read_memarg(4)?),
1532 0x0c => visitor.visit_v128_const(self.read_v128()?),
1533 0x0d => {
1534 let mut lanes: [u8; 16] = [0; 16];
1535 for lane in &mut lanes {
1536 *lane = self.read_lane_index()?
1537 }
1538 visitor.visit_i8x16_shuffle(lanes)
1539 }
1540
1541 0x0e => visitor.visit_i8x16_swizzle(),
1542 0x0f => visitor.visit_i8x16_splat(),
1543 0x10 => visitor.visit_i16x8_splat(),
1544 0x11 => visitor.visit_i32x4_splat(),
1545 0x12 => visitor.visit_i64x2_splat(),
1546 0x13 => visitor.visit_f32x4_splat(),
1547 0x14 => visitor.visit_f64x2_splat(),
1548
1549 0x15 => visitor.visit_i8x16_extract_lane_s(self.read_lane_index()?),
1550 0x16 => visitor.visit_i8x16_extract_lane_u(self.read_lane_index()?),
1551 0x17 => visitor.visit_i8x16_replace_lane(self.read_lane_index()?),
1552 0x18 => visitor.visit_i16x8_extract_lane_s(self.read_lane_index()?),
1553 0x19 => visitor.visit_i16x8_extract_lane_u(self.read_lane_index()?),
1554 0x1a => visitor.visit_i16x8_replace_lane(self.read_lane_index()?),
1555 0x1b => visitor.visit_i32x4_extract_lane(self.read_lane_index()?),
1556
1557 0x1c => visitor.visit_i32x4_replace_lane(self.read_lane_index()?),
1558 0x1d => visitor.visit_i64x2_extract_lane(self.read_lane_index()?),
1559 0x1e => visitor.visit_i64x2_replace_lane(self.read_lane_index()?),
1560 0x1f => visitor.visit_f32x4_extract_lane(self.read_lane_index()?),
1561 0x20 => visitor.visit_f32x4_replace_lane(self.read_lane_index()?),
1562 0x21 => visitor.visit_f64x2_extract_lane(self.read_lane_index()?),
1563 0x22 => visitor.visit_f64x2_replace_lane(self.read_lane_index()?),
1564
1565 0x23 => visitor.visit_i8x16_eq(),
1566 0x24 => visitor.visit_i8x16_ne(),
1567 0x25 => visitor.visit_i8x16_lt_s(),
1568 0x26 => visitor.visit_i8x16_lt_u(),
1569 0x27 => visitor.visit_i8x16_gt_s(),
1570 0x28 => visitor.visit_i8x16_gt_u(),
1571 0x29 => visitor.visit_i8x16_le_s(),
1572 0x2a => visitor.visit_i8x16_le_u(),
1573 0x2b => visitor.visit_i8x16_ge_s(),
1574 0x2c => visitor.visit_i8x16_ge_u(),
1575 0x2d => visitor.visit_i16x8_eq(),
1576 0x2e => visitor.visit_i16x8_ne(),
1577 0x2f => visitor.visit_i16x8_lt_s(),
1578 0x30 => visitor.visit_i16x8_lt_u(),
1579 0x31 => visitor.visit_i16x8_gt_s(),
1580 0x32 => visitor.visit_i16x8_gt_u(),
1581 0x33 => visitor.visit_i16x8_le_s(),
1582 0x34 => visitor.visit_i16x8_le_u(),
1583 0x35 => visitor.visit_i16x8_ge_s(),
1584 0x36 => visitor.visit_i16x8_ge_u(),
1585 0x37 => visitor.visit_i32x4_eq(),
1586 0x38 => visitor.visit_i32x4_ne(),
1587 0x39 => visitor.visit_i32x4_lt_s(),
1588 0x3a => visitor.visit_i32x4_lt_u(),
1589 0x3b => visitor.visit_i32x4_gt_s(),
1590 0x3c => visitor.visit_i32x4_gt_u(),
1591 0x3d => visitor.visit_i32x4_le_s(),
1592 0x3e => visitor.visit_i32x4_le_u(),
1593 0x3f => visitor.visit_i32x4_ge_s(),
1594 0x40 => visitor.visit_i32x4_ge_u(),
1595 0x41 => visitor.visit_f32x4_eq(),
1596 0x42 => visitor.visit_f32x4_ne(),
1597 0x43 => visitor.visit_f32x4_lt(),
1598 0x44 => visitor.visit_f32x4_gt(),
1599 0x45 => visitor.visit_f32x4_le(),
1600 0x46 => visitor.visit_f32x4_ge(),
1601 0x47 => visitor.visit_f64x2_eq(),
1602 0x48 => visitor.visit_f64x2_ne(),
1603 0x49 => visitor.visit_f64x2_lt(),
1604 0x4a => visitor.visit_f64x2_gt(),
1605 0x4b => visitor.visit_f64x2_le(),
1606 0x4c => visitor.visit_f64x2_ge(),
1607 0x4d => visitor.visit_v128_not(),
1608 0x4e => visitor.visit_v128_and(),
1609 0x4f => visitor.visit_v128_andnot(),
1610 0x50 => visitor.visit_v128_or(),
1611 0x51 => visitor.visit_v128_xor(),
1612 0x52 => visitor.visit_v128_bitselect(),
1613 0x53 => visitor.visit_v128_any_true(),
1614
1615 0x54 => {
1616 let memarg = self.read_memarg(0)?;
1617 let lane = self.read_lane_index()?;
1618 visitor.visit_v128_load8_lane(memarg, lane)
1619 }
1620 0x55 => {
1621 let memarg = self.read_memarg(1)?;
1622 let lane = self.read_lane_index()?;
1623 visitor.visit_v128_load16_lane(memarg, lane)
1624 }
1625 0x56 => {
1626 let memarg = self.read_memarg(2)?;
1627 let lane = self.read_lane_index()?;
1628 visitor.visit_v128_load32_lane(memarg, lane)
1629 }
1630 0x57 => {
1631 let memarg = self.read_memarg(3)?;
1632 let lane = self.read_lane_index()?;
1633 visitor.visit_v128_load64_lane(memarg, lane)
1634 }
1635 0x58 => {
1636 let memarg = self.read_memarg(0)?;
1637 let lane = self.read_lane_index()?;
1638 visitor.visit_v128_store8_lane(memarg, lane)
1639 }
1640 0x59 => {
1641 let memarg = self.read_memarg(1)?;
1642 let lane = self.read_lane_index()?;
1643 visitor.visit_v128_store16_lane(memarg, lane)
1644 }
1645 0x5a => {
1646 let memarg = self.read_memarg(2)?;
1647 let lane = self.read_lane_index()?;
1648 visitor.visit_v128_store32_lane(memarg, lane)
1649 }
1650 0x5b => {
1651 let memarg = self.read_memarg(3)?;
1652 let lane = self.read_lane_index()?;
1653 visitor.visit_v128_store64_lane(memarg, lane)
1654 }
1655
1656 0x5c => visitor.visit_v128_load32_zero(self.read_memarg(2)?),
1657 0x5d => visitor.visit_v128_load64_zero(self.read_memarg(3)?),
1658 0x5e => visitor.visit_f32x4_demote_f64x2_zero(),
1659 0x5f => visitor.visit_f64x2_promote_low_f32x4(),
1660 0x60 => visitor.visit_i8x16_abs(),
1661 0x61 => visitor.visit_i8x16_neg(),
1662 0x62 => visitor.visit_i8x16_popcnt(),
1663 0x63 => visitor.visit_i8x16_all_true(),
1664 0x64 => visitor.visit_i8x16_bitmask(),
1665 0x65 => visitor.visit_i8x16_narrow_i16x8_s(),
1666 0x66 => visitor.visit_i8x16_narrow_i16x8_u(),
1667 0x67 => visitor.visit_f32x4_ceil(),
1668 0x68 => visitor.visit_f32x4_floor(),
1669 0x69 => visitor.visit_f32x4_trunc(),
1670 0x6a => visitor.visit_f32x4_nearest(),
1671 0x6b => visitor.visit_i8x16_shl(),
1672 0x6c => visitor.visit_i8x16_shr_s(),
1673 0x6d => visitor.visit_i8x16_shr_u(),
1674 0x6e => visitor.visit_i8x16_add(),
1675 0x6f => visitor.visit_i8x16_add_sat_s(),
1676 0x70 => visitor.visit_i8x16_add_sat_u(),
1677 0x71 => visitor.visit_i8x16_sub(),
1678 0x72 => visitor.visit_i8x16_sub_sat_s(),
1679 0x73 => visitor.visit_i8x16_sub_sat_u(),
1680 0x74 => visitor.visit_f64x2_ceil(),
1681 0x75 => visitor.visit_f64x2_floor(),
1682 0x76 => visitor.visit_i8x16_min_s(),
1683 0x77 => visitor.visit_i8x16_min_u(),
1684 0x78 => visitor.visit_i8x16_max_s(),
1685 0x79 => visitor.visit_i8x16_max_u(),
1686 0x7a => visitor.visit_f64x2_trunc(),
1687 0x7b => visitor.visit_i8x16_avgr_u(),
1688 0x7c => visitor.visit_i16x8_extadd_pairwise_i8x16_s(),
1689 0x7d => visitor.visit_i16x8_extadd_pairwise_i8x16_u(),
1690 0x7e => visitor.visit_i32x4_extadd_pairwise_i16x8_s(),
1691 0x7f => visitor.visit_i32x4_extadd_pairwise_i16x8_u(),
1692 0x80 => visitor.visit_i16x8_abs(),
1693 0x81 => visitor.visit_i16x8_neg(),
1694 0x82 => visitor.visit_i16x8_q15mulr_sat_s(),
1695 0x83 => visitor.visit_i16x8_all_true(),
1696 0x84 => visitor.visit_i16x8_bitmask(),
1697 0x85 => visitor.visit_i16x8_narrow_i32x4_s(),
1698 0x86 => visitor.visit_i16x8_narrow_i32x4_u(),
1699 0x87 => visitor.visit_i16x8_extend_low_i8x16_s(),
1700 0x88 => visitor.visit_i16x8_extend_high_i8x16_s(),
1701 0x89 => visitor.visit_i16x8_extend_low_i8x16_u(),
1702 0x8a => visitor.visit_i16x8_extend_high_i8x16_u(),
1703 0x8b => visitor.visit_i16x8_shl(),
1704 0x8c => visitor.visit_i16x8_shr_s(),
1705 0x8d => visitor.visit_i16x8_shr_u(),
1706 0x8e => visitor.visit_i16x8_add(),
1707 0x8f => visitor.visit_i16x8_add_sat_s(),
1708 0x90 => visitor.visit_i16x8_add_sat_u(),
1709 0x91 => visitor.visit_i16x8_sub(),
1710 0x92 => visitor.visit_i16x8_sub_sat_s(),
1711 0x93 => visitor.visit_i16x8_sub_sat_u(),
1712 0x94 => visitor.visit_f64x2_nearest(),
1713 0x95 => visitor.visit_i16x8_mul(),
1714 0x96 => visitor.visit_i16x8_min_s(),
1715 0x97 => visitor.visit_i16x8_min_u(),
1716 0x98 => visitor.visit_i16x8_max_s(),
1717 0x99 => visitor.visit_i16x8_max_u(),
1718 0x9b => visitor.visit_i16x8_avgr_u(),
1719 0x9c => visitor.visit_i16x8_extmul_low_i8x16_s(),
1720 0x9d => visitor.visit_i16x8_extmul_high_i8x16_s(),
1721 0x9e => visitor.visit_i16x8_extmul_low_i8x16_u(),
1722 0x9f => visitor.visit_i16x8_extmul_high_i8x16_u(),
1723 0xa0 => visitor.visit_i32x4_abs(),
1724 0xa1 => visitor.visit_i32x4_neg(),
1725 0xa3 => visitor.visit_i32x4_all_true(),
1726 0xa4 => visitor.visit_i32x4_bitmask(),
1727 0xa7 => visitor.visit_i32x4_extend_low_i16x8_s(),
1728 0xa8 => visitor.visit_i32x4_extend_high_i16x8_s(),
1729 0xa9 => visitor.visit_i32x4_extend_low_i16x8_u(),
1730 0xaa => visitor.visit_i32x4_extend_high_i16x8_u(),
1731 0xab => visitor.visit_i32x4_shl(),
1732 0xac => visitor.visit_i32x4_shr_s(),
1733 0xad => visitor.visit_i32x4_shr_u(),
1734 0xae => visitor.visit_i32x4_add(),
1735 0xb1 => visitor.visit_i32x4_sub(),
1736 0xb5 => visitor.visit_i32x4_mul(),
1737 0xb6 => visitor.visit_i32x4_min_s(),
1738 0xb7 => visitor.visit_i32x4_min_u(),
1739 0xb8 => visitor.visit_i32x4_max_s(),
1740 0xb9 => visitor.visit_i32x4_max_u(),
1741 0xba => visitor.visit_i32x4_dot_i16x8_s(),
1742 0xbc => visitor.visit_i32x4_extmul_low_i16x8_s(),
1743 0xbd => visitor.visit_i32x4_extmul_high_i16x8_s(),
1744 0xbe => visitor.visit_i32x4_extmul_low_i16x8_u(),
1745 0xbf => visitor.visit_i32x4_extmul_high_i16x8_u(),
1746 0xc0 => visitor.visit_i64x2_abs(),
1747 0xc1 => visitor.visit_i64x2_neg(),
1748 0xc3 => visitor.visit_i64x2_all_true(),
1749 0xc4 => visitor.visit_i64x2_bitmask(),
1750 0xc7 => visitor.visit_i64x2_extend_low_i32x4_s(),
1751 0xc8 => visitor.visit_i64x2_extend_high_i32x4_s(),
1752 0xc9 => visitor.visit_i64x2_extend_low_i32x4_u(),
1753 0xca => visitor.visit_i64x2_extend_high_i32x4_u(),
1754 0xcb => visitor.visit_i64x2_shl(),
1755 0xcc => visitor.visit_i64x2_shr_s(),
1756 0xcd => visitor.visit_i64x2_shr_u(),
1757 0xce => visitor.visit_i64x2_add(),
1758 0xd1 => visitor.visit_i64x2_sub(),
1759 0xd5 => visitor.visit_i64x2_mul(),
1760 0xd6 => visitor.visit_i64x2_eq(),
1761 0xd7 => visitor.visit_i64x2_ne(),
1762 0xd8 => visitor.visit_i64x2_lt_s(),
1763 0xd9 => visitor.visit_i64x2_gt_s(),
1764 0xda => visitor.visit_i64x2_le_s(),
1765 0xdb => visitor.visit_i64x2_ge_s(),
1766 0xdc => visitor.visit_i64x2_extmul_low_i32x4_s(),
1767 0xdd => visitor.visit_i64x2_extmul_high_i32x4_s(),
1768 0xde => visitor.visit_i64x2_extmul_low_i32x4_u(),
1769 0xdf => visitor.visit_i64x2_extmul_high_i32x4_u(),
1770 0xe0 => visitor.visit_f32x4_abs(),
1771 0xe1 => visitor.visit_f32x4_neg(),
1772 0xe3 => visitor.visit_f32x4_sqrt(),
1773 0xe4 => visitor.visit_f32x4_add(),
1774 0xe5 => visitor.visit_f32x4_sub(),
1775 0xe6 => visitor.visit_f32x4_mul(),
1776 0xe7 => visitor.visit_f32x4_div(),
1777 0xe8 => visitor.visit_f32x4_min(),
1778 0xe9 => visitor.visit_f32x4_max(),
1779 0xea => visitor.visit_f32x4_pmin(),
1780 0xeb => visitor.visit_f32x4_pmax(),
1781 0xec => visitor.visit_f64x2_abs(),
1782 0xed => visitor.visit_f64x2_neg(),
1783 0xef => visitor.visit_f64x2_sqrt(),
1784 0xf0 => visitor.visit_f64x2_add(),
1785 0xf1 => visitor.visit_f64x2_sub(),
1786 0xf2 => visitor.visit_f64x2_mul(),
1787 0xf3 => visitor.visit_f64x2_div(),
1788 0xf4 => visitor.visit_f64x2_min(),
1789 0xf5 => visitor.visit_f64x2_max(),
1790 0xf6 => visitor.visit_f64x2_pmin(),
1791 0xf7 => visitor.visit_f64x2_pmax(),
1792 0xf8 => visitor.visit_i32x4_trunc_sat_f32x4_s(),
1793 0xf9 => visitor.visit_i32x4_trunc_sat_f32x4_u(),
1794 0xfa => visitor.visit_f32x4_convert_i32x4_s(),
1795 0xfb => visitor.visit_f32x4_convert_i32x4_u(),
1796 0xfc => visitor.visit_i32x4_trunc_sat_f64x2_s_zero(),
1797 0xfd => visitor.visit_i32x4_trunc_sat_f64x2_u_zero(),
1798 0xfe => visitor.visit_f64x2_convert_low_i32x4_s(),
1799 0xff => visitor.visit_f64x2_convert_low_i32x4_u(),
1800 0x100 => visitor.visit_i8x16_relaxed_swizzle(),
1801 0x101 => visitor.visit_i32x4_relaxed_trunc_f32x4_s(),
1802 0x102 => visitor.visit_i32x4_relaxed_trunc_f32x4_u(),
1803 0x103 => visitor.visit_i32x4_relaxed_trunc_f64x2_s_zero(),
1804 0x104 => visitor.visit_i32x4_relaxed_trunc_f64x2_u_zero(),
1805 0x105 => visitor.visit_f32x4_relaxed_madd(),
1806 0x106 => visitor.visit_f32x4_relaxed_nmadd(),
1807 0x107 => visitor.visit_f64x2_relaxed_madd(),
1808 0x108 => visitor.visit_f64x2_relaxed_nmadd(),
1809 0x109 => visitor.visit_i8x16_relaxed_laneselect(),
1810 0x10a => visitor.visit_i16x8_relaxed_laneselect(),
1811 0x10b => visitor.visit_i32x4_relaxed_laneselect(),
1812 0x10c => visitor.visit_i64x2_relaxed_laneselect(),
1813 0x10d => visitor.visit_f32x4_relaxed_min(),
1814 0x10e => visitor.visit_f32x4_relaxed_max(),
1815 0x10f => visitor.visit_f64x2_relaxed_min(),
1816 0x110 => visitor.visit_f64x2_relaxed_max(),
1817 0x111 => visitor.visit_i16x8_relaxed_q15mulr_s(),
1818 0x112 => visitor.visit_i16x8_relaxed_dot_i8x16_i7x16_s(),
1819 0x113 => visitor.visit_i32x4_relaxed_dot_i8x16_i7x16_add_s(),
1820
1821 _ => bail!(pos, "unknown 0xfd subopcode: 0x{code:x}"),
1822 })
1823 }
1824
1825 fn visit_0xfe_operator<T>(
1826 &mut self,
1827 pos: usize,
1828 visitor: &mut T,
1829 ) -> Result<<T as VisitOperator<'a>>::Output>
1830 where
1831 T: VisitOperator<'a>,
1832 {
1833 let code = self.read_var_u32()?;
1834 Ok(match code {
1835 0x00 => visitor.visit_memory_atomic_notify(self.read_memarg(2)?),
1836 0x01 => visitor.visit_memory_atomic_wait32(self.read_memarg(2)?),
1837 0x02 => visitor.visit_memory_atomic_wait64(self.read_memarg(3)?),
1838 0x03 => {
1839 if self.read_u8()? != 0 {
1840 bail!(pos, "nonzero byte after `atomic.fence`");
1841 }
1842 visitor.visit_atomic_fence()
1843 }
1844 0x10 => visitor.visit_i32_atomic_load(self.read_memarg(2)?),
1845 0x11 => visitor.visit_i64_atomic_load(self.read_memarg(3)?),
1846 0x12 => visitor.visit_i32_atomic_load8_u(self.read_memarg(0)?),
1847 0x13 => visitor.visit_i32_atomic_load16_u(self.read_memarg(1)?),
1848 0x14 => visitor.visit_i64_atomic_load8_u(self.read_memarg(0)?),
1849 0x15 => visitor.visit_i64_atomic_load16_u(self.read_memarg(1)?),
1850 0x16 => visitor.visit_i64_atomic_load32_u(self.read_memarg(2)?),
1851 0x17 => visitor.visit_i32_atomic_store(self.read_memarg(2)?),
1852 0x18 => visitor.visit_i64_atomic_store(self.read_memarg(3)?),
1853 0x19 => visitor.visit_i32_atomic_store8(self.read_memarg(0)?),
1854 0x1a => visitor.visit_i32_atomic_store16(self.read_memarg(1)?),
1855 0x1b => visitor.visit_i64_atomic_store8(self.read_memarg(0)?),
1856 0x1c => visitor.visit_i64_atomic_store16(self.read_memarg(1)?),
1857 0x1d => visitor.visit_i64_atomic_store32(self.read_memarg(2)?),
1858 0x1e => visitor.visit_i32_atomic_rmw_add(self.read_memarg(2)?),
1859 0x1f => visitor.visit_i64_atomic_rmw_add(self.read_memarg(3)?),
1860 0x20 => visitor.visit_i32_atomic_rmw8_add_u(self.read_memarg(0)?),
1861 0x21 => visitor.visit_i32_atomic_rmw16_add_u(self.read_memarg(1)?),
1862 0x22 => visitor.visit_i64_atomic_rmw8_add_u(self.read_memarg(0)?),
1863 0x23 => visitor.visit_i64_atomic_rmw16_add_u(self.read_memarg(1)?),
1864 0x24 => visitor.visit_i64_atomic_rmw32_add_u(self.read_memarg(2)?),
1865 0x25 => visitor.visit_i32_atomic_rmw_sub(self.read_memarg(2)?),
1866 0x26 => visitor.visit_i64_atomic_rmw_sub(self.read_memarg(3)?),
1867 0x27 => visitor.visit_i32_atomic_rmw8_sub_u(self.read_memarg(0)?),
1868 0x28 => visitor.visit_i32_atomic_rmw16_sub_u(self.read_memarg(1)?),
1869 0x29 => visitor.visit_i64_atomic_rmw8_sub_u(self.read_memarg(0)?),
1870 0x2a => visitor.visit_i64_atomic_rmw16_sub_u(self.read_memarg(1)?),
1871 0x2b => visitor.visit_i64_atomic_rmw32_sub_u(self.read_memarg(2)?),
1872 0x2c => visitor.visit_i32_atomic_rmw_and(self.read_memarg(2)?),
1873 0x2d => visitor.visit_i64_atomic_rmw_and(self.read_memarg(3)?),
1874 0x2e => visitor.visit_i32_atomic_rmw8_and_u(self.read_memarg(0)?),
1875 0x2f => visitor.visit_i32_atomic_rmw16_and_u(self.read_memarg(1)?),
1876 0x30 => visitor.visit_i64_atomic_rmw8_and_u(self.read_memarg(0)?),
1877 0x31 => visitor.visit_i64_atomic_rmw16_and_u(self.read_memarg(1)?),
1878 0x32 => visitor.visit_i64_atomic_rmw32_and_u(self.read_memarg(2)?),
1879 0x33 => visitor.visit_i32_atomic_rmw_or(self.read_memarg(2)?),
1880 0x34 => visitor.visit_i64_atomic_rmw_or(self.read_memarg(3)?),
1881 0x35 => visitor.visit_i32_atomic_rmw8_or_u(self.read_memarg(0)?),
1882 0x36 => visitor.visit_i32_atomic_rmw16_or_u(self.read_memarg(1)?),
1883 0x37 => visitor.visit_i64_atomic_rmw8_or_u(self.read_memarg(0)?),
1884 0x38 => visitor.visit_i64_atomic_rmw16_or_u(self.read_memarg(1)?),
1885 0x39 => visitor.visit_i64_atomic_rmw32_or_u(self.read_memarg(2)?),
1886 0x3a => visitor.visit_i32_atomic_rmw_xor(self.read_memarg(2)?),
1887 0x3b => visitor.visit_i64_atomic_rmw_xor(self.read_memarg(3)?),
1888 0x3c => visitor.visit_i32_atomic_rmw8_xor_u(self.read_memarg(0)?),
1889 0x3d => visitor.visit_i32_atomic_rmw16_xor_u(self.read_memarg(1)?),
1890 0x3e => visitor.visit_i64_atomic_rmw8_xor_u(self.read_memarg(0)?),
1891 0x3f => visitor.visit_i64_atomic_rmw16_xor_u(self.read_memarg(1)?),
1892 0x40 => visitor.visit_i64_atomic_rmw32_xor_u(self.read_memarg(2)?),
1893 0x41 => visitor.visit_i32_atomic_rmw_xchg(self.read_memarg(2)?),
1894 0x42 => visitor.visit_i64_atomic_rmw_xchg(self.read_memarg(3)?),
1895 0x43 => visitor.visit_i32_atomic_rmw8_xchg_u(self.read_memarg(0)?),
1896 0x44 => visitor.visit_i32_atomic_rmw16_xchg_u(self.read_memarg(1)?),
1897 0x45 => visitor.visit_i64_atomic_rmw8_xchg_u(self.read_memarg(0)?),
1898 0x46 => visitor.visit_i64_atomic_rmw16_xchg_u(self.read_memarg(1)?),
1899 0x47 => visitor.visit_i64_atomic_rmw32_xchg_u(self.read_memarg(2)?),
1900 0x48 => visitor.visit_i32_atomic_rmw_cmpxchg(self.read_memarg(2)?),
1901 0x49 => visitor.visit_i64_atomic_rmw_cmpxchg(self.read_memarg(3)?),
1902 0x4a => visitor.visit_i32_atomic_rmw8_cmpxchg_u(self.read_memarg(0)?),
1903 0x4b => visitor.visit_i32_atomic_rmw16_cmpxchg_u(self.read_memarg(1)?),
1904 0x4c => visitor.visit_i64_atomic_rmw8_cmpxchg_u(self.read_memarg(0)?),
1905 0x4d => visitor.visit_i64_atomic_rmw16_cmpxchg_u(self.read_memarg(1)?),
1906 0x4e => visitor.visit_i64_atomic_rmw32_cmpxchg_u(self.read_memarg(2)?),
1907
1908 0x4f => visitor.visit_global_atomic_get(self.read_ordering()?, self.read_var_u32()?),
1910 0x50 => visitor.visit_global_atomic_set(self.read_ordering()?, self.read_var_u32()?),
1911 0x51 => {
1912 visitor.visit_global_atomic_rmw_add(self.read_ordering()?, self.read_var_u32()?)
1913 }
1914 0x52 => {
1915 visitor.visit_global_atomic_rmw_sub(self.read_ordering()?, self.read_var_u32()?)
1916 }
1917 0x53 => {
1918 visitor.visit_global_atomic_rmw_and(self.read_ordering()?, self.read_var_u32()?)
1919 }
1920 0x54 => visitor.visit_global_atomic_rmw_or(self.read_ordering()?, self.read_var_u32()?),
1921 0x55 => {
1922 visitor.visit_global_atomic_rmw_xor(self.read_ordering()?, self.read_var_u32()?)
1923 }
1924 0x56 => {
1925 visitor.visit_global_atomic_rmw_xchg(self.read_ordering()?, self.read_var_u32()?)
1926 }
1927 0x57 => {
1928 visitor.visit_global_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_var_u32()?)
1929 }
1930 0x58 => visitor.visit_table_atomic_get(self.read_ordering()?, self.read_var_u32()?),
1931 0x59 => visitor.visit_table_atomic_set(self.read_ordering()?, self.read_var_u32()?),
1932 0x5a => {
1933 visitor.visit_table_atomic_rmw_xchg(self.read_ordering()?, self.read_var_u32()?)
1934 }
1935 0x5b => {
1936 visitor.visit_table_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_var_u32()?)
1937 }
1938 0x5c => visitor.visit_struct_atomic_get(
1939 self.read_ordering()?,
1940 self.read_var_u32()?,
1941 self.read_var_u32()?,
1942 ),
1943 0x5d => visitor.visit_struct_atomic_get_s(
1944 self.read_ordering()?,
1945 self.read_var_u32()?,
1946 self.read_var_u32()?,
1947 ),
1948 0x5e => visitor.visit_struct_atomic_get_u(
1949 self.read_ordering()?,
1950 self.read_var_u32()?,
1951 self.read_var_u32()?,
1952 ),
1953 0x5f => visitor.visit_struct_atomic_set(
1954 self.read_ordering()?,
1955 self.read_var_u32()?,
1956 self.read_var_u32()?,
1957 ),
1958 0x60 => visitor.visit_struct_atomic_rmw_add(
1959 self.read_ordering()?,
1960 self.read_var_u32()?,
1961 self.read_var_u32()?,
1962 ),
1963 0x61 => visitor.visit_struct_atomic_rmw_sub(
1964 self.read_ordering()?,
1965 self.read_var_u32()?,
1966 self.read_var_u32()?,
1967 ),
1968 0x62 => visitor.visit_struct_atomic_rmw_and(
1969 self.read_ordering()?,
1970 self.read_var_u32()?,
1971 self.read_var_u32()?,
1972 ),
1973 0x63 => visitor.visit_struct_atomic_rmw_or(
1974 self.read_ordering()?,
1975 self.read_var_u32()?,
1976 self.read_var_u32()?,
1977 ),
1978 0x64 => visitor.visit_struct_atomic_rmw_xor(
1979 self.read_ordering()?,
1980 self.read_var_u32()?,
1981 self.read_var_u32()?,
1982 ),
1983 0x65 => visitor.visit_struct_atomic_rmw_xchg(
1984 self.read_ordering()?,
1985 self.read_var_u32()?,
1986 self.read_var_u32()?,
1987 ),
1988 0x66 => visitor.visit_struct_atomic_rmw_cmpxchg(
1989 self.read_ordering()?,
1990 self.read_var_u32()?,
1991 self.read_var_u32()?,
1992 ),
1993 0x67 => visitor.visit_array_atomic_get(self.read_ordering()?, self.read_var_u32()?),
1994 0x68 => visitor.visit_array_atomic_get_s(self.read_ordering()?, self.read_var_u32()?),
1995 0x69 => visitor.visit_array_atomic_get_u(self.read_ordering()?, self.read_var_u32()?),
1996 0x6a => visitor.visit_array_atomic_set(self.read_ordering()?, self.read_var_u32()?),
1997 0x6b => visitor.visit_array_atomic_rmw_add(self.read_ordering()?, self.read_var_u32()?),
1998 0x6c => visitor.visit_array_atomic_rmw_sub(self.read_ordering()?, self.read_var_u32()?),
1999 0x6d => visitor.visit_array_atomic_rmw_and(self.read_ordering()?, self.read_var_u32()?),
2000 0x6e => visitor.visit_array_atomic_rmw_or(self.read_ordering()?, self.read_var_u32()?),
2001 0x6f => visitor.visit_array_atomic_rmw_xor(self.read_ordering()?, self.read_var_u32()?),
2002 0x70 => {
2003 visitor.visit_array_atomic_rmw_xchg(self.read_ordering()?, self.read_var_u32()?)
2004 }
2005 0x71 => {
2006 visitor.visit_array_atomic_rmw_cmpxchg(self.read_ordering()?, self.read_var_u32()?)
2007 }
2008 0x72 => visitor.visit_ref_i31_shared(),
2009
2010 _ => bail!(pos, "unknown 0xfe subopcode: 0x{code:x}"),
2011 })
2012 }
2013
2014 fn read_memarg(&mut self, max_align: u8) -> Result<MemArg> {
2015 let flags_pos = self.original_position();
2016 let mut flags = self.read_var_u32()?;
2017
2018 let memory = if self.multi_memory() && flags & (1 << 6) != 0 {
2019 flags ^= 1 << 6;
2020 self.read_var_u32()?
2021 } else {
2022 0
2023 };
2024 let max_flag_bits = if self.multi_memory() { 6 } else { 5 };
2025 if flags >= (1 << max_flag_bits) {
2026 return Err(BinaryReaderError::new(
2027 "malformed memop alignment: alignment too large",
2028 flags_pos,
2029 ));
2030 }
2031 let align = flags as u8;
2032 let offset = if self.memory64() {
2033 self.read_var_u64()?
2034 } else {
2035 u64::from(self.read_var_u32()?)
2036 };
2037 Ok(MemArg {
2038 align,
2039 max_align,
2040 offset,
2041 memory,
2042 })
2043 }
2044
2045 fn read_ordering(&mut self) -> Result<Ordering> {
2046 let byte = self.read_var_u32()?;
2047 match byte {
2048 0 => Ok(Ordering::SeqCst),
2049 1 => Ok(Ordering::AcqRel),
2050 x => Err(BinaryReaderError::new(
2051 &format!("invalid atomic consistency ordering {x}"),
2052 self.original_position() - 1,
2053 )),
2054 }
2055 }
2056
2057 fn read_br_table(&mut self) -> Result<BrTable<'a>> {
2058 let cnt = self.read_size(MAX_WASM_BR_TABLE_SIZE, "br_table")?;
2059 let reader = self.skip(|reader| {
2060 for _ in 0..cnt {
2061 reader.read_var_u32()?;
2062 }
2063 Ok(())
2064 })?;
2065 let default = self.read_var_u32()?;
2066 Ok(BrTable {
2067 reader,
2068 cnt: cnt as u32,
2069 default,
2070 })
2071 }
2072
2073 #[cfg(feature = "simd")]
2074 fn read_lane_index(&mut self) -> Result<u8> {
2075 self.read_u8()
2076 }
2077
2078 #[cfg(feature = "simd")]
2079 fn read_v128(&mut self) -> Result<V128> {
2080 let mut bytes = [0; 16];
2081 bytes.clone_from_slice(self.read_bytes(16)?);
2082 Ok(V128(bytes))
2083 }
2084
2085 fn read_memory_index_or_zero_if_not_multi_memory(&mut self) -> Result<u32> {
2086 if self.multi_memory() {
2087 self.read_var_u32()
2088 } else {
2089 match self.read_u8()? {
2092 0 => Ok(0),
2093 _ => bail!(self.original_position() - 1, "zero byte expected"),
2094 }
2095 }
2096 }
2097
2098 fn read_call_indirect_table_immediate(&mut self) -> Result<u32> {
2099 if self.call_indirect_overlong() {
2103 return self.read_var_u32();
2104 }
2105
2106 match self.read_u8()? {
2109 0 => Ok(0),
2110 _ => bail!(self.original_position() - 1, "zero byte expected"),
2111 }
2112 }
2113}