1use self::bitvec::BitVec;
2use anyhow::{Result, bail};
3use indexmap::{IndexMap, IndexSet};
4use std::{
5    borrow::Cow,
6    collections::{HashMap, HashSet},
7    convert::Infallible,
8    mem,
9    ops::Deref,
10};
11use wasm_encoder::{Encode, EntityType, RawCustomSection, reencode::Reencode};
12use wasmparser::*;
13
14const PAGE_SIZE: i32 = 64 * 1024;
15
16pub fn run(
22    wasm: &[u8],
23    required: &IndexSet<String>,
24    main_module_realloc: Option<&str>,
25) -> Result<Vec<u8>> {
26    assert!(!required.is_empty());
27
28    let mut module = Module::default();
29    module.parse(wasm)?;
30
31    for name in required {
34        if !module.exports.contains_key(name.as_str()) {
35            bail!("adapter module does not have export `{name}`")
36        }
37    }
38    let mut not_required = IndexSet::new();
39    for name in module.exports.keys().copied() {
40        if !required.contains(name) {
41            not_required.insert(name);
42        }
43    }
44    for name in not_required {
45        module.exports.swap_remove(name);
46    }
47    assert!(!module.exports.is_empty());
48    module.liveness()?;
49    module.encode(main_module_realloc)
50}
51
52fn realloc_via_memory_grow() -> wasm_encoder::Function {
55    let mut func = wasm_encoder::Function::new([(1, wasm_encoder::ValType::I32)]);
56
57    func.instructions().i32_const(0);
59    func.instructions().local_get(0);
60    func.instructions().i32_ne();
61    func.instructions().if_(wasm_encoder::BlockType::Empty);
62    func.instructions().unreachable();
63    func.instructions().end();
64
65    func.instructions().i32_const(0);
67    func.instructions().local_get(1);
68    func.instructions().i32_ne();
69    func.instructions().if_(wasm_encoder::BlockType::Empty);
70    func.instructions().unreachable();
71    func.instructions().end();
72
73    func.instructions().i32_const(PAGE_SIZE);
76    func.instructions().local_get(3);
77    func.instructions().i32_ne();
78    func.instructions().if_(wasm_encoder::BlockType::Empty);
79    func.instructions().unreachable();
80    func.instructions().end();
81
82    func.instructions().i32_const(1);
84    func.instructions().memory_grow(0);
85    func.instructions().local_tee(4);
86
87    func.instructions().i32_const(-1);
89    func.instructions().i32_eq();
90    func.instructions().if_(wasm_encoder::BlockType::Empty);
91    func.instructions().unreachable();
92    func.instructions().end();
93
94    func.instructions().local_get(4);
95    func.instructions().i32_const(16);
96    func.instructions().i32_shl();
97    func.instructions().end();
98
99    func
100}
101
102#[repr(i32)]
103#[non_exhaustive]
104enum StackAllocationState {
105    Unallocated,
106    Allocating,
107    Allocated,
108}
109
110fn allocate_stack_via_realloc(
111    realloc_index: u32,
112    sp: u32,
113    allocation_state: Option<u32>,
114) -> wasm_encoder::Function {
115    let mut func = wasm_encoder::Function::new([]);
116
117    if let Some(allocation_state) = allocation_state {
118        func.instructions().global_get(allocation_state);
120        func.instructions()
121            .i32_const(StackAllocationState::Unallocated as _);
122        func.instructions().i32_eq();
123        func.instructions().if_(wasm_encoder::BlockType::Empty);
124        func.instructions()
125            .i32_const(StackAllocationState::Allocating as _);
126        func.instructions().global_set(allocation_state);
127        }
130
131    func.instructions().i32_const(0);
132    func.instructions().i32_const(0);
133    func.instructions().i32_const(8);
134    func.instructions().i32_const(PAGE_SIZE);
135    func.instructions().call(realloc_index);
136    func.instructions().i32_const(PAGE_SIZE);
137    func.instructions().i32_add();
138    func.instructions().global_set(sp);
139
140    if let Some(allocation_state) = allocation_state {
141        func.instructions()
142            .i32_const(StackAllocationState::Allocated as _);
143        func.instructions().global_set(allocation_state);
144        func.instructions().end();
145    }
146
147    func.instructions().end();
148
149    func
150}
151
152type WorklistFunc<'a> = fn(&mut Module<'a>, u32) -> Result<()>;
154
155#[derive(Default)]
163struct Module<'a> {
164    types: Vec<FuncType>,
166    tables: Vec<Table<'a>>,
167    globals: Vec<Global<'a>>,
168    memories: Vec<Memory<'a>>,
169    funcs: Vec<Func<'a>>,
170    exports: IndexMap<&'a str, Export<'a>>,
171    func_names: HashMap<u32, &'a str>,
172    global_names: HashMap<u32, &'a str>,
173    producers: Option<wasm_metadata::Producers>,
174
175    live_types: BitVec,
177    live_tables: BitVec,
178    live_globals: BitVec,
179    live_memories: BitVec,
180    live_funcs: BitVec,
181
182    worklist: Vec<(u32, WorklistFunc<'a>)>,
188}
189
190struct Table<'a> {
191    def: Definition<'a, ()>,
192    ty: TableType,
193}
194
195struct Memory<'a> {
196    def: Definition<'a, ()>,
197    ty: MemoryType,
198}
199
200struct Global<'a> {
201    def: Definition<'a, ConstExpr<'a>>,
202    ty: GlobalType,
203}
204
205#[derive(Clone)]
206struct Func<'a> {
207    def: Definition<'a, FunctionBody<'a>>,
208    ty: u32,
209}
210
211#[derive(Clone)]
212enum Definition<'a, T> {
213    Import(&'a str, &'a str),
214    Local(T),
215}
216
217impl<'a> Module<'a> {
218    fn parse(&mut self, wasm: &'a [u8]) -> Result<()> {
219        let mut next_code_index = 0;
220        let mut validator = Validator::new();
221        for payload in Parser::new(0).parse_all(wasm) {
222            let payload = payload?;
223            validator.payload(&payload)?;
224            match payload {
225                Payload::Version { encoding, .. } => {
226                    if encoding != Encoding::Module {
227                        bail!("adapter must be a core wasm module, not a component");
228                    }
229                }
230                Payload::End(_) => {}
231                Payload::TypeSection(s) => {
232                    for ty in s.into_iter_err_on_gc_types() {
233                        self.types.push(ty?);
234                    }
235                }
236                Payload::ImportSection(s) => {
237                    for i in s {
238                        let i = i?;
239                        match i.ty {
240                            TypeRef::Func(ty) => self.funcs.push(Func {
241                                def: Definition::Import(i.module, i.name),
242                                ty,
243                            }),
244                            TypeRef::Table(ty) => self.tables.push(Table {
245                                def: Definition::Import(i.module, i.name),
246                                ty,
247                            }),
248                            TypeRef::Global(ty) => self.globals.push(Global {
249                                def: Definition::Import(i.module, i.name),
250                                ty,
251                            }),
252                            TypeRef::Memory(ty) => self.memories.push(Memory {
253                                def: Definition::Import(i.module, i.name),
254                                ty,
255                            }),
256                            TypeRef::Tag(_) => bail!("unsupported `tag` type"),
257                        }
258                    }
259                }
260                Payload::TableSection(s) => {
261                    for table in s {
262                        let table = table?;
263                        self.tables.push(Table {
264                            def: Definition::Local(()),
265                            ty: table.ty,
266                        });
267                    }
268                }
269                Payload::MemorySection(s) => {
270                    for ty in s {
271                        let ty = ty?;
272                        self.memories.push(Memory {
273                            def: Definition::Local(()),
274                            ty,
275                        });
276                    }
277                }
278                Payload::GlobalSection(s) => {
279                    for g in s {
280                        let g = g?;
281                        self.globals.push(Global {
282                            def: Definition::Local(g.init_expr),
283                            ty: g.ty,
284                        });
285                    }
286                }
287
288                Payload::ExportSection(s) => {
289                    for e in s {
290                        let e = e?;
291                        self.exports.insert(e.name, e);
292                    }
293                }
294
295                Payload::FunctionSection(s) => {
296                    next_code_index = self.funcs.len();
297                    for ty in s {
298                        let ty = ty?;
299                        self.funcs.push(Func {
300                            def: Definition::Local(FunctionBody::new(BinaryReader::new(&[], 0))),
303                            ty,
304                        });
305                    }
306                }
307
308                Payload::CodeSectionStart { .. } => {}
309                Payload::CodeSectionEntry(body) => {
310                    self.funcs[next_code_index].def = Definition::Local(body);
311                    next_code_index += 1;
312                }
313
314                Payload::CustomSection(s) => match s.as_known() {
317                    KnownCustom::Name(s) => drop(self.parse_name_section(s)),
318                    KnownCustom::Producers(_) => drop(self.parse_producers_section(&s)),
319                    _ => {}
320                },
321
322                other => match other.as_section() {
325                    Some((id, _)) => bail!("unsupported section `{}` in adapter", id),
326                    None => bail!("unsupported payload in adapter"),
327                },
328            }
329        }
330
331        Ok(())
332    }
333
334    fn parse_name_section(&mut self, section: NameSectionReader<'a>) -> Result<()> {
335        for s in section {
336            match s? {
337                Name::Function(map) => {
338                    for naming in map {
339                        let naming = naming?;
340                        self.func_names.insert(naming.index, naming.name);
341                    }
342                }
343                Name::Global(map) => {
344                    for naming in map {
345                        let naming = naming?;
346                        self.global_names.insert(naming.index, naming.name);
347                    }
348                }
349                _ => {}
350            }
351        }
352        Ok(())
353    }
354
355    fn parse_producers_section(&mut self, section: &CustomSectionReader<'a>) -> Result<()> {
356        let producers =
357            wasm_metadata::Producers::from_bytes(section.data(), section.data_offset())?;
358        self.producers = Some(producers);
359        Ok(())
360    }
361
362    fn liveness(&mut self) -> Result<()> {
365        let exports = mem::take(&mut self.exports);
366        for (_, e) in exports.iter() {
367            match e.kind {
368                ExternalKind::Func => self.func(e.index),
369                ExternalKind::Global => self.global(e.index),
370                ExternalKind::Table => self.table(e.index),
371                ExternalKind::Memory => self.memory(e.index),
372                ExternalKind::Tag => bail!("unsupported exported tag"),
373            }
374        }
375        self.exports = exports;
376
377        while let Some((idx, func)) = self.worklist.pop() {
378            func(self, idx)?;
379        }
380        Ok(())
381    }
382
383    fn func(&mut self, func: u32) {
384        if !self.live_funcs.insert(func) {
385            return;
386        }
387        self.worklist.push((func, |me, func| {
388            let func = me.funcs[func as usize].clone();
389            me.ty(func.ty);
390            let mut body = match &func.def {
391                Definition::Import(..) => return Ok(()),
392                Definition::Local(e) => e.get_binary_reader(),
393            };
394            let local_count = body.read_var_u32()?;
395            for _ in 0..local_count {
396                body.read_var_u32()?;
397                body.read::<ValType>()?;
398            }
399            me.operators(body)
400        }));
401    }
402
403    fn global(&mut self, global: u32) {
404        if !self.live_globals.insert(global) {
405            return;
406        }
407        self.worklist.push((global, |me, global| {
408            let init = match &me.globals[global as usize].def {
409                Definition::Import(..) => return Ok(()),
410                Definition::Local(e) => e,
411            };
412            me.operators(init.get_binary_reader())
413        }));
414    }
415
416    fn table(&mut self, table: u32) {
417        if !self.live_tables.insert(table) {
418            return;
419        }
420        self.worklist.push((table, |me, table| {
421            let ty = me.tables[table as usize].ty.element_type;
422            me.valty(ty.into());
423            Ok(())
424        }));
425    }
426
427    fn memory(&mut self, memory: u32) {
428        self.live_memories.insert(memory);
429    }
430
431    fn blockty(&mut self, ty: BlockType) {
432        if let BlockType::FuncType(ty) = ty {
433            self.ty(ty);
434        }
435    }
436
437    fn valty(&mut self, ty: ValType) {
438        match ty {
439            ValType::Ref(r) => self.refty(r),
440            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => {}
441        }
442    }
443
444    fn valtys(&mut self, tys: &[ValType]) {
445        for i in tys {
446            self.valty(*i);
447        }
448    }
449
450    fn refty(&mut self, ty: RefType) {
451        self.heapty(ty.heap_type())
452    }
453
454    fn heapty(&mut self, ty: HeapType) {
455        match ty {
456            HeapType::Abstract { .. } => {}
457            HeapType::Concrete(i) => self.ty(i.as_module_index().unwrap()),
458        }
459    }
460
461    fn ty(&mut self, ty: u32) {
462        if !self.live_types.insert(ty) {
463            return;
464        }
465        self.worklist.push((ty, |me, ty| {
466            let ty = me.types[ty as usize].clone();
467            for param in ty.params().iter().chain(ty.results()) {
468                me.valty(*param);
469            }
470            Ok(())
471        }));
472    }
473
474    fn operators(&mut self, reader: BinaryReader<'a>) -> Result<()> {
475        let mut ops = OperatorsReader::new(reader);
476        while !ops.eof() {
477            ops.visit_operator(self)?;
478        }
479        ops.finish()?;
480        Ok(())
481    }
482
483    fn live_types(&self) -> impl Iterator<Item = (u32, &FuncType)> + '_ {
484        live_iter(&self.live_types, self.types.iter())
485    }
486
487    fn live_funcs(&self) -> impl Iterator<Item = (u32, &Func<'a>)> + '_ {
488        live_iter(&self.live_funcs, self.funcs.iter())
489    }
490
491    fn live_memories(&self) -> impl Iterator<Item = (u32, &Memory<'a>)> + '_ {
492        live_iter(&self.live_memories, self.memories.iter())
493    }
494
495    fn live_globals(&self) -> impl Iterator<Item = (u32, &Global<'a>)> + '_ {
496        live_iter(&self.live_globals, self.globals.iter())
497    }
498
499    fn live_tables(&self) -> impl Iterator<Item = (u32, &Table<'a>)> + '_ {
500        live_iter(&self.live_tables, self.tables.iter())
501    }
502
503    fn encode(&mut self, main_module_realloc: Option<&str>) -> Result<Vec<u8>> {
506        let mut map = Encoder::default();
509
510        let mut types = wasm_encoder::TypeSection::new();
513        let mut imports = wasm_encoder::ImportSection::new();
514        let mut funcs = wasm_encoder::FunctionSection::new();
515        let mut tables = wasm_encoder::TableSection::new();
516        let mut memories = wasm_encoder::MemorySection::new();
517        let mut globals = wasm_encoder::GlobalSection::new();
518        let mut code = wasm_encoder::CodeSection::new();
519
520        let mut empty_type = None;
521        for (i, ty) in self.live_types() {
522            map.types.push(i);
523
524            let ty = map.func_type(ty.clone())?;
525            types.ty().func_type(&ty);
526
527            if ty.params().is_empty() && ty.results().is_empty() {
531                empty_type = Some(map.types.remap(i));
532            }
533        }
534
535        let mut num_memories = 0;
536        for (i, mem) in self.live_memories() {
537            map.memories.push(i);
538            let ty = map.memory_type(mem.ty);
539            match &mem.def {
540                Definition::Import(m, n) => {
541                    imports.import(m, n, ty?);
542                }
543                Definition::Local(()) => {
544                    memories.memory(ty?);
545                }
546            }
547            num_memories += 1;
548        }
549
550        for (i, table) in self.live_tables() {
551            map.tables.push(i);
552            let ty = map.table_type(table.ty)?;
553            match &table.def {
554                Definition::Import(m, n) => {
555                    imports.import(m, n, ty);
556                }
557                Definition::Local(()) => {
558                    tables.table(ty);
559                }
560            }
561        }
562
563        for (i, global) in self.live_globals() {
564            map.globals.push(i);
565            let ty = map.global_type(global.ty)?;
566            match &global.def {
567                Definition::Import(m, n) => {
568                    imports.import(m, n, ty);
569                }
570                Definition::Local(init) => {
571                    let init = &map.const_expr(init.clone())?;
572                    globals.global(ty, &init);
573                }
574            }
575        }
576
577        let mut realloc_index = None;
578        let mut num_func_imports = 0;
579
580        let is_realloc =
585            |m, n| m == "__main_module__" && matches!(n, "canonical_abi_realloc" | "cabi_realloc");
586
587        let (imported, local) =
588            self.live_funcs()
589                .partition::<Vec<_>, _>(|(_, func)| match &func.def {
590                    Definition::Import(m, n) => {
591                        !is_realloc(*m, *n) || main_module_realloc.is_some()
592                    }
593                    Definition::Local(_) => false,
594                });
595
596        for (i, func) in imported {
597            map.funcs.push(i);
598            let ty = map.types.remap(func.ty);
599            match &func.def {
600                Definition::Import(m, n) => {
601                    let name = if is_realloc(*m, *n) {
602                        realloc_index = Some(num_func_imports);
606                        main_module_realloc.unwrap_or(n)
607                    } else {
608                        n
609                    };
610                    imports.import(m, name, EntityType::Function(ty));
611                    num_func_imports += 1;
612                }
613                Definition::Local(_) => unreachable!(),
614            }
615        }
616
617        let add_realloc_type = |types: &mut wasm_encoder::TypeSection| {
618            let type_index = types.len();
619            types.ty().function(
620                [
621                    wasm_encoder::ValType::I32,
622                    wasm_encoder::ValType::I32,
623                    wasm_encoder::ValType::I32,
624                    wasm_encoder::ValType::I32,
625                ],
626                [wasm_encoder::ValType::I32],
627            );
628            type_index
629        };
630
631        let add_empty_type = |types: &mut wasm_encoder::TypeSection| {
632            let type_index = types.len();
633            types.ty().function([], []);
634            type_index
635        };
636
637        let sp = self.find_mut_i32_global("__stack_pointer")?;
638        let allocation_state = self.find_mut_i32_global("allocation_state")?;
639
640        let mut func_names = Vec::new();
641
642        if let (Some(realloc), Some(_), None) = (main_module_realloc, sp, realloc_index) {
643            map.funcs.next += 1;
648
649            realloc_index = Some(num_func_imports);
650            imports.import(
651                "__main_module__",
652                realloc,
653                EntityType::Function(add_realloc_type(&mut types)),
654            );
655            func_names.push((num_func_imports, realloc));
656            num_func_imports += 1;
657        }
658
659        for (i, func) in local {
660            map.funcs.push(i);
661            let ty = map.types.remap(func.ty);
662            match &func.def {
663                Definition::Import(_, _) => {
664                    realloc_index = Some(num_func_imports + funcs.len());
667                    funcs.function(ty);
668                    code.function(&realloc_via_memory_grow());
669                }
670                Definition::Local(_) => {
671                    funcs.function(ty);
672                }
673            }
674        }
675
676        let lazy_stack_init_index =
677            if sp.is_some() && allocation_state.is_some() && main_module_realloc.is_some() {
678                let index = num_func_imports + funcs.len();
682
683                map.funcs.next += 1;
685
686                funcs.function(add_empty_type(&mut types));
687
688                Some(index)
689            } else {
690                None
691            };
692
693        let exported_funcs = self
694            .exports
695            .values()
696            .filter_map(|export| match export.kind {
697                ExternalKind::Func => Some(export.index),
698                _ => None,
699            })
700            .collect::<HashSet<_>>();
701
702        for (i, func) in self.live_funcs() {
703            let body = match &func.def {
704                Definition::Import(..) => continue,
705                Definition::Local(body) => body,
706            };
707
708            match (lazy_stack_init_index, exported_funcs.contains(&i)) {
709                (Some(lazy_stack_init_index), true) => {
712                    let mut func = map.new_function_with_parsed_locals(&body)?;
713                    func.instructions().call(lazy_stack_init_index);
714                    let mut reader = body.get_operators_reader()?;
715                    while !reader.eof() {
716                        func.instruction(&map.parse_instruction(&mut reader)?);
717                    }
718                    code.function(&func);
719                }
720                _ => {
721                    map.parse_function_body(&mut code, body.clone())?;
722                }
723            }
724        }
725
726        if lazy_stack_init_index.is_some() {
727            code.function(&allocate_stack_via_realloc(
728                realloc_index.unwrap(),
729                sp.unwrap(),
730                allocation_state,
731            ));
732        }
733
734        if sp.is_some() && (realloc_index.is_none() || allocation_state.is_none()) {
735            realloc_index = Some(num_func_imports + funcs.len());
738            funcs.function(add_realloc_type(&mut types));
739            code.function(&realloc_via_memory_grow());
740        }
741
742        let mut start = None;
746        if let (Some(sp), None) = (sp, lazy_stack_init_index) {
747            if num_memories > 0 {
748                if num_memories != 1 {
752                    bail!("adapter modules don't support multi-memory");
753                }
754
755                let sp = map.globals.remap(sp);
756
757                let function_index = num_func_imports + funcs.len();
758
759                let empty_type = empty_type.unwrap_or_else(|| {
762                    types.ty().function([], []);
763                    types.len() - 1
764                });
765                funcs.function(empty_type);
766                func_names.push((function_index, "allocate_stack"));
767                code.function(&allocate_stack_via_realloc(
768                    realloc_index.unwrap(),
769                    sp,
770                    allocation_state,
771                ));
772
773                start = Some(wasm_encoder::StartSection { function_index });
774            }
775        }
776
777        if self.live_tables().count() != 0 {
784            bail!("tables should not be present in the final adapter module");
785        }
786
787        if self.live_memories().count() > 1 {
790            bail!("the adapter module should not use multi-memory");
791        }
792        if !memories.is_empty() {
793            bail!("locally-defined memories are not allowed define a local memory");
794        }
795
796        let mut ret = wasm_encoder::Module::default();
797        if !types.is_empty() {
798            ret.section(&types);
799        }
800        if !imports.is_empty() {
801            ret.section(&imports);
802        }
803        if !funcs.is_empty() {
804            ret.section(&funcs);
805        }
806        if !tables.is_empty() {
807            ret.section(&tables);
808        }
809        if !memories.is_empty() {
810            ret.section(&memories);
811        }
812        if !globals.is_empty() {
813            ret.section(&globals);
814        }
815
816        if !self.exports.is_empty() {
817            let mut exports = wasm_encoder::ExportSection::new();
818            for (_, export) in self.exports.iter() {
819                let (kind, index) = match export.kind {
820                    ExternalKind::Func => (
821                        wasm_encoder::ExportKind::Func,
822                        map.funcs.remap(export.index),
823                    ),
824                    ExternalKind::Table => (
825                        wasm_encoder::ExportKind::Table,
826                        map.tables.remap(export.index),
827                    ),
828                    ExternalKind::Memory => (
829                        wasm_encoder::ExportKind::Memory,
830                        map.memories.remap(export.index),
831                    ),
832                    ExternalKind::Global => (
833                        wasm_encoder::ExportKind::Global,
834                        map.globals.remap(export.index),
835                    ),
836                    kind => bail!("unsupported export kind {kind:?}"),
837                };
838                exports.export(export.name, kind, index);
839            }
840            ret.section(&exports);
841        }
842
843        if let Some(start) = &start {
844            ret.section(start);
845        }
846
847        if !code.is_empty() {
848            ret.section(&code);
849        }
850
851        let mut global_names = Vec::new();
854        for (i, _func) in self.live_funcs() {
855            let name = match self.func_names.get(&i) {
856                Some(name) => name,
857                None => continue,
858            };
859            func_names.push((map.funcs.remap(i), *name));
860        }
861        for (i, _global) in self.live_globals() {
862            let name = match self.global_names.get(&i) {
863                Some(name) => name,
864                None => continue,
865            };
866            global_names.push((map.globals.remap(i), *name));
867        }
868        let mut section = Vec::new();
869        let mut encode_subsection = |code: u8, names: &[(u32, &str)]| {
870            if names.is_empty() {
871                return;
872            }
873            let mut subsection = Vec::new();
874            names.len().encode(&mut subsection);
875            for (i, name) in names {
876                i.encode(&mut subsection);
877                name.encode(&mut subsection);
878            }
879            section.push(code);
880            subsection.encode(&mut section);
881        };
882        if let (Some(realloc_index), true) = (
883            realloc_index,
884            main_module_realloc.is_none() || allocation_state.is_none(),
885        ) {
886            func_names.push((realloc_index, "realloc_via_memory_grow"));
887        }
888        if let Some(lazy_stack_init_index) = lazy_stack_init_index {
889            func_names.push((lazy_stack_init_index, "allocate_stack"));
890        }
891        encode_subsection(0x01, &func_names);
892        encode_subsection(0x07, &global_names);
893        if !section.is_empty() {
894            ret.section(&wasm_encoder::CustomSection {
895                name: "name".into(),
896                data: Cow::Borrowed(§ion),
897            });
898        }
899        if let Some(producers) = &self.producers {
900            ret.section(&RawCustomSection(&producers.raw_custom_section()));
901        }
902
903        Ok(ret.finish())
904    }
905
906    fn find_mut_i32_global(&self, name: &str) -> Result<Option<u32>> {
907        let matches = &self
908            .live_globals()
909            .filter_map(|(i, g)| {
910                if g.ty.mutable
911                    && g.ty.content_type == ValType::I32
912                    && *self.global_names.get(&i)? == name
913                {
914                    Some(i)
915                } else {
916                    None
917                }
918            })
919            .collect::<Vec<_>>();
920
921        match matches.deref() {
922            [] => Ok(None),
923            [i] => Ok(Some(*i)),
924            _ => bail!(
925                "found {} mutable i32 globals with name {name}",
926                matches.len()
927            ),
928        }
929    }
930}
931
932macro_rules! define_visit {
940    ($(@$p:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
941        $(
942            fn $visit(&mut self $(, $($arg: $argty),*)?)  {
943                $(
944                    $(
945                        define_visit!(mark_live self $arg $arg);
946                    )*
947                )?
948            }
949        )*
950    };
951
952    (mark_live $self:ident $arg:ident type_index) => {$self.ty($arg);};
953    (mark_live $self:ident $arg:ident array_type_index) => {$self.ty($arg);};
954    (mark_live $self:ident $arg:ident array_type_index_dst) => {$self.ty($arg);};
955    (mark_live $self:ident $arg:ident array_type_index_src) => {$self.ty($arg);};
956    (mark_live $self:ident $arg:ident struct_type_index) => {$self.ty($arg);};
957    (mark_live $self:ident $arg:ident src_table) => {$self.table($arg);};
958    (mark_live $self:ident $arg:ident dst_table) => {$self.table($arg);};
959    (mark_live $self:ident $arg:ident table_index) => {$self.table($arg);};
960    (mark_live $self:ident $arg:ident table) => {$self.table($arg);};
961    (mark_live $self:ident $arg:ident global_index) => {$self.global($arg);};
962    (mark_live $self:ident $arg:ident function_index) => {$self.func($arg);};
963    (mark_live $self:ident $arg:ident mem) => {$self.memory($arg);};
964    (mark_live $self:ident $arg:ident src_mem) => {$self.memory($arg);};
965    (mark_live $self:ident $arg:ident dst_mem) => {$self.memory($arg);};
966    (mark_live $self:ident $arg:ident memarg) => {$self.memory($arg.memory);};
967    (mark_live $self:ident $arg:ident blockty) => {$self.blockty($arg);};
968    (mark_live $self:ident $arg:ident ty) => {$self.valty($arg)};
969    (mark_live $self:ident $arg:ident tys) => {$self.valtys(&$arg)};
970    (mark_live $self:ident $arg:ident hty) => {$self.heapty($arg)};
971    (mark_live $self:ident $arg:ident from_ref_type) => {$self.refty($arg);};
972    (mark_live $self:ident $arg:ident to_ref_type) => {$self.refty($arg);};
973    (mark_live $self:ident $arg:ident lane) => {};
974    (mark_live $self:ident $arg:ident lanes) => {};
975    (mark_live $self:ident $arg:ident value) => {};
976    (mark_live $self:ident $arg:ident local_index) => {};
977    (mark_live $self:ident $arg:ident relative_depth) => {};
978    (mark_live $self:ident $arg:ident tag_index) => {};
979    (mark_live $self:ident $arg:ident targets) => {};
980    (mark_live $self:ident $arg:ident data_index) => {};
981    (mark_live $self:ident $arg:ident array_data_index) => {};
982    (mark_live $self:ident $arg:ident elem_index) => {};
983    (mark_live $self:ident $arg:ident array_elem_index) => {};
984    (mark_live $self:ident $arg:ident array_size) => {};
985    (mark_live $self:ident $arg:ident field_index) => {};
986    (mark_live $self:ident $arg:ident ordering) => {};
987    (mark_live $self:ident $arg:ident try_table) => {unimplemented!();};
988    (mark_live $self:ident $arg:ident argument_index) => {};
989    (mark_live $self:ident $arg:ident result_index) => {};
990    (mark_live $self:ident $arg:ident cont_type_index) => {};
991    (mark_live $self:ident $arg:ident resume_table) => {unimplemented!();};
992}
993
994impl<'a> VisitOperator<'a> for Module<'a> {
995    type Output = ();
996
997    fn simd_visitor(&mut self) -> Option<&mut dyn VisitSimdOperator<'a, Output = Self::Output>> {
998        Some(self)
999    }
1000
1001    wasmparser::for_each_visit_operator!(define_visit);
1002}
1003
1004impl<'a> VisitSimdOperator<'a> for Module<'a> {
1005    wasmparser::for_each_visit_simd_operator!(define_visit);
1006}
1007
1008fn live_iter<'a, T>(
1011    live: &'a BitVec,
1012    iter: impl Iterator<Item = T> + 'a,
1013) -> impl Iterator<Item = (u32, T)> + 'a {
1014    iter.enumerate().filter_map(|(i, t)| {
1015        let i = i as u32;
1016        if live.contains(i) { Some((i, t)) } else { None }
1017    })
1018}
1019
1020#[derive(Default)]
1021struct Encoder {
1022    types: Remap,
1023    funcs: Remap,
1024    memories: Remap,
1025    globals: Remap,
1026    tables: Remap,
1027}
1028
1029type ReencodeResult<T> = Result<T, wasm_encoder::reencode::Error<Infallible>>;
1030
1031impl Reencode for Encoder {
1032    type Error = Infallible;
1033
1034    fn type_index(&mut self, i: u32) -> ReencodeResult<u32> {
1035        Ok(self.types.remap(i))
1036    }
1037    fn function_index(&mut self, i: u32) -> ReencodeResult<u32> {
1038        Ok(self.funcs.remap(i))
1039    }
1040    fn memory_index(&mut self, i: u32) -> ReencodeResult<u32> {
1041        Ok(self.memories.remap(i))
1042    }
1043    fn global_index(&mut self, i: u32) -> ReencodeResult<u32> {
1044        Ok(self.globals.remap(i))
1045    }
1046    fn table_index(&mut self, i: u32) -> ReencodeResult<u32> {
1047        Ok(self.tables.remap(i))
1048    }
1049}
1050
1051mod bitvec {
1054    use std::mem;
1055
1056    type T = u64;
1057
1058    #[derive(Default)]
1059    pub struct BitVec {
1060        bits: Vec<T>,
1061    }
1062
1063    impl BitVec {
1064        pub fn insert(&mut self, idx: u32) -> bool {
1067            let (idx, bit) = idx_bit(idx);
1068            match self.bits.get_mut(idx) {
1069                Some(bits) => {
1070                    if *bits & bit != 0 {
1071                        return false;
1072                    }
1073                    *bits |= bit;
1074                }
1075                None => {
1076                    self.bits.resize(idx + 1, 0);
1077                    self.bits[idx] = bit;
1078                }
1079            }
1080            true
1081        }
1082
1083        pub fn contains(&self, idx: u32) -> bool {
1085            let (idx, bit) = idx_bit(idx);
1086            match self.bits.get(idx) {
1087                Some(bits) => (*bits & bit) != 0,
1088                None => false,
1089            }
1090        }
1091    }
1092
1093    fn idx_bit(idx: u32) -> (usize, T) {
1094        let idx = idx as usize;
1095        let size = mem::size_of::<T>() * 8;
1096        let index = idx / size;
1097        let bit = 1 << (idx % size);
1098        (index, bit)
1099    }
1100}
1101
1102#[derive(Default)]
1105struct Remap {
1106    map: HashMap<u32, u32>,
1108    next: u32,
1110}
1111
1112impl Remap {
1113    fn push(&mut self, old: u32) {
1117        self.map.insert(old, self.next);
1118        self.next += 1;
1119    }
1120
1121    fn remap(&self, old: u32) -> u32 {
1125        *self
1126            .map
1127            .get(&old)
1128            .unwrap_or_else(|| panic!("can't map {old} to a new index"))
1129    }
1130}