xref: /wasmtime-44.0.1/pulley/src/decode.rs (revision 1d738975)
1 //! Decoding support for pulley bytecode.
2 
3 use crate::imms::*;
4 use crate::opcode::*;
5 use crate::regs::*;
6 use alloc::vec::Vec;
7 use core::convert::Infallible;
8 use core::ptr::NonNull;
9 use cranelift_bitset::ScalarBitSet;
10 use cranelift_bitset::scalar::ScalarBitSetStorage;
11 
12 /// Either an `Ok(T)` or an `Err(DecodingError)`.
13 pub type Result<T, E = DecodingError> = core::result::Result<T, E>;
14 
15 /// An error when decoding Pulley bytecode.
16 pub enum DecodingError {
17     /// Reached the end of the bytecode stream before we finished decoding a
18     /// single bytecode.
19     UnexpectedEof {
20         /// The position in the bytecode stream where this error occurred.
21         position: usize,
22     },
23 
24     /// Found an invalid opcode.
25     InvalidOpcode {
26         /// The position in the bytecode stream where this error occurred.
27         position: usize,
28         /// The invalid opcode that was found.
29         code: u8,
30     },
31 
32     /// Found an invalid extended opcode.
33     InvalidExtendedOpcode {
34         /// The position in the bytecode stream where this error occurred.
35         position: usize,
36         /// The invalid extended opcode that was found.
37         code: u16,
38     },
39 
40     /// Found an invalid register.
41     InvalidReg {
42         /// The position in the bytecode stream where this error occurred.
43         position: usize,
44         /// The invalid register that was found.
45         reg: u8,
46     },
47 }
48 
49 impl core::fmt::Debug for DecodingError {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result50     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51         core::fmt::Display::fmt(self, f)
52     }
53 }
54 
55 impl core::fmt::Display for DecodingError {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result56     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
57         match self {
58             Self::UnexpectedEof { position } => {
59                 write!(f, "unexpected end-of-file at bytecode offset {position:#x}")
60             }
61             Self::InvalidOpcode { position, code } => {
62                 write!(
63                     f,
64                     "found invalid opcode {code:#x} at bytecode offset {position:#x}"
65                 )
66             }
67             Self::InvalidExtendedOpcode { position, code } => {
68                 write!(
69                     f,
70                     "found invalid opcode {code:#x} at bytecode offset {position:#x}"
71                 )
72             }
73             Self::InvalidReg { position, reg } => {
74                 write!(
75                     f,
76                     "found invalid register {reg:#x} at bytecode offset {position:#x}"
77                 )
78             }
79         }
80     }
81 }
82 
83 #[cfg(feature = "std")]
84 impl std::error::Error for DecodingError {}
85 
86 /// An abstraction over any kind of bytecode stream.
87 ///
88 /// There are two primary implementations:
89 ///
90 /// 1. `SafeBytecodeStream`: A thin wrapper around an index into a `&[u8]`. This
91 ///    implementation is 100% safe code.
92 ///
93 /// 2. `UnsafeBytecodeStream`: A thin wrapper over a raw pointer. This
94 ///    implementation is wildly unsafe and will result in memory unsafety and
95 ///    other terrors when given invalid bytecode, or even valid bytecode
96 ///    encoding a program that itself does not preserve memory safety.
97 pub trait BytecodeStream: Copy {
98     /// The type of error that this bytecode stream produces on invalid
99     /// operations.
100     type Error;
101 
102     /// Create an "unexpected end-of-stream" error at the current position.
unexpected_eof(&self) -> Self::Error103     fn unexpected_eof(&self) -> Self::Error;
104 
105     /// Create an "invalid opcode" error at the current position.
invalid_opcode(&self, code: u8) -> Self::Error106     fn invalid_opcode(&self, code: u8) -> Self::Error;
107 
108     /// Create an "invalid extended opcode" error at the current position.
invalid_extended_opcode(&self, code: u16) -> Self::Error109     fn invalid_extended_opcode(&self, code: u16) -> Self::Error;
110 
111     /// Create an "invalid register" error at the current position.
invalid_reg(&self, reg: u8) -> Self::Error112     fn invalid_reg(&self, reg: u8) -> Self::Error;
113 
114     /// Read `N` bytes from this bytecode stream, advancing the stream's
115     /// position at the same time.
read<const N: usize>(&mut self) -> Result<[u8; N], Self::Error>116     fn read<const N: usize>(&mut self) -> Result<[u8; N], Self::Error>;
117 }
118 
119 /// A 100% safe implementation of a bytecode stream.
120 ///
121 /// This is a thin wrapper around an index into a `&[u8]`.
122 #[derive(Clone, Copy, Debug)]
123 pub struct SafeBytecodeStream<'a> {
124     bytecode: &'a [u8],
125     position: usize,
126 }
127 
128 impl<'a> SafeBytecodeStream<'a> {
129     /// Create a new `SafeBytecodeStream` from the given slice and with an
130     /// initial position pointing at the start of the slice.
new(bytecode: &'a [u8]) -> Self131     pub fn new(bytecode: &'a [u8]) -> Self {
132         Self {
133             bytecode,
134             position: 0,
135         }
136     }
137 
138     /// Get this stream's current position within its underlying slice.
position(&self) -> usize139     pub fn position(&self) -> usize {
140         self.position
141     }
142 
143     /// Get this stream's underlying bytecode slice.
as_slice(&self) -> &[u8]144     pub fn as_slice(&self) -> &[u8] {
145         &self.bytecode
146     }
147 }
148 
149 impl BytecodeStream for SafeBytecodeStream<'_> {
read<const N: usize>(&mut self) -> Result<[u8; N], Self::Error>150     fn read<const N: usize>(&mut self) -> Result<[u8; N], Self::Error> {
151         let (bytes, rest) = self
152             .bytecode
153             .split_first_chunk()
154             .ok_or_else(|| self.unexpected_eof())?;
155         self.bytecode = rest;
156         self.position += N;
157         Ok(*bytes)
158     }
159 
160     type Error = DecodingError;
161 
unexpected_eof(&self) -> Self::Error162     fn unexpected_eof(&self) -> Self::Error {
163         DecodingError::UnexpectedEof {
164             position: self.position,
165         }
166     }
167 
invalid_opcode(&self, code: u8) -> Self::Error168     fn invalid_opcode(&self, code: u8) -> Self::Error {
169         DecodingError::InvalidOpcode {
170             position: self.position - 1,
171             code,
172         }
173     }
174 
invalid_extended_opcode(&self, code: u16) -> Self::Error175     fn invalid_extended_opcode(&self, code: u16) -> Self::Error {
176         DecodingError::InvalidExtendedOpcode {
177             position: self.position,
178             code,
179         }
180     }
181 
invalid_reg(&self, reg: u8) -> Self::Error182     fn invalid_reg(&self, reg: u8) -> Self::Error {
183         DecodingError::InvalidReg {
184             position: self.position,
185             reg,
186         }
187     }
188 }
189 
190 /// An unsafe bytecode stream.
191 ///
192 /// This is a wrapper over a raw pointer to bytecode somewhere in memory.
193 #[derive(Clone, Copy, Debug)]
194 pub struct UnsafeBytecodeStream(NonNull<u8>);
195 
196 impl UnsafeBytecodeStream {
197     /// Construct a new `UnsafeBytecodeStream` pointing at the given PC.
198     ///
199     /// # Safety
200     ///
201     /// The given `pc` must point to valid Pulley bytecode, and it is the
202     /// caller's responsibility to ensure that the resulting
203     /// `UnsafeBytecodeStream` is only used to access the valid bytecode. For
204     /// example, if the current bytecode instruction unconditionally jumps to a
205     /// new PC, this stream must not be used to read just after the
206     /// unconditional jump instruction because there is no guarantee that that
207     /// memory is part of the bytecode stream or not.
new(pc: NonNull<u8>) -> Self208     pub unsafe fn new(pc: NonNull<u8>) -> Self {
209         UnsafeBytecodeStream(pc)
210     }
211 
212     /// Get a new `UnsafeBytecodeStream` pointing at the bytecode that is at the
213     /// given relative offset from this stream's current position.
214     ///
215     /// # Safety
216     ///
217     /// Same as the `new` constructor. May only be used when it is guaranteed
218     /// that the address at `self._as_ptr() + offset` contains valid Pulley
219     /// bytecode.
offset(&self, offset: isize) -> Self220     pub unsafe fn offset(&self, offset: isize) -> Self {
221         UnsafeBytecodeStream(unsafe { NonNull::new_unchecked(self.0.as_ptr().offset(offset)) })
222     }
223 
224     /// Get this stream's underlying raw pointer.
as_ptr(&self) -> NonNull<u8>225     pub fn as_ptr(&self) -> NonNull<u8> {
226         self.0
227     }
228 }
229 
230 impl BytecodeStream for UnsafeBytecodeStream {
read<const N: usize>(&mut self) -> Result<[u8; N], Self::Error>231     fn read<const N: usize>(&mut self) -> Result<[u8; N], Self::Error> {
232         let bytes = unsafe { self.0.cast::<[u8; N]>().as_ptr().read() };
233         self.0 = unsafe { NonNull::new_unchecked(self.0.as_ptr().add(N)) };
234         Ok(bytes)
235     }
236 
237     type Error = Infallible;
238 
unexpected_eof(&self) -> Self::Error239     fn unexpected_eof(&self) -> Self::Error {
240         unsafe { crate::unreachable_unchecked() }
241     }
242 
invalid_opcode(&self, _code: u8) -> Self::Error243     fn invalid_opcode(&self, _code: u8) -> Self::Error {
244         unsafe { crate::unreachable_unchecked() }
245     }
246 
invalid_extended_opcode(&self, _code: u16) -> Self::Error247     fn invalid_extended_opcode(&self, _code: u16) -> Self::Error {
248         unsafe { crate::unreachable_unchecked() }
249     }
250 
invalid_reg(&self, _reg: u8) -> Self::Error251     fn invalid_reg(&self, _reg: u8) -> Self::Error {
252         unsafe { crate::unreachable_unchecked() }
253     }
254 }
255 
256 /// Anything that can be decoded from a bytecode stream, e.g. opcodes,
257 /// immediates, registers, etc...
258 pub trait Decode: Sized {
259     /// Decode this type from the given bytecode stream.
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream260     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
261     where
262         T: BytecodeStream;
263 }
264 
265 impl Decode for u8 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,266     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
267     where
268         T: BytecodeStream,
269     {
270         bytecode.read::<1>().map(|a| a[0])
271     }
272 }
273 
274 impl Decode for u16 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,275     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
276     where
277         T: BytecodeStream,
278     {
279         Ok(u16::from_le_bytes(bytecode.read()?))
280     }
281 }
282 
283 impl Decode for u32 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,284     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
285     where
286         T: BytecodeStream,
287     {
288         Ok(u32::from_le_bytes(bytecode.read()?))
289     }
290 }
291 
292 impl Decode for u64 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,293     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
294     where
295         T: BytecodeStream,
296     {
297         Ok(u64::from_le_bytes(bytecode.read()?))
298     }
299 }
300 
301 impl Decode for u128 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,302     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
303     where
304         T: BytecodeStream,
305     {
306         Ok(u128::from_le_bytes(bytecode.read()?))
307     }
308 }
309 
310 impl Decode for i8 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,311     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
312     where
313         T: BytecodeStream,
314     {
315         bytecode.read::<1>().map(|a| a[0] as i8)
316     }
317 }
318 
319 impl Decode for i16 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,320     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
321     where
322         T: BytecodeStream,
323     {
324         Ok(i16::from_le_bytes(bytecode.read()?))
325     }
326 }
327 
328 impl Decode for i32 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,329     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
330     where
331         T: BytecodeStream,
332     {
333         Ok(i32::from_le_bytes(bytecode.read()?))
334     }
335 }
336 
337 impl Decode for i64 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,338     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
339     where
340         T: BytecodeStream,
341     {
342         Ok(i64::from_le_bytes(bytecode.read()?))
343     }
344 }
345 
346 impl Decode for i128 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,347     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
348     where
349         T: BytecodeStream,
350     {
351         Ok(i128::from_le_bytes(bytecode.read()?))
352     }
353 }
354 
355 impl Decode for XReg {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,356     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
357     where
358         T: BytecodeStream,
359     {
360         let byte = u8::decode(bytecode)?;
361         XReg::new(byte).ok_or_else(|| bytecode.invalid_reg(byte))
362     }
363 }
364 
365 impl Decode for FReg {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,366     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
367     where
368         T: BytecodeStream,
369     {
370         let byte = u8::decode(bytecode)?;
371         FReg::new(byte).ok_or_else(|| bytecode.invalid_reg(byte))
372     }
373 }
374 
375 impl Decode for VReg {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,376     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
377     where
378         T: BytecodeStream,
379     {
380         let byte = u8::decode(bytecode)?;
381         VReg::new(byte).ok_or_else(|| bytecode.invalid_reg(byte))
382     }
383 }
384 
385 impl Decode for PcRelOffset {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,386     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
387     where
388         T: BytecodeStream,
389     {
390         i32::decode(bytecode).map(|x| Self::from(x))
391     }
392 }
393 
394 impl Decode for Opcode {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,395     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
396     where
397         T: BytecodeStream,
398     {
399         let byte = u8::decode(bytecode)?;
400         match Opcode::new(byte) {
401             Some(v) => Ok(v),
402             None => Err(bytecode.invalid_opcode(byte)),
403         }
404     }
405 }
406 
407 impl Decode for ExtendedOpcode {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,408     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
409     where
410         T: BytecodeStream,
411     {
412         let word = u16::decode(bytecode)?;
413         match ExtendedOpcode::new(word) {
414             Some(v) => Ok(v),
415             None => Err(bytecode.invalid_extended_opcode(word)),
416         }
417     }
418 }
419 
420 impl<D: Reg, S1: Reg, S2: Reg> Decode for BinaryOperands<D, S1, S2> {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,421     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
422     where
423         T: BytecodeStream,
424     {
425         u16::decode(bytecode).map(|bits| Self::from_bits(bits))
426     }
427 }
428 
429 impl<D: Reg, S1: Reg> Decode for BinaryOperands<D, S1, U6> {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,430     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
431     where
432         T: BytecodeStream,
433     {
434         u16::decode(bytecode).map(|bits| Self::from_bits(bits))
435     }
436 }
437 
438 impl<S: Decode + ScalarBitSetStorage> Decode for ScalarBitSet<S> {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,439     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
440     where
441         T: BytecodeStream,
442     {
443         S::decode(bytecode).map(ScalarBitSet::from)
444     }
445 }
446 
447 impl<R: Reg + Decode> Decode for UpperRegSet<R> {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,448     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
449     where
450         T: BytecodeStream,
451     {
452         ScalarBitSet::decode(bytecode).map(Self::from)
453     }
454 }
455 
456 impl Decode for AddrO32 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,457     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
458     where
459         T: BytecodeStream,
460     {
461         Ok(AddrO32 {
462             addr: XReg::decode(bytecode)?,
463             offset: i32::decode(bytecode)?,
464         })
465     }
466 }
467 
468 impl Decode for AddrZ {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,469     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
470     where
471         T: BytecodeStream,
472     {
473         Ok(AddrZ {
474             addr: XReg::decode(bytecode)?,
475             offset: i32::decode(bytecode)?,
476         })
477     }
478 }
479 
480 impl Decode for AddrG32 {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,481     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
482     where
483         T: BytecodeStream,
484     {
485         Ok(AddrG32::from_bits(u32::decode(bytecode)?))
486     }
487 }
488 
489 impl Decode for AddrG32Bne {
decode<T>(bytecode: &mut T) -> Result<Self, T::Error> where T: BytecodeStream,490     fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error>
491     where
492         T: BytecodeStream,
493     {
494         Ok(AddrG32Bne::from_bits(u32::decode(bytecode)?))
495     }
496 }
497 
498 /// A Pulley bytecode decoder.
499 ///
500 /// Does not materialize bytecode instructions, instead all decoding methods are
501 /// given an `OpVisitor` implementation and the appropriate visitor methods are
502 /// called upon decoding an instruction. This minimizes the amount of times we
503 /// branch on the opcode, avoids constructing temporary storage, and plays well
504 /// with our variable-length instruction encoding.
505 #[derive(Default)]
506 pub struct Decoder {
507     _private: (),
508 }
509 
510 impl Decoder {
511     /// Create a new decoder.
new() -> Self512     pub fn new() -> Self {
513         Self::default()
514     }
515 
516     /// Decode all instructions in the visitor's bytecode stream.
517     ///
518     /// The associated visitor method is invoked after each instruction is
519     /// decoded.
decode_all<'a, V>(visitor: &mut V) -> Result<Vec<V::Return>> where V: OpVisitor<BytecodeStream = SafeBytecodeStream<'a>> + ExtendedOpVisitor,520     pub fn decode_all<'a, V>(visitor: &mut V) -> Result<Vec<V::Return>>
521     where
522         V: OpVisitor<BytecodeStream = SafeBytecodeStream<'a>> + ExtendedOpVisitor,
523     {
524         let mut decoder = Decoder::new();
525         let mut results = Vec::new();
526 
527         while !visitor.bytecode().as_slice().is_empty() {
528             results.push(decoder.decode_one(visitor)?);
529         }
530 
531         Ok(results)
532     }
533 }
534 
535 /// An `OpVisitor` combinator to sequence one visitor and then another.
536 pub struct SequencedVisitor<'a, F, V1, V2> {
537     join: F,
538     v1: &'a mut V1,
539     v2: &'a mut V2,
540 }
541 
542 impl<'a, F, V1, V2> SequencedVisitor<'a, F, V1, V2> {
543     /// Create a new sequenced visitor.
544     ///
545     /// The given `join` function is used to combine the results of each
546     /// sub-visitor so that it can be returned from this combined visitor.
new(join: F, v1: &'a mut V1, v2: &'a mut V2) -> Self547     pub fn new(join: F, v1: &'a mut V1, v2: &'a mut V2) -> Self {
548         SequencedVisitor { join, v1, v2 }
549     }
550 }
551 
552 macro_rules! define_decoder {
553     (
554         $(
555             $( #[$attr:meta] )*
556                 $snake_name:ident = $name:ident $( {
557                 $(
558                     $( #[$field_attr:meta] )*
559                     $field:ident : $field_ty:ty
560                 ),*
561             } )? ;
562         )*
563     ) => {
564         impl Decoder {
565             /// Decode one instruction from the visitor's bytestream.
566             ///
567             /// Upon decoding, the visitor's associated callback is invoked and
568             /// the results returned.
569             #[inline(always)]
570             pub fn decode_one<V>(
571                 &mut self,
572                 visitor: &mut V,
573             ) -> Result<V::Return, <V::BytecodeStream as BytecodeStream>::Error>
574             where
575                 V: OpVisitor + ExtendedOpVisitor,
576             {
577                 visitor.before_visit();
578 
579                 let byte = u8::decode(visitor.bytecode())?;
580                 let opcode = Opcode::new(byte).ok_or_else(|| {
581                     visitor.bytecode().invalid_opcode(byte)
582                 })?;
583 
584                 match opcode {
585                     $(
586                         Opcode::$name => {
587                             $(
588                                 $(
589                                     let $field = <$field_ty>::decode(
590                                         visitor.bytecode(),
591                                     )?;
592                                 )*
593                             )?
594 
595                             let ret = visitor.$snake_name($( $( $field ),* )?);
596                             visitor.after_visit();
597                             Ok(ret)
598                         },
599                     )*
600                     Opcode::ExtendedOp => {
601                         decode_one_extended(visitor)
602                     }
603                 }
604             }
605         }
606 
607         /// Callbacks upon decoding instructions from bytecode.
608         ///
609         /// Implement this trait for your type, give an instance of your type to
610         /// a `Decoder` method, and the `Decoder` will invoke the associated
611         /// method for each instruction that it decodes. For example, if the
612         /// `Decoder` decodes an `xadd32` instruction, then it will invoke the
613         /// `xadd32` visitor method, passing along any decoded immediates,
614         /// operands, etc... as arguments.
615         pub trait OpVisitor {
616             /// The type of this visitor's bytecode stream.
617             type BytecodeStream: BytecodeStream;
618 
619             /// Get this visitor's underlying bytecode stream.
620             fn bytecode(&mut self) -> &mut Self::BytecodeStream;
621 
622             /// The type of values returned by each visitor method.
623             type Return;
624 
625             /// A callback invoked before starting to decode an instruction.
626             ///
627             /// Does nothing by default.
628             fn before_visit(&mut self) {}
629 
630             /// A callback invoked after an instruction has been completely
631             /// decoded.
632             ///
633             /// Does nothing by default.
634             fn after_visit(&mut self) {}
635 
636             $(
637                 $( #[$attr] )*
638                 fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return;
639             )*
640         }
641 
642         impl<F, T, V1, V2> OpVisitor for SequencedVisitor<'_, F, V1, V2>
643         where
644             F: FnMut(V1::Return, V2::Return) -> T,
645             V1: OpVisitor,
646             V2: OpVisitor<BytecodeStream = V1::BytecodeStream>,
647         {
648             type BytecodeStream = V1::BytecodeStream;
649 
650             fn bytecode(&mut self) -> &mut Self::BytecodeStream {
651                 self.v1.bytecode()
652             }
653 
654             type Return = T;
655 
656             fn before_visit(&mut self) {
657                 self.v1.before_visit();
658                 self.v2.before_visit();
659             }
660 
661             fn after_visit(&mut self) {
662                 *self.v2.bytecode() = *self.v1.bytecode();
663                 self.v1.after_visit();
664                 self.v2.after_visit();
665             }
666 
667             $(
668                 $( #[$attr] )*
669                 fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return {
670                     let a = self.v1.$snake_name( $( $( $field , )* )? );
671                     let b = self.v2.$snake_name( $( $( $field , )* )? );
672                     (self.join)(a, b)
673                 }
674             )*
675         }
676     };
677 }
678 for_each_op!(define_decoder);
679 
680 macro_rules! define_extended_decoder {
681     (
682         $(
683             $( #[$attr:meta] )*
684                 $snake_name:ident = $name:ident $( {
685                 $(
686                     $( #[$field_attr:meta] )*
687                     $field:ident : $field_ty:ty
688                 ),*
689             } )? ;
690         )*
691     ) => {
692         /// Like `OpVisitor` but for extended operations.
693         pub trait ExtendedOpVisitor: OpVisitor {
694             $(
695                 $( #[$attr] )*
696                 fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return;
697             )*
698         }
699 
700         fn decode_one_extended<V>(
701             visitor: &mut V,
702         ) -> Result<V::Return, <V::BytecodeStream as BytecodeStream>::Error>
703         where
704             V: ExtendedOpVisitor,
705         {
706             let code = u16::decode(visitor.bytecode())?;
707             let opcode = ExtendedOpcode::new(code).ok_or_else(|| {
708                 visitor.bytecode().invalid_extended_opcode(code)
709             })?;
710 
711             match opcode {
712                 $(
713                     ExtendedOpcode::$name => {
714                         $(
715                             $(
716                                 let $field = <$field_ty>::decode(
717                                     visitor.bytecode(),
718                                 )?;
719                             )*
720                         )?
721 
722                         let ret = visitor.$snake_name($( $( $field ),* )?);
723                         visitor.after_visit();
724                         Ok(ret)
725                     }
726                 )*
727             }
728         }
729 
730 
731         impl<F, T, V1, V2> ExtendedOpVisitor for SequencedVisitor<'_, F, V1, V2>
732         where
733             F: FnMut(V1::Return, V2::Return) -> T,
734             V1: ExtendedOpVisitor,
735             V2: ExtendedOpVisitor<BytecodeStream = V1::BytecodeStream>,
736         {
737             $(
738                 $( #[$attr] )*
739                 fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return {
740                     let a = self.v1.$snake_name( $( $( $field , )* )? );
741                     let b = self.v2.$snake_name( $( $( $field , )* )? );
742                     (self.join)(a, b)
743                 }
744             )*
745         }
746     };
747 }
748 for_each_extended_op!(define_extended_decoder);
749 
750 /// Functions for decoding the operands of an instruction, assuming the opcode
751 /// has already been decoded.
752 pub mod operands {
753     use super::*;
754 
755     macro_rules! define_operands_decoder {
756         (
757             $(
758                 $( #[$attr:meta] )*
759                     $snake_name:ident = $name:ident $( {
760                     $(
761                         $( #[$field_attr:meta] )*
762                         $field:ident : $field_ty:ty
763                     ),*
764                 } )? ;
765             )*
766         ) => {
767             $(
768                 #[allow(unused_variables, reason = "macro-generated")]
769                 #[expect(missing_docs, reason = "macro-generated")]
770                 pub fn $snake_name<T: BytecodeStream>(pc: &mut T) -> Result<($($($field_ty,)*)?), T::Error> {
771                     Ok((($($((<$field_ty>::decode(pc))?,)*)?)))
772                 }
773             )*
774         };
775     }
776 
777     for_each_op!(define_operands_decoder);
778 
779     /// Decode an extended opcode from `pc` to match the payload of the
780     /// "extended" opcode.
extended<T: BytecodeStream>(pc: &mut T) -> Result<(ExtendedOpcode,), T::Error>781     pub fn extended<T: BytecodeStream>(pc: &mut T) -> Result<(ExtendedOpcode,), T::Error> {
782         Ok((ExtendedOpcode::decode(pc)?,))
783     }
784 
785     for_each_extended_op!(define_operands_decoder);
786 }
787