template_compiler/gen/
component.rs

1use wasm_encoder::{
2    Alias, CanonicalFunctionSection, CanonicalOption, Component, ComponentAliasSection,
3    ComponentExportKind, ComponentExportSection, ComponentSectionId, ComponentTypeSection,
4    ComponentValType, ExportKind, InstanceSection, ModuleArg, ModuleSection, PrimitiveValType,
5    RawSection,
6};
7
8use crate::Config;
9
10use super::{module::gen_module, template::TemplateGenerator};
11
12/// Generate a component representing the given file data
13pub fn gen_component(config: &Config, template: &TemplateGenerator) -> Component {
14    let mut component = Component::new();
15
16    // Encode the allocator module
17    let allocator = gen_allocator();
18    let id = ComponentSectionId::CoreModule.into();
19    let data = allocator.as_slice();
20    component.section(&RawSection { id, data });
21    let allocator_module_index = 0;
22
23    // Encode the inner module
24    let module = gen_module(config, template);
25    component.section(&ModuleSection(&module));
26    let inner_module_index = 1;
27
28    // Instantiate the allocator & inner module
29    let mut instances = InstanceSection::new();
30    instances.instantiate::<Vec<(&str, ModuleArg)>, &str>(allocator_module_index, vec![]);
31    instances.instantiate(
32        inner_module_index,
33        [("allocator", ModuleArg::Instance(allocator_module_index))].into_iter(),
34    );
35    component.section(&instances);
36
37    // Project the function and memory into the component index space
38    let mut aliases = ComponentAliasSection::new();
39    aliases.alias(Alias::CoreInstanceExport {
40        instance: allocator_module_index,
41        kind: ExportKind::Memory,
42        name: "memory",
43    });
44    aliases.alias(Alias::CoreInstanceExport {
45        instance: allocator_module_index,
46        kind: ExportKind::Func,
47        name: "realloc",
48    });
49    aliases.alias(Alias::CoreInstanceExport {
50        instance: inner_module_index,
51        kind: ExportKind::Func,
52        name: &config.export_func_name,
53    });
54    component.section(&aliases);
55
56    // Define the component-level argument type
57    let types = template.params().record_type();
58    let params_type_index = 0;
59    component.section(&types);
60
61    // Export the component-level argument type
62    let mut exports = ComponentExportSection::new();
63    exports.export("params", ComponentExportKind::Type, params_type_index, None);
64    let params_export_index = 1;
65    component.section(&exports);
66
67    // Define the component-level function type
68    let mut types = ComponentTypeSection::new();
69    types
70        .function()
71        .params([("params", ComponentValType::Type(params_export_index))])
72        .result(ComponentValType::Primitive(PrimitiveValType::String));
73    let apply_type_index = 2;
74    component.section(&types);
75
76    // Define the component-level function
77    let mut functions = CanonicalFunctionSection::new();
78    functions.lift(
79        1,
80        apply_type_index,
81        [
82            CanonicalOption::UTF8,
83            CanonicalOption::Memory(0),
84            CanonicalOption::Realloc(0),
85        ],
86    );
87    component.section(&functions);
88
89    // Export the component-level function
90    let mut exports = ComponentExportSection::new();
91    exports.export(&config.export_func_name, ComponentExportKind::Func, 0, None);
92    component.section(&exports);
93
94    component
95}
96
97pub fn gen_allocator() -> Vec<u8> {
98    let wat = include_str!("../../allocator.wat");
99    wat::parse_str(wat).unwrap()
100}