inf_wast/core/
binary.rs

1#[cfg(feature = "component-model")]
2use crate::component::Component;
3use crate::core::*;
4use crate::encode::Encode;
5use crate::token::*;
6use crate::Wat;
7use std::borrow::Cow;
8use std::marker;
9#[cfg(feature = "dwarf")]
10use std::path::Path;
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 Path, &'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 Path, 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    ) -> std::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    ) -> std::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<'_>) -> std::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.get(0) {
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::default();
999    ret.module = get_name(module_id, module_name);
1000    let mut names = Vec::new();
1001    for field in fields {
1002        // Extract the kind/id/name from whatever kind of field this is...
1003        let (kind, id, name) = match field {
1004            ModuleField::Import(i) => (
1005                match i.item.kind {
1006                    ItemKind::Func(_) => Name::Func,
1007                    ItemKind::Table(_) => Name::Table,
1008                    ItemKind::Memory(_) => Name::Memory,
1009                    ItemKind::Global(_) => Name::Global,
1010                    ItemKind::Tag(_) => Name::Tag,
1011                },
1012                &i.item.id,
1013                &i.item.name,
1014            ),
1015            ModuleField::Global(g) => (Name::Global, &g.id, &g.name),
1016            ModuleField::Table(t) => (Name::Table, &t.id, &t.name),
1017            ModuleField::Memory(m) => (Name::Memory, &m.id, &m.name),
1018            ModuleField::Tag(t) => (Name::Tag, &t.id, &t.name),
1019            ModuleField::Type(t) => (Name::Type, &t.id, &t.name),
1020            ModuleField::Rec(r) => {
1021                for ty in &r.types {
1022                    names.push((Name::Type, &ty.id, &ty.name, field));
1023                }
1024                continue;
1025            }
1026            ModuleField::Elem(e) => (Name::Elem, &e.id, &e.name),
1027            ModuleField::Data(d) => (Name::Data, &d.id, &d.name),
1028            ModuleField::Func(f) => (Name::Func, &f.id, &f.name),
1029            ModuleField::Export(_) | ModuleField::Start(_) | ModuleField::Custom(_) => continue,
1030        };
1031        names.push((kind, id, name, field));
1032    }
1033
1034    for (kind, id, name, field) in names {
1035        // .. and using the kind we can figure out where to place this name
1036        let (list, idx) = match kind {
1037            Name::Func => (&mut ret.funcs, &mut ret.func_idx),
1038            Name::Table => (&mut ret.tables, &mut ret.table_idx),
1039            Name::Memory => (&mut ret.memories, &mut ret.memory_idx),
1040            Name::Global => (&mut ret.globals, &mut ret.global_idx),
1041            Name::Tag => (&mut ret.tags, &mut ret.tag_idx),
1042            Name::Type => (&mut ret.types, &mut ret.type_idx),
1043            Name::Elem => (&mut ret.elems, &mut ret.elem_idx),
1044            Name::Data => (&mut ret.data, &mut ret.data_idx),
1045        };
1046        if let Some(name) = get_name(id, name) {
1047            list.push((*idx, name));
1048        }
1049
1050        // Handle module locals separately from above
1051        if let ModuleField::Func(f) = field {
1052            let mut local_names = Vec::new();
1053            let mut label_names = Vec::new();
1054            let mut local_idx = 0;
1055            let mut label_idx = 0;
1056
1057            // Consult the inline type listed for local names of parameters.
1058            // This is specifically preserved during the name resolution
1059            // pass, but only for functions, so here we can look at the
1060            // original source's names.
1061            if let Some(ty) = &f.ty.inline {
1062                for (id, name, _) in ty.params.iter() {
1063                    if let Some(name) = get_name(id, name) {
1064                        local_names.push((local_idx, name));
1065                    }
1066                    local_idx += 1;
1067                }
1068            }
1069            if let FuncKind::Inline {
1070                locals, expression, ..
1071            } = &f.kind
1072            {
1073                for local in locals.iter() {
1074                    if let Some(name) = get_name(&local.id, &local.name) {
1075                        local_names.push((local_idx, name));
1076                    }
1077                    local_idx += 1;
1078                }
1079
1080                for i in expression.instrs.iter() {
1081                    match i {
1082                        Instruction::If(block)
1083                        | Instruction::Block(block)
1084                        | Instruction::Loop(block)
1085                        | Instruction::Forall(block)
1086                        | Instruction::Exists(block)
1087                        | Instruction::Assume(block)
1088                        | Instruction::Unique(block)
1089                        | Instruction::Try(block)
1090                        | Instruction::TryTable(TryTable { block, .. }) => {
1091                            if let Some(name) = get_name(&block.label, &block.label_name) {
1092                                label_names.push((label_idx, name));
1093                            }
1094                            label_idx += 1;
1095                        }
1096                        _ => {}
1097                    }
1098                }
1099            }
1100            if local_names.len() > 0 {
1101                ret.locals.push((*idx, local_names));
1102            }
1103            if label_names.len() > 0 {
1104                ret.labels.push((*idx, label_names));
1105            }
1106        }
1107
1108        // Handle struct fields separately from above
1109        if let ModuleField::Type(ty) = field {
1110            let mut field_names = vec![];
1111            match &ty.def.kind {
1112                InnerTypeKind::Func(_) | InnerTypeKind::Array(_) | InnerTypeKind::Cont(_) => {}
1113                InnerTypeKind::Struct(ty_struct) => {
1114                    for (idx, field) in ty_struct.fields.iter().enumerate() {
1115                        if let Some(name) = get_name(&field.id, &None) {
1116                            field_names.push((idx as u32, name))
1117                        }
1118                    }
1119                }
1120            }
1121            if field_names.len() > 0 {
1122                ret.fields.push((*idx, field_names))
1123            }
1124        }
1125
1126        *idx += 1;
1127    }
1128
1129    return ret;
1130}
1131
1132impl Names<'_> {
1133    fn is_empty(&self) -> bool {
1134        self.module.is_none()
1135            && self.funcs.is_empty()
1136            && self.locals.is_empty()
1137            && self.labels.is_empty()
1138            && self.globals.is_empty()
1139            && self.memories.is_empty()
1140            && self.tables.is_empty()
1141            && self.types.is_empty()
1142            && self.elems.is_empty()
1143            && self.data.is_empty()
1144            && self.fields.is_empty()
1145            && self.tags.is_empty()
1146    }
1147}
1148
1149impl Names<'_> {
1150    fn to_name_section(&self) -> wasm_encoder::NameSection {
1151        let mut names = wasm_encoder::NameSection::default();
1152
1153        if let Some(id) = self.module {
1154            names.module(id);
1155        }
1156        let name_map = |indices: &[(u32, &str)]| {
1157            if indices.is_empty() {
1158                return None;
1159            }
1160            let mut map = wasm_encoder::NameMap::default();
1161            for (idx, name) in indices {
1162                map.append(*idx, *name);
1163            }
1164            Some(map)
1165        };
1166        let indirect_name_map = |indices: &[(u32, Vec<(u32, &str)>)]| {
1167            if indices.is_empty() {
1168                return None;
1169            }
1170            let mut map = wasm_encoder::IndirectNameMap::default();
1171            for (idx, names) in indices {
1172                if let Some(names) = name_map(names) {
1173                    map.append(*idx, &names);
1174                }
1175            }
1176            Some(map)
1177        };
1178        if let Some(map) = name_map(&self.funcs) {
1179            names.functions(&map);
1180        }
1181        if let Some(map) = indirect_name_map(&self.locals) {
1182            names.locals(&map);
1183        }
1184        if let Some(map) = indirect_name_map(&self.labels) {
1185            names.labels(&map);
1186        }
1187        if let Some(map) = name_map(&self.types) {
1188            names.types(&map);
1189        }
1190        if let Some(map) = name_map(&self.tables) {
1191            names.tables(&map);
1192        }
1193        if let Some(map) = name_map(&self.memories) {
1194            names.memories(&map);
1195        }
1196        if let Some(map) = name_map(&self.globals) {
1197            names.globals(&map);
1198        }
1199        if let Some(map) = name_map(&self.elems) {
1200            names.elements(&map);
1201        }
1202        if let Some(map) = name_map(&self.data) {
1203            names.data(&map);
1204        }
1205        if let Some(map) = indirect_name_map(&self.fields) {
1206            names.fields(&map);
1207        }
1208        if let Some(map) = name_map(&self.tags) {
1209            names.tags(&map);
1210        }
1211        names
1212    }
1213}
1214
1215impl Encode for Id<'_> {
1216    fn encode(&self, dst: &mut Vec<u8>) {
1217        assert!(!self.is_gensym());
1218        self.name().encode(dst);
1219    }
1220}
1221
1222impl<'a> Encode for TryTable<'a> {
1223    fn encode(&self, dst: &mut Vec<u8>) {
1224        self.block.encode(dst);
1225        self.catches.encode(dst);
1226    }
1227}
1228
1229impl<'a> Encode for TryTableCatch<'a> {
1230    fn encode(&self, dst: &mut Vec<u8>) {
1231        let flag_byte: u8 = match self.kind {
1232            TryTableCatchKind::Catch(..) => 0,
1233            TryTableCatchKind::CatchRef(..) => 1,
1234            TryTableCatchKind::CatchAll => 2,
1235            TryTableCatchKind::CatchAllRef => 3,
1236        };
1237        flag_byte.encode(dst);
1238        match self.kind {
1239            TryTableCatchKind::Catch(tag) | TryTableCatchKind::CatchRef(tag) => {
1240                tag.encode(dst);
1241            }
1242            TryTableCatchKind::CatchAll | TryTableCatchKind::CatchAllRef => {}
1243        }
1244        self.label.encode(dst);
1245    }
1246}
1247
1248impl<'a> Encode for ContBind<'a> {
1249    fn encode(&self, dst: &mut Vec<u8>) {
1250        self.argument_index.encode(dst);
1251        self.result_index.encode(dst);
1252    }
1253}
1254
1255impl<'a> Encode for Resume<'a> {
1256    fn encode(&self, dst: &mut Vec<u8>) {
1257        self.type_index.encode(dst);
1258        self.table.encode(dst);
1259    }
1260}
1261
1262impl<'a> Encode for ResumeThrow<'a> {
1263    fn encode(&self, dst: &mut Vec<u8>) {
1264        self.type_index.encode(dst);
1265        self.tag_index.encode(dst);
1266        self.table.encode(dst);
1267    }
1268}
1269
1270impl<'a> Encode for ResumeTable<'a> {
1271    fn encode(&self, dst: &mut Vec<u8>) {
1272        self.handlers.encode(dst);
1273    }
1274}
1275
1276impl<'a> Encode for Handle<'a> {
1277    fn encode(&self, dst: &mut Vec<u8>) {
1278        match self {
1279            Handle::OnLabel { tag, label } => {
1280                dst.push(0x00);
1281                tag.encode(dst);
1282                label.encode(dst);
1283            }
1284            Handle::OnSwitch { tag } => {
1285                dst.push(0x01);
1286                tag.encode(dst);
1287            }
1288        }
1289    }
1290}
1291
1292impl<'a> Encode for Switch<'a> {
1293    fn encode(&self, dst: &mut Vec<u8>) {
1294        self.type_index.encode(dst);
1295        self.tag_index.encode(dst);
1296    }
1297}
1298
1299impl Encode for V128Const {
1300    fn encode(&self, dst: &mut Vec<u8>) {
1301        dst.extend_from_slice(&self.to_le_bytes());
1302    }
1303}
1304
1305impl Encode for I8x16Shuffle {
1306    fn encode(&self, dst: &mut Vec<u8>) {
1307        dst.extend_from_slice(&self.lanes);
1308    }
1309}
1310
1311impl<'a> Encode for SelectTypes<'a> {
1312    fn encode(&self, dst: &mut Vec<u8>) {
1313        match &self.tys {
1314            Some(list) => {
1315                dst.push(0x1c);
1316                list.encode(dst);
1317            }
1318            None => dst.push(0x1b),
1319        }
1320    }
1321}
1322
1323impl Custom<'_> {
1324    fn encode(&self, module: &mut wasm_encoder::Module) {
1325        match self {
1326            Custom::Raw(r) => {
1327                module.section(&r.to_section());
1328            }
1329            Custom::Producers(p) => {
1330                module.section(&p.to_section());
1331            }
1332            Custom::Dylink0(p) => {
1333                module.section(&p.to_section());
1334            }
1335        }
1336    }
1337}
1338
1339impl RawCustomSection<'_> {
1340    fn to_section(&self) -> wasm_encoder::CustomSection<'_> {
1341        let mut ret = Vec::new();
1342        for list in self.data.iter() {
1343            ret.extend_from_slice(list);
1344        }
1345        wasm_encoder::CustomSection {
1346            name: self.name.into(),
1347            data: ret.into(),
1348        }
1349    }
1350}
1351
1352impl Producers<'_> {
1353    pub(crate) fn to_section(&self) -> wasm_encoder::ProducersSection {
1354        let mut ret = wasm_encoder::ProducersSection::default();
1355        for (name, fields) in self.fields.iter() {
1356            let mut field = wasm_encoder::ProducersField::new();
1357            for (key, value) in fields {
1358                field.value(key, value);
1359            }
1360            ret.field(name, &field);
1361        }
1362        ret
1363    }
1364}
1365
1366impl Dylink0<'_> {
1367    fn to_section(&self) -> wasm_encoder::CustomSection<'_> {
1368        let mut e = Vec::new();
1369        for section in self.subsections.iter() {
1370            e.push(section.id());
1371            let mut tmp = Vec::new();
1372            section.encode(&mut tmp);
1373            tmp.encode(&mut e);
1374        }
1375        wasm_encoder::CustomSection {
1376            name: "dylink.0".into(),
1377            data: e.into(),
1378        }
1379    }
1380}
1381
1382impl Encode for Dylink0Subsection<'_> {
1383    fn encode(&self, e: &mut Vec<u8>) {
1384        match self {
1385            Dylink0Subsection::MemInfo {
1386                memory_size,
1387                memory_align,
1388                table_size,
1389                table_align,
1390            } => {
1391                memory_size.encode(e);
1392                memory_align.encode(e);
1393                table_size.encode(e);
1394                table_align.encode(e);
1395            }
1396            Dylink0Subsection::Needed(libs) => libs.encode(e),
1397            Dylink0Subsection::ExportInfo(list) => list.encode(e),
1398            Dylink0Subsection::ImportInfo(list) => list.encode(e),
1399        }
1400    }
1401}
1402
1403impl SectionItem for Tag<'_> {
1404    type Section = wasm_encoder::TagSection;
1405    const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Tag;
1406
1407    fn encode(&self, section: &mut wasm_encoder::TagSection) {
1408        section.tag(self.ty.to_tag_type());
1409        match &self.kind {
1410            TagKind::Inline() => {}
1411            _ => panic!("TagKind should be inline during encoding"),
1412        }
1413    }
1414}
1415
1416impl Encode for StructAccess<'_> {
1417    fn encode(&self, e: &mut Vec<u8>) {
1418        self.r#struct.encode(e);
1419        self.field.encode(e);
1420    }
1421}
1422
1423impl Encode for ArrayFill<'_> {
1424    fn encode(&self, e: &mut Vec<u8>) {
1425        self.array.encode(e);
1426    }
1427}
1428
1429impl Encode for ArrayCopy<'_> {
1430    fn encode(&self, e: &mut Vec<u8>) {
1431        self.dest_array.encode(e);
1432        self.src_array.encode(e);
1433    }
1434}
1435
1436impl Encode for ArrayInit<'_> {
1437    fn encode(&self, e: &mut Vec<u8>) {
1438        self.array.encode(e);
1439        self.segment.encode(e);
1440    }
1441}
1442
1443impl Encode for ArrayNewFixed<'_> {
1444    fn encode(&self, e: &mut Vec<u8>) {
1445        self.array.encode(e);
1446        self.length.encode(e);
1447    }
1448}
1449
1450impl Encode for ArrayNewData<'_> {
1451    fn encode(&self, e: &mut Vec<u8>) {
1452        self.array.encode(e);
1453        self.data_idx.encode(e);
1454    }
1455}
1456
1457impl Encode for ArrayNewElem<'_> {
1458    fn encode(&self, e: &mut Vec<u8>) {
1459        self.array.encode(e);
1460        self.elem_idx.encode(e);
1461    }
1462}
1463
1464impl Encode for RefTest<'_> {
1465    fn encode(&self, e: &mut Vec<u8>) {
1466        e.push(0xfb);
1467        if self.r#type.nullable {
1468            e.push(0x15);
1469        } else {
1470            e.push(0x14);
1471        }
1472        self.r#type.heap.encode(e);
1473    }
1474}
1475
1476impl Encode for RefCast<'_> {
1477    fn encode(&self, e: &mut Vec<u8>) {
1478        e.push(0xfb);
1479        if self.r#type.nullable {
1480            e.push(0x17);
1481        } else {
1482            e.push(0x16);
1483        }
1484        self.r#type.heap.encode(e);
1485    }
1486}
1487
1488fn br_on_cast_flags(from_nullable: bool, to_nullable: bool) -> u8 {
1489    let mut flag = 0;
1490    if from_nullable {
1491        flag |= 1 << 0;
1492    }
1493    if to_nullable {
1494        flag |= 1 << 1;
1495    }
1496    flag
1497}
1498
1499impl Encode for BrOnCast<'_> {
1500    fn encode(&self, e: &mut Vec<u8>) {
1501        e.push(0xfb);
1502        e.push(0x18);
1503        e.push(br_on_cast_flags(
1504            self.from_type.nullable,
1505            self.to_type.nullable,
1506        ));
1507        self.label.encode(e);
1508        self.from_type.heap.encode(e);
1509        self.to_type.heap.encode(e);
1510    }
1511}
1512
1513impl Encode for BrOnCastFail<'_> {
1514    fn encode(&self, e: &mut Vec<u8>) {
1515        e.push(0xfb);
1516        e.push(0x19);
1517        e.push(br_on_cast_flags(
1518            self.from_type.nullable,
1519            self.to_type.nullable,
1520        ));
1521        self.label.encode(e);
1522        self.from_type.heap.encode(e);
1523        self.to_type.heap.encode(e);
1524    }
1525}