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