orca_wasm/ir/
component.rs

1#![allow(clippy::mut_range_bound)] // see https://github.com/rust-lang/rust-clippy/issues/6072
2//! Intermediate Representation of a wasm component.
3
4use wasm_encoder::reencode::{Reencode, ReencodeComponent};
5use wasm_encoder::{ComponentAliasSection, ModuleArg, ModuleSection, NestedComponentSection};
6use wasmparser::{
7    CanonicalFunction, ComponentAlias, ComponentExport, ComponentImport, ComponentInstance,
8    ComponentStartFunction, ComponentType, ComponentTypeDeclaration, CoreType, Encoding, Instance,
9    Parser, Payload,
10};
11
12use crate::error::Error;
13use crate::ir::helpers::{
14    print_alias, print_component_export, print_component_import, print_component_type,
15    print_core_type,
16};
17use crate::ir::id::{CustomSectionID, FunctionID, GlobalID, ModuleID};
18use crate::ir::module::module_functions::FuncKind;
19use crate::ir::module::module_globals::Global;
20use crate::ir::module::Module;
21use crate::ir::section::ComponentSection;
22use crate::ir::types::CustomSections;
23use crate::ir::wrappers::{
24    add_to_namemap, convert_component_type, convert_instance_type, convert_module_type_declaration,
25    convert_results, encode_core_type_subtype, process_alias,
26};
27
28#[derive(Debug)]
29/// Intermediate Representation of a wasm component.
30pub struct Component<'a> {
31    /// Modules
32    pub modules: Vec<Module<'a>>,
33    ///Alias
34    pub alias: Vec<ComponentAlias<'a>>,
35    /// Core Types
36    pub core_types: Vec<CoreType<'a>>,
37    /// Component Types
38    pub component_types: Vec<ComponentType<'a>>,
39    /// Imports
40    pub imports: Vec<ComponentImport<'a>>,
41    /// Exports
42    pub exports: Vec<ComponentExport<'a>>,
43    /// Core Instances
44    pub instances: Vec<Instance<'a>>,
45    /// Component Instances
46    pub component_instance: Vec<ComponentInstance<'a>>,
47    /// Canons
48    pub canons: Vec<CanonicalFunction>,
49    /// Custom sections
50    pub custom_sections: CustomSections<'a>,
51    /// Nested Components
52    pub components: Vec<Component<'a>>,
53    /// Number of modules
54    pub num_modules: usize,
55    /// Component Start Section
56    pub start_section: Vec<ComponentStartFunction>,
57    /// Sections of the Component. Represented as (#num of occurrences of a section, type of section)
58    pub sections: Vec<(u32, ComponentSection)>,
59    num_sections: usize,
60
61    // Names
62    pub(crate) component_name: Option<String>,
63    pub(crate) core_func_names: wasm_encoder::NameMap,
64    pub(crate) global_names: wasm_encoder::NameMap,
65    pub(crate) memory_names: wasm_encoder::NameMap,
66    pub(crate) table_names: wasm_encoder::NameMap,
67    pub(crate) module_names: wasm_encoder::NameMap,
68    pub(crate) core_instances_names: wasm_encoder::NameMap,
69    pub(crate) core_type_names: wasm_encoder::NameMap,
70    pub(crate) type_names: wasm_encoder::NameMap,
71    pub(crate) instance_names: wasm_encoder::NameMap,
72    pub(crate) components_names: wasm_encoder::NameMap,
73    pub(crate) func_names: wasm_encoder::NameMap,
74    pub(crate) value_names: wasm_encoder::NameMap,
75}
76
77impl Default for Component<'_> {
78    fn default() -> Self {
79        Component::new()
80    }
81}
82
83impl<'a> Component<'a> {
84    /// Creates a new Empty Component
85    pub fn new() -> Self {
86        Component {
87            modules: vec![],
88            alias: vec![],
89            core_types: vec![],
90            component_types: vec![],
91            imports: vec![],
92            exports: vec![],
93            instances: vec![],
94            component_instance: vec![],
95            canons: vec![],
96            custom_sections: CustomSections::new(vec![]),
97            num_modules: 0,
98            start_section: vec![],
99            sections: vec![],
100            num_sections: 0,
101            components: vec![],
102            component_name: None,
103            core_func_names: wasm_encoder::NameMap::new(),
104            global_names: wasm_encoder::NameMap::new(),
105            memory_names: wasm_encoder::NameMap::new(),
106            table_names: wasm_encoder::NameMap::new(),
107            module_names: wasm_encoder::NameMap::new(),
108            core_instances_names: wasm_encoder::NameMap::new(),
109            core_type_names: wasm_encoder::NameMap::new(),
110            type_names: wasm_encoder::NameMap::new(),
111            instance_names: wasm_encoder::NameMap::new(),
112            components_names: wasm_encoder::NameMap::new(),
113            func_names: wasm_encoder::NameMap::new(),
114            value_names: wasm_encoder::NameMap::new(),
115        }
116    }
117
118    fn add_to_own_section(&mut self, section: ComponentSection) {
119        if self.sections[self.num_sections - 1].1 == section {
120            self.sections[self.num_sections - 1].0 += 1;
121        } else {
122            self.sections.push((1, section));
123        }
124    }
125
126    /// Add a Module to this Component.
127    pub fn add_module(&mut self, module: Module<'a>) {
128        self.modules.push(module);
129        self.add_to_own_section(ComponentSection::Module);
130        self.num_modules += 1;
131    }
132
133    /// Add a Global to this Component.
134    pub fn add_globals(&mut self, global: Global, module_idx: usize) -> GlobalID {
135        self.modules[module_idx].globals.add(global)
136    }
137
138    fn add_to_sections(
139        sections: &mut Vec<(u32, ComponentSection)>,
140        section: ComponentSection,
141        num_sections: &mut usize,
142        sections_added: u32,
143    ) {
144        if *num_sections > 0 && sections[*num_sections - 1].1 == section {
145            sections[*num_sections - 1].0 += sections_added;
146        } else {
147            sections.push((sections_added, section));
148            *num_sections += 1;
149        }
150    }
151
152    /// Parse a `Component` from a wasm binary.
153    ///
154    /// # Example
155    ///
156    /// ```no_run
157    /// use orca_wasm::Component;
158    ///
159    /// let file = "path_to_file";
160    /// let buff = wat::parse_file(file).expect("couldn't convert the input wat to Wasm");
161    /// let comp = Component::parse(&buff, false).unwrap();
162    /// ```
163    pub fn parse(wasm: &'a [u8], enable_multi_memory: bool) -> Result<Self, Error> {
164        let parser = Parser::new(0);
165        Component::parse_comp(wasm, enable_multi_memory, parser, 0, &mut vec![])
166    }
167
168    fn parse_comp(
169        wasm: &'a [u8],
170        enable_multi_memory: bool,
171        parser: Parser,
172        start: usize,
173        parent_stack: &mut Vec<Encoding>,
174    ) -> Result<Self, Error> {
175        let mut modules = vec![];
176        let mut core_types = vec![];
177        let mut component_types = vec![];
178        let mut imports = vec![];
179        let mut exports = vec![];
180        let mut instances = vec![];
181        let mut canons = vec![];
182        let mut alias = vec![];
183        let mut component_instance = vec![];
184        let mut custom_sections = vec![];
185        let mut sections = vec![];
186        let mut num_sections: usize = 0;
187        let mut components: Vec<Component> = vec![];
188        let mut start_section = vec![];
189        let mut stack = vec![];
190
191        // Names
192        let mut component_name: Option<String> = None;
193        let mut core_func_names = wasm_encoder::NameMap::new();
194        let mut global_names = wasm_encoder::NameMap::new();
195        let mut memory_names = wasm_encoder::NameMap::new();
196        let mut table_names = wasm_encoder::NameMap::new();
197        let mut module_names = wasm_encoder::NameMap::new();
198        let mut core_instance_names = wasm_encoder::NameMap::new();
199        let mut instance_names = wasm_encoder::NameMap::new();
200        let mut components_names = wasm_encoder::NameMap::new();
201        let mut func_names = wasm_encoder::NameMap::new();
202        let mut value_names = wasm_encoder::NameMap::new();
203        let mut core_type_names = wasm_encoder::NameMap::new();
204        let mut type_names = wasm_encoder::NameMap::new();
205
206        for payload in parser.parse_all(wasm) {
207            let payload = payload?;
208            if let Payload::End(..) = payload {
209                if !stack.is_empty() {
210                    stack.pop();
211                }
212            }
213            if !stack.is_empty() {
214                continue;
215            }
216            match payload {
217                Payload::ComponentImportSection(import_section_reader) => {
218                    let temp: &mut Vec<ComponentImport> = &mut import_section_reader
219                        .into_iter()
220                        .collect::<Result<_, _>>()?;
221                    let l = temp.len();
222                    imports.append(temp);
223                    Self::add_to_sections(
224                        &mut sections,
225                        ComponentSection::ComponentImport,
226                        &mut num_sections,
227                        l as u32,
228                    );
229                }
230                Payload::ComponentExportSection(export_section_reader) => {
231                    let temp: &mut Vec<ComponentExport> = &mut export_section_reader
232                        .into_iter()
233                        .collect::<Result<_, _>>()?;
234                    let l = temp.len();
235                    exports.append(temp);
236                    Self::add_to_sections(
237                        &mut sections,
238                        ComponentSection::ComponentExport,
239                        &mut num_sections,
240                        l as u32,
241                    );
242                }
243                Payload::InstanceSection(instance_section_reader) => {
244                    let temp: &mut Vec<Instance> = &mut instance_section_reader
245                        .into_iter()
246                        .collect::<Result<_, _>>()?;
247                    let l = temp.len();
248                    instances.append(temp);
249                    Self::add_to_sections(
250                        &mut sections,
251                        ComponentSection::CoreInstance,
252                        &mut num_sections,
253                        l as u32,
254                    );
255                }
256                Payload::CoreTypeSection(core_type_reader) => {
257                    let temp: &mut Vec<CoreType> =
258                        &mut core_type_reader.into_iter().collect::<Result<_, _>>()?;
259                    let l = temp.len();
260                    core_types.append(temp);
261                    Self::add_to_sections(
262                        &mut sections,
263                        ComponentSection::CoreType,
264                        &mut num_sections,
265                        l as u32,
266                    );
267                }
268                Payload::ComponentTypeSection(component_type_reader) => {
269                    let temp: &mut Vec<ComponentType> = &mut component_type_reader
270                        .into_iter()
271                        .collect::<Result<_, _>>()?;
272                    let l = temp.len();
273                    component_types.append(temp);
274                    Self::add_to_sections(
275                        &mut sections,
276                        ComponentSection::ComponentType,
277                        &mut num_sections,
278                        l as u32,
279                    );
280                }
281                Payload::ComponentInstanceSection(component_instances) => {
282                    let temp: &mut Vec<ComponentInstance> =
283                        &mut component_instances.into_iter().collect::<Result<_, _>>()?;
284                    let l = temp.len();
285                    component_instance.append(temp);
286                    Self::add_to_sections(
287                        &mut sections,
288                        ComponentSection::ComponentInstance,
289                        &mut num_sections,
290                        l as u32,
291                    );
292                }
293                Payload::ComponentAliasSection(alias_reader) => {
294                    let temp: &mut Vec<ComponentAlias> =
295                        &mut alias_reader.into_iter().collect::<Result<_, _>>()?;
296                    let l = temp.len();
297                    alias.append(temp);
298                    Self::add_to_sections(
299                        &mut sections,
300                        ComponentSection::Alias,
301                        &mut num_sections,
302                        l as u32,
303                    );
304                }
305                Payload::ComponentCanonicalSection(canon_reader) => {
306                    let temp: &mut Vec<CanonicalFunction> =
307                        &mut canon_reader.into_iter().collect::<Result<_, _>>()?;
308                    let l = temp.len();
309                    canons.append(temp);
310                    Self::add_to_sections(
311                        &mut sections,
312                        ComponentSection::Canon,
313                        &mut num_sections,
314                        l as u32,
315                    );
316                }
317                Payload::ModuleSection {
318                    parser,
319                    unchecked_range,
320                } => {
321                    // Indicating the start of a new module
322                    parent_stack.push(Encoding::Module);
323                    stack.push(Encoding::Module);
324                    modules.push(Module::parse_internal(
325                        &wasm[unchecked_range.start - start..unchecked_range.end - start],
326                        enable_multi_memory,
327                        parser,
328                    )?);
329                    Self::add_to_sections(
330                        &mut sections,
331                        ComponentSection::Module,
332                        &mut num_sections,
333                        1,
334                    );
335                }
336                Payload::ComponentSection {
337                    parser,
338                    unchecked_range,
339                } => {
340                    // Indicating the start of a new component
341                    parent_stack.push(Encoding::Component);
342                    stack.push(Encoding::Component);
343                    let cmp = Component::parse_comp(
344                        &wasm[unchecked_range.start - start..unchecked_range.end - start],
345                        enable_multi_memory,
346                        parser,
347                        unchecked_range.start,
348                        &mut stack,
349                    )?;
350                    components.push(cmp);
351                    Self::add_to_sections(
352                        &mut sections,
353                        ComponentSection::Component,
354                        &mut num_sections,
355                        1,
356                    );
357                }
358                Payload::ComponentStartSection { start, range: _ } => {
359                    start_section.push(start);
360                    Self::add_to_sections(
361                        &mut sections,
362                        ComponentSection::ComponentStartSection,
363                        &mut num_sections,
364                        1,
365                    );
366                }
367                Payload::CustomSection(custom_section_reader) => {
368                    match custom_section_reader.as_known() {
369                        wasmparser::KnownCustom::ComponentName(name_section_reader) => {
370                            for subsection in name_section_reader {
371                                #[allow(clippy::single_match)]
372                                match subsection? {
373                                    wasmparser::ComponentName::Component { name, .. } => {
374                                        component_name = Some(name.parse().unwrap())
375                                    }
376                                    wasmparser::ComponentName::CoreFuncs(names) => {
377                                        add_to_namemap(&mut core_func_names, names);
378                                    }
379                                    wasmparser::ComponentName::CoreGlobals(names) => {
380                                        add_to_namemap(&mut global_names, names);
381                                    }
382                                    wasmparser::ComponentName::CoreTables(names) => {
383                                        add_to_namemap(&mut table_names, names);
384                                    }
385                                    wasmparser::ComponentName::CoreModules(names) => {
386                                        add_to_namemap(&mut module_names, names);
387                                    }
388                                    wasmparser::ComponentName::CoreInstances(names) => {
389                                        add_to_namemap(&mut core_instance_names, names);
390                                    }
391                                    wasmparser::ComponentName::CoreTypes(names) => {
392                                        add_to_namemap(&mut core_type_names, names);
393                                    }
394                                    wasmparser::ComponentName::Types(names) => {
395                                        add_to_namemap(&mut type_names, names);
396                                    }
397                                    wasmparser::ComponentName::Instances(names) => {
398                                        add_to_namemap(&mut instance_names, names);
399                                    }
400                                    wasmparser::ComponentName::Components(names) => {
401                                        add_to_namemap(&mut components_names, names);
402                                    }
403                                    wasmparser::ComponentName::Funcs(names) => {
404                                        add_to_namemap(&mut func_names, names);
405                                    }
406                                    wasmparser::ComponentName::Values(names) => {
407                                        add_to_namemap(&mut value_names, names);
408                                    }
409                                    wasmparser::ComponentName::CoreMemories(names) => {
410                                        add_to_namemap(&mut memory_names, names);
411                                    }
412                                    wasmparser::ComponentName::Unknown { .. } => {}
413                                }
414                            }
415                        }
416                        _ => {
417                            custom_sections
418                                .push((custom_section_reader.name(), custom_section_reader.data()));
419                            Self::add_to_sections(
420                                &mut sections,
421                                ComponentSection::CustomSection,
422                                &mut num_sections,
423                                1,
424                            );
425                        }
426                    }
427                }
428                Payload::UnknownSection {
429                    id,
430                    contents: _,
431                    range: _,
432                } => return Err(Error::UnknownSection { section_id: id }),
433                _ => {}
434            }
435        }
436        let num_modules = modules.len();
437        Ok(Component {
438            modules,
439            alias,
440            core_types,
441            component_types,
442            imports,
443            exports,
444            instances,
445            component_instance,
446            canons,
447            custom_sections: CustomSections::new(custom_sections),
448            num_modules,
449            sections,
450            start_section,
451            num_sections,
452            component_name,
453            core_func_names,
454            global_names,
455            memory_names,
456            table_names,
457            module_names,
458            core_instances_names: core_instance_names,
459            core_type_names,
460            type_names,
461            instance_names,
462            components_names,
463            func_names,
464            components,
465            value_names,
466        })
467    }
468
469    /// Encode a `Component` to bytes..
470    ///
471    /// # Example
472    ///
473    /// ```no_run
474    /// use orca_wasm::Component;
475    ///
476    /// let file = "path_to_file";
477    /// let buff = wat::parse_file(file).expect("couldn't convert the input wat to Wasm");
478    /// let mut comp = Component::parse(&buff, false).unwrap();
479    /// let result = comp.encode();
480    /// ```
481    pub fn encode(&mut self) -> Vec<u8> {
482        self.encode_comp().finish()
483    }
484
485    fn encode_comp(&mut self) -> wasm_encoder::Component {
486        let mut component = wasm_encoder::Component::new();
487        let mut reencode = wasm_encoder::reencode::RoundtripReencoder;
488        // NOTE: All of these are 1-indexed and not 0-indexed
489        let mut last_processed_module = 0;
490        let mut last_processed_core_ty = 0;
491        let mut last_processed_comp_ty = 0;
492        let mut last_processed_imp = 0;
493        let mut last_processed_exp = 0;
494        let mut last_processed_comp_inst = 0;
495        let mut last_processed_core_inst = 0;
496        let mut last_processed_alias = 0;
497        let mut last_processed_canon = 0;
498        let mut last_processed_custom_section = 0;
499        let mut last_processed_component = 0;
500
501        for (num, section) in self.sections.iter() {
502            match section {
503                ComponentSection::Component => {
504                    assert!(
505                        *num as usize + last_processed_component as usize <= self.components.len()
506                    );
507                    for comp_idx in last_processed_component..last_processed_component + num {
508                        component.section(&NestedComponentSection(
509                            &self.components[comp_idx as usize].encode_comp(),
510                        ));
511                        last_processed_component += 1;
512                    }
513                }
514                ComponentSection::Module => {
515                    assert!(*num as usize + last_processed_module as usize <= self.modules.len());
516                    for mod_idx in last_processed_module..last_processed_module + num {
517                        component.section(&ModuleSection(
518                            &self.modules[mod_idx as usize].encode_internal(),
519                        ));
520                        last_processed_module += 1;
521                    }
522                }
523                ComponentSection::CoreType => {
524                    assert!(
525                        *num as usize + last_processed_core_ty as usize <= self.core_types.len()
526                    );
527                    let mut type_section = wasm_encoder::CoreTypeSection::new();
528                    for cty_idx in last_processed_core_ty..last_processed_core_ty + num {
529                        match &self.core_types[cty_idx as usize] {
530                            CoreType::Rec(recgroup) => {
531                                for subtype in recgroup.types() {
532                                    let enc = type_section.ty().core();
533                                    encode_core_type_subtype(enc, subtype, &mut reencode);
534                                }
535                            }
536                            CoreType::Module(module) => {
537                                let enc = type_section.ty();
538                                convert_module_type_declaration(module, enc, &mut reencode);
539                            }
540                        }
541                        last_processed_core_ty += 1;
542                    }
543                    component.section(&type_section);
544                }
545                ComponentSection::ComponentType => {
546                    assert!(
547                        *num as usize + last_processed_comp_ty as usize
548                            <= self.component_types.len()
549                    );
550                    let mut component_ty_section = wasm_encoder::ComponentTypeSection::new();
551                    for comp_ty_idx in last_processed_comp_ty..last_processed_comp_ty + num {
552                        match &self.component_types[comp_ty_idx as usize] {
553                            ComponentType::Defined(comp_ty) => {
554                                let enc = component_ty_section.defined_type();
555                                match comp_ty {
556                                    wasmparser::ComponentDefinedType::Primitive(p) => {
557                                        enc.primitive(wasm_encoder::PrimitiveValType::from(*p))
558                                    }
559                                    wasmparser::ComponentDefinedType::Record(records) => {
560                                        enc.record(records.iter().map(|record| {
561                                            (record.0, reencode.component_val_type(record.1))
562                                        }));
563                                    }
564                                    wasmparser::ComponentDefinedType::Variant(variants) => enc
565                                        .variant(variants.iter().map(|variant| {
566                                            (
567                                                variant.name,
568                                                variant
569                                                    .ty
570                                                    .map(|ty| reencode.component_val_type(ty)),
571                                                variant.refines,
572                                            )
573                                        })),
574                                    wasmparser::ComponentDefinedType::List(l) => {
575                                        enc.list(reencode.component_val_type(*l))
576                                    }
577                                    wasmparser::ComponentDefinedType::Tuple(tup) => enc
578                                        .tuple(tup.iter().map(|val_type| {
579                                            reencode.component_val_type(*val_type)
580                                        })),
581                                    wasmparser::ComponentDefinedType::Flags(flags) => {
582                                        enc.flags(flags.clone().into_vec().into_iter())
583                                    }
584                                    wasmparser::ComponentDefinedType::Enum(en) => {
585                                        enc.enum_type(en.clone().into_vec().into_iter())
586                                    }
587                                    wasmparser::ComponentDefinedType::Option(opt) => {
588                                        enc.option(reencode.component_val_type(*opt))
589                                    }
590                                    wasmparser::ComponentDefinedType::Result { ok, err } => enc
591                                        .result(
592                                            ok.map(|val_type| {
593                                                reencode.component_val_type(val_type)
594                                            }),
595                                            err.map(|val_type| {
596                                                reencode.component_val_type(val_type)
597                                            }),
598                                        ),
599                                    wasmparser::ComponentDefinedType::Own(u) => enc.own(*u),
600                                    wasmparser::ComponentDefinedType::Borrow(u) => enc.borrow(*u),
601                                    wasmparser::ComponentDefinedType::Future(opt) => match opt {
602                                        Some(u) => {
603                                            enc.future(Some(reencode.component_val_type(*u)))
604                                        }
605                                        None => enc.future(None),
606                                    },
607                                    wasmparser::ComponentDefinedType::Stream(opt) => match opt {
608                                        Some(u) => {
609                                            enc.stream(Some(reencode.component_val_type(*u)))
610                                        }
611                                        None => enc.stream(None),
612                                    },
613                                }
614                            }
615                            ComponentType::Func(func_ty) => {
616                                let mut enc = component_ty_section.function();
617                                enc.params(func_ty.params.iter().map(
618                                    |p: &(&str, wasmparser::ComponentValType)| {
619                                        (p.0, reencode.component_val_type(p.1))
620                                    },
621                                ));
622                                convert_results(func_ty.result, enc, &mut reencode);
623                            }
624                            ComponentType::Component(comp) => {
625                                let mut new_comp = wasm_encoder::ComponentType::new();
626                                for c in comp.iter() {
627                                    match c {
628                                        ComponentTypeDeclaration::CoreType(core) => match core {
629                                            CoreType::Rec(recgroup) => {
630                                                for sub in recgroup.types() {
631                                                    let enc = new_comp.core_type().core();
632                                                    encode_core_type_subtype(
633                                                        enc,
634                                                        sub,
635                                                        &mut reencode,
636                                                    );
637                                                }
638                                            }
639                                            CoreType::Module(module) => {
640                                                let enc = new_comp.core_type();
641                                                convert_module_type_declaration(
642                                                    module,
643                                                    enc,
644                                                    &mut reencode,
645                                                );
646                                            }
647                                        },
648                                        ComponentTypeDeclaration::Type(typ) => {
649                                            let enc = new_comp.ty();
650                                            convert_component_type(
651                                                &(*typ).clone(),
652                                                enc,
653                                                &mut reencode,
654                                            );
655                                        }
656                                        ComponentTypeDeclaration::Alias(a) => {
657                                            new_comp.alias(process_alias(a, &mut reencode));
658                                        }
659                                        ComponentTypeDeclaration::Export { name, ty } => {
660                                            new_comp
661                                                .export(name.0, reencode.component_type_ref(*ty));
662                                        }
663                                        ComponentTypeDeclaration::Import(imp) => {
664                                            new_comp.import(
665                                                imp.name.0,
666                                                reencode.component_type_ref(imp.ty),
667                                            );
668                                        }
669                                    }
670                                }
671                                component_ty_section.component(&new_comp);
672                            }
673                            ComponentType::Instance(inst) => {
674                                component_ty_section
675                                    .instance(&convert_instance_type(inst, &mut reencode));
676                            }
677                            ComponentType::Resource { rep, dtor } => {
678                                component_ty_section
679                                    .resource(reencode.val_type(*rep).unwrap(), *dtor);
680                            }
681                        }
682                        last_processed_comp_ty += 1;
683                    }
684                    component.section(&component_ty_section);
685                }
686                ComponentSection::ComponentImport => {
687                    assert!(*num as usize + last_processed_imp as usize <= self.imports.len());
688                    let mut imports = wasm_encoder::ComponentImportSection::new();
689                    for imp_idx in last_processed_imp..last_processed_imp + num {
690                        let imp = &self.imports[imp_idx as usize];
691                        imports.import(imp.name.0, reencode.component_type_ref(imp.ty));
692                        last_processed_imp += 1;
693                    }
694                    component.section(&imports);
695                }
696                ComponentSection::ComponentExport => {
697                    assert!(*num as usize + last_processed_exp as usize <= self.exports.len());
698                    let mut exports = wasm_encoder::ComponentExportSection::new();
699                    for exp_idx in last_processed_exp..last_processed_exp + num {
700                        let exp = &self.exports[exp_idx as usize];
701                        exports.export(
702                            exp.name.0,
703                            reencode.component_export_kind(exp.kind),
704                            exp.index,
705                            exp.ty.map(|ty| reencode.component_type_ref(ty)),
706                        );
707                        last_processed_exp += 1;
708                    }
709                    component.section(&exports);
710                }
711                ComponentSection::ComponentInstance => {
712                    assert!(
713                        *num as usize + last_processed_comp_inst as usize
714                            <= self.component_instance.len()
715                    );
716                    let mut instances = wasm_encoder::ComponentInstanceSection::new();
717                    for instance_idx in last_processed_comp_inst..last_processed_comp_inst + num {
718                        let instance = &self.component_instance[instance_idx as usize];
719                        match instance {
720                            ComponentInstance::Instantiate {
721                                component_index,
722                                args,
723                            } => {
724                                instances.instantiate(
725                                    *component_index,
726                                    args.iter().map(|arg| {
727                                        (
728                                            arg.name,
729                                            reencode.component_export_kind(arg.kind),
730                                            arg.index,
731                                        )
732                                    }),
733                                );
734                            }
735                            ComponentInstance::FromExports(export) => {
736                                instances.export_items(export.iter().map(|value| {
737                                    (
738                                        value.name.0,
739                                        reencode.component_export_kind(value.kind),
740                                        value.index,
741                                    )
742                                }));
743                            }
744                        }
745                        last_processed_comp_inst += 1;
746                    }
747                    component.section(&instances);
748                }
749                ComponentSection::CoreInstance => {
750                    assert!(
751                        *num as usize + last_processed_core_inst as usize <= self.instances.len()
752                    );
753                    let mut instances = wasm_encoder::InstanceSection::new();
754                    for instance_idx in last_processed_core_inst..last_processed_core_inst + num {
755                        let instance = &self.instances[instance_idx as usize];
756                        match instance {
757                            Instance::Instantiate { module_index, args } => {
758                                instances.instantiate(
759                                    *module_index,
760                                    args.iter()
761                                        .map(|arg| (arg.name, ModuleArg::Instance(arg.index))),
762                                );
763                            }
764                            Instance::FromExports(exports) => {
765                                instances.export_items(exports.iter().map(|export| {
766                                    (
767                                        export.name,
768                                        wasm_encoder::ExportKind::from(export.kind),
769                                        export.index,
770                                    )
771                                }));
772                            }
773                        }
774                        last_processed_core_inst += 1;
775                    }
776                    component.section(&instances);
777                }
778                ComponentSection::Alias => {
779                    assert!(*num as usize + last_processed_alias as usize <= self.alias.len());
780                    let mut alias = ComponentAliasSection::new();
781                    for a_idx in last_processed_alias..last_processed_alias + num {
782                        let a = &self.alias[a_idx as usize];
783                        alias.alias(process_alias(a, &mut reencode));
784                        last_processed_alias += 1;
785                    }
786                    component.section(&alias);
787                }
788                ComponentSection::Canon => {
789                    assert!(*num as usize + last_processed_canon as usize <= self.canons.len());
790                    let mut canon_sec = wasm_encoder::CanonicalFunctionSection::new();
791                    for canon_idx in last_processed_canon..last_processed_canon + num {
792                        let canon = &self.canons[canon_idx as usize];
793                        match canon {
794                            CanonicalFunction::Lift {
795                                core_func_index,
796                                type_index,
797                                options,
798                            } => {
799                                canon_sec.lift(
800                                    *core_func_index,
801                                    *type_index,
802                                    options
803                                        .iter()
804                                        .map(|canon| reencode.canonical_option(*canon)),
805                                );
806                            }
807                            CanonicalFunction::Lower {
808                                func_index,
809                                options,
810                            } => {
811                                canon_sec.lower(
812                                    *func_index,
813                                    options
814                                        .iter()
815                                        .map(|canon| reencode.canonical_option(*canon)),
816                                );
817                            }
818                            CanonicalFunction::ResourceNew { resource } => {
819                                canon_sec.resource_new(*resource);
820                            }
821                            CanonicalFunction::ResourceDrop { resource } => {
822                                canon_sec.resource_drop(*resource);
823                            }
824                            CanonicalFunction::ResourceRep { resource } => {
825                                canon_sec.resource_rep(*resource);
826                            }
827                            CanonicalFunction::ThreadSpawn { func_ty_index } => {
828                                canon_sec.thread_spawn(*func_ty_index);
829                            }
830                            CanonicalFunction::ResourceDropAsync { resource } => {
831                                canon_sec.resource_drop_async(*resource);
832                            }
833                            CanonicalFunction::ThreadAvailableParallelism => {
834                                canon_sec.thread_available_parallelism();
835                            }
836                            CanonicalFunction::BackpressureSet => {
837                                canon_sec.backpressure_set();
838                            }
839                            CanonicalFunction::TaskReturn { result, options } => {
840                                let options = options
841                                    .iter()
842                                    .cloned()
843                                    .map(|v| v.into())
844                                    .collect::<Vec<_>>();
845                                let result = result.map(|v| v.into());
846                                canon_sec.task_return(result, options);
847                            }
848                            CanonicalFunction::Yield { async_ } => {
849                                canon_sec.yield_(*async_);
850                            }
851                            CanonicalFunction::WaitableSetNew => {
852                                canon_sec.waitable_set_new();
853                            }
854                            CanonicalFunction::WaitableSetWait { async_, memory } => {
855                                canon_sec.waitable_set_wait(*async_, *memory);
856                            }
857                            CanonicalFunction::WaitableSetPoll { async_, memory } => {
858                                canon_sec.waitable_set_poll(*async_, *memory);
859                            }
860                            CanonicalFunction::WaitableSetDrop => {
861                                canon_sec.waitable_set_drop();
862                            }
863                            CanonicalFunction::WaitableJoin => {
864                                canon_sec.waitable_join();
865                            }
866                            CanonicalFunction::SubtaskDrop => {
867                                canon_sec.subtask_drop();
868                            }
869                            CanonicalFunction::StreamNew { ty } => {
870                                canon_sec.stream_new(*ty);
871                            }
872                            CanonicalFunction::StreamRead { ty, options } => {
873                                canon_sec.stream_read(
874                                    *ty,
875                                    options
876                                        .into_iter()
877                                        .map(|t| reencode.canonical_option(*t))
878                                        .collect::<Vec<wasm_encoder::CanonicalOption>>(),
879                                );
880                            }
881                            CanonicalFunction::StreamWrite { ty, options } => {
882                                canon_sec.stream_write(
883                                    *ty,
884                                    options
885                                        .into_iter()
886                                        .map(|t| reencode.canonical_option(*t))
887                                        .collect::<Vec<wasm_encoder::CanonicalOption>>(),
888                                );
889                            }
890                            CanonicalFunction::StreamCancelRead { ty, async_ } => {
891                                canon_sec.stream_cancel_read(*ty, *async_);
892                            }
893                            CanonicalFunction::StreamCancelWrite { ty, async_ } => {
894                                canon_sec.stream_cancel_write(*ty, *async_);
895                            }
896                            CanonicalFunction::StreamCloseReadable { ty } => {
897                                canon_sec.stream_close_readable(*ty);
898                            }
899                            CanonicalFunction::StreamCloseWritable { ty } => {
900                                canon_sec.stream_close_writable(*ty);
901                            }
902                            CanonicalFunction::FutureNew { ty } => {
903                                canon_sec.future_new(*ty);
904                            }
905                            CanonicalFunction::FutureRead { ty, options } => {
906                                canon_sec.future_read(
907                                    *ty,
908                                    options
909                                        .into_iter()
910                                        .map(|t| reencode.canonical_option(*t))
911                                        .collect::<Vec<wasm_encoder::CanonicalOption>>(),
912                                );
913                            }
914                            CanonicalFunction::FutureWrite { ty, options } => {
915                                canon_sec.future_write(
916                                    *ty,
917                                    options
918                                        .into_iter()
919                                        .map(|t| reencode.canonical_option(*t))
920                                        .collect::<Vec<wasm_encoder::CanonicalOption>>(),
921                                );
922                            }
923                            CanonicalFunction::FutureCancelRead { ty, async_ } => {
924                                canon_sec.future_cancel_read(*ty, *async_);
925                            }
926                            CanonicalFunction::FutureCancelWrite { ty, async_ } => {
927                                canon_sec.future_cancel_write(*ty, *async_);
928                            }
929                            CanonicalFunction::FutureCloseReadable { ty } => {
930                                canon_sec.future_close_readable(*ty);
931                            }
932                            CanonicalFunction::FutureCloseWritable { ty } => {
933                                canon_sec.future_close_writable(*ty);
934                            }
935                            CanonicalFunction::ErrorContextNew { options } => {
936                                canon_sec.error_context_new(
937                                    options
938                                        .into_iter()
939                                        .map(|t| reencode.canonical_option(*t))
940                                        .collect::<Vec<wasm_encoder::CanonicalOption>>(),
941                                );
942                            }
943                            CanonicalFunction::ErrorContextDebugMessage { options } => {
944                                canon_sec.error_context_debug_message(
945                                    options
946                                        .into_iter()
947                                        .map(|t| reencode.canonical_option(*t))
948                                        .collect::<Vec<wasm_encoder::CanonicalOption>>(),
949                                );
950                            }
951                            CanonicalFunction::ErrorContextDrop => {
952                                canon_sec.error_context_drop();
953                            }
954                        }
955                        last_processed_canon += 1;
956                    }
957                    component.section(&canon_sec);
958                }
959                ComponentSection::ComponentStartSection => {
960                    // Should only be 1 start section
961                    assert_eq!(self.start_section.len(), 1);
962                    let start_fn = &self.start_section[0];
963                    let start_sec = wasm_encoder::ComponentStartSection {
964                        function_index: start_fn.func_index,
965                        args: start_fn.arguments.iter(),
966                        results: start_fn.results,
967                    };
968                    component.section(&start_sec);
969                }
970                ComponentSection::CustomSection => {
971                    assert!(
972                        *num as usize + last_processed_custom_section as usize
973                            <= self.custom_sections.len()
974                    );
975                    for custom_sec_idx in
976                        last_processed_custom_section..last_processed_custom_section + num
977                    {
978                        let section = &self
979                            .custom_sections
980                            .get_by_id(CustomSectionID(custom_sec_idx));
981                        component.section(&wasm_encoder::CustomSection {
982                            name: std::borrow::Cow::Borrowed(section.name),
983                            data: std::borrow::Cow::Borrowed(section.data),
984                        });
985                        last_processed_custom_section += 1;
986                    }
987                }
988            }
989        }
990
991        // Name section
992        let mut name_sec = wasm_encoder::ComponentNameSection::new();
993
994        if let Some(comp_name) = &self.component_name {
995            name_sec.component(comp_name);
996        }
997
998        name_sec.core_funcs(&self.core_func_names);
999        name_sec.core_tables(&self.table_names);
1000        name_sec.core_memories(&self.memory_names);
1001        name_sec.core_globals(&self.global_names);
1002        name_sec.core_types(&self.core_type_names);
1003        name_sec.core_modules(&self.module_names);
1004        name_sec.core_instances(&self.core_instances_names);
1005        name_sec.funcs(&self.func_names);
1006        name_sec.values(&self.value_names);
1007        name_sec.types(&self.type_names);
1008        name_sec.components(&self.components_names);
1009        name_sec.instances(&self.instance_names);
1010
1011        // Add the name section back to the component
1012        component.section(&name_sec);
1013
1014        component
1015    }
1016
1017    /// Print a rudimentary textual representation of a `Component`
1018    pub fn print(&self) {
1019        // Print Alias
1020        if !self.alias.is_empty() {
1021            eprintln!("Alias Section:");
1022            for alias in self.alias.iter() {
1023                print_alias(alias);
1024            }
1025            eprintln!();
1026        }
1027
1028        // Print CoreType
1029        if !self.core_types.is_empty() {
1030            eprintln!("Core Type Section:");
1031            for cty in self.core_types.iter() {
1032                print_core_type(cty);
1033            }
1034            eprintln!();
1035        }
1036
1037        // Print ComponentType
1038        if !self.component_types.is_empty() {
1039            eprintln!("Component Type Section:");
1040            for cty in self.component_types.iter() {
1041                print_component_type(cty);
1042            }
1043            eprintln!();
1044        }
1045
1046        // Print Imports
1047        if !self.imports.is_empty() {
1048            eprintln!("Imports Section:");
1049            for imp in self.imports.iter() {
1050                print_component_import(imp);
1051            }
1052            eprintln!();
1053        }
1054
1055        // Print Exports
1056        if !self.imports.is_empty() {
1057            eprintln!("Exports Section:");
1058            for exp in self.exports.iter() {
1059                print_component_export(exp);
1060            }
1061            eprintln!();
1062        }
1063    }
1064
1065    /// Emit the Component into a wasm binary file.
1066    pub fn emit_wasm(&mut self, file_name: &str) -> Result<(), std::io::Error> {
1067        let comp = self.encode_comp();
1068        let wasm = comp.finish();
1069        std::fs::write(file_name, wasm)?;
1070        Ok(())
1071    }
1072
1073    /// Get Local Function ID by name
1074    // Note: returned absolute id here
1075    pub fn get_fid_by_name(&self, name: &str, module_idx: ModuleID) -> Option<FunctionID> {
1076        for (idx, func) in self.modules[*module_idx as usize]
1077            .functions
1078            .iter()
1079            .enumerate()
1080        {
1081            if let FuncKind::Local(l) = &func.kind {
1082                if let Some(n) = &l.body.name {
1083                    if n == name {
1084                        return Some(FunctionID(idx as u32));
1085                    }
1086                }
1087            }
1088        }
1089        None
1090    }
1091}