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#[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#[derive(Copy, Clone, Debug)]
35#[non_exhaustive]
36pub enum GenerateDwarf {
37 Lines,
40
41 Full,
44}
45
46impl<'a> EncodeOptions<'a> {
47 pub fn new() -> EncodeOptions<'a> {
49 EncodeOptions::default()
50 }
51
52 #[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 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 #[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 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 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(§ion);
237 }
238 self.custom_sections(CustomPlace::After(T::ANCHOR));
239 }
240
241 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 if !branch_hints.is_empty() {
277 self.wasm.section(&branch_hints);
278 }
279
280 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 }
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 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 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 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 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 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 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 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 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 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 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 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 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}