Next Generation WASM Microkernel Operating System
at trap_handler 1520 lines 46 kB view raw
1use alloc::borrow::Cow; 2#[cfg(feature = "component-model")] 3use crate::component::Component; 4use crate::core::*; 5use crate::encode::Encode; 6use crate::token::*; 7use crate::Wat; 8use alloc::vec; 9use alloc::vec::Vec; 10use core::marker; 11 12/// Options that can be specified when encoding a component or a module to 13/// customize what the final binary looks like. 14/// 15/// Methods such as [`Module::encode`], [`Wat::encode`], and 16/// [`Component::encode`] will use the default options. 17#[derive(Default)] 18pub struct EncodeOptions<'a> { 19 #[cfg(feature = "dwarf")] 20 dwarf_info: Option<(&'a str, &'a str, GenerateDwarf)>, 21 22 _marker: marker::PhantomData<&'a str>, 23} 24 25#[cfg(feature = "dwarf")] 26mod dwarf; 27 28#[cfg(not(feature = "dwarf"))] 29mod dwarf_disabled; 30#[cfg(not(feature = "dwarf"))] 31use self::dwarf_disabled as dwarf; 32 33/// Configuration of how DWARF debugging information may be generated. 34#[derive(Copy, Clone, Debug)] 35#[non_exhaustive] 36pub enum GenerateDwarf { 37 /// Only generate line tables to map binary offsets back to source 38 /// locations. 39 Lines, 40 41 /// Generate full debugging information for both line numbers and 42 /// variables/locals/operands. 43 Full, 44} 45 46impl<'a> EncodeOptions<'a> { 47 /// Creates a new set of default encoding options. 48 pub fn new() -> EncodeOptions<'a> { 49 EncodeOptions::default() 50 } 51 52 /// Enables emission of DWARF debugging information in the final binary. 53 /// 54 /// This method will use the `file` specified as the source file for the 55 /// `*.wat` file whose `contents` must also be supplied here. These are 56 /// used to calculate filenames/line numbers and are referenced from the 57 /// generated DWARF. 58 #[cfg(feature = "dwarf")] 59 pub fn dwarf(&mut self, file: &'a str, contents: &'a str, style: GenerateDwarf) -> &mut Self { 60 self.dwarf_info = Some((file, contents, style)); 61 self 62 } 63 64 /// Encodes the given [`Module`] with these options. 65 /// 66 /// For more information see [`Module::encode`]. 67 pub fn encode_module( 68 &self, 69 module: &mut Module<'_>, 70 ) -> core::result::Result<Vec<u8>, crate::Error> { 71 module.resolve()?; 72 Ok(match &module.kind { 73 ModuleKind::Text(fields) => encode(&module.id, &module.name, fields, self), 74 ModuleKind::Binary(blobs) => blobs.iter().flat_map(|b| b.iter().cloned()).collect(), 75 }) 76 } 77 78 /// Encodes the given [`Component`] with these options. 79 /// 80 /// For more information see [`Component::encode`]. 81 #[cfg(feature = "component-model")] 82 pub fn encode_component( 83 &self, 84 component: &mut Component<'_>, 85 ) -> core::result::Result<Vec<u8>, crate::Error> { 86 component.resolve()?; 87 Ok(crate::component::binary::encode(component, self)) 88 } 89 90 /// Encodes the given [`Wat`] with these options. 91 /// 92 /// For more information see [`Wat::encode`]. 93 pub fn encode_wat(&self, wat: &mut Wat<'_>) -> core::result::Result<Vec<u8>, crate::Error> { 94 match wat { 95 Wat::Module(m) => self.encode_module(m), 96 #[cfg(feature = "component-model")] 97 Wat::Component(c) => self.encode_component(c), 98 #[cfg(not(feature = "component-model"))] 99 Wat::Component(_) => unreachable!(), 100 } 101 } 102} 103 104pub(crate) fn encode( 105 module_id: &Option<Id<'_>>, 106 module_name: &Option<NameAnnotation<'_>>, 107 fields: &[ModuleField<'_>], 108 opts: &EncodeOptions, 109) -> Vec<u8> { 110 use CustomPlace::*; 111 use CustomPlaceAnchor::*; 112 113 let mut types = Vec::new(); 114 let mut imports = Vec::new(); 115 let mut funcs = Vec::new(); 116 let mut tables = Vec::new(); 117 let mut memories = Vec::new(); 118 let mut globals = Vec::new(); 119 let mut exports = Vec::new(); 120 let mut start = Vec::new(); 121 let mut elem = Vec::new(); 122 let mut data = Vec::new(); 123 let mut tags = Vec::new(); 124 let mut customs = Vec::new(); 125 for field in fields { 126 match field { 127 ModuleField::Type(i) => types.push(RecOrType::Type(i)), 128 ModuleField::Rec(i) => types.push(RecOrType::Rec(i)), 129 ModuleField::Import(i) => imports.push(i), 130 ModuleField::Func(i) => funcs.push(i), 131 ModuleField::Table(i) => tables.push(i), 132 ModuleField::Memory(i) => memories.push(i), 133 ModuleField::Global(i) => globals.push(i), 134 ModuleField::Export(i) => exports.push(i), 135 ModuleField::Start(i) => start.push(i), 136 ModuleField::Elem(i) => elem.push(i), 137 ModuleField::Data(i) => data.push(i), 138 ModuleField::Tag(i) => tags.push(i), 139 ModuleField::Custom(i) => customs.push(i), 140 } 141 } 142 143 let mut e = Encoder { 144 wasm: wasm_encoder::Module::new(), 145 customs: &customs, 146 }; 147 148 e.custom_sections(BeforeFirst); 149 150 e.typed_section(&types); 151 e.typed_section(&imports); 152 153 let functys = funcs 154 .iter() 155 .map(|f| FuncSectionTy(&f.ty)) 156 .collect::<Vec<_>>(); 157 e.typed_section(&functys); 158 e.typed_section(&tables); 159 e.typed_section(&memories); 160 e.typed_section(&tags); 161 e.typed_section(&globals); 162 e.typed_section(&exports); 163 e.custom_sections(Before(Start)); 164 if let Some(start) = start.first() { 165 e.wasm.section(&wasm_encoder::StartSection { 166 function_index: start.unwrap_u32(), 167 }); 168 } 169 e.custom_sections(After(Start)); 170 e.typed_section(&elem); 171 if needs_data_count(&funcs) { 172 e.wasm.section(&wasm_encoder::DataCountSection { 173 count: data.len().try_into().unwrap(), 174 }); 175 } 176 177 // Prepare to and emit the code section. This is where DWARF may optionally 178 // be emitted depending on configuration settings. Note that `code_section` 179 // will internally emit the branch hints section if necessary. 180 let names = find_names(module_id, module_name, fields); 181 let num_import_funcs = imports 182 .iter() 183 .filter(|i| matches!(i.item.kind, ItemKind::Func(..))) 184 .count() as u32; 185 let mut dwarf = dwarf::Dwarf::new(num_import_funcs, opts, &names, &types); 186 e.code_section(&funcs, num_import_funcs, dwarf.as_mut()); 187 188 e.typed_section(&data); 189 190 if !names.is_empty() { 191 e.wasm.section(&names.to_name_section()); 192 } 193 e.custom_sections(AfterLast); 194 if let Some(dwarf) = &mut dwarf { 195 dwarf.emit(&mut e); 196 } 197 198 return e.wasm.finish(); 199 200 fn needs_data_count(funcs: &[&crate::core::Func<'_>]) -> bool { 201 funcs 202 .iter() 203 .filter_map(|f| match &f.kind { 204 FuncKind::Inline { expression, .. } => Some(expression), 205 _ => None, 206 }) 207 .flat_map(|e| e.instrs.iter()) 208 .any(|i| i.needs_data_count()) 209 } 210} 211 212struct Encoder<'a> { 213 wasm: wasm_encoder::Module, 214 customs: &'a [&'a Custom<'a>], 215} 216 217impl Encoder<'_> { 218 fn custom_sections(&mut self, place: CustomPlace) { 219 for entry in self.customs.iter() { 220 if entry.place() == place { 221 entry.encode(&mut self.wasm); 222 } 223 } 224 } 225 226 fn typed_section<T>(&mut self, list: &[T]) 227 where 228 T: SectionItem, 229 { 230 self.custom_sections(CustomPlace::Before(T::ANCHOR)); 231 if !list.is_empty() { 232 let mut section = T::Section::default(); 233 for item in list { 234 item.encode(&mut section); 235 } 236 self.wasm.section(&section); 237 } 238 self.custom_sections(CustomPlace::After(T::ANCHOR)); 239 } 240 241 /// Encodes the code section of a wasm module module while additionally 242 /// handling the branch hinting proposal. 243 /// 244 /// The branch hinting proposal requires to encode the offsets of the 245 /// instructions relative from the beginning of the function. Here we encode 246 /// each instruction and we save its offset. If needed, we use this 247 /// information to build the branch hint section and insert it before the 248 /// code section. 249 /// 250 /// The `list` provided is the list of functions that are emitted into the 251 /// code section. The `func_index` provided is the initial index of defined 252 /// functions, so it's the count of imported functions. The `dwarf` field is 253 /// optionally used to track debugging information. 254 fn code_section<'a>( 255 &'a mut self, 256 list: &[&'a Func<'_>], 257 mut func_index: u32, 258 mut dwarf: Option<&mut dwarf::Dwarf>, 259 ) { 260 self.custom_sections(CustomPlace::Before(CustomPlaceAnchor::Code)); 261 262 if !list.is_empty() { 263 let mut branch_hints = wasm_encoder::BranchHints::new(); 264 let mut code_section = wasm_encoder::CodeSection::new(); 265 266 for func in list.iter() { 267 let hints = func.encode(&mut code_section, dwarf.as_deref_mut()); 268 if !hints.is_empty() { 269 branch_hints.function_hints(func_index, hints.into_iter()); 270 } 271 func_index += 1; 272 } 273 274 // Branch hints section has to be inserted before the Code section 275 // Insert the section only if we have some hints 276 if !branch_hints.is_empty() { 277 self.wasm.section(&branch_hints); 278 } 279 280 // Finally, insert the Code section from the tmp buffer 281 self.wasm.section(&code_section); 282 283 if let Some(dwarf) = &mut dwarf { 284 dwarf.set_code_section_size(code_section.byte_len()); 285 } 286 } 287 self.custom_sections(CustomPlace::After(CustomPlaceAnchor::Code)); 288 } 289} 290 291trait SectionItem { 292 type Section: wasm_encoder::Section + Default; 293 const ANCHOR: CustomPlaceAnchor; 294 295 fn encode(&self, section: &mut Self::Section); 296} 297 298impl<T> SectionItem for &T 299where 300 T: SectionItem, 301{ 302 type Section = T::Section; 303 const ANCHOR: CustomPlaceAnchor = T::ANCHOR; 304 305 fn encode(&self, section: &mut Self::Section) { 306 T::encode(self, section) 307 } 308} 309 310impl From<&FunctionType<'_>> for wasm_encoder::FuncType { 311 fn from(ft: &FunctionType) -> Self { 312 wasm_encoder::FuncType::new( 313 ft.params.iter().map(|(_, _, ty)| (*ty).into()), 314 ft.results.iter().map(|ty| (*ty).into()), 315 ) 316 } 317} 318 319impl From<&StructType<'_>> for wasm_encoder::StructType { 320 fn from(st: &StructType) -> wasm_encoder::StructType { 321 wasm_encoder::StructType { 322 fields: st.fields.iter().map(|f| f.into()).collect(), 323 } 324 } 325} 326 327impl From<&StructField<'_>> for wasm_encoder::FieldType { 328 fn from(f: &StructField) -> wasm_encoder::FieldType { 329 wasm_encoder::FieldType { 330 element_type: f.ty.into(), 331 mutable: f.mutable, 332 } 333 } 334} 335 336impl From<&ArrayType<'_>> for wasm_encoder::ArrayType { 337 fn from(at: &ArrayType) -> Self { 338 let field = wasm_encoder::FieldType { 339 element_type: at.ty.into(), 340 mutable: at.mutable, 341 }; 342 wasm_encoder::ArrayType(field) 343 } 344} 345 346impl From<&ContType<'_>> for wasm_encoder::ContType { 347 fn from(at: &ContType) -> Self { 348 wasm_encoder::ContType(at.0.into()) 349 } 350} 351 352enum RecOrType<'a> { 353 Type(&'a Type<'a>), 354 Rec(&'a Rec<'a>), 355} 356 357impl SectionItem for RecOrType<'_> { 358 type Section = wasm_encoder::TypeSection; 359 const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Type; 360 361 fn encode(&self, types: &mut wasm_encoder::TypeSection) { 362 match self { 363 RecOrType::Type(ty) => types.ty().subtype(&ty.to_subtype()), 364 RecOrType::Rec(rec) => types.ty().rec(rec.types.iter().map(|t| t.to_subtype())), 365 } 366 } 367} 368 369impl Type<'_> { 370 pub(crate) fn to_subtype(&self) -> wasm_encoder::SubType { 371 self.def.to_subtype() 372 } 373} 374 375impl TypeDef<'_> { 376 pub(crate) fn to_subtype(&self) -> wasm_encoder::SubType { 377 use wasm_encoder::CompositeInnerType::*; 378 let composite_type = wasm_encoder::CompositeType { 379 inner: match &self.kind { 380 InnerTypeKind::Func(ft) => Func(ft.into()), 381 InnerTypeKind::Struct(st) => Struct(st.into()), 382 InnerTypeKind::Array(at) => Array(at.into()), 383 InnerTypeKind::Cont(ct) => Cont(ct.into()), 384 }, 385 shared: self.shared, 386 }; 387 wasm_encoder::SubType { 388 composite_type, 389 is_final: self.final_type.unwrap_or(true), 390 supertype_idx: self.parent.map(|i| i.unwrap_u32()), 391 } 392 } 393} 394 395impl From<ValType<'_>> for wasm_encoder::ValType { 396 fn from(ty: ValType) -> Self { 397 match ty { 398 ValType::I32 => Self::I32, 399 ValType::I64 => Self::I64, 400 ValType::F32 => Self::F32, 401 ValType::F64 => Self::F64, 402 ValType::V128 => Self::V128, 403 ValType::Ref(r) => Self::Ref(r.into()), 404 } 405 } 406} 407 408impl From<RefType<'_>> for wasm_encoder::RefType { 409 fn from(r: RefType<'_>) -> Self { 410 wasm_encoder::RefType { 411 nullable: r.nullable, 412 heap_type: r.heap.into(), 413 } 414 } 415} 416 417impl From<HeapType<'_>> for wasm_encoder::HeapType { 418 fn from(r: HeapType<'_>) -> Self { 419 use wasm_encoder::AbstractHeapType::*; 420 match r { 421 HeapType::Abstract { shared, ty } => { 422 let ty = match ty { 423 AbstractHeapType::Func => Func, 424 AbstractHeapType::Extern => Extern, 425 AbstractHeapType::Exn => Exn, 426 AbstractHeapType::NoExn => NoExn, 427 AbstractHeapType::Any => Any, 428 AbstractHeapType::Eq => Eq, 429 AbstractHeapType::Struct => Struct, 430 AbstractHeapType::Array => Array, 431 AbstractHeapType::NoFunc => NoFunc, 432 AbstractHeapType::NoExtern => NoExtern, 433 AbstractHeapType::None => None, 434 AbstractHeapType::I31 => I31, 435 AbstractHeapType::Cont => Cont, 436 AbstractHeapType::NoCont => NoCont, 437 }; 438 Self::Abstract { shared, ty } 439 } 440 HeapType::Concrete(i) => Self::Concrete(i.unwrap_u32()), 441 } 442 } 443} 444 445impl Encode for Option<Id<'_>> { 446 fn encode(&self, _e: &mut Vec<u8>) { 447 // used for parameters in the tuple impl as well as instruction labels 448 } 449} 450 451impl<'a> Encode for ValType<'a> { 452 fn encode(&self, e: &mut Vec<u8>) { 453 wasm_encoder::Encode::encode(&wasm_encoder::ValType::from(*self), e) 454 } 455} 456 457impl<'a> Encode for HeapType<'a> { 458 fn encode(&self, e: &mut Vec<u8>) { 459 wasm_encoder::Encode::encode(&wasm_encoder::HeapType::from(*self), e) 460 } 461} 462 463impl From<StorageType<'_>> for wasm_encoder::StorageType { 464 fn from(st: StorageType) -> Self { 465 use wasm_encoder::StorageType::*; 466 match st { 467 StorageType::I8 => I8, 468 StorageType::I16 => I16, 469 StorageType::Val(vt) => Val(vt.into()), 470 } 471 } 472} 473 474impl SectionItem for Import<'_> { 475 type Section = wasm_encoder::ImportSection; 476 const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Import; 477 478 fn encode(&self, section: &mut wasm_encoder::ImportSection) { 479 section.import(self.module, self.field, self.item.to_entity_type()); 480 } 481} 482 483impl ItemSig<'_> { 484 pub(crate) fn to_entity_type(&self) -> wasm_encoder::EntityType { 485 self.kind.to_entity_type() 486 } 487} 488 489impl ItemKind<'_> { 490 fn to_entity_type(&self) -> wasm_encoder::EntityType { 491 use wasm_encoder::EntityType as ET; 492 match self { 493 ItemKind::Func(t) => ET::Function(t.unwrap_u32()), 494 ItemKind::Table(t) => ET::Table(t.to_table_type()), 495 ItemKind::Memory(t) => ET::Memory(t.to_memory_type()), 496 ItemKind::Global(t) => ET::Global(t.to_global_type()), 497 ItemKind::Tag(t) => ET::Tag(t.to_tag_type()), 498 } 499 } 500} 501 502impl TableType<'_> { 503 fn to_table_type(self) -> wasm_encoder::TableType { 504 wasm_encoder::TableType { 505 element_type: self.elem.into(), 506 minimum: self.limits.min, 507 maximum: self.limits.max, 508 table64: self.limits.is64, 509 shared: self.shared, 510 } 511 } 512} 513 514impl MemoryType { 515 fn to_memory_type(self) -> wasm_encoder::MemoryType { 516 wasm_encoder::MemoryType { 517 minimum: self.limits.min, 518 maximum: self.limits.max, 519 memory64: self.limits.is64, 520 shared: self.shared, 521 page_size_log2: self.page_size_log2, 522 } 523 } 524} 525 526impl GlobalType<'_> { 527 fn to_global_type(self) -> wasm_encoder::GlobalType { 528 wasm_encoder::GlobalType { 529 val_type: self.ty.into(), 530 mutable: self.mutable, 531 shared: self.shared, 532 } 533 } 534} 535 536impl TagType<'_> { 537 fn to_tag_type(&self) -> wasm_encoder::TagType { 538 match self { 539 TagType::Exception(r) => wasm_encoder::TagType { 540 kind: wasm_encoder::TagKind::Exception, 541 func_type_idx: r.unwrap_u32(), 542 }, 543 } 544 } 545} 546 547impl<T> TypeUse<'_, T> { 548 fn unwrap_u32(&self) -> u32 { 549 self.index 550 .as_ref() 551 .expect("TypeUse should be filled in by this point") 552 .unwrap_u32() 553 } 554} 555 556struct FuncSectionTy<'a>(&'a TypeUse<'a, FunctionType<'a>>); 557 558impl SectionItem for FuncSectionTy<'_> { 559 type Section = wasm_encoder::FunctionSection; 560 const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Func; 561 562 fn encode(&self, section: &mut wasm_encoder::FunctionSection) { 563 section.function(self.0.unwrap_u32()); 564 } 565} 566 567impl Encode for Index<'_> { 568 fn encode(&self, e: &mut Vec<u8>) { 569 self.unwrap_u32().encode(e) 570 } 571} 572 573impl Index<'_> { 574 fn unwrap_u32(&self) -> u32 { 575 match self { 576 Index::Num(n, _) => *n, 577 Index::Id(n) => panic!("unresolved index in emission: {:?}", n), 578 } 579 } 580} 581 582impl From<Index<'_>> for u32 { 583 fn from(i: Index<'_>) -> Self { 584 match i { 585 Index::Num(i, _) => i, 586 Index::Id(_) => unreachable!("unresolved index in encoding: {:?}", i), 587 } 588 } 589} 590 591impl SectionItem for Table<'_> { 592 type Section = wasm_encoder::TableSection; 593 const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Table; 594 595 fn encode(&self, section: &mut wasm_encoder::TableSection) { 596 assert!(self.exports.names.is_empty()); 597 match &self.kind { 598 TableKind::Normal { 599 ty, 600 init_expr: None, 601 } => { 602 section.table(ty.to_table_type()); 603 } 604 TableKind::Normal { 605 ty, 606 init_expr: Some(init_expr), 607 } => { 608 section.table_with_init(ty.to_table_type(), &init_expr.to_const_expr()); 609 } 610 _ => panic!("TableKind should be normal during encoding"), 611 } 612 } 613} 614 615impl SectionItem for Memory<'_> { 616 type Section = wasm_encoder::MemorySection; 617 const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Memory; 618 619 fn encode(&self, section: &mut wasm_encoder::MemorySection) { 620 assert!(self.exports.names.is_empty()); 621 match &self.kind { 622 MemoryKind::Normal(t) => { 623 section.memory(t.to_memory_type()); 624 } 625 _ => panic!("MemoryKind should be normal during encoding"), 626 } 627 } 628} 629 630impl SectionItem for Global<'_> { 631 type Section = wasm_encoder::GlobalSection; 632 const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Global; 633 634 fn encode(&self, section: &mut wasm_encoder::GlobalSection) { 635 assert!(self.exports.names.is_empty()); 636 let init = match &self.kind { 637 GlobalKind::Inline(expr) => expr.to_const_expr(), 638 _ => panic!("GlobalKind should be inline during encoding"), 639 }; 640 section.global(self.ty.to_global_type(), &init); 641 } 642} 643 644impl SectionItem for Export<'_> { 645 type Section = wasm_encoder::ExportSection; 646 const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Export; 647 648 fn encode(&self, section: &mut wasm_encoder::ExportSection) { 649 section.export(self.name, self.kind.into(), self.item.unwrap_u32()); 650 } 651} 652 653impl From<ExportKind> for wasm_encoder::ExportKind { 654 fn from(kind: ExportKind) -> Self { 655 match kind { 656 ExportKind::Func => Self::Func, 657 ExportKind::Table => Self::Table, 658 ExportKind::Memory => Self::Memory, 659 ExportKind::Global => Self::Global, 660 ExportKind::Tag => Self::Tag, 661 } 662 } 663} 664 665impl SectionItem for Elem<'_> { 666 type Section = wasm_encoder::ElementSection; 667 const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Elem; 668 669 fn encode(&self, section: &mut wasm_encoder::ElementSection) { 670 use wasm_encoder::Elements; 671 672 let elements = match &self.payload { 673 ElemPayload::Indices(v) => { 674 Elements::Functions(Cow::Owned(v.iter().map(|i| i.unwrap_u32()).collect())) 675 } 676 ElemPayload::Exprs { exprs, ty } => Elements::Expressions( 677 (*ty).into(), 678 Cow::Owned(exprs.iter().map(|e| e.to_const_expr()).collect()), 679 ), 680 }; 681 match &self.kind { 682 ElemKind::Active { table, offset } => { 683 section.active( 684 table.map(|t| t.unwrap_u32()), 685 &offset.to_const_expr(), 686 elements, 687 ); 688 } 689 ElemKind::Passive => { 690 section.passive(elements); 691 } 692 ElemKind::Declared => { 693 section.declared(elements); 694 } 695 } 696 } 697} 698 699impl SectionItem for Data<'_> { 700 type Section = wasm_encoder::DataSection; 701 const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Data; 702 703 fn encode(&self, section: &mut wasm_encoder::DataSection) { 704 let mut data = Vec::new(); 705 for val in self.data.iter() { 706 val.push_onto(&mut data); 707 } 708 match &self.kind { 709 DataKind::Passive => { 710 section.passive(data); 711 } 712 DataKind::Active { memory, offset } => { 713 section.active(memory.unwrap_u32(), &offset.to_const_expr(), data); 714 } 715 } 716 } 717} 718 719impl Func<'_> { 720 /// Encodes the function into `e` while returning all branch hints with 721 /// known relative offsets after encoding. 722 /// 723 /// The `dwarf` field is optional and used to track debugging information 724 /// for each instruction. 725 fn encode( 726 &self, 727 section: &mut wasm_encoder::CodeSection, 728 mut dwarf: Option<&mut dwarf::Dwarf>, 729 ) -> Vec<wasm_encoder::BranchHint> { 730 assert!(self.exports.names.is_empty()); 731 let (expr, locals) = match &self.kind { 732 FuncKind::Inline { expression, locals } => (expression, locals), 733 _ => panic!("should only have inline functions in emission"), 734 }; 735 736 if let Some(dwarf) = &mut dwarf { 737 let index = match self.ty.index.as_ref().unwrap() { 738 Index::Num(n, _) => *n, 739 _ => unreachable!(), 740 }; 741 dwarf.start_func(self.span, index, locals); 742 } 743 744 // Encode the function into a temporary vector because functions are 745 // prefixed with their length. The temporary vector, when encoded, 746 // encodes its length first then the body. 747 let mut func = 748 wasm_encoder::Function::new_with_locals_types(locals.iter().map(|t| t.ty.into())); 749 let branch_hints = expr.encode(&mut func, dwarf.as_deref_mut()); 750 let func_size = func.byte_len(); 751 section.function(&func); 752 753 if let Some(dwarf) = &mut dwarf { 754 dwarf.end_func(func_size, section.byte_len()); 755 } 756 757 branch_hints 758 } 759} 760 761impl Expression<'_> { 762 /// Encodes this expression into `e` and optionally tracks debugging 763 /// information for each instruction in `dwarf`. 764 /// 765 /// Returns all branch hints, if any, found while parsing this function. 766 fn encode( 767 &self, 768 func: &mut wasm_encoder::Function, 769 mut dwarf: Option<&mut dwarf::Dwarf>, 770 ) -> Vec<wasm_encoder::BranchHint> { 771 let mut hints = Vec::with_capacity(self.branch_hints.len()); 772 let mut next_hint = self.branch_hints.iter().peekable(); 773 let mut tmp = Vec::new(); 774 775 for (i, instr) in self.instrs.iter().enumerate() { 776 // Branch hints are stored in order of increasing `instr_index` so 777 // check to see if the next branch hint matches this instruction's 778 // index. 779 if let Some(hint) = next_hint.next_if(|h| h.instr_index == i) { 780 hints.push(wasm_encoder::BranchHint { 781 branch_func_offset: u32::try_from(func.byte_len() + tmp.len()).unwrap(), 782 branch_hint_value: hint.value, 783 }); 784 } 785 786 // If DWARF is enabled then track this instruction's binary offset 787 // and source location. 788 if let Some(dwarf) = &mut dwarf { 789 if let Some(span) = self.instr_spans.as_ref().map(|s| s[i]) { 790 dwarf.instr(func.byte_len() + tmp.len(), span); 791 } 792 } 793 794 // Finally emit the instruction and move to the next. 795 instr.encode(&mut tmp); 796 } 797 func.raw(tmp.iter().copied()); 798 func.instructions().end(); 799 800 hints 801 } 802 803 fn to_const_expr(&self) -> wasm_encoder::ConstExpr { 804 let mut tmp = Vec::new(); 805 for instr in self.instrs.iter() { 806 instr.encode(&mut tmp); 807 } 808 wasm_encoder::ConstExpr::raw(tmp) 809 } 810} 811 812impl Encode for BlockType<'_> { 813 fn encode(&self, e: &mut Vec<u8>) { 814 // block types using an index are encoded as an sleb, not a uleb 815 if let Some(Index::Num(n, _)) = &self.ty.index { 816 return i64::from(*n).encode(e); 817 } 818 let ty = self 819 .ty 820 .inline 821 .as_ref() 822 .expect("function type not filled in"); 823 if ty.params.is_empty() && ty.results.is_empty() { 824 return e.push(0x40); 825 } 826 if ty.params.is_empty() && ty.results.len() == 1 { 827 return ty.results[0].encode(e); 828 } 829 panic!("multi-value block types should have an index"); 830 } 831} 832 833impl Encode for LaneArg { 834 fn encode(&self, e: &mut Vec<u8>) { 835 self.lane.encode(e); 836 } 837} 838 839impl Encode for MemArg<'_> { 840 fn encode(&self, e: &mut Vec<u8>) { 841 match &self.memory { 842 Index::Num(0, _) => { 843 self.align.trailing_zeros().encode(e); 844 self.offset.encode(e); 845 } 846 _ => { 847 (self.align.trailing_zeros() | (1 << 6)).encode(e); 848 self.memory.encode(e); 849 self.offset.encode(e); 850 } 851 } 852 } 853} 854 855impl Encode for Ordering { 856 fn encode(&self, buf: &mut Vec<u8>) { 857 let flag: u8 = match self { 858 Ordering::SeqCst => 0, 859 Ordering::AcqRel => 1, 860 }; 861 flag.encode(buf); 862 } 863} 864 865impl<T> Encode for Ordered<T> 866where 867 T: Encode, 868{ 869 fn encode(&self, buf: &mut Vec<u8>) { 870 self.ordering.encode(buf); 871 self.inner.encode(buf); 872 } 873} 874 875impl Encode for LoadOrStoreLane<'_> { 876 fn encode(&self, e: &mut Vec<u8>) { 877 self.memarg.encode(e); 878 self.lane.encode(e); 879 } 880} 881 882impl Encode for CallIndirect<'_> { 883 fn encode(&self, e: &mut Vec<u8>) { 884 self.ty.unwrap_u32().encode(e); 885 self.table.encode(e); 886 } 887} 888 889impl Encode for TableInit<'_> { 890 fn encode(&self, e: &mut Vec<u8>) { 891 self.elem.encode(e); 892 self.table.encode(e); 893 } 894} 895 896impl Encode for TableCopy<'_> { 897 fn encode(&self, e: &mut Vec<u8>) { 898 self.dst.encode(e); 899 self.src.encode(e); 900 } 901} 902 903impl Encode for TableArg<'_> { 904 fn encode(&self, e: &mut Vec<u8>) { 905 self.dst.encode(e); 906 } 907} 908 909impl Encode for MemoryArg<'_> { 910 fn encode(&self, e: &mut Vec<u8>) { 911 self.mem.encode(e); 912 } 913} 914 915impl Encode for MemoryInit<'_> { 916 fn encode(&self, e: &mut Vec<u8>) { 917 self.data.encode(e); 918 self.mem.encode(e); 919 } 920} 921 922impl Encode for MemoryCopy<'_> { 923 fn encode(&self, e: &mut Vec<u8>) { 924 self.dst.encode(e); 925 self.src.encode(e); 926 } 927} 928 929impl Encode for BrTableIndices<'_> { 930 fn encode(&self, e: &mut Vec<u8>) { 931 self.labels.encode(e); 932 self.default.encode(e); 933 } 934} 935 936impl Encode for F32 { 937 fn encode(&self, e: &mut Vec<u8>) { 938 e.extend_from_slice(&self.bits.to_le_bytes()); 939 } 940} 941 942impl Encode for F64 { 943 fn encode(&self, e: &mut Vec<u8>) { 944 e.extend_from_slice(&self.bits.to_le_bytes()); 945 } 946} 947 948#[derive(Default)] 949struct Names<'a> { 950 module: Option<&'a str>, 951 funcs: Vec<(u32, &'a str)>, 952 func_idx: u32, 953 locals: Vec<(u32, Vec<(u32, &'a str)>)>, 954 labels: Vec<(u32, Vec<(u32, &'a str)>)>, 955 globals: Vec<(u32, &'a str)>, 956 global_idx: u32, 957 memories: Vec<(u32, &'a str)>, 958 memory_idx: u32, 959 tables: Vec<(u32, &'a str)>, 960 table_idx: u32, 961 tags: Vec<(u32, &'a str)>, 962 tag_idx: u32, 963 types: Vec<(u32, &'a str)>, 964 type_idx: u32, 965 data: Vec<(u32, &'a str)>, 966 data_idx: u32, 967 elems: Vec<(u32, &'a str)>, 968 elem_idx: u32, 969 fields: Vec<(u32, Vec<(u32, &'a str)>)>, 970} 971 972fn find_names<'a>( 973 module_id: &Option<Id<'a>>, 974 module_name: &Option<NameAnnotation<'a>>, 975 fields: &[ModuleField<'a>], 976) -> Names<'a> { 977 fn get_name<'a>(id: &Option<Id<'a>>, name: &Option<NameAnnotation<'a>>) -> Option<&'a str> { 978 name.as_ref().map(|n| n.name).or(id.and_then(|id| { 979 if id.is_gensym() { 980 None 981 } else { 982 Some(id.name()) 983 } 984 })) 985 } 986 987 enum Name { 988 Type, 989 Global, 990 Func, 991 Memory, 992 Table, 993 Tag, 994 Elem, 995 Data, 996 } 997 998 let mut ret = Names { module: get_name(module_id, module_name), ..Default::default() }; 999 let mut names = Vec::new(); 1000 for field in fields { 1001 // Extract the kind/id/name from whatever kind of field this is... 1002 let (kind, id, name) = match field { 1003 ModuleField::Import(i) => ( 1004 match i.item.kind { 1005 ItemKind::Func(_) => Name::Func, 1006 ItemKind::Table(_) => Name::Table, 1007 ItemKind::Memory(_) => Name::Memory, 1008 ItemKind::Global(_) => Name::Global, 1009 ItemKind::Tag(_) => Name::Tag, 1010 }, 1011 &i.item.id, 1012 &i.item.name, 1013 ), 1014 ModuleField::Global(g) => (Name::Global, &g.id, &g.name), 1015 ModuleField::Table(t) => (Name::Table, &t.id, &t.name), 1016 ModuleField::Memory(m) => (Name::Memory, &m.id, &m.name), 1017 ModuleField::Tag(t) => (Name::Tag, &t.id, &t.name), 1018 ModuleField::Type(t) => (Name::Type, &t.id, &t.name), 1019 ModuleField::Rec(r) => { 1020 for ty in &r.types { 1021 names.push((Name::Type, &ty.id, &ty.name, field)); 1022 } 1023 continue; 1024 } 1025 ModuleField::Elem(e) => (Name::Elem, &e.id, &e.name), 1026 ModuleField::Data(d) => (Name::Data, &d.id, &d.name), 1027 ModuleField::Func(f) => (Name::Func, &f.id, &f.name), 1028 ModuleField::Export(_) | ModuleField::Start(_) | ModuleField::Custom(_) => continue, 1029 }; 1030 names.push((kind, id, name, field)); 1031 } 1032 1033 for (kind, id, name, field) in names { 1034 // .. and using the kind we can figure out where to place this name 1035 let (list, idx) = match kind { 1036 Name::Func => (&mut ret.funcs, &mut ret.func_idx), 1037 Name::Table => (&mut ret.tables, &mut ret.table_idx), 1038 Name::Memory => (&mut ret.memories, &mut ret.memory_idx), 1039 Name::Global => (&mut ret.globals, &mut ret.global_idx), 1040 Name::Tag => (&mut ret.tags, &mut ret.tag_idx), 1041 Name::Type => (&mut ret.types, &mut ret.type_idx), 1042 Name::Elem => (&mut ret.elems, &mut ret.elem_idx), 1043 Name::Data => (&mut ret.data, &mut ret.data_idx), 1044 }; 1045 if let Some(name) = get_name(id, name) { 1046 list.push((*idx, name)); 1047 } 1048 1049 // Handle module locals separately from above 1050 if let ModuleField::Func(f) = field { 1051 let mut local_names = Vec::new(); 1052 let mut label_names = Vec::new(); 1053 let mut local_idx = 0; 1054 let mut label_idx = 0; 1055 1056 // Consult the inline type listed for local names of parameters. 1057 // This is specifically preserved during the name resolution 1058 // pass, but only for functions, so here we can look at the 1059 // original source's names. 1060 if let Some(ty) = &f.ty.inline { 1061 for (id, name, _) in ty.params.iter() { 1062 if let Some(name) = get_name(id, name) { 1063 local_names.push((local_idx, name)); 1064 } 1065 local_idx += 1; 1066 } 1067 } 1068 if let FuncKind::Inline { 1069 locals, expression, .. 1070 } = &f.kind 1071 { 1072 for local in locals.iter() { 1073 if let Some(name) = get_name(&local.id, &local.name) { 1074 local_names.push((local_idx, name)); 1075 } 1076 local_idx += 1; 1077 } 1078 1079 for i in expression.instrs.iter() { 1080 match i { 1081 Instruction::If(block) 1082 | Instruction::Block(block) 1083 | Instruction::Loop(block) 1084 | Instruction::Try(block) 1085 | Instruction::TryTable(TryTable { block, .. }) => { 1086 if let Some(name) = get_name(&block.label, &block.label_name) { 1087 label_names.push((label_idx, name)); 1088 } 1089 label_idx += 1; 1090 } 1091 _ => {} 1092 } 1093 } 1094 } 1095 if !local_names.is_empty() { 1096 ret.locals.push((*idx, local_names)); 1097 } 1098 if !label_names.is_empty() { 1099 ret.labels.push((*idx, label_names)); 1100 } 1101 } 1102 1103 // Handle struct fields separately from above 1104 if let ModuleField::Type(ty) = field { 1105 let mut field_names = vec![]; 1106 match &ty.def.kind { 1107 InnerTypeKind::Func(_) | InnerTypeKind::Array(_) | InnerTypeKind::Cont(_) => {} 1108 InnerTypeKind::Struct(ty_struct) => { 1109 for (idx, field) in ty_struct.fields.iter().enumerate() { 1110 if let Some(name) = get_name(&field.id, &None) { 1111 field_names.push((idx as u32, name)) 1112 } 1113 } 1114 } 1115 } 1116 if !field_names.is_empty() { 1117 ret.fields.push((*idx, field_names)) 1118 } 1119 } 1120 1121 *idx += 1; 1122 } 1123 1124 ret 1125} 1126 1127impl Names<'_> { 1128 fn is_empty(&self) -> bool { 1129 self.module.is_none() 1130 && self.funcs.is_empty() 1131 && self.locals.is_empty() 1132 && self.labels.is_empty() 1133 && self.globals.is_empty() 1134 && self.memories.is_empty() 1135 && self.tables.is_empty() 1136 && self.types.is_empty() 1137 && self.elems.is_empty() 1138 && self.data.is_empty() 1139 && self.fields.is_empty() 1140 && self.tags.is_empty() 1141 } 1142} 1143 1144impl Names<'_> { 1145 fn to_name_section(&self) -> wasm_encoder::NameSection { 1146 let mut names = wasm_encoder::NameSection::default(); 1147 1148 if let Some(id) = self.module { 1149 names.module(id); 1150 } 1151 let name_map = |indices: &[(u32, &str)]| { 1152 if indices.is_empty() { 1153 return None; 1154 } 1155 let mut map = wasm_encoder::NameMap::default(); 1156 for (idx, name) in indices { 1157 map.append(*idx, name); 1158 } 1159 Some(map) 1160 }; 1161 let indirect_name_map = |indices: &[(u32, Vec<(u32, &str)>)]| { 1162 if indices.is_empty() { 1163 return None; 1164 } 1165 let mut map = wasm_encoder::IndirectNameMap::default(); 1166 for (idx, names) in indices { 1167 if let Some(names) = name_map(names) { 1168 map.append(*idx, &names); 1169 } 1170 } 1171 Some(map) 1172 }; 1173 if let Some(map) = name_map(&self.funcs) { 1174 names.functions(&map); 1175 } 1176 if let Some(map) = indirect_name_map(&self.locals) { 1177 names.locals(&map); 1178 } 1179 if let Some(map) = indirect_name_map(&self.labels) { 1180 names.labels(&map); 1181 } 1182 if let Some(map) = name_map(&self.types) { 1183 names.types(&map); 1184 } 1185 if let Some(map) = name_map(&self.tables) { 1186 names.tables(&map); 1187 } 1188 if let Some(map) = name_map(&self.memories) { 1189 names.memories(&map); 1190 } 1191 if let Some(map) = name_map(&self.globals) { 1192 names.globals(&map); 1193 } 1194 if let Some(map) = name_map(&self.elems) { 1195 names.elements(&map); 1196 } 1197 if let Some(map) = name_map(&self.data) { 1198 names.data(&map); 1199 } 1200 if let Some(map) = indirect_name_map(&self.fields) { 1201 names.fields(&map); 1202 } 1203 if let Some(map) = name_map(&self.tags) { 1204 names.tags(&map); 1205 } 1206 names 1207 } 1208} 1209 1210impl Encode for Id<'_> { 1211 fn encode(&self, dst: &mut Vec<u8>) { 1212 assert!(!self.is_gensym()); 1213 self.name().encode(dst); 1214 } 1215} 1216 1217impl<'a> Encode for TryTable<'a> { 1218 fn encode(&self, dst: &mut Vec<u8>) { 1219 self.block.encode(dst); 1220 self.catches.encode(dst); 1221 } 1222} 1223 1224impl<'a> Encode for TryTableCatch<'a> { 1225 fn encode(&self, dst: &mut Vec<u8>) { 1226 let flag_byte: u8 = match self.kind { 1227 TryTableCatchKind::Catch(..) => 0, 1228 TryTableCatchKind::CatchRef(..) => 1, 1229 TryTableCatchKind::CatchAll => 2, 1230 TryTableCatchKind::CatchAllRef => 3, 1231 }; 1232 flag_byte.encode(dst); 1233 match self.kind { 1234 TryTableCatchKind::Catch(tag) | TryTableCatchKind::CatchRef(tag) => { 1235 tag.encode(dst); 1236 } 1237 TryTableCatchKind::CatchAll | TryTableCatchKind::CatchAllRef => {} 1238 } 1239 self.label.encode(dst); 1240 } 1241} 1242 1243impl<'a> Encode for ContBind<'a> { 1244 fn encode(&self, dst: &mut Vec<u8>) { 1245 self.argument_index.encode(dst); 1246 self.result_index.encode(dst); 1247 } 1248} 1249 1250impl<'a> Encode for Resume<'a> { 1251 fn encode(&self, dst: &mut Vec<u8>) { 1252 self.type_index.encode(dst); 1253 self.table.encode(dst); 1254 } 1255} 1256 1257impl<'a> Encode for ResumeThrow<'a> { 1258 fn encode(&self, dst: &mut Vec<u8>) { 1259 self.type_index.encode(dst); 1260 self.tag_index.encode(dst); 1261 self.table.encode(dst); 1262 } 1263} 1264 1265impl<'a> Encode for ResumeTable<'a> { 1266 fn encode(&self, dst: &mut Vec<u8>) { 1267 self.handlers.encode(dst); 1268 } 1269} 1270 1271impl<'a> Encode for Handle<'a> { 1272 fn encode(&self, dst: &mut Vec<u8>) { 1273 match self { 1274 Handle::OnLabel { tag, label } => { 1275 dst.push(0x00); 1276 tag.encode(dst); 1277 label.encode(dst); 1278 } 1279 Handle::OnSwitch { tag } => { 1280 dst.push(0x01); 1281 tag.encode(dst); 1282 } 1283 } 1284 } 1285} 1286 1287impl<'a> Encode for Switch<'a> { 1288 fn encode(&self, dst: &mut Vec<u8>) { 1289 self.type_index.encode(dst); 1290 self.tag_index.encode(dst); 1291 } 1292} 1293 1294impl Encode for V128Const { 1295 fn encode(&self, dst: &mut Vec<u8>) { 1296 dst.extend_from_slice(&self.to_le_bytes()); 1297 } 1298} 1299 1300impl Encode for I8x16Shuffle { 1301 fn encode(&self, dst: &mut Vec<u8>) { 1302 dst.extend_from_slice(&self.lanes); 1303 } 1304} 1305 1306impl<'a> Encode for SelectTypes<'a> { 1307 fn encode(&self, dst: &mut Vec<u8>) { 1308 match &self.tys { 1309 Some(list) => { 1310 dst.push(0x1c); 1311 list.encode(dst); 1312 } 1313 None => dst.push(0x1b), 1314 } 1315 } 1316} 1317 1318impl Custom<'_> { 1319 fn encode(&self, module: &mut wasm_encoder::Module) { 1320 match self { 1321 Custom::Raw(r) => { 1322 module.section(&r.to_section()); 1323 } 1324 Custom::Producers(p) => { 1325 module.section(&p.to_section()); 1326 } 1327 Custom::Dylink0(p) => { 1328 module.section(&p.to_section()); 1329 } 1330 } 1331 } 1332} 1333 1334impl RawCustomSection<'_> { 1335 fn to_section(&self) -> wasm_encoder::CustomSection<'_> { 1336 let mut ret = Vec::new(); 1337 for list in self.data.iter() { 1338 ret.extend_from_slice(list); 1339 } 1340 wasm_encoder::CustomSection { 1341 name: self.name.into(), 1342 data: ret.into(), 1343 } 1344 } 1345} 1346 1347impl Producers<'_> { 1348 pub(crate) fn to_section(&self) -> wasm_encoder::ProducersSection { 1349 let mut ret = wasm_encoder::ProducersSection::default(); 1350 for (name, fields) in self.fields.iter() { 1351 let mut field = wasm_encoder::ProducersField::new(); 1352 for (key, value) in fields { 1353 field.value(key, value); 1354 } 1355 ret.field(name, &field); 1356 } 1357 ret 1358 } 1359} 1360 1361impl Dylink0<'_> { 1362 fn to_section(&self) -> wasm_encoder::CustomSection<'_> { 1363 let mut e = Vec::new(); 1364 for section in self.subsections.iter() { 1365 e.push(section.id()); 1366 let mut tmp = Vec::new(); 1367 section.encode(&mut tmp); 1368 tmp.encode(&mut e); 1369 } 1370 wasm_encoder::CustomSection { 1371 name: "dylink.0".into(), 1372 data: e.into(), 1373 } 1374 } 1375} 1376 1377impl Encode for Dylink0Subsection<'_> { 1378 fn encode(&self, e: &mut Vec<u8>) { 1379 match self { 1380 Dylink0Subsection::MemInfo { 1381 memory_size, 1382 memory_align, 1383 table_size, 1384 table_align, 1385 } => { 1386 memory_size.encode(e); 1387 memory_align.encode(e); 1388 table_size.encode(e); 1389 table_align.encode(e); 1390 } 1391 Dylink0Subsection::Needed(libs) => libs.encode(e), 1392 Dylink0Subsection::ExportInfo(list) => list.encode(e), 1393 Dylink0Subsection::ImportInfo(list) => list.encode(e), 1394 } 1395 } 1396} 1397 1398impl SectionItem for Tag<'_> { 1399 type Section = wasm_encoder::TagSection; 1400 const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Tag; 1401 1402 fn encode(&self, section: &mut wasm_encoder::TagSection) { 1403 section.tag(self.ty.to_tag_type()); 1404 match &self.kind { 1405 TagKind::Inline() => {} 1406 _ => panic!("TagKind should be inline during encoding"), 1407 } 1408 } 1409} 1410 1411impl Encode for StructAccess<'_> { 1412 fn encode(&self, e: &mut Vec<u8>) { 1413 self.r#struct.encode(e); 1414 self.field.encode(e); 1415 } 1416} 1417 1418impl Encode for ArrayFill<'_> { 1419 fn encode(&self, e: &mut Vec<u8>) { 1420 self.array.encode(e); 1421 } 1422} 1423 1424impl Encode for ArrayCopy<'_> { 1425 fn encode(&self, e: &mut Vec<u8>) { 1426 self.dest_array.encode(e); 1427 self.src_array.encode(e); 1428 } 1429} 1430 1431impl Encode for ArrayInit<'_> { 1432 fn encode(&self, e: &mut Vec<u8>) { 1433 self.array.encode(e); 1434 self.segment.encode(e); 1435 } 1436} 1437 1438impl Encode for ArrayNewFixed<'_> { 1439 fn encode(&self, e: &mut Vec<u8>) { 1440 self.array.encode(e); 1441 self.length.encode(e); 1442 } 1443} 1444 1445impl Encode for ArrayNewData<'_> { 1446 fn encode(&self, e: &mut Vec<u8>) { 1447 self.array.encode(e); 1448 self.data_idx.encode(e); 1449 } 1450} 1451 1452impl Encode for ArrayNewElem<'_> { 1453 fn encode(&self, e: &mut Vec<u8>) { 1454 self.array.encode(e); 1455 self.elem_idx.encode(e); 1456 } 1457} 1458 1459impl Encode for RefTest<'_> { 1460 fn encode(&self, e: &mut Vec<u8>) { 1461 e.push(0xfb); 1462 if self.r#type.nullable { 1463 e.push(0x15); 1464 } else { 1465 e.push(0x14); 1466 } 1467 self.r#type.heap.encode(e); 1468 } 1469} 1470 1471impl Encode for RefCast<'_> { 1472 fn encode(&self, e: &mut Vec<u8>) { 1473 e.push(0xfb); 1474 if self.r#type.nullable { 1475 e.push(0x17); 1476 } else { 1477 e.push(0x16); 1478 } 1479 self.r#type.heap.encode(e); 1480 } 1481} 1482 1483fn br_on_cast_flags(from_nullable: bool, to_nullable: bool) -> u8 { 1484 let mut flag = 0; 1485 if from_nullable { 1486 flag |= 1 << 0; 1487 } 1488 if to_nullable { 1489 flag |= 1 << 1; 1490 } 1491 flag 1492} 1493 1494impl Encode for BrOnCast<'_> { 1495 fn encode(&self, e: &mut Vec<u8>) { 1496 e.push(0xfb); 1497 e.push(0x18); 1498 e.push(br_on_cast_flags( 1499 self.from_type.nullable, 1500 self.to_type.nullable, 1501 )); 1502 self.label.encode(e); 1503 self.from_type.heap.encode(e); 1504 self.to_type.heap.encode(e); 1505 } 1506} 1507 1508impl Encode for BrOnCastFail<'_> { 1509 fn encode(&self, e: &mut Vec<u8>) { 1510 e.push(0xfb); 1511 e.push(0x19); 1512 e.push(br_on_cast_flags( 1513 self.from_type.nullable, 1514 self.to_type.nullable, 1515 )); 1516 self.label.encode(e); 1517 self.from_type.heap.encode(e); 1518 self.to_type.heap.encode(e); 1519 } 1520}