1 //! Decoding support for pulley bytecode. 2 3 use alloc::vec::Vec; 4 5 use crate::imms::*; 6 use crate::opcode::*; 7 use crate::regs::*; 8 9 /// Either an `Ok(T)` or an `Err(DecodingError)`. 10 pub type Result<T, E = DecodingError> = core::result::Result<T, E>; 11 12 /// An error when decoding Pulley bytecode. 13 pub enum DecodingError { 14 /// Reached the end of the bytecode stream before we finished decoding a 15 /// single bytecode. 16 UnexpectedEof { 17 /// The position in the bytecode stream where this error occurred. 18 position: usize, 19 }, 20 21 /// Found an invalid opcode. 22 InvalidOpcode { 23 /// The position in the bytecode stream where this error occurred. 24 position: usize, 25 /// The invalid opcode that was found. 26 code: u8, 27 }, 28 29 /// Found an invalid extended opcode. 30 InvalidExtendedOpcode { 31 /// The position in the bytecode stream where this error occurred. 32 position: usize, 33 /// The invalid extended opcode that was found. 34 code: u16, 35 }, 36 37 /// Found an invalid register. 38 InvalidReg { 39 /// The position in the bytecode stream where this error occurred. 40 position: usize, 41 /// The invalid register that was found. 42 reg: u8, 43 }, 44 } 45 46 impl core::fmt::Debug for DecodingError { 47 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 48 core::fmt::Display::fmt(self, f) 49 } 50 } 51 52 impl core::fmt::Display for DecodingError { 53 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 54 match self { 55 Self::UnexpectedEof { position } => { 56 write!(f, "unexpected end-of-file at bytecode offset {position:#x}") 57 } 58 Self::InvalidOpcode { position, code } => { 59 write!( 60 f, 61 "found invalid opcode {code:#x} at bytecode offset {position:#x}" 62 ) 63 } 64 Self::InvalidExtendedOpcode { position, code } => { 65 write!( 66 f, 67 "found invalid opcode {code:#x} at bytecode offset {position:#x}" 68 ) 69 } 70 Self::InvalidReg { position, reg } => { 71 write!( 72 f, 73 "found invalid register {reg:#x} at bytecode offset {position:#x}" 74 ) 75 } 76 } 77 } 78 } 79 80 #[cfg(feature = "std")] 81 impl std::error::Error for DecodingError {} 82 83 /// An abstraction over any kind of bytecode stream. 84 /// 85 /// There are two primary implementations: 86 /// 87 /// 1. `SafeBytecodeStream`: A thin wrapper around an index into a `&[u8]`. This 88 /// implementation is 100% safe code. 89 /// 90 /// 2. `UnsafeBytecodeStream`: A thin wrapper over a raw pointer. This 91 /// implementation is wildly unsafe and will result in memory unsafety and 92 /// other terrors when given invalid bytecode, or even valid bytecode 93 /// encoding a program that itself does not preserve memory safety. 94 pub trait BytecodeStream: Copy { 95 /// The type of error that this bytecode stream produces on invalid 96 /// operations. 97 type Error; 98 99 /// Create an "unexpected end-of-stream" error at the current position. 100 fn unexpected_eof(&self) -> Self::Error; 101 102 /// Create an "invalid opcode" error at the current position. 103 fn invalid_opcode(&self, code: u8) -> Self::Error; 104 105 /// Create an "invalid extended opcode" error at the current position. 106 fn invalid_extended_opcode(&self, code: u16) -> Self::Error; 107 108 /// Create an "invalid register" error at the current position. 109 fn invalid_reg(&self, reg: u8) -> Self::Error; 110 111 /// Read `N` bytes from this bytecode stream, advancing the stream's 112 /// position at the same time. 113 fn read<const N: usize>(&mut self) -> Result<[u8; N], Self::Error>; 114 } 115 116 /// A 100% safe implementation of a bytecode stream. 117 /// 118 /// This is a thin wrapper around an index into a `&[u8]`. 119 #[derive(Clone, Copy, Debug)] 120 pub struct SafeBytecodeStream<'a> { 121 bytecode: &'a [u8], 122 position: usize, 123 } 124 125 impl<'a> SafeBytecodeStream<'a> { 126 /// Create a new `SafeBytecodeStream` from the given slice and with an 127 /// initial position pointing at the start of the slice. 128 pub fn new(bytecode: &'a [u8]) -> Self { 129 Self { 130 bytecode, 131 position: 0, 132 } 133 } 134 135 /// Get this stream's current position within its underlying slice. 136 pub fn position(&self) -> usize { 137 self.position 138 } 139 140 /// Get this stream's underlying bytecode slice. 141 pub fn as_slice(&self) -> &[u8] { 142 &self.bytecode 143 } 144 } 145 146 impl BytecodeStream for SafeBytecodeStream<'_> { 147 fn read<const N: usize>(&mut self) -> Result<[u8; N], Self::Error> { 148 let bytes = *self 149 .bytecode 150 .first_chunk::<N>() 151 .ok_or_else(|| self.unexpected_eof())?; 152 self.bytecode = &self.bytecode[N..]; 153 self.position += N; 154 Ok(bytes) 155 } 156 157 type Error = DecodingError; 158 159 fn unexpected_eof(&self) -> Self::Error { 160 DecodingError::UnexpectedEof { 161 position: self.position, 162 } 163 } 164 165 fn invalid_opcode(&self, code: u8) -> Self::Error { 166 DecodingError::InvalidOpcode { 167 position: self.position - 1, 168 code, 169 } 170 } 171 172 fn invalid_extended_opcode(&self, code: u16) -> Self::Error { 173 DecodingError::InvalidExtendedOpcode { 174 position: self.position, 175 code, 176 } 177 } 178 179 fn invalid_reg(&self, reg: u8) -> Self::Error { 180 DecodingError::InvalidReg { 181 position: self.position, 182 reg, 183 } 184 } 185 } 186 187 /// An uninhabited type that cannot be constructed at runtime. 188 #[derive(Debug)] 189 pub enum Uninhabited {} 190 191 /// An unsafe bytecode stream. 192 /// 193 /// This is a wrapper over a raw pointer to bytecode somewhere in memory. 194 #[derive(Clone, Copy, Debug)] 195 pub struct UnsafeBytecodeStream(*mut u8); 196 197 impl UnsafeBytecodeStream { 198 /// Construct a new `UnsafeBytecodeStream` pointing at the given PC. 199 /// 200 /// # Safety 201 /// 202 /// The given `pc` must point to valid Pulley bytecode, and it is the 203 /// caller's responsibility to ensure that the resulting 204 /// `UnsafeBytecodeStream` is only used to access the valid bytecode. For 205 /// example, if the current bytecode instruction unconditionally jumps to a 206 /// new PC, this stream must not be used to read just after the 207 /// unconditional jump instruction because there is no guarantee that that 208 /// memory is part of the bytecode stream or not. 209 pub unsafe fn new(pc: *mut u8) -> Self { 210 assert!(!pc.is_null()); 211 UnsafeBytecodeStream(pc) 212 } 213 214 /// Get a new `UnsafeBytecodeStream` pointing at the bytecode that is at the 215 /// given relative offset from this stream's current position. 216 /// 217 /// # Safety 218 /// 219 /// Same as the `new` constructor. May only be used when it is guaranteed 220 /// that the address at `self._as_ptr() + offset` contains valid Pulley 221 /// bytecode. 222 pub unsafe fn offset(&self, offset: isize) -> Self { 223 UnsafeBytecodeStream(self.0.offset(offset)) 224 } 225 226 /// Get this stream's underlying raw pointer. 227 pub fn as_ptr(&self) -> *mut u8 { 228 self.0 229 } 230 } 231 232 impl BytecodeStream for UnsafeBytecodeStream { 233 fn read<const N: usize>(&mut self) -> Result<[u8; N], Self::Error> { 234 debug_assert!(!self.0.is_null()); 235 let bytes = unsafe { self.0.cast::<[u8; N]>().read() }; 236 self.0 = unsafe { self.0.add(N) }; 237 Ok(bytes) 238 } 239 240 type Error = Uninhabited; 241 242 fn unexpected_eof(&self) -> Self::Error { 243 unsafe { crate::unreachable_unchecked() } 244 } 245 246 fn invalid_opcode(&self, _code: u8) -> Self::Error { 247 unsafe { crate::unreachable_unchecked() } 248 } 249 250 fn invalid_extended_opcode(&self, _code: u16) -> Self::Error { 251 unsafe { crate::unreachable_unchecked() } 252 } 253 254 fn invalid_reg(&self, _reg: u8) -> Self::Error { 255 unsafe { crate::unreachable_unchecked() } 256 } 257 } 258 259 /// Anything that can be decoded from a bytecode stream, e.g. opcodes, 260 /// immediates, registers, etc... 261 trait Decode: Sized { 262 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 263 where 264 T: BytecodeStream; 265 } 266 267 impl Decode for u8 { 268 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 269 where 270 T: BytecodeStream, 271 { 272 bytecode.read::<1>().map(|a| a[0]) 273 } 274 } 275 276 impl Decode for u16 { 277 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 278 where 279 T: BytecodeStream, 280 { 281 Ok(u16::from_le_bytes(bytecode.read()?)) 282 } 283 } 284 285 impl Decode for u32 { 286 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 287 where 288 T: BytecodeStream, 289 { 290 Ok(u32::from_le_bytes(bytecode.read()?)) 291 } 292 } 293 294 impl Decode for u64 { 295 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 296 where 297 T: BytecodeStream, 298 { 299 Ok(u64::from_le_bytes(bytecode.read()?)) 300 } 301 } 302 303 impl Decode for i8 { 304 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 305 where 306 T: BytecodeStream, 307 { 308 bytecode.read::<1>().map(|a| a[0] as i8) 309 } 310 } 311 312 impl Decode for i16 { 313 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 314 where 315 T: BytecodeStream, 316 { 317 Ok(i16::from_le_bytes(bytecode.read()?)) 318 } 319 } 320 321 impl Decode for i32 { 322 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 323 where 324 T: BytecodeStream, 325 { 326 Ok(i32::from_le_bytes(bytecode.read()?)) 327 } 328 } 329 330 impl Decode for i64 { 331 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 332 where 333 T: BytecodeStream, 334 { 335 Ok(i64::from_le_bytes(bytecode.read()?)) 336 } 337 } 338 339 impl Decode for XReg { 340 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 341 where 342 T: BytecodeStream, 343 { 344 let byte = u8::decode(bytecode)?; 345 XReg::new(byte).ok_or_else(|| bytecode.invalid_reg(byte)) 346 } 347 } 348 349 impl Decode for FReg { 350 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 351 where 352 T: BytecodeStream, 353 { 354 let byte = u8::decode(bytecode)?; 355 FReg::new(byte).ok_or_else(|| bytecode.invalid_reg(byte)) 356 } 357 } 358 359 impl Decode for VReg { 360 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 361 where 362 T: BytecodeStream, 363 { 364 let byte = u8::decode(bytecode)?; 365 VReg::new(byte).ok_or_else(|| bytecode.invalid_reg(byte)) 366 } 367 } 368 369 impl Decode for PcRelOffset { 370 fn decode<T>(bytecode: &mut T) -> Result<Self, T::Error> 371 where 372 T: BytecodeStream, 373 { 374 i32::decode(bytecode).map(|x| Self::from(x)) 375 } 376 } 377 378 /// A Pulley bytecode decoder. 379 /// 380 /// Does not materialize bytecode instructions, instead all decoding methods are 381 /// given an `OpVisitor` implementation and the appropriate visitor methods are 382 /// called upon decoding an instruction. This minimizes the amount of times we 383 /// branch on the opcode, avoids constructing temporary storage, and plays well 384 /// with our variable-length instruction encoding. 385 #[derive(Default)] 386 pub struct Decoder { 387 _private: (), 388 } 389 390 impl Decoder { 391 /// Create a new decoder. 392 pub fn new() -> Self { 393 Self::default() 394 } 395 396 /// Decode all instructions in the visitor's bytecode stream. 397 /// 398 /// The associated visitor method is invoked after each instruction is 399 /// decoded. 400 pub fn decode_all<'a, V>(visitor: &mut V) -> Result<Vec<V::Return>> 401 where 402 V: OpVisitor<BytecodeStream = SafeBytecodeStream<'a>> + ExtendedOpVisitor, 403 { 404 let mut decoder = Decoder::new(); 405 let mut results = Vec::new(); 406 407 while !visitor.bytecode().as_slice().is_empty() { 408 results.push(decoder.decode_one(visitor)?); 409 } 410 411 Ok(results) 412 } 413 } 414 415 /// An `OpVisitor` combinator to sequence one visitor and then another. 416 pub struct SequencedVisitor<'a, F, V1, V2> { 417 join: F, 418 v1: &'a mut V1, 419 v2: &'a mut V2, 420 } 421 422 impl<'a, F, V1, V2> SequencedVisitor<'a, F, V1, V2> { 423 /// Create a new sequenced visitor. 424 /// 425 /// The given `join` function is used to combine the results of each 426 /// sub-visitor so that it can be returned from this combined visitor. 427 pub fn new(join: F, v1: &'a mut V1, v2: &'a mut V2) -> Self { 428 SequencedVisitor { join, v1, v2 } 429 } 430 } 431 432 macro_rules! define_decoder { 433 ( 434 $( 435 $( #[$attr:meta] )* 436 $snake_name:ident = $name:ident $( { 437 $( 438 $( #[$field_attr:meta] )* 439 $field:ident : $field_ty:ty 440 ),* 441 } )? ; 442 )* 443 ) => { 444 impl Decoder { 445 /// Decode one instruction from the visitor's bytestream. 446 /// 447 /// Upon decoding, the visitor's associated callback is invoked and 448 /// the results returned. 449 #[inline(always)] 450 pub fn decode_one<V>( 451 &mut self, 452 visitor: &mut V, 453 ) -> Result<V::Return, <V::BytecodeStream as BytecodeStream>::Error> 454 where 455 V: OpVisitor + ExtendedOpVisitor, 456 { 457 visitor.before_visit(); 458 459 let byte = u8::decode(visitor.bytecode())?; 460 let opcode = Opcode::new(byte).ok_or_else(|| { 461 visitor.bytecode().invalid_opcode(byte) 462 })?; 463 464 match opcode { 465 $( 466 Opcode::$name => { 467 $( 468 $( 469 let $field = <$field_ty>::decode( 470 visitor.bytecode(), 471 )?; 472 )* 473 )? 474 475 let ret = visitor.$snake_name($( $( $field ),* )?); 476 visitor.after_visit(); 477 Ok(ret) 478 }, 479 )* 480 Opcode::ExtendedOp => { 481 decode_one_extended(visitor) 482 } 483 } 484 } 485 } 486 487 /// Callbacks upon decoding instructions from bytecode. 488 /// 489 /// Implement this trait for your type, give an instance of your type to 490 /// a `Decoder` method, and the `Decoder` will invoke the associated 491 /// method for each instruction that it decodes. For example, if the 492 /// `Decoder` decodes an `xadd32` instruction, then it will invoke the 493 /// `xadd32` visitor method, passing along any decoded immediates, 494 /// operands, etc... as arguments. 495 pub trait OpVisitor { 496 /// The type of this visitor's bytecode stream. 497 type BytecodeStream: BytecodeStream; 498 499 /// Get this visitor's underlying bytecode stream. 500 fn bytecode(&mut self) -> &mut Self::BytecodeStream; 501 502 /// The type of values returned by each visitor method. 503 type Return; 504 505 /// A callback invoked before starting to decode an instruction. 506 /// 507 /// Does nothing by default. 508 fn before_visit(&mut self) {} 509 510 /// A callback invoked after an instruction has been completely 511 /// decoded. 512 /// 513 /// Does nothing by default. 514 fn after_visit(&mut self) {} 515 516 $( 517 $( #[$attr] )* 518 fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return; 519 )* 520 } 521 522 impl<F, T, V1, V2> OpVisitor for SequencedVisitor<'_, F, V1, V2> 523 where 524 F: FnMut(V1::Return, V2::Return) -> T, 525 V1: OpVisitor, 526 V2: OpVisitor<BytecodeStream = V1::BytecodeStream>, 527 { 528 type BytecodeStream = V1::BytecodeStream; 529 530 fn bytecode(&mut self) -> &mut Self::BytecodeStream { 531 self.v1.bytecode() 532 } 533 534 type Return = T; 535 536 fn before_visit(&mut self) { 537 self.v1.before_visit(); 538 self.v2.before_visit(); 539 } 540 541 fn after_visit(&mut self) { 542 *self.v2.bytecode() = *self.v1.bytecode(); 543 self.v1.after_visit(); 544 self.v2.after_visit(); 545 } 546 547 $( 548 $( #[$attr] )* 549 fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return { 550 let a = self.v1.$snake_name( $( $( $field , )* )? ); 551 let b = self.v2.$snake_name( $( $( $field , )* )? ); 552 (self.join)(a, b) 553 } 554 )* 555 } 556 }; 557 } 558 for_each_op!(define_decoder); 559 560 macro_rules! define_extended_decoder { 561 ( 562 $( 563 $( #[$attr:meta] )* 564 $snake_name:ident = $name:ident $( { 565 $( 566 $( #[$field_attr:meta] )* 567 $field:ident : $field_ty:ty 568 ),* 569 } )? ; 570 )* 571 ) => { 572 /// Like `OpVisitor` but for extended operations. 573 pub trait ExtendedOpVisitor: OpVisitor { 574 $( 575 $( #[$attr] )* 576 fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return; 577 )* 578 } 579 580 fn decode_one_extended<V>( 581 visitor: &mut V, 582 ) -> Result<V::Return, <V::BytecodeStream as BytecodeStream>::Error> 583 where 584 V: ExtendedOpVisitor, 585 { 586 let code = u16::decode(visitor.bytecode())?; 587 let opcode = ExtendedOpcode::new(code).ok_or_else(|| { 588 visitor.bytecode().invalid_extended_opcode(code) 589 })?; 590 591 match opcode { 592 $( 593 ExtendedOpcode::$name => { 594 $( 595 $( 596 let $field = <$field_ty>::decode( 597 visitor.bytecode(), 598 )?; 599 )* 600 )? 601 602 let ret = visitor.$snake_name($( $( $field ),* )?); 603 visitor.after_visit(); 604 Ok(ret) 605 } 606 )* 607 } 608 } 609 610 611 impl<F, T, V1, V2> ExtendedOpVisitor for SequencedVisitor<'_, F, V1, V2> 612 where 613 F: FnMut(V1::Return, V2::Return) -> T, 614 V1: ExtendedOpVisitor, 615 V2: ExtendedOpVisitor<BytecodeStream = V1::BytecodeStream>, 616 { 617 $( 618 $( #[$attr] )* 619 fn $snake_name(&mut self $( $( , $field : $field_ty )* )? ) -> Self::Return { 620 let a = self.v1.$snake_name( $( $( $field , )* )? ); 621 let b = self.v2.$snake_name( $( $( $field , )* )? ); 622 (self.join)(a, b) 623 } 624 )* 625 } 626 }; 627 } 628 for_each_extended_op!(define_extended_decoder); 629