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