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 params:ft.params.iter().map(|(_, _, ty)| (*ty).into()),
314 results:ft.results.iter().map(|ty: &ValType<'_>| (*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: &StructField<'_>| 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: FieldType = 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: &&Type<'_>) => types.ty().subtype(&ty.to_subtype()),
364 RecOrType::Rec(rec: &&Rec<'_>) => types.ty().rec(types:rec.types.iter().map(|t: &Type<'_>| 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: CompositeType = wasm_encoder::CompositeType {
379 inner: match &self.kind {
380 InnerTypeKind::Func(ft: &FunctionType<'_>) => Func(ft.into()),
381 InnerTypeKind::Struct(st: &StructType<'_>) => Struct(st.into()),
382 InnerTypeKind::Array(at: &ArrayType<'_>) => Array(at.into()),
383 InnerTypeKind::Cont(ct: &ContType<'_>) => Cont(ct.into()),
384 },
385 shared: self.shared,
386 };
387 wasm_encoder::SubType {
388 composite_type,
389 is_final: self.final_type.unwrap_or(default:true),
390 supertype_idx: self.parent.map(|i: Index<'_>| 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: RefType<'_>) => 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), sink: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), sink: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: ValType<'_>) => 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: &TypeUse<'_, FunctionType<'_>>) => ET::Function(t.unwrap_u32()),
494 ItemKind::Table(t: &TableType<'_>) => ET::Table(t.to_table_type()),
495 ItemKind::Memory(t: &MemoryType) => ET::Memory(t.to_memory_type()),
496 ItemKind::Global(t: &GlobalType<'_>) => ET::Global(t.to_global_type()),
497 ItemKind::Tag(t: &TagType<'_>) => 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: &TypeUse<'_, FunctionType<'_>>) => 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(msg:"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: &u32, _) => *n,
577 Index::Id(n: &Id<'_>) => 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: u32, _) => 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: &TableType<'_>,
600 init_expr: None,
601 } => {
602 section.table(ty.to_table_type());
603 }
604 TableKind::Normal {
605 ty: &TableType<'_>,
606 init_expr: Some(init_expr: &Expression<'_>),
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: &MemoryType) => {
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: ConstExpr = match &self.kind {
637 GlobalKind::Inline(expr: &Expression<'_>) => 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 = Vec::new();
705 for val: &DataVal<'_> 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: &Index<'_>, offset: &Expression<'_> } => {
713 section.active(memory_index: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.instruction(&wasm_encoder::Instruction::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: &u32, _)) = &self.ty.index {
816 return i64::from(*n).encode(e);
817 }
818 let ty: &FunctionType<'_> = self
819 .ty
820 .inline
821 .as_ref()
822 .expect(msg:"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::Try(block)
1086 | Instruction::TryTable(TryTable { block, .. }) => {
1087 if let Some(name) = get_name(&block.label, &block.label_name) {
1088 label_names.push((label_idx, name));
1089 }
1090 label_idx += 1;
1091 }
1092 _ => {}
1093 }
1094 }
1095 }
1096 if local_names.len() > 0 {
1097 ret.locals.push((*idx, local_names));
1098 }
1099 if label_names.len() > 0 {
1100 ret.labels.push((*idx, label_names));
1101 }
1102 }
1103
1104 // Handle struct fields separately from above
1105 if let ModuleField::Type(ty) = field {
1106 let mut field_names = vec![];
1107 match &ty.def.kind {
1108 InnerTypeKind::Func(_) | InnerTypeKind::Array(_) | InnerTypeKind::Cont(_) => {}
1109 InnerTypeKind::Struct(ty_struct) => {
1110 for (idx, field) in ty_struct.fields.iter().enumerate() {
1111 if let Some(name) = get_name(&field.id, &None) {
1112 field_names.push((idx as u32, name))
1113 }
1114 }
1115 }
1116 }
1117 if field_names.len() > 0 {
1118 ret.fields.push((*idx, field_names))
1119 }
1120 }
1121
1122 *idx += 1;
1123 }
1124
1125 return ret;
1126}
1127
1128impl Names<'_> {
1129 fn is_empty(&self) -> bool {
1130 self.module.is_none()
1131 && self.funcs.is_empty()
1132 && self.locals.is_empty()
1133 && self.labels.is_empty()
1134 && self.globals.is_empty()
1135 && self.memories.is_empty()
1136 && self.tables.is_empty()
1137 && self.types.is_empty()
1138 && self.elems.is_empty()
1139 && self.data.is_empty()
1140 && self.fields.is_empty()
1141 && self.tags.is_empty()
1142 }
1143}
1144
1145impl Names<'_> {
1146 fn to_name_section(&self) -> wasm_encoder::NameSection {
1147 let mut names = wasm_encoder::NameSection::default();
1148
1149 if let Some(id) = self.module {
1150 names.module(id);
1151 }
1152 let name_map = |indices: &[(u32, &str)]| {
1153 if indices.is_empty() {
1154 return None;
1155 }
1156 let mut map = wasm_encoder::NameMap::default();
1157 for (idx, name) in indices {
1158 map.append(*idx, *name);
1159 }
1160 Some(map)
1161 };
1162 let indirect_name_map = |indices: &[(u32, Vec<(u32, &str)>)]| {
1163 if indices.is_empty() {
1164 return None;
1165 }
1166 let mut map = wasm_encoder::IndirectNameMap::default();
1167 for (idx, names) in indices {
1168 if let Some(names) = name_map(names) {
1169 map.append(*idx, &names);
1170 }
1171 }
1172 Some(map)
1173 };
1174 if let Some(map) = name_map(&self.funcs) {
1175 names.functions(&map);
1176 }
1177 if let Some(map) = indirect_name_map(&self.locals) {
1178 names.locals(&map);
1179 }
1180 if let Some(map) = indirect_name_map(&self.labels) {
1181 names.labels(&map);
1182 }
1183 if let Some(map) = name_map(&self.types) {
1184 names.types(&map);
1185 }
1186 if let Some(map) = name_map(&self.tables) {
1187 names.tables(&map);
1188 }
1189 if let Some(map) = name_map(&self.memories) {
1190 names.memories(&map);
1191 }
1192 if let Some(map) = name_map(&self.globals) {
1193 names.globals(&map);
1194 }
1195 if let Some(map) = name_map(&self.elems) {
1196 names.elements(&map);
1197 }
1198 if let Some(map) = name_map(&self.data) {
1199 names.data(&map);
1200 }
1201 if let Some(map) = indirect_name_map(&self.fields) {
1202 names.fields(&map);
1203 }
1204 if let Some(map) = name_map(&self.tags) {
1205 names.tags(&map);
1206 }
1207 names
1208 }
1209}
1210
1211impl Encode for Id<'_> {
1212 fn encode(&self, dst: &mut Vec<u8>) {
1213 assert!(!self.is_gensym());
1214 self.name().encode(dst);
1215 }
1216}
1217
1218impl<'a> Encode for TryTable<'a> {
1219 fn encode(&self, dst: &mut Vec<u8>) {
1220 self.block.encode(dst);
1221 self.catches.encode(dst);
1222 }
1223}
1224
1225impl<'a> Encode for TryTableCatch<'a> {
1226 fn encode(&self, dst: &mut Vec<u8>) {
1227 let flag_byte: u8 = match self.kind {
1228 TryTableCatchKind::Catch(..) => 0,
1229 TryTableCatchKind::CatchRef(..) => 1,
1230 TryTableCatchKind::CatchAll => 2,
1231 TryTableCatchKind::CatchAllRef => 3,
1232 };
1233 flag_byte.encode(dst);
1234 match self.kind {
1235 TryTableCatchKind::Catch(tag: Index<'_>) | TryTableCatchKind::CatchRef(tag: Index<'_>) => {
1236 tag.encode(dst);
1237 }
1238 TryTableCatchKind::CatchAll | TryTableCatchKind::CatchAllRef => {}
1239 }
1240 self.label.encode(dst);
1241 }
1242}
1243
1244impl<'a> Encode for ContBind<'a> {
1245 fn encode(&self, dst: &mut Vec<u8>) {
1246 self.argument_index.encode(dst);
1247 self.result_index.encode(dst);
1248 }
1249}
1250
1251impl<'a> Encode for Resume<'a> {
1252 fn encode(&self, dst: &mut Vec<u8>) {
1253 self.type_index.encode(dst);
1254 self.table.encode(dst);
1255 }
1256}
1257
1258impl<'a> Encode for ResumeThrow<'a> {
1259 fn encode(&self, dst: &mut Vec<u8>) {
1260 self.type_index.encode(dst);
1261 self.tag_index.encode(dst);
1262 self.table.encode(dst);
1263 }
1264}
1265
1266impl<'a> Encode for ResumeTable<'a> {
1267 fn encode(&self, dst: &mut Vec<u8>) {
1268 self.handlers.encode(dst);
1269 }
1270}
1271
1272impl<'a> Encode for Handle<'a> {
1273 fn encode(&self, dst: &mut Vec<u8>) {
1274 match self {
1275 Handle::OnLabel { tag: &Index<'_>, label: &Index<'_> } => {
1276 dst.push(0x00);
1277 tag.encode(dst);
1278 label.encode(dst);
1279 }
1280 Handle::OnSwitch { tag: &Index<'_> } => {
1281 dst.push(0x01);
1282 tag.encode(dst);
1283 }
1284 }
1285 }
1286}
1287
1288impl<'a> Encode for Switch<'a> {
1289 fn encode(&self, dst: &mut Vec<u8>) {
1290 self.type_index.encode(dst);
1291 self.tag_index.encode(dst);
1292 }
1293}
1294
1295impl Encode for V128Const {
1296 fn encode(&self, dst: &mut Vec<u8>) {
1297 dst.extend_from_slice(&self.to_le_bytes());
1298 }
1299}
1300
1301impl Encode for I8x16Shuffle {
1302 fn encode(&self, dst: &mut Vec<u8>) {
1303 dst.extend_from_slice(&self.lanes);
1304 }
1305}
1306
1307impl<'a> Encode for SelectTypes<'a> {
1308 fn encode(&self, dst: &mut Vec<u8>) {
1309 match &self.tys {
1310 Some(list: &Vec>) => {
1311 dst.push(0x1c);
1312 list.encode(dst);
1313 }
1314 None => dst.push(0x1b),
1315 }
1316 }
1317}
1318
1319impl Custom<'_> {
1320 fn encode(&self, module: &mut wasm_encoder::Module) {
1321 match self {
1322 Custom::Raw(r: &RawCustomSection<'_>) => {
1323 module.section(&r.to_section());
1324 }
1325 Custom::Producers(p: &Producers<'_>) => {
1326 module.section(&p.to_section());
1327 }
1328 Custom::Dylink0(p: &Dylink0<'_>) => {
1329 module.section(&p.to_section());
1330 }
1331 }
1332 }
1333}
1334
1335impl RawCustomSection<'_> {
1336 fn to_section(&self) -> wasm_encoder::CustomSection<'_> {
1337 let mut ret: Vec = Vec::new();
1338 for list: &&[u8] in self.data.iter() {
1339 ret.extend_from_slice(list);
1340 }
1341 wasm_encoder::CustomSection {
1342 name: self.name.into(),
1343 data: ret.into(),
1344 }
1345 }
1346}
1347
1348impl Producers<'_> {
1349 pub(crate) fn to_section(&self) -> wasm_encoder::ProducersSection {
1350 let mut ret: ProducersSection = wasm_encoder::ProducersSection::default();
1351 for (name: &&str, fields: &Vec<(&str, &str)>) in self.fields.iter() {
1352 let mut field: ProducersField = wasm_encoder::ProducersField::new();
1353 for (key: &&str, value: &&str) in fields {
1354 field.value(name:key, version:value);
1355 }
1356 ret.field(name, &field);
1357 }
1358 ret
1359 }
1360}
1361
1362impl Dylink0<'_> {
1363 fn to_section(&self) -> wasm_encoder::CustomSection<'_> {
1364 let mut e: Vec = Vec::new();
1365 for section: &Dylink0Subsection<'_> in self.subsections.iter() {
1366 e.push(section.id());
1367 let mut tmp: Vec = Vec::new();
1368 section.encode(&mut tmp);
1369 tmp.encode(&mut e);
1370 }
1371 wasm_encoder::CustomSection {
1372 name: "dylink.0".into(),
1373 data: e.into(),
1374 }
1375 }
1376}
1377
1378impl Encode for Dylink0Subsection<'_> {
1379 fn encode(&self, e: &mut Vec<u8>) {
1380 match self {
1381 Dylink0Subsection::MemInfo {
1382 memory_size: &u32,
1383 memory_align: &u32,
1384 table_size: &u32,
1385 table_align: &u32,
1386 } => {
1387 memory_size.encode(e);
1388 memory_align.encode(e);
1389 table_size.encode(e);
1390 table_align.encode(e);
1391 }
1392 Dylink0Subsection::Needed(libs: &Vec<&str>) => libs.encode(e),
1393 Dylink0Subsection::ExportInfo(list: &Vec<(&str, u32)>) => list.encode(e),
1394 Dylink0Subsection::ImportInfo(list: &Vec<(&str, &str, u32)>) => list.encode(e),
1395 }
1396 }
1397}
1398
1399impl SectionItem for Tag<'_> {
1400 type Section = wasm_encoder::TagSection;
1401 const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Tag;
1402
1403 fn encode(&self, section: &mut wasm_encoder::TagSection) {
1404 section.tag(self.ty.to_tag_type());
1405 match &self.kind {
1406 TagKind::Inline() => {}
1407 _ => panic!("TagKind should be inline during encoding"),
1408 }
1409 }
1410}
1411
1412impl Encode for StructAccess<'_> {
1413 fn encode(&self, e: &mut Vec<u8>) {
1414 self.r#struct.encode(e);
1415 self.field.encode(e);
1416 }
1417}
1418
1419impl Encode for ArrayFill<'_> {
1420 fn encode(&self, e: &mut Vec<u8>) {
1421 self.array.encode(e);
1422 }
1423}
1424
1425impl Encode for ArrayCopy<'_> {
1426 fn encode(&self, e: &mut Vec<u8>) {
1427 self.dest_array.encode(e);
1428 self.src_array.encode(e);
1429 }
1430}
1431
1432impl Encode for ArrayInit<'_> {
1433 fn encode(&self, e: &mut Vec<u8>) {
1434 self.array.encode(e);
1435 self.segment.encode(e);
1436 }
1437}
1438
1439impl Encode for ArrayNewFixed<'_> {
1440 fn encode(&self, e: &mut Vec<u8>) {
1441 self.array.encode(e);
1442 self.length.encode(e);
1443 }
1444}
1445
1446impl Encode for ArrayNewData<'_> {
1447 fn encode(&self, e: &mut Vec<u8>) {
1448 self.array.encode(e);
1449 self.data_idx.encode(e);
1450 }
1451}
1452
1453impl Encode for ArrayNewElem<'_> {
1454 fn encode(&self, e: &mut Vec<u8>) {
1455 self.array.encode(e);
1456 self.elem_idx.encode(e);
1457 }
1458}
1459
1460impl Encode for RefTest<'_> {
1461 fn encode(&self, e: &mut Vec<u8>) {
1462 e.push(0xfb);
1463 if self.r#type.nullable {
1464 e.push(0x15);
1465 } else {
1466 e.push(0x14);
1467 }
1468 self.r#type.heap.encode(e);
1469 }
1470}
1471
1472impl Encode for RefCast<'_> {
1473 fn encode(&self, e: &mut Vec<u8>) {
1474 e.push(0xfb);
1475 if self.r#type.nullable {
1476 e.push(0x17);
1477 } else {
1478 e.push(0x16);
1479 }
1480 self.r#type.heap.encode(e);
1481 }
1482}
1483
1484fn br_on_cast_flags(from_nullable: bool, to_nullable: bool) -> u8 {
1485 let mut flag: u8 = 0;
1486 if from_nullable {
1487 flag |= 1 << 0;
1488 }
1489 if to_nullable {
1490 flag |= 1 << 1;
1491 }
1492 flag
1493}
1494
1495impl Encode for BrOnCast<'_> {
1496 fn encode(&self, e: &mut Vec<u8>) {
1497 e.push(0xfb);
1498 e.push(0x18);
1499 e.push(br_on_cast_flags(
1500 self.from_type.nullable,
1501 self.to_type.nullable,
1502 ));
1503 self.label.encode(e);
1504 self.from_type.heap.encode(e);
1505 self.to_type.heap.encode(e);
1506 }
1507}
1508
1509impl Encode for BrOnCastFail<'_> {
1510 fn encode(&self, e: &mut Vec<u8>) {
1511 e.push(0xfb);
1512 e.push(0x19);
1513 e.push(br_on_cast_flags(
1514 self.from_type.nullable,
1515 self.to_type.nullable,
1516 ));
1517 self.label.encode(e);
1518 self.from_type.heap.encode(e);
1519 self.to_type.heap.encode(e);
1520 }
1521}
1522