1use alloc::{collections::btree_map::BTreeMap, string::String, vec, vec::Vec};
2
3use crate::{
4 core::{
5 indices::{DataIdx, ElemIdx, FuncIdx, GlobalIdx, IdxVec, MemIdx, TableIdx, TypeIdx},
6 reader::{
7 span::Span,
8 types::{FuncType, MemType, TableType},
9 },
10 sidetable::Sidetable,
11 utils::ToUsizeExt,
12 },
13 linear_memory::LinearMemory,
14 value::Ref,
15 GlobalType, Limits, RefType, RuntimeError, TrapError, ValType, Value,
16};
17
18use super::{
19 addrs::{DataAddr, ElemAddr, FuncAddr, GlobalAddr, MemAddr, ModuleAddr, TableAddr},
20 ExternVal, HaltExecutionError,
21};
22
23#[derive(Debug)]
24pub enum FuncInst<T> {
26 WasmFunc(WasmFuncInst),
27 HostFunc(HostFuncInst<T>),
28}
29
30#[derive(Debug)]
31pub struct WasmFuncInst {
32 pub function_type: FuncType,
33 pub _ty: TypeIdx,
34 pub locals: Vec<ValType>,
35 pub code_expr: Span,
36 pub stp: usize,
38
39 pub module_addr: ModuleAddr,
42}
43
44#[derive(Debug)]
45pub struct HostFuncInst<T> {
46 pub function_type: FuncType,
47 pub hostcode: fn(&mut T, Vec<Value>) -> Result<Vec<Value>, HaltExecutionError>,
48}
49
50impl<T> FuncInst<T> {
51 pub fn ty(&self) -> &FuncType {
52 match self {
53 FuncInst::WasmFunc(wasm_func_inst) => &wasm_func_inst.function_type,
54 FuncInst::HostFunc(host_func_inst) => &host_func_inst.function_type,
55 }
56 }
57}
58
59#[derive(Clone, Debug)]
60pub struct ElemInst {
62 pub _ty: RefType,
63 pub references: Vec<Ref>,
64}
65
66impl ElemInst {
67 pub fn len(&self) -> usize {
68 self.references.len()
69 }
70}
71
72#[derive(Debug)]
76pub struct TableInst {
77 pub ty: TableType,
78 pub elem: Vec<Ref>,
79}
80
81impl TableInst {
82 pub fn len(&self) -> usize {
83 self.elem.len()
84 }
85
86 pub fn grow(&mut self, n: u32, reff: Ref) -> Result<(), RuntimeError> {
88 let len = n
90 .checked_add(self.elem.len() as u32)
91 .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
92
93 if self.ty.lim.max.map(|max| len > max).unwrap_or(false) {
97 return Err(TrapError::TableOrElementAccessOutOfBounds.into());
98 }
99 let limits_prime = Limits {
100 min: len,
101 max: self.ty.lim.max,
102 };
103
104 self.elem.extend(vec![reff; n.into_usize()]);
105
106 self.ty.lim = limits_prime;
107 Ok(())
108 }
109}
110
111pub struct MemInst {
112 pub ty: MemType,
113 pub mem: LinearMemory,
114}
115impl core::fmt::Debug for MemInst {
116 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
117 f.debug_struct("MemInst")
118 .field("ty", &self.ty)
119 .finish_non_exhaustive()
120 }
121}
122
123impl MemInst {
124 pub fn grow(&mut self, n: u32) -> Result<(), RuntimeError> {
126 let len = n + self.mem.pages() as u32;
128 if len > Limits::MAX_MEM_PAGES {
129 return Err(TrapError::MemoryOrDataAccessOutOfBounds.into());
130 }
131
132 if self.ty.limits.max.map(|max| len > max).unwrap_or(false) {
136 return Err(TrapError::MemoryOrDataAccessOutOfBounds.into());
137 }
138 let limits_prime = Limits {
139 min: len,
140 max: self.ty.limits.max,
141 };
142
143 self.mem.grow(n.try_into().unwrap());
144
145 self.ty.limits = limits_prime;
146 Ok(())
147 }
148
149 pub fn size(&self) -> usize {
151 self.mem.len() / (crate::Limits::MEM_PAGE_SIZE.into_usize())
152 }
153}
154
155#[derive(Debug)]
161pub struct GlobalInst {
162 pub ty: GlobalType,
163 pub value: Value,
165}
166
167pub struct DataInst {
168 pub data: Vec<u8>,
169}
170
171impl core::fmt::Debug for DataInst {
172 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
173 f.debug_struct("DataInst").finish_non_exhaustive()
174 }
175}
176
177#[derive(Debug)]
179pub struct ModuleInst<'b> {
180 pub types: IdxVec<TypeIdx, FuncType>,
181 pub func_addrs: IdxVec<FuncIdx, FuncAddr>,
182 pub table_addrs: IdxVec<TableIdx, TableAddr>,
183 pub mem_addrs: IdxVec<MemIdx, MemAddr>,
184 pub global_addrs: IdxVec<GlobalIdx, GlobalAddr>,
185 pub elem_addrs: IdxVec<ElemIdx, ElemAddr>,
186 pub data_addrs: IdxVec<DataIdx, DataAddr>,
187 pub exports: BTreeMap<String, ExternVal>,
192
193 pub wasm_bytecode: &'b [u8],
195
196 pub sidetable: Sidetable,
198}