1use alloc::vec;
17use alloc::vec::Vec;
18
19use wasefire_common::id::UniqueId;
20
21use crate::cursor::*;
22use crate::error::*;
23use crate::module::*;
24use crate::side_table::*;
25use crate::syntax::*;
26use crate::toctou::*;
27use crate::*;
28
29pub const MEMORY_ALIGN: usize = 16;
30
31#[derive(Copy, Clone, PartialEq, Eq)]
34pub enum Val {
35 I32(u32),
36 I64(u64),
37 #[cfg(feature = "float-types")]
38 F32(u32),
39 #[cfg(feature = "float-types")]
40 F64(u64),
41 #[cfg(feature = "vector-types")]
42 V128(u128),
43 Null(RefType),
44 Ref(Ptr),
45 RefExtern(usize),
46}
47
48static STORE_ID: UniqueId = UniqueId::new();
49
50#[derive(Debug)]
53pub struct Store<'m> {
54 id: usize,
55 insts: Vec<Instance<'m>>,
56 funcs: Vec<(HostName<'m>, FuncType<'m>)>,
59 func_default: Option<(&'m str, usize)>,
64 threads: Vec<Continuation<'m>>,
65}
66
67#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
68struct HostName<'m> {
69 module: &'m str,
70 name: &'m str,
71}
72
73#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
75pub struct StoreId(usize);
76
77#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
79pub struct InstId {
80 store_id: usize,
81 inst_id: usize,
82}
83
84impl InstId {
85 pub fn store_id(self) -> StoreId {
87 StoreId(self.store_id)
88 }
89}
90
91#[derive(Debug)]
93pub struct Call<'a, 'm> {
95 store: &'a mut Store<'m>,
96}
97
98impl Default for Store<'_> {
99 fn default() -> Self {
100 Self {
101 id: STORE_ID.next() as usize,
102 insts: vec![],
103 funcs: vec![],
104 func_default: None,
105 threads: vec![],
106 }
107 }
108}
109
110impl<'m> Store<'m> {
111 pub fn id(&self) -> StoreId {
113 StoreId(self.id)
114 }
115
116 pub fn instantiate(
122 &mut self, module: Module<'m>, memory: &'m mut [u8],
123 ) -> Result<InstId, Error> {
124 let inst_id = self.insts.len();
125 self.insts.push(Instance::new(module));
126 for import in self.last_inst().module.imports() {
127 let type_ = import.type_(&self.last_inst().module);
128 let id = self.resolve(&import, type_)?;
129 match import.desc {
130 ImportDesc::Func(_) => self.last_inst().funcs.ext.push(id),
131 ImportDesc::Table(_) => self.last_inst().tables.ext.push(id),
132 ImportDesc::Mem(_) => self.last_inst().mems.ext.push(id),
133 ImportDesc::Global(_) => self.last_inst().globals.ext.push(id),
134 }
135 }
136 if let Some(mut parser) = self.last_inst().module.section(SectionId::Table) {
137 for _ in 0 .. parser.parse_vec().into_ok() {
138 (self.last_inst().tables.int).push(Table::new(parser.parse_tabletype().into_ok()));
139 }
140 }
141 if let Some(mut parser) = self.last_inst().module.section(SectionId::Memory) {
142 match parser.parse_vec().into_ok() {
143 0 => (),
144 1 => {
145 let limits = parser.parse_memtype().into_ok();
146 self.last_inst().mems.int.init(memory, limits)?;
147 }
148 _ => unimplemented!(),
149 }
150 }
151 if let Some(mut parser) = self.last_inst().module.section(SectionId::Global) {
152 for _ in 0 .. parser.parse_vec().into_ok() {
153 parser.parse_globaltype().into_ok();
154 let value = Thread::const_expr(self, inst_id, &mut parser);
155 self.last_inst().globals.int.push(Global::new(value));
156 }
157 }
158 if let Some(mut parser) = self.last_inst().module.section(SectionId::Element) {
159 for _ in 0 .. parser.parse_vec().into_ok() {
160 let mut elem = ComputeElem::new(self, inst_id);
162 parser.parse_elem(&mut elem).into_ok();
163 let ComputeElem { mode, init, .. } = elem;
164 let drop = match mode {
165 ElemMode::Passive => false,
166 ElemMode::Active { table, offset } => {
167 let n = init.len();
168 let table = self.table(inst_id, table);
169 table_init(offset, 0, n, table, &init)?;
170 true
171 }
172 ElemMode::Declarative => true,
173 };
174 self.last_inst().elems.push(drop);
175 }
176 }
177 if let Some(mut parser) = self.last_inst().module.section(SectionId::Data) {
178 for _ in 0 .. parser.parse_vec().into_ok() {
179 let mut data = ComputeData::new(self, inst_id);
180 parser.parse_data(&mut data).into_ok();
181 let ComputeData { mode, init, .. } = data;
182 let drop = match mode {
183 DataMode::Passive => false,
184 DataMode::Active { memory, offset } => {
185 let n = init.len();
186 let memory = self.mem(inst_id, memory);
187 memory_init(offset, 0, n, memory, init)?;
188 true
189 }
190 };
191 self.last_inst().datas.push(drop);
192 }
193 }
194 if let Some(mut parser) = self.last_inst().module.section(SectionId::Start) {
195 let x = parser.parse_funcidx().into_ok();
196 let ptr = self.func_ptr(inst_id, x);
197 let inst_id = ptr.instance().unwrap_wasm();
198 let (mut parser, side_table) = self.insts[inst_id].module.func(ptr.index());
199 let mut locals = Vec::new();
200 append_locals(&mut parser, &mut locals);
201 let ret = Parser::default();
202 let thread = Thread::new(parser, Frame::new(inst_id, 0, ret, locals, side_table, 0));
203 let result = thread.run(self)?;
204 assert!(matches!(result, RunResult::Done(x) if x.is_empty()));
205 }
206 Ok(InstId { store_id: self.id, inst_id })
207 }
208
209 pub fn invoke<'a>(
215 &'a mut self, inst: InstId, name: &str, args: Vec<Val>,
216 ) -> Result<RunResult<'a, 'm>, Error> {
217 let inst_id = self.inst_id(inst)?;
218 let inst = &self.insts[inst_id];
219 let ptr = match inst.module.export(name).ok_or_else(not_found)? {
220 ExportDesc::Func(x) => inst.funcs.ptr(inst_id, x),
221 _ => return Err(Error::Invalid),
222 };
223 let inst_id = ptr.instance().unwrap_wasm();
224 let inst = &self.insts[inst_id];
225 let x = ptr.index();
226 let t = inst.module.func_type(x);
227 let (mut parser, side_table) = inst.module.func(x);
228 check_types(&t.params, &args)?;
229 let mut locals = args;
230 append_locals(&mut parser, &mut locals);
231 let ret = Parser::default();
232 let frame = Frame::new(inst_id, t.results.len(), ret, locals, side_table, 0);
233 Thread::new(parser, frame).run(self)
234 }
235
236 pub fn get_global(&mut self, inst: InstId, name: &str) -> Result<Val, Error> {
238 let inst_id = self.inst_id(inst)?;
239 let inst = &self.insts[inst_id];
240 let ptr = match inst.module.export(name).ok_or_else(not_found)? {
241 ExportDesc::Global(x) => inst.globals.ptr(inst_id, x),
242 _ => return Err(Error::Invalid),
243 };
244 let inst_id = ptr.instance().unwrap_wasm();
245 let x = ptr.index() as usize;
246 Ok(self.insts[inst_id].globals.int[x].value)
247 }
248
249 pub fn set_name(&mut self, inst: InstId, name: &'m str) -> Result<(), Error> {
251 let inst_id = self.inst_id(inst)?;
252 self.insts[inst_id].name = name;
253 Ok(())
254 }
255
256 pub fn link_func(
262 &mut self, module: &'m str, name: &'m str, params: usize, results: usize,
263 ) -> Result<(), Error> {
264 static TYPES: &[ValType] = &[ValType::I32; 8];
265 check(params <= TYPES.len() && results <= TYPES.len())?;
266 let type_ = FuncType { params: TYPES[.. params].into(), results: TYPES[.. results].into() };
267 self.link_func_custom(module, name, type_)
268 }
269
270 pub fn link_func_default(&mut self, module: &'m str) -> Result<(), Error> {
279 check(self.func_default.is_none())?;
280 self.func_default = Some((module, self.funcs.len()));
281 Ok(())
282 }
283
284 pub fn link_func_custom(
290 &mut self, module: &'m str, name: &'m str, type_: FuncType<'m>,
291 ) -> Result<(), Error> {
292 let name = HostName { module, name };
293 check(self.func_default.is_none())?;
294 check(self.insts.is_empty())?;
295 check(self.funcs.last().is_none_or(|x| x.0 < name))?;
296 self.funcs.push((name, type_));
297 Ok(())
298 }
299
300 pub fn last_call(&mut self) -> Option<Call<'_, 'm>> {
305 if self.threads.is_empty() { None } else { Some(Call { store: self }) }
306 }
307
308 pub fn memory(&mut self, inst: InstId) -> Result<&mut [u8], Error> {
310 check(self.id == inst.store_id)?;
311 Ok(self.mem(inst.inst_id, 0).data)
312 }
313}
314
315impl<'a, 'm> Call<'a, 'm> {
316 pub fn index(&self) -> usize {
318 self.cont().index
319 }
320
321 pub fn args(&self) -> &[Val] {
323 &self.cont().args
324 }
325
326 pub fn inst(&self) -> InstId {
328 self.cont().thread.inst(self.store)
329 }
330
331 pub fn mem(self) -> &'a mut [u8] {
333 self.store.mem(self.inst().inst_id, 0).data
334 }
335
336 pub fn mem_mut(&mut self) -> &mut [u8] {
338 self.store.mem(self.inst().inst_id, 0).data
339 }
340
341 pub fn resume(self, results: &[Val]) -> Result<RunResult<'a, 'm>, Error> {
343 let Continuation { mut thread, arity, .. } = self.store.threads.pop().unwrap();
344 check(results.len() == arity)?;
345 thread.push_values(results);
346 thread.run(self.store)
347 }
348
349 fn cont(&self) -> &Continuation<'_> {
350 self.store.threads.last().unwrap()
351 }
352}
353
354#[derive(Copy, Clone, PartialEq, Eq)]
355pub struct Ptr(u32);
356
357impl core::fmt::Debug for Ptr {
358 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
359 f.debug_struct("Ptr")
360 .field("instance", &self.instance())
361 .field("index", &self.index())
362 .finish()
363 }
364}
365
366#[derive(Debug, Copy, Clone, PartialEq, Eq)]
367enum Side {
368 Host,
369 Wasm(usize),
370}
371
372impl Side {
373 fn into_repr(self) -> usize {
374 match self {
375 Side::Host => 0,
376 Side::Wasm(x) => 1 + x,
377 }
378 }
379
380 fn from_repr(x: usize) -> Self {
381 match x.checked_sub(1) {
382 None => Side::Host,
383 Some(x) => Side::Wasm(x),
384 }
385 }
386
387 fn unwrap_wasm(self) -> usize {
388 match self {
389 Side::Host => unreachable!(),
390 Side::Wasm(x) => x,
391 }
392 }
393}
394
395impl Ptr {
396 const INDEX_BITS: usize = 20;
398 const INDEX_MASK: u32 = (1 << Self::INDEX_BITS) - 1;
399 const INST_MASK: u32 = (1 << (32 - Self::INDEX_BITS)) - 1;
400
401 fn new(inst: Side, idx: u32) -> Self {
402 let inst = inst.into_repr() as u32;
403 assert_eq!(inst & !Self::INST_MASK, 0);
404 assert_eq!(idx & !Self::INDEX_MASK, 0);
405 Self((inst << Self::INDEX_BITS) | idx)
406 }
407
408 fn instance(self) -> Side {
409 Side::from_repr((self.0 >> Self::INDEX_BITS) as usize)
410 }
411
412 fn index(self) -> u32 {
413 self.0 & Self::INDEX_MASK
414 }
415}
416
417impl core::fmt::Debug for Val {
418 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
419 match *self {
420 Val::I32(x) => write!(f, "{x}"),
421 Val::I64(x) => write!(f, "{x}"),
422 #[cfg(feature = "float-types")]
423 Val::F32(x) => write!(f, "{}", f32::from_bits(x)),
424 #[cfg(feature = "float-types")]
425 Val::F64(x) => write!(f, "{}", f64::from_bits(x)),
426 #[cfg(feature = "vector-types")]
427 Val::V128(_) => todo!(),
428 Val::Null(_) => write!(f, "null"),
429 Val::Ref(p) => write!(f, "ref@{:?}:{}", p.instance(), p.index()),
430 Val::RefExtern(p) => write!(f, "ext@{p}"),
431 }
432 }
433}
434
435impl Val {
436 pub fn type_(self) -> ValType {
437 match self {
438 Val::I32(_) => ValType::I32,
439 Val::I64(_) => ValType::I64,
440 #[cfg(feature = "float-types")]
441 Val::F32(_) => ValType::F32,
442 #[cfg(feature = "float-types")]
443 Val::F64(_) => ValType::F64,
444 #[cfg(feature = "vector-types")]
445 Val::V128(_) => ValType::V128,
446 Val::Null(t) => t.into(),
447 Val::Ref(_) => ValType::FuncRef,
448 Val::RefExtern(_) => ValType::ExternRef,
449 }
450 }
451}
452
453#[derive(Debug)]
454struct Instance<'m> {
455 name: &'m str,
457 module: Module<'m>,
458 funcs: Component<()>,
459 tables: Component<Vec<Table>>,
460 mems: Component<Memory<'m>>,
461 globals: Component<Vec<Global>>,
462 elems: Vec<bool>, datas: Vec<bool>, }
465
466#[derive(Debug)]
467struct Thread<'m> {
468 parser: Parser<'m>,
469 frames: Vec<Frame<'m>>,
470 values: Vec<Val>,
473}
474
475#[derive(Debug)]
477pub enum RunResult<'a, 'm> {
478 Done(Vec<Val>),
480
481 Host(Call<'a, 'm>),
483}
484
485#[derive(Debug)]
487pub enum RunAnswer {
488 Done(Vec<Val>),
489 Host,
490}
491
492impl RunResult<'_, '_> {
493 pub fn forget(self) -> RunAnswer {
494 match self {
495 RunResult::Done(result) => RunAnswer::Done(result),
496 RunResult::Host(_) => RunAnswer::Host,
497 }
498 }
499}
500
501#[derive(Debug)]
502struct Continuation<'m> {
503 thread: Thread<'m>,
504 index: usize,
505 args: Vec<Val>,
506 arity: usize,
507}
508
509impl<'m> Store<'m> {
510 fn last_inst(&mut self) -> &mut Instance<'m> {
511 self.insts.last_mut().unwrap()
512 }
513
514 fn inst_id(&self, inst: InstId) -> Result<usize, Error> {
515 check(self.id == inst.store_id)?;
516 Ok(inst.inst_id)
517 }
518
519 fn resolve_inst(&self, name: &str) -> Result<usize, Error> {
520 self.insts.iter().position(|x| x.name == name).ok_or_else(not_found)
521 }
522
523 fn func_type(&self, ptr: Ptr) -> FuncType<'m> {
524 match ptr.instance() {
525 Side::Host => self.funcs[ptr.index() as usize].1,
526 Side::Wasm(x) => self.insts[x].module.func_type(ptr.index()),
527 }
528 }
529
530 fn func_ptr(&self, inst_id: usize, x: FuncIdx) -> Ptr {
531 self.insts[inst_id].funcs.ptr(inst_id, x)
532 }
533
534 fn table_ptr(&self, inst_id: usize, x: TableIdx) -> Ptr {
535 self.insts[inst_id].tables.ptr(inst_id, x)
536 }
537
538 fn mem_ptr(&self, inst_id: usize, x: MemIdx) -> Ptr {
539 self.insts[inst_id].mems.ptr(inst_id, x)
540 }
541
542 fn global_ptr(&self, inst_id: usize, x: GlobalIdx) -> Ptr {
543 self.insts[inst_id].globals.ptr(inst_id, x)
544 }
545
546 fn table(&mut self, inst_id: usize, x: TableIdx) -> &mut Table {
547 let ptr = self.table_ptr(inst_id, x);
548 let x = ptr.instance().unwrap_wasm();
549 &mut self.insts[x].tables.int[ptr.index() as usize]
550 }
551
552 fn mem(&mut self, inst_id: usize, x: MemIdx) -> &mut Memory<'m> {
553 let ptr = self.mem_ptr(inst_id, x);
554 let x = ptr.instance().unwrap_wasm();
555 assert_eq!(ptr.index(), 0);
556 &mut self.insts[x].mems.int
557 }
558
559 fn global(&mut self, inst_id: usize, x: GlobalIdx) -> &mut Global {
560 let ptr = self.global_ptr(inst_id, x);
561 let x = ptr.instance().unwrap_wasm();
562 &mut self.insts[x].globals.int[ptr.index() as usize]
563 }
564
565 fn resolve(&mut self, import: &Import<'m>, imp_type_: ExternType<'m>) -> Result<Ptr, Error> {
566 let host_name = HostName { module: import.module, name: import.name };
567 let mut found = None;
568 let funcs_len = match self.func_default {
569 Some((_, x)) => x,
570 None => self.funcs.len(),
571 };
572 if let Ok(x) = self.funcs[.. funcs_len].binary_search_by(|x| x.0.cmp(&host_name)) {
573 found = Some((Ptr::new(Side::Host, x as u32), ExternType::Func(self.funcs[x].1)));
574 } else if matches!(imp_type_, ExternType::Func(x) if *x.results == [ValType::I32])
575 && matches!(self.func_default, Some((x, _)) if x == host_name.module)
576 {
577 let type_ = match imp_type_ {
578 ExternType::Func(x) => x,
579 _ => unreachable!(),
580 };
581 let idx = match self.funcs[funcs_len ..].iter().position(|x| x.1 == type_) {
582 Some(x) => funcs_len + x,
583 None => {
584 let idx = self.funcs.len();
585 self.funcs.push((host_name, type_));
586 idx
587 }
588 };
589 found = Some((Ptr::new(Side::Host, idx as u32), ExternType::Func(type_)));
590 } else {
591 let inst_id = self.resolve_inst(import.module)?;
592 let inst = &self.insts[inst_id];
593 if let Some(mut parser) = inst.module.section(SectionId::Export) {
594 for _ in 0 .. parser.parse_vec().into_ok() {
595 let name = parser.parse_name().into_ok();
596 let desc = parser.parse_exportdesc().into_ok();
597 if name != import.name {
598 continue;
599 }
600 found = Some(match desc {
601 ExportDesc::Func(x) => {
602 let ptr = self.func_ptr(inst_id, x);
603 (ptr, ExternType::Func(self.func_type(ptr)))
604 }
605 ExportDesc::Table(x) => {
606 let ptr = self.table_ptr(inst_id, x);
607 let inst = &self.insts[ptr.instance().unwrap_wasm()];
608 let mut t = inst.module.table_type(ptr.index());
609 t.limits.min = inst.tables.int[ptr.index() as usize].size();
610 (ptr, ExternType::Table(t))
611 }
612 ExportDesc::Mem(x) => {
613 let ptr = self.mem_ptr(inst_id, x);
614 let inst = &self.insts[ptr.instance().unwrap_wasm()];
615 let mut t = inst.module.mem_type(ptr.index());
616 assert_eq!(ptr.index(), 0);
617 t.min = inst.mems.int.size();
618 (ptr, ExternType::Mem(t))
619 }
620 ExportDesc::Global(x) => {
621 let ptr = self.global_ptr(inst_id, x);
622 let inst = &self.insts[ptr.instance().unwrap_wasm()];
623 (ptr, ExternType::Global(inst.module.global_type(ptr.index())))
624 }
625 });
626 break;
627 }
628 }
629 }
630 let (ptr, ext_type_) = found.ok_or_else(not_found)?;
631 if ext_type_.matches(&imp_type_) { Ok(ptr) } else { Err(not_found()) }
632 }
633}
634
635impl<'m> Instance<'m> {
636 fn new(module: Module<'m>) -> Self {
637 Instance {
638 name: "",
639 module,
640 funcs: Component::default(),
641 tables: Component::default(),
642 mems: Component::default(),
643 globals: Component::default(),
644 elems: Vec::new(),
645 datas: Vec::new(),
646 }
647 }
648}
649
650#[derive(Debug)]
651enum ElemMode {
652 Passive,
653 Active { table: TableIdx, offset: usize },
654 Declarative,
655}
656
657struct ComputeElem<'a, 'm> {
658 store: &'a mut Store<'m>,
659 inst_id: usize,
660 mode: ElemMode,
661 init: Vec<Val>,
662}
663
664impl<'a, 'm> ComputeElem<'a, 'm> {
665 fn new(store: &'a mut Store<'m>, inst_id: usize) -> Self {
666 Self { store, inst_id, mode: ElemMode::Passive, init: Vec::new() }
667 }
668}
669
670impl<'m> parser::ParseElem<'m, Use> for ComputeElem<'_, 'm> {
671 fn mode(&mut self, mode: parser::ElemMode<'_, 'm, Use>) -> MResult<(), Use> {
672 let mode = match mode {
673 parser::ElemMode::Passive => ElemMode::Passive,
674 parser::ElemMode::Active { table, offset } => ElemMode::Active {
675 table,
676 offset: Thread::const_expr(self.store, self.inst_id, offset).unwrap_i32() as usize,
677 },
678 parser::ElemMode::Declarative => ElemMode::Declarative,
679 };
680 self.mode = mode;
681 Ok(())
682 }
683
684 fn init_funcidx(&mut self, x: FuncIdx) -> MResult<(), Use> {
685 self.init.push(Val::Ref(self.store.func_ptr(self.inst_id, x)));
686 Ok(())
687 }
688
689 fn init_expr(&mut self, parser: &mut Parser<'m>) -> MResult<(), Use> {
690 self.init.push(Thread::const_expr(self.store, self.inst_id, parser));
691 Ok(())
692 }
693}
694
695#[derive(Debug)]
696enum DataMode {
697 Passive,
698 Active { memory: MemIdx, offset: usize },
699}
700
701struct ComputeData<'a, 'm> {
702 store: &'a mut Store<'m>,
703 inst_id: usize,
704 mode: DataMode,
705 init: &'m [u8],
706}
707
708impl<'a, 'm> ComputeData<'a, 'm> {
709 fn new(store: &'a mut Store<'m>, inst_id: usize) -> Self {
710 Self { store, inst_id, mode: DataMode::Passive, init: &[] }
711 }
712}
713
714impl<'m> parser::ParseData<'m, Use> for ComputeData<'_, 'm> {
715 fn mode(&mut self, mode: parser::DataMode<'_, 'm, Use>) -> MResult<(), Use> {
716 let mode = match mode {
717 parser::DataMode::Passive => DataMode::Passive,
718 parser::DataMode::Active { memory, offset } => DataMode::Active {
719 memory,
720 offset: Thread::const_expr(self.store, self.inst_id, offset).unwrap_i32() as usize,
721 },
722 };
723 self.mode = mode;
724 Ok(())
725 }
726
727 fn init(&mut self, init: &'m [u8]) -> MResult<(), Use> {
728 self.init = init;
729 Ok(())
730 }
731}
732
733#[derive(Debug)]
734struct Table {
735 max: u32,
736 elems: Vec<Val>,
737}
738
739#[derive(Debug)]
740struct Global {
741 value: Val,
742}
743
744enum ThreadResult<'m> {
745 Continue(Thread<'m>),
746 Done(Vec<Val>),
747 Host,
748}
749
750impl<'m> Thread<'m> {
751 fn new(parser: Parser<'m>, frame: Frame<'m>) -> Thread<'m> {
752 Thread { parser, frames: vec![frame], values: vec![] }
753 }
754
755 fn const_expr(store: &mut Store<'m>, inst_id: usize, mut_parser: &mut Parser<'m>) -> Val {
756 let mut thread = Thread::new(
757 mut_parser.clone(),
758 Frame::new(inst_id, 1, Parser::default(), Vec::new(), Cursor::default(), 0),
759 );
760 let (state, results) = loop {
761 let s = thread.parser.save();
762 match thread.step(store).unwrap() {
763 ThreadResult::Continue(x) => thread = x,
764 ThreadResult::Done(x) => break (s, x),
765 ThreadResult::Host => unreachable!(),
766 }
767 };
768 unsafe { mut_parser.restore(state) };
769 let instr = mut_parser.parse_instr().into_ok();
770 debug_assert_eq!(instr, Instr::End);
771 debug_assert_eq!(results.len(), 1);
772 results[0]
773 }
774
775 fn run<'a>(mut self, store: &'a mut Store<'m>) -> Result<RunResult<'a, 'm>, Error> {
776 loop {
777 match self.step(store)? {
780 ThreadResult::Continue(x) => self = x,
781 ThreadResult::Done(x) => return Ok(RunResult::Done(x)),
782 ThreadResult::Host => return Ok(RunResult::Host(Call { store })),
783 }
784 }
785 }
786
787 fn step(mut self, store: &mut Store<'m>) -> Result<ThreadResult<'m>, Error> {
788 use Instr::*;
789 let inst_id = self.frame().inst_id;
790 let inst = &mut store.insts[inst_id];
791 match self.parser.parse_instr().into_ok() {
792 Unreachable => return Err(trap()),
793 Nop => (),
794 Block(_) => self.push_label(),
795 Loop(_) => self.push_label(),
796 If(_) => match self.pop_value().unwrap_i32() {
797 0 => {
798 self.take_jump(0);
799 self.push_label();
800 }
801 _ => {
802 self.frame().skip_jump();
803 self.push_label();
804 }
805 },
806 Else => {
807 self.take_jump(0);
808 return Ok(self.exit_label());
809 }
810 End => return Ok(self.exit_label()),
811 Br(l) => return Ok(self.pop_label(l, 0)),
812 BrIf(l) => {
813 if self.pop_value().unwrap_i32() != 0 {
814 return Ok(self.pop_label(l, 0));
815 }
816 self.frame().skip_jump();
817 }
818 BrTable(ls, ln) => {
819 let i = self.pop_value().unwrap_i32() as usize;
820 let (l, offset) = match ls.get(i) {
821 None => (ln, 0),
822 Some(&li) => (li, i + 1),
823 };
824 return Ok(self.pop_label(l, offset));
825 }
826 Return => return Ok(self.exit_frame()),
827 Call(x) => return self.invoke(store, store.func_ptr(inst_id, x)),
828 CallIndirect(x, y) => {
829 let i = self.pop_value().unwrap_i32();
830 let x = match store.table(inst_id, x).elems.get(i as usize) {
831 None | Some(Val::Null(_)) => return Err(trap()),
832 Some(x) => x.unwrap_ref(),
833 };
834 if store.func_type(x) != store.insts[inst_id].module.types()[y as usize] {
835 return Err(trap());
836 }
837 return self.invoke(store, x);
838 }
839 Drop => drop(self.pop_value()),
840 Select(_) => {
841 let c = self.pop_value().unwrap_i32();
842 let v2 = self.pop_value();
843 let v1 = self.pop_value();
844 self.push_value(match c {
845 0 => v2,
846 _ => v1,
847 });
848 }
849 LocalGet(x) => {
850 let v = self.frame().locals[x as usize];
851 self.push_value(v);
852 }
853 LocalSet(x) => {
854 let v = self.pop_value();
855 self.frame().locals[x as usize] = v;
856 }
857 LocalTee(x) => {
858 let v = self.peek_value();
859 self.frame().locals[x as usize] = v;
860 }
861 GlobalGet(x) => self.push_value(store.global(inst_id, x).value),
862 GlobalSet(x) => store.global(inst_id, x).value = self.pop_value(),
863 TableGet(x) => {
864 let i = self.pop_value().unwrap_i32();
865 let v = *store.table(inst_id, x).elems.get(i as usize).ok_or_else(trap)?;
866 self.push_value(v);
867 }
868 TableSet(x) => {
869 let val = self.pop_value();
870 let i = self.pop_value().unwrap_i32();
871 let v = store.table(inst_id, x).elems.get_mut(i as usize).ok_or_else(trap)?;
872 *v = val;
873 }
874 ILoad(n, m) => self.load(store.mem(inst_id, 0), NumType::i(n), n.into(), Sx::U, m)?,
875 #[cfg(feature = "float-types")]
876 FLoad(n, m) => self.load(store.mem(inst_id, 0), NumType::f(n), n.into(), Sx::U, m)?,
877 ILoad_(b, s, m) => {
878 self.load(store.mem(inst_id, 0), NumType::i(b.into()), b.into(), s, m)?
879 }
880 IStore(n, m) => self.store(store.mem(inst_id, 0), NumType::i(n), n.into(), m)?,
881 #[cfg(feature = "float-types")]
882 FStore(n, m) => self.store(store.mem(inst_id, 0), NumType::f(n), n.into(), m)?,
883 IStore_(b, m) => {
884 self.store(store.mem(inst_id, 0), NumType::i(b.into()), b.into(), m)?
885 }
886 MemorySize => self.push_value(Val::I32(store.mem(inst_id, 0).size())),
887 MemoryGrow => {
888 let n = self.pop_value().unwrap_i32();
889 self.push_value(Val::I32(grow(store.mem(inst_id, 0), n, ())));
890 }
891 I32Const(c) => self.push_value(Val::I32(c)),
892 I64Const(c) => self.push_value(Val::I64(c)),
893 #[cfg(feature = "float-types")]
894 F32Const(c) => self.push_value(Val::F32(c)),
895 #[cfg(feature = "float-types")]
896 F64Const(c) => self.push_value(Val::F64(c)),
897 ITestOp(n, op) => self.itestop(n, op),
898 IRelOp(n, op) => self.irelop(n, op),
899 #[cfg(feature = "float-types")]
900 FRelOp(n, op) => self.frelop(n, op),
901 IUnOp(n, op) => self.iunop(n, op)?,
902 #[cfg(feature = "float-types")]
903 FUnOp(n, op) => self.funop(n, op),
904 IBinOp(n, op) => self.ibinop(n, op)?,
905 #[cfg(feature = "float-types")]
906 FBinOp(n, op) => self.fbinop(n, op),
907 CvtOp(op) => self.cvtop(op)?,
908 IExtend(b) => self.extend(b),
909 RefNull(t) => self.push_value(Val::Null(t)),
910 RefIsNull => {
911 let c = matches!(self.pop_value(), Val::Null(_)) as u32;
912 self.push_value(Val::I32(c));
913 }
914 RefFunc(x) => self.push_value(Val::Ref(store.func_ptr(inst_id, x))),
915 MemoryInit(x) => {
916 let n = self.pop_value().unwrap_i32() as usize;
917 let s = self.pop_value().unwrap_i32() as usize;
918 let d = self.pop_value().unwrap_i32() as usize;
919 let data = if inst.datas[x as usize] {
920 &[]
921 } else {
922 let mut parser = inst.module.data(x);
923 let mut data = ComputeData::new(store, inst_id);
924 parser.parse_data(&mut data).into_ok();
925 data.init
926 };
927 let mem = store.mem(inst_id, 0);
928 memory_init(d, s, n, mem, data)?;
929 }
930 DataDrop(x) => inst.datas[x as usize] = true,
931 MemoryCopy => {
932 let n = self.pop_value().unwrap_i32() as usize;
933 let s = self.pop_value().unwrap_i32() as usize;
934 let d = self.pop_value().unwrap_i32() as usize;
935 let mem = store.mem(inst_id, 0);
936 if core::cmp::max(s, d).checked_add(n).is_none_or(|x| x > mem.len() as usize) {
937 return Err(trap());
938 }
939 mem.data.copy_within(s .. s + n, d);
940 }
941 MemoryFill => {
942 let n = self.pop_value().unwrap_i32() as usize;
943 let val = self.pop_value().unwrap_i32() as u8;
944 let d = self.pop_value().unwrap_i32() as usize;
945 let mem = store.mem(inst_id, 0);
946 if d.checked_add(n).is_none_or(|x| x > mem.len() as usize) {
947 memory_too_small(d, n, mem);
948 return Err(trap());
949 }
950 mem.data[d ..][.. n].fill(val);
951 }
952 TableInit(x, y) => {
953 let n = self.pop_value().unwrap_i32() as usize;
954 let s = self.pop_value().unwrap_i32() as usize;
955 let d = self.pop_value().unwrap_i32() as usize;
956 let elems = if inst.elems[y as usize] {
957 Vec::new()
958 } else {
959 let mut parser = inst.module.elem(y);
960 let mut elems = ComputeElem::new(store, inst_id);
961 parser.parse_elem(&mut elems).into_ok();
962 elems.init
963 };
964 let table = store.table(inst_id, x);
965 table_init(d, s, n, table, &elems)?;
966 }
967 ElemDrop(x) => inst.elems[x as usize] = true,
968 TableCopy(x, y) => {
969 let n = self.pop_value().unwrap_i32() as usize;
970 let s = self.pop_value().unwrap_i32() as usize;
971 let d = self.pop_value().unwrap_i32() as usize;
972 let sn = s.checked_add(n).ok_or_else(trap)?;
973 let dn = d.checked_add(n).ok_or_else(trap)?;
974 let ys = store.table(inst_id, y).elems.get(s .. sn).ok_or_else(trap)?.to_vec();
976 let xs = store.table(inst_id, x).elems.get_mut(d .. dn).ok_or_else(trap)?;
977 xs.copy_from_slice(&ys);
978 }
979 TableGrow(x) => {
980 let n = self.pop_value().unwrap_i32();
981 let val = self.pop_value();
982 let table = store.table(inst_id, x);
983 self.push_value(Val::I32(grow(table, n, val)));
984 }
985 TableSize(x) => self.push_value(Val::I32(store.table(inst_id, x).size())),
986 TableFill(x) => {
987 let n = self.pop_value().unwrap_i32() as usize;
988 let val = self.pop_value();
989 let i = self.pop_value().unwrap_i32() as usize;
990 let table = store.table(inst_id, x);
991 if i.checked_add(n).is_none_or(|x| x > table.elems.len()) {
992 return Err(trap());
993 }
994 table.elems[i ..][.. n].fill(val);
995 }
996 }
997 Ok(ThreadResult::Continue(self))
998 }
999
1000 fn inst_id(&self) -> usize {
1001 self.frames.last().unwrap().inst_id
1002 }
1003
1004 fn inst(&self, store: &Store<'m>) -> InstId {
1005 InstId { store_id: store.id, inst_id: self.inst_id() }
1006 }
1007
1008 fn frame(&mut self) -> &mut Frame<'m> {
1009 self.frames.last_mut().unwrap()
1010 }
1011
1012 fn values(&mut self) -> &mut Vec<Val> {
1013 &mut self.values
1014 }
1015
1016 fn peek_value(&mut self) -> Val {
1017 *self.values().last().unwrap()
1018 }
1019
1020 fn push_value(&mut self, value: Val) {
1021 self.values().push(value);
1022 }
1023
1024 fn push_value_or_trap(&mut self, value: Option<Val>) -> Result<(), Error> {
1025 if let Some(x) = value {
1026 self.push_value(x);
1027 Ok(())
1028 } else {
1029 Err(trap())
1030 }
1031 }
1032
1033 fn push_values(&mut self, values: &[Val]) {
1034 self.values().extend_from_slice(values);
1035 }
1036
1037 fn pop_value(&mut self) -> Val {
1038 self.values().pop().unwrap()
1039 }
1040
1041 fn pop_values(&mut self, n: usize) -> Vec<Val> {
1042 let len = self.values().len() - n;
1043 self.values().split_off(len)
1044 }
1045
1046 fn push_label(&mut self) {
1047 self.frame().labels_cnt += 1;
1048 }
1049
1050 fn pop_label(mut self, l: LabelIdx, offset: usize) -> ThreadResult<'m> {
1051 let frame = self.frame();
1052 let i = frame.labels_cnt - l as usize - 1;
1053 if i == 0 {
1054 return self.exit_frame();
1055 }
1056 frame.labels_cnt = i;
1057 let Ok(BranchTableEntryView { val_cnt, pop_cnt, .. }) =
1058 frame.side_table.get(offset).view::<Use>();
1059 let val_pos = self.values().len() - val_cnt as usize;
1060 self.values().drain(val_pos - pop_cnt as usize .. val_pos);
1061 self.take_jump(offset);
1062 ThreadResult::Continue(self)
1063 }
1064
1065 fn exit_label(mut self) -> ThreadResult<'m> {
1066 let frame = self.frame();
1067 frame.labels_cnt -= 1;
1068 if frame.labels_cnt == 0 {
1069 let arity = frame.arity;
1070 let values = self.pop_values(arity);
1071 let frame = self.frames.pop().unwrap();
1072 if self.frames.is_empty() {
1073 return ThreadResult::Done(values);
1074 }
1075 self.parser = frame.ret;
1076 self.values().extend(values);
1077 }
1078 ThreadResult::Continue(self)
1079 }
1080
1081 fn exit_frame(mut self) -> ThreadResult<'m> {
1082 let prev_stack = self.frame().prev_stack;
1083 let mut values = self.values().split_off(prev_stack);
1084 let frame = self.frames.pop().unwrap();
1085 let mid = values.len() - frame.arity;
1086 if self.frames.is_empty() {
1087 values.drain(0 .. mid);
1088 return ThreadResult::Done(values);
1089 }
1090 self.parser = frame.ret;
1091 self.values().extend_from_slice(&values[mid ..]);
1092 ThreadResult::Continue(self)
1093 }
1094
1095 fn take_jump(&mut self, offset: usize) {
1096 let offset = self.frame().take_jump(offset);
1097 self.parser.update(offset);
1098 }
1099
1100 fn mem_slice<'a>(
1101 &mut self, mem: &'a mut Memory<'m>, m: MemArg, i: u32, len: usize,
1102 ) -> Option<&'a mut [u8]> {
1103 let ea = i.checked_add(m.offset)?;
1104 if ea.checked_add(len as u32)? > mem.len() {
1105 memory_too_small(ea as usize, len, mem);
1106 return None;
1107 }
1108 Some(&mut mem.data[ea as usize ..][.. len])
1109 }
1110
1111 fn load(
1112 &mut self, mem: &mut Memory<'m>, t: NumType, n: usize, s: Sx, m: MemArg,
1113 ) -> Result<(), Error> {
1114 let i = self.pop_value().unwrap_i32();
1115 let mem = match self.mem_slice(mem, m, i, n / 8) {
1116 None => return Err(trap()),
1117 Some(x) => x,
1118 };
1119 macro_rules! convert {
1120 ($T:ident, $t:ident, $s:ident) => {
1121 Val::$T($s::from_le_bytes(mem.try_into().unwrap()) as $t)
1122 };
1123 }
1124 let c = match (t, n, s) {
1125 (NumType::I32, 32, Sx::U) => convert!(I32, u32, u32),
1126 (NumType::I32, 16, Sx::U) => convert!(I32, u32, u16),
1127 (NumType::I32, 16, Sx::S) => convert!(I32, u32, i16),
1128 (NumType::I32, 8, Sx::U) => convert!(I32, u32, u8),
1129 (NumType::I32, 8, Sx::S) => convert!(I32, u32, i8),
1130 (NumType::I64, 64, Sx::U) => convert!(I64, u64, u64),
1131 (NumType::I64, 32, Sx::U) => convert!(I64, u64, u32),
1132 (NumType::I64, 32, Sx::S) => convert!(I64, u64, i32),
1133 (NumType::I64, 16, Sx::U) => convert!(I64, u64, u16),
1134 (NumType::I64, 16, Sx::S) => convert!(I64, u64, i16),
1135 (NumType::I64, 8, Sx::U) => convert!(I64, u64, u8),
1136 (NumType::I64, 8, Sx::S) => convert!(I64, u64, i8),
1137 #[cfg(feature = "float-types")]
1138 (NumType::F32, 32, _) => convert!(F32, u32, u32),
1139 #[cfg(feature = "float-types")]
1140 (NumType::F64, 64, _) => convert!(F64, u64, u64),
1141 _ => unreachable!(),
1142 };
1143 self.push_value(c);
1144 Ok(())
1145 }
1146
1147 fn store(
1148 &mut self, mem: &mut Memory<'m>, t: NumType, n: usize, m: MemArg,
1149 ) -> Result<(), Error> {
1150 let c = self.pop_value();
1151 let i = self.pop_value().unwrap_i32();
1152 let mem = match self.mem_slice(mem, m, i, n / 8) {
1153 None => return Err(trap()),
1154 Some(x) => x,
1155 };
1156 macro_rules! convert {
1157 ($s:ident, $t:ident) => {
1158 paste::paste! {
1159 mem.copy_from_slice(&(c.[<unwrap_ $s>]() as $t).to_le_bytes())
1160 }
1161 };
1162 }
1163 match (t, n) {
1164 (NumType::I32, 32) => convert!(i32, u32),
1165 (NumType::I32, 16) => convert!(i32, u16),
1166 (NumType::I32, 8) => convert!(i32, u8),
1167 (NumType::I64, 64) => convert!(i64, u64),
1168 (NumType::I64, 32) => convert!(i64, u32),
1169 (NumType::I64, 16) => convert!(i64, u16),
1170 (NumType::I64, 8) => convert!(i64, u8),
1171 #[cfg(feature = "float-types")]
1172 (NumType::F32, 32) => convert!(f32, u32),
1173 #[cfg(feature = "float-types")]
1174 (NumType::F64, 64) => convert!(f64, u64),
1175 _ => unreachable!(),
1176 }
1177 Ok(())
1178 }
1179
1180 fn itestop(&mut self, n: Nx, op: ITestOp) {
1181 let x = self.pop_value();
1182 let z = match n {
1183 Nx::N32 => op.n32(x.unwrap_i32()),
1184 Nx::N64 => op.n64(x.unwrap_i64()),
1185 };
1186 self.push_value(Val::I32(z as u32))
1187 }
1188
1189 fn irelop(&mut self, n: Nx, op: IRelOp) {
1190 let y = self.pop_value();
1191 let x = self.pop_value();
1192 let z = match n {
1193 Nx::N32 => op.n32(x.unwrap_i32(), y.unwrap_i32()),
1194 Nx::N64 => op.n64(x.unwrap_i64(), y.unwrap_i64()),
1195 };
1196 self.push_value(Val::I32(z as u32))
1197 }
1198
1199 fn iunop(&mut self, n: Nx, op: IUnOp) -> Result<(), Error> {
1200 let x = self.pop_value();
1201 let z = try {
1202 match n {
1203 Nx::N32 => Val::I32(op.n32(x.unwrap_i32())?),
1204 Nx::N64 => Val::I64(op.n64(x.unwrap_i64())?),
1205 }
1206 };
1207 self.push_value_or_trap(z)
1208 }
1209
1210 fn ibinop(&mut self, n: Nx, op: IBinOp) -> Result<(), Error> {
1211 let y = self.pop_value();
1212 let x = self.pop_value();
1213 let z = try {
1214 match n {
1215 Nx::N32 => Val::I32(op.n32(x.unwrap_i32(), y.unwrap_i32())?),
1216 Nx::N64 => Val::I64(op.n64(x.unwrap_i64(), y.unwrap_i64())?),
1217 }
1218 };
1219 self.push_value_or_trap(z)
1220 }
1221
1222 #[cfg(feature = "float-types")]
1223 fn frelop(&mut self, n: Nx, op: FRelOp) {
1224 let y = self.pop_value();
1225 let x = self.pop_value();
1226 let z = match n {
1227 Nx::N32 => op.n32(x.unwrap_f32(), y.unwrap_f32()),
1228 Nx::N64 => op.n64(x.unwrap_f64(), y.unwrap_f64()),
1229 };
1230 self.push_value(Val::I32(z as u32))
1231 }
1232
1233 #[cfg(feature = "float-types")]
1234 fn funop(&mut self, n: Nx, op: FUnOp) {
1235 let x = self.pop_value();
1236 let z = match n {
1237 Nx::N32 => Val::F32(op.n32(x.unwrap_f32())),
1238 Nx::N64 => Val::F64(op.n64(x.unwrap_f64())),
1239 };
1240 self.push_value(z);
1241 }
1242
1243 #[cfg(feature = "float-types")]
1244 fn fbinop(&mut self, n: Nx, op: FBinOp) {
1245 let y = self.pop_value();
1246 let x = self.pop_value();
1247 let z = match n {
1248 Nx::N32 => Val::F32(op.n32(x.unwrap_f32(), y.unwrap_f32())),
1249 Nx::N64 => Val::F64(op.n64(x.unwrap_f64(), y.unwrap_f64())),
1250 };
1251 self.push_value(z);
1252 }
1253
1254 fn cvtop(&mut self, op: CvtOp) -> Result<(), Error> {
1255 #[cfg(feature = "float-types")]
1256 macro_rules! trunc {
1257 ($x:expr, $n:tt, $m:tt, $s:tt) => {{
1258 paste::paste! {
1259 let x = [<f $m>]::from_bits($x.[<unwrap_f $m>]());
1260 let min = ([<$s $n>]::MIN as [<f $m>]);
1261 let max = ([<$s $n>]::MAX as [<f $m>]);
1262 let min = if min - 1. == min { min <= x } else { min - 1. < x };
1263 (min && x < max + 1.).then(|| Val::[<I $n>](x as [<$s $n>] as [<u $n>]))?
1264 }
1265 }};
1266 }
1267 #[cfg(feature = "float-types")]
1268 macro_rules! trunc_sat {
1269 ($x:expr, $n:tt, $m:tt, $s:tt) => {
1270 paste::paste! {
1271 Val::[<I $n>](match [<f $m>]::from_bits($x.[<unwrap_f $m>]()) {
1272 x if x.is_nan() => 0,
1273 x if x.is_infinite() && x.is_sign_positive() => [<$s $n>]::MAX,
1274 x if x.is_infinite() && x.is_sign_negative() => [<$s $n>]::MIN,
1275 x => x as [<$s $n>],
1276 } as [<u $n>])
1277 }
1278 };
1279 }
1280 #[cfg(feature = "float-types")]
1281 macro_rules! convert {
1282 ($x:expr, $n:tt, $m:tt, $s:tt) => {
1283 paste::paste! {
1284 Val::[<F $n>](($x.[<unwrap_i $m>]() as [<$s $m>] as [<f $n>]).to_bits())
1285 }
1286 };
1287 }
1288 #[cfg(feature = "float-types")]
1289 macro_rules! dispatch {
1290 ($f:ident, $x:expr, $n:expr, $m:expr, $s:expr) => {
1291 match ($n, $m, $s) {
1292 (Nx::N32, Nx::N32, Sx::U) => $f!($x, 32, 32, u),
1293 (Nx::N32, Nx::N32, Sx::S) => $f!($x, 32, 32, i),
1294 (Nx::N32, Nx::N64, Sx::U) => $f!($x, 32, 64, u),
1295 (Nx::N32, Nx::N64, Sx::S) => $f!($x, 32, 64, i),
1296 (Nx::N64, Nx::N32, Sx::U) => $f!($x, 64, 32, u),
1297 (Nx::N64, Nx::N32, Sx::S) => $f!($x, 64, 32, i),
1298 (Nx::N64, Nx::N64, Sx::U) => $f!($x, 64, 64, u),
1299 (Nx::N64, Nx::N64, Sx::S) => $f!($x, 64, 64, i),
1300 }
1301 };
1302 }
1303 use CvtOp::*;
1304 let x = self.pop_value();
1305 let z = try {
1306 match op {
1307 Wrap => Val::I32(x.unwrap_i64() as u32),
1308 Extend(Sx::U) => Val::I64(x.unwrap_i32() as u64),
1309 Extend(Sx::S) => Val::I64(x.unwrap_i32() as i32 as u64),
1310 #[cfg(feature = "float-types")]
1311 Trunc(n, m, s) => dispatch!(trunc, x, n, m, s),
1312 #[cfg(feature = "float-types")]
1313 TruncSat(n, m, s) => dispatch!(trunc_sat, x, n, m, s),
1314 #[cfg(feature = "float-types")]
1315 Convert(n, m, s) => dispatch!(convert, x, n, m, s),
1316 #[cfg(feature = "float-types")]
1317 Demote => Val::F32((f64::from_bits(x.unwrap_f64()) as f32).to_bits()),
1318 #[cfg(feature = "float-types")]
1319 Promote => Val::F64((f32::from_bits(x.unwrap_f32()) as f64).to_bits()),
1320 #[cfg(feature = "float-types")]
1321 IReinterpret(n) => match n {
1322 Nx::N32 => Val::I32(x.unwrap_f32()),
1323 Nx::N64 => Val::I64(x.unwrap_f64()),
1324 },
1325 #[cfg(feature = "float-types")]
1326 FReinterpret(n) => match n {
1327 Nx::N32 => Val::F32(x.unwrap_i32()),
1328 Nx::N64 => Val::F64(x.unwrap_i64()),
1329 },
1330 }
1331 };
1332 self.push_value_or_trap(z)
1333 }
1334
1335 fn extend(&mut self, n: Bx) {
1336 let x = self.pop_value();
1337 let z = match n {
1338 Bx::N32B8 => Val::I32(x.unwrap_i32() as i8 as u32),
1339 Bx::N32B16 => Val::I32(x.unwrap_i32() as i16 as u32),
1340 Bx::N64B8 => Val::I64(x.unwrap_i64() as i8 as u64),
1341 Bx::N64B16 => Val::I64(x.unwrap_i64() as i16 as u64),
1342 Bx::N64B32 => Val::I64(x.unwrap_i64() as i32 as u64),
1343 };
1344 self.push_value(z)
1345 }
1346
1347 fn invoke(mut self, store: &mut Store<'m>, ptr: Ptr) -> Result<ThreadResult<'m>, Error> {
1348 const MAX_FRAMES: usize = 1000;
1350 if self.frames.len() >= MAX_FRAMES {
1351 return Err(trap());
1352 }
1353 let t = store.func_type(ptr);
1354 let inst_id = match ptr.instance() {
1355 Side::Host => {
1356 let index = ptr.index() as usize;
1357 let t = store.funcs[index].1;
1358 let arity = t.results.len();
1359 let args = self.pop_values(t.params.len());
1360 store.threads.push(Continuation { thread: self, arity, index, args });
1361 return Ok(ThreadResult::Host);
1362 }
1363 Side::Wasm(x) => x,
1364 };
1365 let (mut parser, side_table) = store.insts[inst_id].module.func(ptr.index());
1366 let mut locals = self.pop_values(t.params.len());
1367 append_locals(&mut parser, &mut locals);
1368 let ret = self.parser;
1369 self.parser = parser;
1370 let prev_stack = self.values().len();
1371 let frame = Frame::new(inst_id, t.results.len(), ret, locals, side_table, prev_stack);
1372 self.frames.push(frame);
1373 Ok(ThreadResult::Continue(self))
1374 }
1375}
1376
1377fn table_init(d: usize, s: usize, n: usize, table: &mut Table, elems: &[Val]) -> Result<(), Error> {
1378 if s.checked_add(n).is_none_or(|x| x > elems.len())
1379 || d.checked_add(n).is_none_or(|x| x > table.elems.len())
1380 {
1381 Err(trap())
1382 } else {
1383 table.elems[d ..][.. n].copy_from_slice(&elems[s ..][.. n]);
1384 Ok(())
1385 }
1386}
1387
1388fn memory_init(d: usize, s: usize, n: usize, mem: &mut Memory, data: &[u8]) -> Result<(), Error> {
1389 if s.checked_add(n).is_none_or(|x| x > data.len())
1390 || d.checked_add(n).is_none_or(|x| x > mem.len() as usize)
1391 {
1392 memory_too_small(d, n, mem);
1393 Err(trap())
1394 } else {
1395 mem.data[d ..][.. n].copy_from_slice(&data[s ..][.. n]);
1396 Ok(())
1397 }
1398}
1399
1400#[derive(Debug)]
1401struct Frame<'m> {
1402 inst_id: usize,
1403 arity: usize,
1404 ret: Parser<'m>,
1405 locals: Vec<Val>,
1406 side_table: Cursor<'m, BranchTableEntry>,
1407 prev_stack: usize,
1409 labels_cnt: usize,
1411}
1412
1413impl<'m> Frame<'m> {
1414 fn new(
1415 inst_id: usize, arity: usize, ret: Parser<'m>, locals: Vec<Val>,
1416 side_table: Cursor<'m, BranchTableEntry>, prev_stack: usize,
1417 ) -> Self {
1418 Frame { inst_id, arity, ret, locals, side_table, prev_stack, labels_cnt: 1 }
1419 }
1420
1421 fn skip_jump(&mut self) {
1422 self.side_table.adjust_start(1);
1423 }
1424
1425 fn take_jump(&mut self, offset: usize) -> isize {
1426 self.side_table.adjust_start(offset as isize);
1427 let entry = self.side_table.get(0).view::<Use>().into_ok();
1428 self.side_table.adjust_start(entry.delta_stp as isize);
1429 entry.delta_ip as isize
1430 }
1431}
1432
1433impl Table {
1434 fn new(type_: TableType) -> Self {
1435 Table {
1436 max: type_.limits.max,
1437 elems: vec![Val::Null(type_.item); type_.limits.min as usize],
1438 }
1439 }
1440}
1441
1442#[derive(Debug, Default)]
1443struct Memory<'m> {
1444 data: &'m mut [u8],
1446 size: u32,
1448 max: u32,
1449}
1450
1451impl<'m> Memory<'m> {
1452 fn init(&mut self, mut data: &'m mut [u8], limits: Limits) -> Result<(), Error> {
1453 if !data.as_ptr().is_aligned_to(MEMORY_ALIGN) {
1454 return Err(invalid());
1455 }
1456 if limits.max < 0x10000 {
1457 let max = core::cmp::min(limits.max as usize * 0x10000, data.len());
1458 data = &mut data[.. max];
1459 }
1460 self.data = data;
1461 self.data.fill(0);
1464 self.size = limits.min;
1465 self.max = limits.max;
1466 Ok(())
1467 }
1468
1469 fn len(&self) -> u32 {
1470 core::cmp::min(self.data.len() as u32, self.size * 0x10000)
1471 }
1472}
1473
1474impl Global {
1475 fn new(value: Val) -> Self {
1476 Global { value }
1477 }
1478}
1479
1480trait Growable {
1481 type Item: Copy;
1482 fn size(&self) -> u32;
1483 fn max(&self) -> u32;
1484 fn grow(&mut self, n: u32, x: Self::Item);
1485}
1486
1487impl Growable for Memory<'_> {
1488 type Item = ();
1489 fn size(&self) -> u32 {
1490 self.size
1491 }
1492 fn max(&self) -> u32 {
1493 self.max
1494 }
1495 fn grow(&mut self, n: u32, _: Self::Item) {
1496 self.size = n;
1497 }
1498}
1499
1500impl Growable for Table {
1501 type Item = Val;
1502 fn size(&self) -> u32 {
1503 self.elems.len() as u32
1504 }
1505 fn max(&self) -> u32 {
1506 self.max
1507 }
1508 fn grow(&mut self, n: u32, x: Self::Item) {
1509 self.elems.resize(n as usize, x);
1510 }
1511}
1512
1513fn grow<T: Growable>(elems: &mut T, n: u32, item: T::Item) -> u32 {
1515 let sz = elems.size();
1516 let len = match sz.checked_add(n) {
1517 Some(x) if x <= elems.max() => x,
1518 _ => return u32::MAX,
1519 };
1520 elems.grow(len, item);
1521 sz
1522}
1523
1524#[derive(Debug, Default)]
1525struct Component<T> {
1526 ext: Vec<Ptr>,
1527 int: T,
1528}
1529
1530impl<T> Component<T> {
1531 fn ptr(&self, inst_id: usize, x: u32) -> Ptr {
1532 match x.checked_sub(self.ext.len() as u32) {
1533 None => self.ext[x as usize],
1534 Some(x) => Ptr::new(Side::Wasm(inst_id), x),
1535 }
1536 }
1537}
1538
1539macro_rules! impl_val_unwrap {
1540 ($n:ident, $T:ident, $t:ident) => {
1541 impl Val {
1542 pub fn $n(self) -> $t {
1543 match self {
1544 Val::$T(x) => x,
1545 _ => unreachable!(),
1546 }
1547 }
1548 }
1549 };
1550}
1551impl_val_unwrap!(unwrap_i32, I32, u32);
1552impl_val_unwrap!(unwrap_i64, I64, u64);
1553#[cfg(feature = "float-types")]
1554impl_val_unwrap!(unwrap_f32, F32, u32);
1555#[cfg(feature = "float-types")]
1556impl_val_unwrap!(unwrap_f64, F64, u64);
1557impl_val_unwrap!(unwrap_ref, Ref, Ptr);
1558
1559impl ValType {
1560 fn default(self) -> Val {
1561 match self {
1562 ValType::I32 => Val::I32(0),
1563 ValType::I64 => Val::I64(0),
1564 ValType::F32 => support_if!("float-types"[], Val::F32(0), unreachable!()),
1565 ValType::F64 => support_if!("float-types"[], Val::F64(0), unreachable!()),
1566 ValType::V128 => support_if!("vector-types"[], Val::V128(0), unreachable!()),
1567 ValType::FuncRef => Val::Null(RefType::FuncRef),
1568 ValType::ExternRef => Val::Null(RefType::ExternRef),
1569 }
1570 }
1571
1572 fn contains(self, value: Val) -> bool {
1573 match (self, value) {
1574 (ValType::I32, Val::I32(_))
1575 | (ValType::I64, Val::I64(_))
1576 | (ValType::FuncRef, Val::Null(RefType::FuncRef) | Val::Ref(_))
1577 | (ValType::ExternRef, Val::Null(RefType::ExternRef) | Val::RefExtern(_)) => true,
1578 #[cfg(feature = "float-types")]
1579 (ValType::F32, Val::F32(_)) | (ValType::F64, Val::F64(_)) => true,
1580 #[cfg(feature = "vector-types")]
1581 (ValType::V128, Val::V128(_)) => true,
1582 _ => false,
1583 }
1584 }
1585}
1586
1587fn append_locals(parser: &mut Parser, locals: &mut Vec<Val>) {
1588 for _ in 0 .. parser.parse_vec().into_ok() {
1589 let len = parser.parse_u32().into_ok() as usize;
1590 let val = parser.parse_valtype().into_ok().default();
1591 locals.extend(core::iter::repeat_n(val, len));
1592 }
1593}
1594
1595fn check_types(types: &[ValType], values: &[Val]) -> Result<(), Error> {
1596 check(types.len() == values.len())?;
1597 check(types.iter().zip(values.iter()).all(|(t, x)| t.contains(*x)))
1598}
1599
1600fn memory_too_small(x: usize, n: usize, mem: &Memory) {
1601 #[cfg(not(feature = "debug"))]
1602 let _ = (x, n, mem);
1603 #[cfg(feature = "debug")]
1604 eprintln!("Memory too small: {x} + {n} > {}", mem.len());
1605}