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}