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