wasm/execution/runtime_structure/
store.rs

1use alloc::{borrow::ToOwned, collections::btree_map::BTreeMap, string::String, vec, vec::Vec};
2use core::convert::Infallible;
3
4use crate::{
5    core::{
6        decoding::{
7            modules::code_section::decode_locals,
8            reader::{span::Span, WasmDecoder},
9        },
10        structure::{
11            import_subtyping::ImportSubTypeRelation,
12            modules::{
13                data_segments::{DataMode, DataModeActive, DataSegment},
14                element_segments::{ActiveElem, ElemItems, ElemMode, ElemType},
15                exports::ExportDesc,
16                indices::{ElemIdx, IdxVec, TypeIdx},
17            },
18        },
19        utils::ToUsizeExt,
20    },
21    execution::{
22        assert_validated::UnwrapValidatedExt,
23        instructions::{
24            self, const_interpreter_loop::run_const_span, data_drop, elem_drop, memory_init,
25            table_init, InterpreterLoopOutcome,
26        },
27        runtime_structure::{
28            data_instances::DataInst,
29            element_instances::ElemInst,
30            external_values::ExternFilterable,
31            function_instances::{FuncInst, HostFuncInst, WasmFuncInst},
32            global_instances::GlobalInst,
33            memory_instances::{linear_memory::LinearMemory, MemInst},
34            module_instances::ModuleInst,
35            table_instances::TableInst,
36            value_stack::Stack,
37        },
38    },
39    AddrVec, Config, DataAddr, ElemAddr, ExternVal, FuncAddr, FuncType, GlobalAddr, GlobalType,
40    HostCall, HostResumable, MemAddr, MemType, Module, ModuleAddr, Ref, RefType, Resumable,
41    RunState, RuntimeError, TableAddr, TableType, Value, WasmResumable,
42};
43
44/// The store represents all global state that can be manipulated by WebAssembly programs. It
45/// consists of the runtime representation of all instances of functions, tables, memories, and
46/// globals, element segments, and data segments that have been allocated during the life time of
47/// the abstract machine.
48/// <https://webassembly.github.io/spec/core/exec/runtime.html#store>
49///
50/// # Safety
51///
52/// All addresses contained in a store must be valid for their associated
53/// address vectors in the same store.
54pub struct Store<'b, T: Config> {
55    /// The actual inner Wasm store.
56    ///
57    /// This is stored as a separate inner type, so that we can partially borrow a [`StoreInner`]
58    /// and other fields of [`Store`] at the same time.
59    pub(crate) inner: StoreInner,
60
61    // fields outside of the spec but are convenient are below
62    /// An address space of modules instantiated within the context of this [`Store`].
63    ///
64    /// Although the WebAssembly Specification 2.0 does not specify module instances
65    /// to be part of the [`Store`], in reality they can be managed very similar to
66    /// other instance types. Therefore, we extend the [`Store`] by a module address
67    /// space along with a `ModuleAddr` index type.
68    pub(crate) modules: AddrVec<ModuleAddr, ModuleInst<'b>>,
69
70    pub user_data: T,
71}
72
73/// This is a Wasm store as defined by the specification. It contains all state relevant for
74/// execution.
75///
76/// There is a directly one-to-one relation between [`Store`] and [`StoreInner`].
77///
78/// See: WebAssembly Specification 2.0 - 4.2.3 - Store
79///
80/// # Safety
81///
82/// All addresses contained in a [`Store`] and its [`StoreInner`] must be valid for their associated
83/// address vectors in the same store.
84pub(crate) struct StoreInner {
85    pub(crate) functions: AddrVec<FuncAddr, FuncInst>,
86    pub(crate) tables: AddrVec<TableAddr, TableInst>,
87    pub(crate) memories: AddrVec<MemAddr, MemInst>,
88    pub(crate) globals: AddrVec<GlobalAddr, GlobalInst>,
89    pub(crate) elements: AddrVec<ElemAddr, ElemInst>,
90    pub(crate) data: AddrVec<DataAddr, DataInst>,
91}
92
93impl<'b, T: Config> Store<'b, T> {
94    /// Creates a new empty store with some user data
95    ///
96    /// See: WebAssembly Specification 2.0 - 7.1.4 - store_init
97    pub fn new(user_data: T) -> Self {
98        // 1. Return the empty store.
99        // For us the store is empty except for the user data, which we do not have control over.
100        Self {
101            inner: StoreInner {
102                functions: AddrVec::default(),
103                tables: AddrVec::default(),
104                memories: AddrVec::default(),
105                globals: AddrVec::default(),
106                elements: AddrVec::default(),
107                data: AddrVec::default(),
108            },
109            modules: AddrVec::default(),
110            user_data,
111        }
112    }
113
114    /// Instantiate a new module instance from a [`Module`] in this [`Store`].
115    ///
116    /// Note that if this returns an `Err(_)`, the store might be left in an ill-defined state. This might cause further
117    /// operations to have unexpected results.
118    ///
119    /// See: WebAssembly Specification 2.0 - 7.1.5 - module_instantiate
120    ///
121    /// # Safety
122    ///
123    /// The caller has to guarantee that any address values contained in the
124    /// [`ExternVal`]s came from the current [`Store`] object.
125    pub unsafe fn module_instantiate(
126        &mut self,
127        validation_info: &Module<'b>,
128        extern_vals: Vec<ExternVal>,
129        maybe_fuel: Option<u64>,
130    ) -> Result<InstantiationOutcome, RuntimeError> {
131        // instantiation: step 1
132        // The module is guaranteed to be valid, because only validation can
133        // produce `Module`s.
134
135        // instantiation: step 3
136        if validation_info.imports.len() != extern_vals.len() {
137            return Err(RuntimeError::ExternValsLenMismatch);
138        }
139
140        // instantiation: step 4
141        let imports_as_extern_types = validation_info.imports.iter().map(|import| {
142            // SAFETY: `import` is part of the same `validation_info` and
143            // therefore it was created as part of the same `validation_info`.
144            unsafe { import.desc.extern_type(validation_info) }
145        });
146        for (extern_val, import_as_extern_type) in extern_vals.iter().zip(imports_as_extern_types) {
147            // instantiation: step 4a
148            // check that extern_val is valid in this Store, which should be guaranteed by the caller through a safety constraint in the future.
149            // TODO document this instantiation step properly
150
151            // instantiation: step 4b
152            let extern_type = extern_val.extern_type(self);
153
154            // instantiation: step 4c
155            if !extern_type.is_subtype_of(&import_as_extern_type) {
156                return Err(RuntimeError::InvalidImportType);
157            }
158        }
159
160        // instantiation: step 5
161        // module_inst_init is unfortunately circularly defined from parts of module_inst that would be defined in step 11, which uses module_inst_init again implicitly.
162        // therefore I am mimicking the reference interpreter code here, I will allocate functions in the store in this step instead of step 11.
163        // https://github.com/WebAssembly/spec/blob/8d6792e3d6709e8d3e90828f9c8468253287f7ed/interpreter/exec/eval.ml#L789
164        let module_inst = ModuleInst {
165            types: validation_info.types.clone(),
166            func_addrs: IdxVec::default(),
167            table_addrs: IdxVec::default(),
168            mem_addrs: IdxVec::default(),
169            // TODO This is weird hack with soundness holes.  Wasm defines a
170            // special `moduleinst_init`. Here, we want to use the `IdxVec` type
171            // safety, but at the same time only the imports can be populated at
172            // this point.
173            global_addrs: IdxVec::new(extern_vals.iter().globals().collect())
174                .expect(
175                    "that the number of imports and therefore also the number of imported globals is <= u32::MAX",
176                ),
177            elem_addrs: IdxVec::default(),
178            data_addrs: IdxVec::default(),
179            exports: BTreeMap::new(),
180            wasm_bytecode: validation_info.wasm,
181            sidetable: validation_info.sidetable.clone(),
182        };
183        let module_addr = self.modules.insert(module_inst);
184
185        let imported_functions = extern_vals.iter().funcs();
186        let local_func_addrs = validation_info
187            .functions
188            .iter_local_definitions()
189            .zip(validation_info.func_blocks_stps.iter())
190            .map(|(ty_idx, (span, stp))| {
191                // SAFETY: The module address is valid for the current store,
192                // because it was just created and the type index is valid for
193                // that same module because it came from that module's
194                // `Module`.
195                unsafe { self.alloc_func((*ty_idx, (*span, *stp)), module_addr) }
196            });
197
198        let func_addrs = validation_info
199            .functions
200            .map(imported_functions.collect(), local_func_addrs.collect())
201            .expect(
202                "that the numbers of imported and local functions always \
203                match the respective numbers in the validation info. Step 3 and 4 \
204                check if the number of imported functions is correct and the number \
205                of local functions is a direct one-to-one mapping of \
206                `validation_info.func_blocks_stps`",
207            )
208            .into_inner();
209
210        // SAFETY: The module with this module address was just inserted into
211        // this `AddrVec`
212        let module_inst = unsafe { self.modules.get_mut(module_addr) };
213        module_inst.func_addrs = func_addrs;
214
215        // instantiation: this roughly matches step 6,7,8
216        // validation guarantees these will evaluate without errors.
217        let local_globals_init_vals: Vec<Value> = validation_info
218            .globals
219            .iter_local_definitions()
220            .map(|global| {
221                // SAFETY: All requirements are met:
222                // 1. Validation guarantees that the constant expression for
223                //    this global is valid.
224                // 2. The module with this module address was just inserted into
225                //    this store's `AddrVec`.
226                let const_expr_result = unsafe {
227                    run_const_span(validation_info.wasm, &global.init_expr, module_addr, self)
228                };
229                const_expr_result.transpose().unwrap_validated()
230            })
231            .collect::<Result<Vec<Value>, _>>()?;
232
233        // instantiation: this roughly matches step 9,10 and performs allocation
234        // step 6,12 already
235        let elem_addrs: IdxVec<ElemIdx, ElemAddr> = validation_info.elements.map(|elem| {
236            let refs = match &elem.init {
237                // shortcut of evaluation of "ref.func <func_idx>; end;"
238                // validation guarantees corresponding func_idx's existence
239                ElemItems::RefFuncs(ref_funcs) => {
240                    ref_funcs
241                        .iter()
242                        .map(|func_idx| {
243                            // SAFETY: The module with this module address was
244                            // just inserted into this `AddrVec`
245                            let module = unsafe { self.modules.get(module_addr) };
246                            // SAFETY: Both the function index and the module
247                            // instance's `func_addrs` come from the same
248                            // `Module`, i.e. the one passed into this
249                            // function.
250                            let func_addr = unsafe { module.func_addrs.get(*func_idx) };
251
252                            Ref::Func(*func_addr)
253                        })
254                        .collect()
255                }
256                ElemItems::Exprs(_, exprs) => exprs
257                    .iter()
258                    .map(|expr| {
259                        // SAFETY: All requirements are met:
260                        // 1. Validation guarantees that all constant expressions
261                        //    for elements, including this one, are valid.
262                        // 2. The module with this module address was just inserted into
263                        //    this store's `AddrVec`.
264                        let const_expr_result = unsafe {
265                            run_const_span(validation_info.wasm, expr, module_addr, self)
266                        };
267                        const_expr_result
268                            .map(|res| res.unwrap_validated().try_into().unwrap_validated())
269                    })
270                    .collect::<Result<Vec<Ref>, RuntimeError>>()?,
271            };
272
273            // SAFETY: The initial values were retrieved by (1) resolving
274            // function indices or (2) running constant expressions in the
275            // context of the current store. Therefore, their results are also
276            // valid in the current store.
277            let elem = unsafe { self.alloc_elem(elem.ty(), refs) };
278            Ok::<_, RuntimeError>(elem)
279        })?;
280
281        // instantiation: step 11 - module allocation (except function allocation - which was made in step 5)
282        // https://webassembly.github.io/spec/core/exec/modules.html#alloc-module
283
284        // allocation: begin
285
286        // allocation: step 1
287        let module = validation_info;
288
289        // allocation: skip step 2 & 8 as it was done in instantiation step 5
290
291        // allocation: step 3, 9
292        let table_addrs_local: Vec<TableAddr> = module
293            .tables
294            .iter_local_definitions()
295            .map(|table_type| {
296                // SAFETY: The initial table value is null, which is not an
297                // address type and therefore not invalid in the current store.
298                unsafe { self.alloc_table(*table_type, Ref::Null(table_type.et)) }
299            })
300            .collect();
301        // allocation: step 4, 10
302        let mem_addrs_local: Vec<MemAddr> = module
303            .memories
304            .iter_local_definitions()
305            .map(|mem_type| self.alloc_mem(*mem_type))
306            .collect();
307        // allocation: step 5, 11
308        let global_addrs_local: Vec<GlobalAddr> = module
309            .globals
310            .iter_local_definitions()
311            .zip(local_globals_init_vals)
312            .map(|(global, val)| {
313                // SAFETY: The initial values were retrieved by running constant
314                // expressions within the current store context. Therefore,
315                // their results are also valid in the current store.
316                unsafe { self.alloc_global(global.ty, val) }
317            })
318            .collect();
319        // allocation: skip step 6, 12 as it was done in instantiation step 9, 10
320
321        // allocation: step 7, 13
322        let data_addrs = module
323            .data
324            .map::<DataAddr, Infallible>(|data_segment| Ok(self.alloc_data(&data_segment.init)))
325            .expect("infallible error type to never be constructed");
326
327        // allocation: skip step 14 as it was done in instantiation step 5
328
329        // allocation: step 15
330        let table_addrs = validation_info
331            .tables
332            .map(extern_vals.iter().tables().collect(), table_addrs_local)
333            .expect(
334                "that the numbers of imported and local tables always \
335                match the respective numbers in the validation info. Step 3 and 4 \
336                check if the number of imported tables is correct and the number \
337                of local tables is produced by iterating through all table \
338                definitions and performing one-to-one mapping on each one.",
339            )
340            .into_inner();
341
342        // allocation: step 16
343        let mem_addrs = validation_info
344            .memories
345            .map(extern_vals.iter().mems().collect(), mem_addrs_local)
346            .expect(
347                "that the number of imported and local memories always \
348            match the respective numbers in the validation info. Step 3 and 4 \
349            check if the number of imported memories is correct and the number \
350            of local memories is produced by iterating through all memory \
351            definitions and performing one-to-one mapping on each one.",
352            )
353            .into_inner();
354
355        // allocation step 17
356        let global_addrs = validation_info
357            .globals
358            .map(extern_vals.iter().globals().collect(), global_addrs_local)
359            .expect(
360                "that the number of imported and local globals always \
361            match the respective numbers in the validation info. Step 3 and 4 \
362            check if the number of imported globals is correct and the number \
363            of local globals is produced by iterating through all global \
364            definitions and performing one-to-one mapping on each one.",
365            )
366            .into_inner();
367
368        // allocation: step 18,19
369        let export_insts: BTreeMap<String, ExternVal> = module
370            .exports
371            .iter()
372            .map(|export| {
373                // SAFETY: The module with this module address was just inserted
374                // into this `AddrVec`
375                let module_inst = unsafe { self.modules.get(module_addr) };
376                let value = match export.desc {
377                    ExportDesc::Func(func_idx) => {
378                        // SAFETY: Both the function index and the functions
379                        // `IdxVec` come from the same module instance.
380                        // Because all indices are valid in their specific
381                        // module instance, this is sound.
382                        let func_addr = unsafe { module_inst.func_addrs.get(func_idx) };
383                        ExternVal::Func(*func_addr)
384                    }
385                    ExportDesc::Table(table_idx) => {
386                        // SAFETY: Both the table index and the tables `IdxVec`
387                        // come from the same module instance. Because all
388                        // indices are valid in their specific module instance,
389                        // this is sound.
390                        let table_addr = unsafe { table_addrs.get(table_idx) };
391                        ExternVal::Table(*table_addr)
392                    }
393                    ExportDesc::Mem(mem_idx) => {
394                        // SAFETY: Both the memory index and the memories
395                        // `IdxVec` come from the same module instance. Because
396                        // all indices are valid in their specific module
397                        // instance, this is sound.
398                        let mem_addr = unsafe { mem_addrs.get(mem_idx) };
399
400                        ExternVal::Mem(*mem_addr)
401                    }
402                    ExportDesc::Global(global_idx) => {
403                        // SAFETY: Both the global index and the globals
404                        // `ExtendedIdxVec` come from the same module instance.
405                        // Because all indices are valid in their specific
406                        // module instance, this is sound.
407                        let global_addr = unsafe { global_addrs.get(global_idx) };
408
409                        ExternVal::Global(*global_addr)
410                    }
411                };
412                (export.name.to_owned(), value)
413            })
414            .collect();
415
416        // allocation: step 20,21 initialize module (except functions to instantiation step 5, allocation step 14)
417
418        // SAFETY: The module with this module address was
419        // just inserted into this `AddrVec`
420        let module_inst = unsafe { self.modules.get_mut(module_addr) };
421        module_inst.table_addrs = table_addrs;
422        module_inst.mem_addrs = mem_addrs;
423        module_inst.global_addrs = global_addrs;
424        module_inst.elem_addrs = elem_addrs;
425        module_inst.data_addrs = data_addrs;
426        module_inst.exports = export_insts;
427
428        // allocation: end
429
430        // instantiation step 11 end: module_inst properly allocated after this point.
431
432        // instantiation: step 12-15
433        // TODO have to stray away from the spec a bit since our codebase does not lend itself well to freely executing instructions by themselves
434        for (
435            element_idx,
436            ElemType {
437                init: elem_items,
438                mode,
439            },
440        ) in validation_info.elements.iter_enumerated()
441        {
442            match mode {
443                ElemMode::Active(ActiveElem {
444                    table_idx: table_idx_i,
445                    init_expr: einstr_i,
446                }) => {
447                    let n = elem_items.len() as u32;
448                    // equivalent to init.len() in spec
449                    // instantiation step 14:
450                    // TODO (for now, we are doing hopefully what is equivalent to it)
451                    // execute:
452                    //   einstr_i
453                    //   i32.const 0
454                    //   i32.const n
455                    //   table.init table_idx_i i
456                    //   elem.drop i
457
458                    // SAFETY: The module with this module address was just
459                    // inserted into this `AddrVec`. Furthermore, the span comes
460                    // from an element contained in the same validation info the
461                    // Wasm bytecode is from. Therefore, the constant expression
462                    // in that span must be validated already.
463                    let const_expr_result = unsafe {
464                        run_const_span(validation_info.wasm, einstr_i, module_addr, self)?
465                    };
466                    let d: i32 = const_expr_result
467                        .unwrap_validated() // there is a return value
468                        .try_into()
469                        .unwrap_validated(); // return value has correct type
470
471                    let s = 0;
472                    // SAFETY: All requirements are met:
473                    // 1. The module address was just retrieved by inserting a
474                    //    new module instance into the current store. Therefore, it
475                    //    is valid in the current store.
476                    // 2. The table index is valid for the current module
477                    //    instance because it came from the validation info of the
478                    //    same module.
479                    // 3./5. The table and element addresses are valid because
480                    //       they come from a module instance that is part of the
481                    //       current store itself.
482                    // 4. The element index is valid for the current module
483                    //    instance because it came from the validation info of the
484                    //    same module.
485                    unsafe {
486                        table_init(
487                            &self.modules,
488                            &mut self.inner.tables,
489                            &self.inner.elements,
490                            module_addr,
491                            element_idx,
492                            *table_idx_i,
493                            n,
494                            s,
495                            d,
496                        )?
497                    };
498                    // SAFETY: All requirements are met:
499                    // 1. The module address was just retrieved by inserting a
500                    //    new module instance into the current store. Therefore, it
501                    //    is valid in the current store.
502                    // 2. The element index is valid for the current module
503                    //    instance because it came from the validation info of the
504                    //    same module.
505                    // 3. The element address is valid because it comes from a
506                    //    module instance that is part of the current store itself.
507                    unsafe {
508                        elem_drop(
509                            &self.modules,
510                            &mut self.inner.elements,
511                            module_addr,
512                            element_idx,
513                        );
514                    }
515                }
516                ElemMode::Declarative => {
517                    // instantiation step 15:
518                    // TODO (for now, we are doing hopefully what is equivalent to it)
519                    // execute:
520                    //   elem.drop i
521
522                    // SAFETY: The passed element index comes from the
523                    // validation info, that was just used to allocate a new
524                    // module instance with address `module_addr` in
525                    // `self.modules`. Therefore, it must be safe to use for
526                    // accessing the referenced element.
527                    // SAFETY: All requirements are met:
528                    // 1. The module address was just retrieved by inserting a
529                    //    new module instance into the current store. Therefore, it
530                    //    is valid in the current store.
531                    // 2. The element index is valid for the current module
532                    //    instance because it came from the validation info of the
533                    //    same module.
534                    // 3. The element address is valid because it comes from a
535                    //    module instance that is part of the current store itself.
536                    unsafe {
537                        elem_drop(
538                            &self.modules,
539                            &mut self.inner.elements,
540                            module_addr,
541                            element_idx,
542                        );
543                    }
544                }
545                ElemMode::Passive => (),
546            }
547        }
548
549        // instantiation: step 16
550        // TODO have to stray away from the spec a bit since our codebase does not lend itself well to freely executing instructions by themselves
551        for (i, DataSegment { init, mode }) in validation_info.data.iter_enumerated() {
552            match mode {
553                DataMode::Active(DataModeActive {
554                    memory_idx,
555                    offset: dinstr_i,
556                }) => {
557                    let n = init.len() as u32;
558
559                    // TODO (for now, we are doing hopefully what is equivalent to it)
560                    // execute:
561                    //   dinstr_i
562                    //   i32.const 0
563                    //   i32.const n
564                    //   memory.init i
565                    //   data.drop i
566                    // SAFETY: The module with this module address was just
567                    // inserted into this `AddrVec`. Furthermore, the span comes
568                    // from a data segment contained in the same validation info
569                    // the Wasm bytecode is from. Therefore, the constant
570                    // expression in that span must be validated already.
571                    let const_expr_result = unsafe {
572                        run_const_span(validation_info.wasm, dinstr_i, module_addr, self)?
573                    };
574                    let d: u32 = const_expr_result
575                        .unwrap_validated() // there is a return value
576                        .try_into()
577                        .unwrap_validated(); // return value has the correct type
578
579                    let s = 0;
580                    // SAFETY: All requirements are met:
581                    // 1. The module address was just retrieved by inserting a
582                    //    new module instance into the current store. Therefore, it
583                    //    is valid in the current store.
584                    // 2. The memory index is valid for the current module
585                    //    instance because it came from the validation info of the
586                    //    same module.
587                    // 3./5. The memory and data addresses are valid because
588                    //       they come from a module instance that is part of the
589                    //       current store itself.
590                    // 4. The data index is valid for the current module
591                    //    instance because it came from the validation info of the
592                    //    same module.
593                    unsafe {
594                        memory_init(
595                            &self.modules,
596                            &mut self.inner.memories,
597                            &self.inner.data,
598                            module_addr,
599                            i,
600                            *memory_idx,
601                            n,
602                            s,
603                            d,
604                        )
605                    }?;
606
607                    // SAFETY: All requirements are met:
608                    // 1. The module address was just retrieved by inserting a
609                    //    new module instance into the current store. Therefore, it
610                    //    is valid in the current store.
611                    // 2. The data index is valid for the current module
612                    //    instance because it came from the validation info of the
613                    //    same module.
614                    // 3. The data address is valid because it comes from a
615                    //    module instance that is part of the current store itself.
616                    unsafe { data_drop(&self.modules, &mut self.inner.data, module_addr, i) };
617                }
618                DataMode::Passive => (),
619            }
620        }
621
622        // instantiation: step 17
623        let maybe_remaining_fuel = if let Some(func_idx) = validation_info.start {
624            // TODO (for now, we are doing hopefully what is equivalent to it)
625            // execute
626            //   call func_ifx
627
628            // SAFETY: The module with this module address was just inserted
629            // into this `AddrVec`
630            let module = unsafe { self.modules.get(module_addr) };
631            // SAFETY: The function index comes from the passed `Module`
632            // and the `IdxVec<FuncIdx, FuncAddr>` comes from the module
633            // instance that originated from that same `Module`.
634            // Therefore, this is sound.
635            let func_addr = unsafe { module.func_addrs.get(func_idx) };
636
637            // SAFETY: The function address just came from the current module
638            // and is therefore valid in the current store. Furthermore, there
639            // are no function arguments and thus also no other address types
640            // can be invalid.
641            let create_resumable_outcome =
642                unsafe { self.create_resumable(*func_addr, Vec::new(), maybe_fuel) }?;
643
644            let Resumable::Wasm(resumable) = create_resumable_outcome else {
645                todo!("calling host functions from the start function");
646            };
647
648            // SAFETY: The resumable just came from the current store.
649            // Therefore, it is always valid in the current store.
650            match unsafe { self.resume_wasm(resumable) }? {
651                RunState::Finished {
652                    maybe_remaining_fuel,
653                    ..
654                } => maybe_remaining_fuel,
655                RunState::Resumable { .. } => return Err(RuntimeError::OutOfFuel),
656                RunState::HostCalled { .. } => {
657                    return Err(RuntimeError::UnsupportedHostCallDuringInstantiation);
658                }
659            }
660        } else {
661            maybe_fuel
662        };
663
664        Ok(InstantiationOutcome {
665            module_addr,
666            maybe_remaining_fuel,
667        })
668    }
669
670    /// Gets an export of a specific module instance by its name
671    ///
672    /// See: WebAssembly Specification 2.0 - 7.1.6 - instance_export
673    ///
674    /// # Safety
675    ///
676    /// The caller has to guarantee that the [`ModuleAddr`] came from the
677    /// current [`Store`] object.
678    pub unsafe fn instance_export(
679        &self,
680        module_addr: ModuleAddr,
681        name: &str,
682    ) -> Result<ExternVal, RuntimeError> {
683        // Fetch the module instance because we store them in the [`Store`]
684        // SAFETY: The caller ensures the module address to be valid in the
685        // current store.
686        let module_inst = unsafe { self.modules.get(module_addr) };
687
688        // 1. Assert: due to validity of the module instance `moduleinst`, all its export names are different
689
690        // 2. If there exists an `exportinst_i` in `moduleinst.exports` such that name `exportinst_i.name` equals `name`, then:
691        //   a. Return the external value `exportinst_i.value`.
692        // 3. Else return `error`.
693        module_inst
694            .exports
695            .get(name)
696            .copied()
697            .ok_or(RuntimeError::UnknownExport)
698    }
699
700    /// Allocates a new function with some host code.
701    ///
702    /// This type of function is also called a host function.
703    ///
704    /// # Panics & Unexpected Behavior
705    /// The specification states that:
706    ///
707    /// > This operation must make sure that the provided host function satisfies the pre-
708    /// > and post-conditions required for a function instance with type `functype`.
709    ///
710    /// Therefore, all "invalid" host functions (e.g. those which return incorrect return values)
711    /// can cause the interpreter to panic or behave unexpectedly.
712    ///
713    /// See: <https://webassembly.github.io/spec/core/exec/modules.html#host-functions>
714    /// See: WebAssembly Specification 2.0 - 7.1.7 - func_alloc
715    pub fn func_alloc(&mut self, func_type: FuncType, hostcode: Hostcode) -> FuncAddr {
716        // 1. Pre-condition: `functype` is valid.
717
718        // 2. Let `funcaddr` be the result of allocating a host function in `store` with
719        //    function type `functype` and host function code `hostfunc`.
720        // 3. Return the new store paired with `funcaddr`.
721        //
722        // Note: Returning the new store is a noop for us because we mutate the store instead.
723        self.inner
724            .functions
725            .insert(FuncInst::HostFunc(HostFuncInst {
726                function_type: func_type,
727                hostcode,
728            }))
729    }
730
731    /// Gets the type of a function by its addr.
732    ///
733    /// See: WebAssembly Specification 2.0 - 7.1.7 - func_type
734    ///
735    /// # Safety
736    ///
737    /// The caller has to guarantee that the [`FuncAddr`] came from the current
738    /// [`Store`] object.
739    pub unsafe fn func_type(&self, func_addr: FuncAddr) -> FuncType {
740        // 1. Return `S.funcs[a].type`.
741        // SAFETY: The caller ensures this function address to be valid for the
742        // current store.
743        let function = unsafe { self.inner.functions.get(func_addr) };
744        function.ty().clone()
745
746        // 2. Post-condition: the returned function type is valid.
747    }
748
749    /// See: WebAssembly Specification 2.0 - 7.1.7 - func_invoke
750    ///
751    /// # Safety
752    ///
753    /// The caller has to guarantee that the given [`FuncAddr`] and any [`FuncAddr`] or
754    /// [`ExternAddr`](crate::ExternAddr) values contained in the parameter values came from the
755    /// current [`Store`] object.
756    pub unsafe fn invoke(
757        &mut self,
758        func_addr: FuncAddr,
759        params: Vec<Value>,
760        maybe_fuel: Option<u64>,
761    ) -> Result<RunState, RuntimeError> {
762        // SAFETY: The caller ensures that the function address and any function
763        // addresses or extern addresses contained in the parameter values are
764        // valid in the current store.
765        let resumable = unsafe { self.create_resumable(func_addr, params, maybe_fuel)? };
766        // SAFETY: The resumable just came from the current store. Therefore, it
767        // must be valid in the current store.
768        unsafe { self.resume(resumable) }
769    }
770
771    /// Allocates a new table with some table type and an initialization value `ref` and returns its table address.
772    ///
773    /// See: WebAssembly Specification 2.0 - 7.1.8 - table_alloc
774    ///
775    /// # Safety
776    ///
777    /// The caller has to guarantee that any [`FuncAddr`] or [`ExternAddr`](crate::ExternAddr)
778    /// values contained in `r#ref` came from the current [`Store`] object.
779    pub unsafe fn table_alloc(
780        &mut self,
781        table_type: TableType,
782        r#ref: Ref,
783    ) -> Result<TableAddr, RuntimeError> {
784        // Check pre-condition: ref has correct type
785        if table_type.et != r#ref.ty() {
786            return Err(RuntimeError::TableTypeMismatch);
787        }
788
789        // 1. Pre-condition: `tabletype` is valid
790
791        // 2. Let `tableaddr` be the result of allocating a table in `store` with table type `tabletype`
792        //    and initialization value `ref`.
793        // SAFETY: The caller ensures that the reference is valid in the current
794        // store.
795        let table_addr = unsafe { self.alloc_table(table_type, r#ref) };
796
797        // 3. Return the new store paired with `tableaddr`.
798        //
799        // Note: Returning the new store is a noop for us because we mutate the store instead.
800        Ok(table_addr)
801    }
802
803    /// Gets the type of some table by its addr.
804    ///
805    /// See: WebAssembly Specification 2.0 - 7.1.8 - table_type
806    ///
807    /// # Safety
808    ///
809    /// The caller has to guarantee that the given [`TableAddr`] came from
810    /// the current [`Store`] object.
811    pub unsafe fn table_type(&self, table_addr: TableAddr) -> TableType {
812        // 1. Return `S.tables[a].type`.
813        // SAFETY: The caller ensures that the given table address is valid in
814        // the current store.
815        let table = unsafe { self.inner.tables.get(table_addr) };
816        table.ty
817
818        // 2. Post-condition: the returned table type is valid.
819    }
820
821    /// Reads a single reference from a table by its table address and an index into the table.
822    ///
823    /// See: WebAssembly Specification 2.0 - 7.1.8 - table_read
824    ///
825    /// # Safety
826    ///
827    /// The caller has to guarantee that the given [`TableAddr`] must come from
828    /// the current [`Store`] object.
829    pub unsafe fn table_read(&self, table_addr: TableAddr, i: u32) -> Result<Ref, RuntimeError> {
830        // Convert `i` to usize for indexing
831        let i = i.into_usize();
832
833        // 1. Let `ti` be the table instance `store.tables[tableaddr]`
834        // SAFETY: The caller ensures that the given table address is valid in
835        // the current store.
836        let ti = unsafe { self.inner.tables.get(table_addr) };
837
838        // 2. If `i` is larger than or equal to the length of `ti.elem`, then return `error`.
839        // 3. Else, return the reference value `ti.elem[i]`.
840        ti.elem
841            .get(i)
842            .copied()
843            .ok_or(RuntimeError::TableAccessOutOfBounds)
844    }
845
846    /// Writes a single reference into a table by its table address and an index into the table.
847    ///
848    /// See: WebAssembly Specification 2.0 - 7.1.8 - table_write
849    ///
850    /// # Safety
851    ///
852    /// The caller has to guarantee that the given [`TableAddr`] and any [`FuncAddr`] or
853    /// [`ExternAddr`](crate::ExternAddr) values contained in the [`Ref`] must come from the current
854    /// [`Store`] object.
855    pub unsafe fn table_write(
856        &mut self,
857        table_addr: TableAddr,
858        i: u32,
859        r#ref: Ref,
860    ) -> Result<(), RuntimeError> {
861        // Convert `i` to usize for indexing
862        let i = i.into_usize();
863
864        // 1. Let `ti` be the table instance `store.tables[tableaddr]`.
865        // SAFETY: The caller ensures that the given table address is valid in
866        // the current store.
867        let ti = unsafe { self.inner.tables.get_mut(table_addr) };
868
869        // Check pre-condition: ref has correct type
870        if ti.ty.et != r#ref.ty() {
871            return Err(RuntimeError::TableTypeMismatch);
872        }
873
874        // 2. If `i` is larger than or equal to the length of `ti.elem`, then return `error`.
875        // 3. Replace `ti.elem[i]` with the reference value `ref`
876        *ti.elem
877            .get_mut(i)
878            .ok_or(RuntimeError::TableAccessOutOfBounds)? = r#ref;
879
880        // 4. Return the updated store.
881        //
882        // Note: Returning the new store is a noop for us because we mutate the store instead.
883        Ok(())
884    }
885
886    /// Gets the current size of a table by its table address.
887    ///
888    /// See: WebAssembly Specification 2.0 - 7.1.8 - table_size
889    ///
890    /// # Safety
891    ///
892    /// The caller has to guarantee that the given [`TableAddr`] must come from
893    /// the current [`Store`] object.
894    pub unsafe fn table_size(&self, table_addr: TableAddr) -> u32 {
895        // 1. Return the length of `store.tables[tableaddr].elem`.
896        // SAFETY: The caller ensures that the table address is valid in the
897        // current store.
898        let table = unsafe { self.inner.tables.get(table_addr) };
899        let len = table.elem.len();
900
901        // In addition we have to convert the length back to a `u32`
902        u32::try_from(len).expect(
903            "the maximum table length to be u32::MAX because thats what the specification allows for indexing",
904        )
905    }
906
907    /// Grows a table referenced by its table address by `n` elements.
908    ///
909    /// See: WebAssembly Specification 2.0 - 7.1.8 - table_grow
910    ///
911    /// # Safety
912    ///
913    /// The caller has to guarantee that the given [`TableAddr`] and any [`FuncAddr`] or
914    /// [`ExternAddr`](crate::ExternAddr) values contained in the [`Ref`] must come from the current
915    /// [`Store`] object.
916    pub unsafe fn table_grow(
917        &mut self,
918        table_addr: TableAddr,
919        n: u32,
920        r#ref: Ref,
921    ) -> Result<(), RuntimeError> {
922        // 1. Try growing the table instance `store.tables[tableaddr] by `n` elements with initialization value `ref`:
923        //   a. If it succeeds, return the updated store.
924        //   b. Else, return `error`.
925        //
926        // Note: Returning the new store is a noop for us because we mutate the store instead.
927        // SAFETY: The caller ensures that the given table address is valid in
928        // the current store.
929        let table = unsafe { self.inner.tables.get_mut(table_addr) };
930        table.grow(n, r#ref)
931    }
932
933    /// Allocates a new linear memory and returns its memory address.
934    ///
935    /// See: WebAssembly Specification 2.0 - 7.1.9 - mem_alloc
936    pub fn mem_alloc(&mut self, mem_type: MemType) -> MemAddr {
937        // 1. Pre-condition: `memtype` is valid.
938
939        // 2. Let `memaddr` be the result of allocating a memory in `store` with memory type `memtype`.
940        // 3. Return the new store paired with `memaddr`.
941        //
942        // Note: Returning the new store is a noop for us because we mutate the store instead.
943        self.alloc_mem(mem_type)
944    }
945
946    /// Gets the memory type of some memory by its memory address
947    ///
948    /// See: WebAssemblySpecification 2.0 - 7.1.9 - mem_type
949    ///
950    /// # Safety
951    ///
952    /// The caller has to guarantee that the given [`MemAddr`] came from the
953    /// current [`Store`] object.
954    pub unsafe fn mem_type(&self, mem_addr: MemAddr) -> MemType {
955        // 1. Return `S.mems[a].type`.
956        // SAFETY: The caller ensures that the given memory address is valid in
957        // the current store.
958        let memory = unsafe { self.inner.memories.get(mem_addr) };
959        memory.ty
960
961        // 2. Post-condition: the returned memory type is valid.
962    }
963
964    /// Reads a byte from some memory by its memory address and an index into the memory
965    ///
966    /// See: WebAssemblySpecification 2.0 - 7.1.9 - mem_read
967    ///
968    /// # Safety
969    ///
970    /// The caller has to guarantee that the given [`MemAddr`] came from the
971    /// current [`Store`] object.
972    pub unsafe fn mem_read(&self, mem_addr: MemAddr, i: u32) -> Result<u8, RuntimeError> {
973        // Convert the index type
974        let i = i.into_usize();
975
976        // 1. Let `mi` be the memory instance `store.mems[memaddr]`.
977        // SAFETY: The caller ensures that the given memory address is valid in
978        // the current store.
979        let mi = unsafe { self.inner.memories.get(mem_addr) };
980
981        // 2. If `i` is larger than or equal to the length of `mi.data`, then return `error`.
982        // 3. Else, return the byte `mi.data[i]`.
983        mi.mem.load(i)
984    }
985
986    /// Writes a byte into some memory by its memory address and an index into the memory
987    ///
988    /// See: WebAssemblySpecification 2.0 - 7.1.9 - mem_write
989    ///
990    /// # Safety
991    ///
992    /// The caller has to guarantee that the given [`MemAddr`] came from the
993    /// current [`Store`] object.
994    pub unsafe fn mem_write(
995        &self,
996        mem_addr: MemAddr,
997        i: u32,
998        byte: u8,
999    ) -> Result<(), RuntimeError> {
1000        // Convert the index type
1001        let i = i.into_usize();
1002
1003        // 1. Let `mi` be the memory instance `store.mems[memaddr]`.
1004        // SAFETY: The caller ensures that the given memory address is valid in
1005        // the current store.
1006        let mi = unsafe { self.inner.memories.get(mem_addr) };
1007
1008        mi.mem.store(i, byte)
1009    }
1010
1011    /// Gets the size of some memory by its memory address in pages.
1012    ///
1013    /// See: WebAssemblySpecification 2.0 - 7.1.9 - mem_size
1014    ///
1015    /// # Safety
1016    ///
1017    /// The caller has to guarantee that the given [`MemAddr`] came from the
1018    /// current [`Store`] object.
1019    pub unsafe fn mem_size(&self, mem_addr: MemAddr) -> u32 {
1020        // 1. Return the length of `store.mems[memaddr].data` divided by the page size.
1021        // SAFETY: The caller ensures that the given memory address is valid in
1022        // the current store.
1023        let memory = unsafe { self.inner.memories.get(mem_addr) };
1024        let length = memory.size();
1025
1026        // In addition we have to convert the length back to a `u32`
1027        length.try_into().expect(
1028            "the maximum memory length to be smaller than u32::MAX because thats what the specification allows for indexing into the memory. Also the memory size is measured in pages, not bytes.")
1029    }
1030
1031    /// Grows some memory by its memory address by `n` pages.
1032    ///
1033    /// See: WebAssemblySpecification 2.0 - 7.1.9 - mem_grow
1034    ///
1035    /// # Safety
1036    ///
1037    /// The caller has to guarantee that the given [`MemAddr`] came from the
1038    /// current [`Store`] object.
1039    pub unsafe fn mem_grow(&mut self, mem_addr: MemAddr, n: u32) -> Result<(), RuntimeError> {
1040        // 1. Try growing the memory instance `store.mems[memaddr]` by `n` pages:
1041        //   a. If it succeeds, then return the updated store.
1042        //   b. Else, return `error`.
1043        //
1044        // Note: Returning the new store is a noop for us because we mutate the store instead.
1045        // SAFETY: The caller ensures that the given memory address is valid in
1046        // the current store.
1047        let memory = unsafe { self.inner.memories.get_mut(mem_addr) };
1048        memory.grow(n)
1049    }
1050
1051    /// Allocates a new global and returns its global address.
1052    ///
1053    /// See: WebAssemblySpecification 2.0 - 7.1.10 - global_alloc
1054    ///
1055    /// # Safety
1056    ///
1057    /// The caller has to guarantee that any [`FuncAddr`] or [`ExternAddr`](crate::ExternAddr)
1058    /// values contained in the [`Value`] came from the current [`Store`] object.
1059    pub unsafe fn global_alloc(
1060        &mut self,
1061        global_type: GlobalType,
1062        val: Value,
1063    ) -> Result<GlobalAddr, RuntimeError> {
1064        // Check pre-condition: val has correct type
1065        if global_type.ty != val.to_ty() {
1066            return Err(RuntimeError::GlobalTypeMismatch);
1067        }
1068
1069        // 1. Pre-condition: `globaltype` is valid.
1070
1071        // 2. Let `globaladdr` be the result of allocating a global with global type `globaltype` and initialization value `val`.
1072        // SAFETY: The caller ensures that any address types contained in the
1073        // initial value are valid in the current store.
1074        let global_addr = unsafe { self.alloc_global(global_type, val) };
1075
1076        // 3. Return the new store paired with `globaladdr`.
1077        //
1078        // Note: Returning the new store is a noop for us because we mutate the store instead.
1079        Ok(global_addr)
1080    }
1081
1082    /// Returns the global type of some global instance by its addr.
1083    ///
1084    /// See: WebAssembly Specification 2.0 - 7.1.10 - global_type
1085    ///
1086    /// # Safety
1087    ///
1088    /// The caller has to guarantee that the given [`GlobalAddr`] came from the
1089    /// current [`Store`] object.
1090    pub unsafe fn global_type(&self, global_addr: GlobalAddr) -> GlobalType {
1091        // 1. Return `S.globals[a].type`.
1092        // SAFETY: The caller ensures that the given global address is valid in
1093        // the current store.
1094        let global = unsafe { self.inner.globals.get(global_addr) };
1095        global.ty
1096        // 2. Post-condition: the returned global type is valid
1097    }
1098
1099    /// Returns the current value of some global instance by its addr.
1100    ///
1101    /// See: WebAssembly Specification 2.0 - 7.1.10 - global_read
1102    ///
1103    /// # Safety
1104    ///
1105    /// The caller has to guarantee that the given [`GlobalAddr`] came from the
1106    /// current [`Store`] object.
1107    pub unsafe fn global_read(&self, global_addr: GlobalAddr) -> Value {
1108        // 1. Let `gi` be the global instance `store.globals[globaladdr].
1109        // SAFETY: The caller ensures that the given global address is valid in
1110        // the current store.
1111        let gi = unsafe { self.inner.globals.get(global_addr) };
1112
1113        // 2. Return the value `gi.value`.
1114        gi.value
1115    }
1116
1117    /// Sets a new value of some global instance by its addr.
1118    ///
1119    /// # Errors
1120    /// - [` RuntimeError::WriteOnImmutableGlobal`]
1121    /// - [` RuntimeError::GlobalTypeMismatch`]
1122    ///
1123    /// See: WebAssembly Specification 2.0 - 7.1.10 - global_write
1124    ///
1125    /// # Safety
1126    ///
1127    /// The caller has to guarantee that the given [`GlobalAddr`] and any [`FuncAddr`] or
1128    /// [`ExternAddr`](crate::ExternAddr) values contained in the [`Value`] came from the current
1129    /// [`Store`] object.
1130    pub unsafe fn global_write(
1131        &mut self,
1132        global_addr: GlobalAddr,
1133        val: Value,
1134    ) -> Result<(), RuntimeError> {
1135        // 1. Let `gi` be the global instance `store.globals[globaladdr]`.
1136        // SAFETY: The caller ensures that the given global address is valid in the current module.
1137        let gi = unsafe { self.inner.globals.get_mut(global_addr) };
1138
1139        // 2. Let `mut t` be the structure of the global type `gi.type`.
1140        let r#mut = gi.ty.is_mut;
1141        let t = gi.ty.ty;
1142
1143        // 3. If `mut` is not `var`, then return error.
1144        if !r#mut {
1145            return Err(RuntimeError::WriteOnImmutableGlobal);
1146        }
1147
1148        // Check invariant:
1149        //   It is an invariant of the semantics that the value has a type equal to the value type of `globaltype`.
1150        // See: WebAssembly Specification 2.0 - 4.2.9
1151        if t != val.to_ty() {
1152            return Err(RuntimeError::GlobalTypeMismatch);
1153        }
1154
1155        // 4. Replace `gi.value` with the value `val`.
1156        gi.value = val;
1157
1158        // 5. Return the updated store.
1159        // This is a noop for us, as our store `self` is mutable.
1160
1161        Ok(())
1162    }
1163
1164    /// roughly matches <https://webassembly.github.io/spec/core/exec/modules.html#functions> with the addition of sidetable pointer to the input signature
1165    ///
1166    /// # Safety
1167    ///
1168    /// The caller has to guarantee that
1169    /// - the given [`ModuleAddr`] came from the current [`Store`] object.
1170    /// - the given [`TypeIdx`] is valid in the module for the given [`ModuleAddr`].
1171    // TODO refactor the type of func
1172    unsafe fn alloc_func(
1173        &mut self,
1174        func: (TypeIdx, (Span, usize)),
1175        module_addr: ModuleAddr,
1176    ) -> FuncAddr {
1177        let (ty, (span, stp)) = func;
1178
1179        // TODO rewrite this huge chunk of parsing after generic way to re-parse(?) structs lands
1180        // SAFETY: The caller ensures that the given module address is valid in
1181        // the current store.
1182        let module = unsafe { self.modules.get(module_addr) };
1183        let mut wasm_reader = WasmDecoder::new(module.wasm_bytecode);
1184        wasm_reader.move_start_to(span).unwrap_validated();
1185
1186        let (locals, bytes_read) = wasm_reader
1187            .measure_num_read_bytes(decode_locals)
1188            .unwrap_validated();
1189
1190        let code_expr = wasm_reader
1191            .make_span(span.len() - bytes_read)
1192            .unwrap_validated();
1193
1194        // core of the method below
1195
1196        // validation guarantees func_ty_idx exists within module_inst.types
1197        // TODO fix clone
1198        // SAFETY: The caller guarantees that the given type index is valid for
1199        // this module.
1200        let function_type = unsafe { module.types.get(ty).clone() };
1201        let func_inst = FuncInst::WasmFunc(WasmFuncInst {
1202            function_type,
1203            _ty: ty,
1204            locals,
1205            code_expr,
1206            stp,
1207            module_addr,
1208        });
1209        self.inner.functions.insert(func_inst)
1210    }
1211
1212    /// <https://webassembly.github.io/spec/core/exec/modules.html#tables>
1213    ///
1214    /// # Safety
1215    ///
1216    /// The caller has to guarantee that any [`FuncAddr`] or [`ExternAddr`](crate::ExternAddr)
1217    /// values contained in the [`Ref`] came from the current [`Store`] object.
1218    unsafe fn alloc_table(&mut self, table_type: TableType, reff: Ref) -> TableAddr {
1219        let table_inst = TableInst {
1220            ty: table_type,
1221            elem: vec![reff; table_type.lim.min.into_usize()],
1222        };
1223
1224        self.inner.tables.insert(table_inst)
1225    }
1226
1227    /// <https://webassembly.github.io/spec/core/exec/modules.html#memories>
1228    fn alloc_mem(&mut self, mem_type: MemType) -> MemAddr {
1229        let mem_inst = MemInst {
1230            ty: mem_type,
1231            mem: LinearMemory::new_with_initial_pages(
1232                mem_type.limits.min.try_into().unwrap_validated(),
1233            ),
1234        };
1235
1236        self.inner.memories.insert(mem_inst)
1237    }
1238
1239    /// <https://webassembly.github.io/spec/core/exec/modules.html#globals>
1240    ///
1241    /// # Safety
1242    ///
1243    /// The caller has to guarantee that any [`FuncAddr`] or [`ExternAddr`](crate::ExternAddr)
1244    /// values contained in the [`Value`] came from the current [`Store`] object.
1245    unsafe fn alloc_global(&mut self, global_type: GlobalType, val: Value) -> GlobalAddr {
1246        let global_inst = GlobalInst {
1247            ty: global_type,
1248            value: val,
1249        };
1250
1251        self.inner.globals.insert(global_inst)
1252    }
1253
1254    /// <https://webassembly.github.io/spec/core/exec/modules.html#element-segments>
1255    ///
1256    /// # Safety
1257    ///
1258    /// The caller has to guarantee that any [`FuncAddr`] or [`ExternAddr`](crate::ExternAddr)
1259    /// values contained in
1260    /// the [`Ref`]s came from the current [`Store`] object.
1261    unsafe fn alloc_elem(&mut self, ref_type: RefType, refs: Vec<Ref>) -> ElemAddr {
1262        let elem_inst = ElemInst {
1263            _ty: ref_type,
1264            references: refs,
1265        };
1266
1267        self.inner.elements.insert(elem_inst)
1268    }
1269
1270    /// <https://webassembly.github.io/spec/core/exec/modules.html#data-segments>
1271    fn alloc_data(&mut self, bytes: &[u8]) -> DataAddr {
1272        let data_inst = DataInst {
1273            data: Vec::from(bytes),
1274        };
1275
1276        self.inner.data.insert(data_inst)
1277    }
1278
1279    /// Creates a new resumable, which when resumed for the first time invokes the function `function_ref` is associated
1280    /// to, with the arguments `params`. The newly created resumable initially stores `fuel` units of fuel. Returns a
1281    /// `[ResumableRef]` associated to the newly created resumable on success.
1282    ///
1283    /// # Safety
1284    ///
1285    /// The caller has to guarantee that the [`FuncAddr`] and any [`FuncAddr`] or
1286    /// [`ExternAddr`](crate::ExternAddr) values contained in the parameter values came from the
1287    /// current [`Store`] object.
1288    pub unsafe fn create_resumable(
1289        &self,
1290        func_addr: FuncAddr,
1291        params: Vec<Value>,
1292        maybe_fuel: Option<u64>,
1293    ) -> Result<Resumable, RuntimeError> {
1294        // SAFETY: The caller ensures that this function address is valid in the
1295        // current store.
1296        let func_inst = unsafe { self.inner.functions.get(func_addr) };
1297
1298        let func_ty = func_inst.ty();
1299
1300        // Verify that the given parameter types match the function parameter types
1301        if func_ty.params.valtypes.len() != params.len() {
1302            return Err(RuntimeError::FunctionInvocationSignatureMismatch);
1303        }
1304
1305        let type_mismatch = func_ty
1306            .params
1307            .valtypes
1308            .iter()
1309            .zip(&params)
1310            .any(|(func_val_ty, param_val)| func_val_ty != &param_val.to_ty());
1311
1312        if type_mismatch {
1313            return Err(RuntimeError::FunctionInvocationSignatureMismatch);
1314        };
1315
1316        let resumable = match func_inst {
1317            FuncInst::WasmFunc(wasm_func_inst) => {
1318                // Prepare a new stack with the locals for the entry function
1319                let stack = Stack::new::<T>(
1320                    params,
1321                    &wasm_func_inst.function_type,
1322                    &wasm_func_inst.locals,
1323                )?;
1324
1325                Resumable::Wasm(WasmResumable {
1326                    current_func_addr: func_addr,
1327                    stack,
1328                    pc: wasm_func_inst.code_expr.from,
1329                    stp: wasm_func_inst.stp,
1330                    maybe_fuel,
1331                })
1332            }
1333            FuncInst::HostFunc(host_func_inst) => Resumable::Host {
1334                host_call: HostCall {
1335                    params,
1336                    hostcode: host_func_inst.hostcode,
1337                },
1338                host_resumable: HostResumable {
1339                    host_func_addr: func_addr,
1340                    inner_resumable: None,
1341                    maybe_fuel: Some(maybe_fuel),
1342                },
1343            },
1344        };
1345
1346        Ok(resumable)
1347    }
1348
1349    /// Resumes execution of a [`Resumable`], regardless of its inner representation.
1350    ///
1351    /// Note: The [`Resumable`] may also be deconstructed by the user and its
1352    /// contents used with [`Store::resume_wasm`] or
1353    /// [`Store::finish_host_call`].
1354    ///
1355    /// # Safety
1356    ///
1357    /// The caller has to guarantee that the [`Resumable`] came from the current
1358    /// [`Store`] object.
1359    pub unsafe fn resume(&mut self, resumable: Resumable) -> Result<RunState, RuntimeError> {
1360        match resumable {
1361            // SAFETY: The caller ensures that this `WasmResumable` came from
1362            // the current store.
1363            Resumable::Wasm(wasm_resumable) => unsafe { self.resume_wasm(wasm_resumable) },
1364            Resumable::Host {
1365                host_call,
1366                host_resumable,
1367            } => Ok(RunState::HostCalled {
1368                host_call,
1369                resumable: host_resumable,
1370            }),
1371        }
1372    }
1373
1374    /// Resumes the given [`WasmResumable`]. Returns a [`RunState`] that may contain
1375    /// a new [`Resumable`] depending on whether execution ran out of fuel or
1376    /// finished normally.
1377    ///
1378    /// # Safety
1379    ///
1380    /// The caller has to guarantee that the [`Resumable`] came from the current
1381    /// [`Store`] object.
1382    pub unsafe fn resume_wasm(
1383        &mut self,
1384        mut resumable: WasmResumable,
1385    ) -> Result<RunState, RuntimeError> {
1386        // SAFETY: The caller guarantees that the resumable comes from the current store.
1387        let result = unsafe { instructions::run(&mut resumable, self) }?;
1388
1389        let run_state = match result {
1390            InterpreterLoopOutcome::ExecutionReturned => RunState::Finished {
1391                values: resumable.stack.into_values(),
1392                maybe_remaining_fuel: resumable.maybe_fuel,
1393            },
1394            InterpreterLoopOutcome::OutOfFuel { required_fuel } => RunState::Resumable {
1395                resumable,
1396                required_fuel: Some(required_fuel),
1397            },
1398            InterpreterLoopOutcome::HostCalled {
1399                func_addr,
1400                params,
1401                hostcode,
1402            } => RunState::HostCalled {
1403                host_call: HostCall { params, hostcode },
1404                resumable: HostResumable {
1405                    host_func_addr: func_addr,
1406                    inner_resumable: Some(resumable),
1407                    maybe_fuel: None,
1408                },
1409            },
1410        };
1411
1412        Ok(run_state)
1413    }
1414
1415    /// To be executed after executing a [`HostCall`].
1416    ///
1417    /// # Safety
1418    ///
1419    /// The caller has to guarantee that the [`HostResumable`] and all
1420    /// addresses in the return values came from the current [`Store`] object.
1421    pub unsafe fn finish_host_call(
1422        &mut self,
1423        host_resumable: HostResumable,
1424        host_call_return_values: Vec<Value>,
1425    ) -> Result<RunState, RuntimeError> {
1426        // Verify that the return parameters match the host function parameters
1427        // since we have no validation guarantees for host functions
1428
1429        // SAFETY: The caller ensures that the `HostResumable`, and thus also
1430        // the function address in it, is valid in the current store.
1431        let function = unsafe { self.inner.functions.get(host_resumable.host_func_addr) };
1432
1433        let FuncInst::HostFunc(host_func_inst) = function else {
1434            unreachable!("expected function to be a host function instance")
1435        };
1436
1437        let return_types = host_call_return_values
1438            .iter()
1439            .map(|v| v.to_ty())
1440            .collect::<Vec<_>>();
1441
1442        if host_func_inst.function_type.returns.valtypes != return_types {
1443            return Err(RuntimeError::HostFunctionSignatureMismatch);
1444        }
1445
1446        if let Some(mut wasm_resumable) = host_resumable.inner_resumable {
1447            for return_value in host_call_return_values {
1448                wasm_resumable.stack.push_value(return_value)?;
1449            }
1450
1451            Ok(RunState::Resumable {
1452                resumable: wasm_resumable,
1453                required_fuel: None,
1454            })
1455        } else {
1456            Ok(RunState::Finished {
1457                values: host_call_return_values,
1458                maybe_remaining_fuel: host_resumable
1459                    .maybe_fuel
1460                    .expect("this to be set if the inner WasmResumable is None"),
1461            })
1462        }
1463    }
1464
1465    /// Invokes a function without support for fuel or host functions.
1466    ///
1467    /// This function wraps [`Store::invoke`].
1468    ///
1469    /// # Safety
1470    ///
1471    /// The caller has to guarantee that the given [`FuncAddr`] and any [`FuncAddr`] or
1472    /// [`ExternAddr`](crate::ExternAddr) values contained in the parameter values came from the
1473    /// current [`Store`] object.
1474    pub unsafe fn invoke_simple(
1475        &mut self,
1476        function: FuncAddr,
1477        params: Vec<Value>,
1478    ) -> Result<Vec<Value>, RuntimeError> {
1479        // SAFETY: The caller ensures that the given function address and all
1480        // address types contained in the parameters are valid in the current
1481        // store.
1482        let run_state = unsafe { self.invoke(function, params, None) }?;
1483
1484        match run_state {
1485            RunState::Finished {
1486                values,
1487                maybe_remaining_fuel: _,
1488            } => Ok(values),
1489            RunState::Resumable { .. } => unreachable!("fuel is disabled"),
1490            RunState::HostCalled { .. } => Err(RuntimeError::UnexpectedHostCall),
1491        }
1492    }
1493
1494    /// Allows a given closure to temporarily access the entire memory as a
1495    /// `&mut [u8]`.
1496    ///
1497    /// # Safety
1498    ///
1499    /// The caller has to guarantee that the given [`MemAddr`] came from the
1500    /// current [`Store`] object.
1501    pub unsafe fn mem_access_mut_slice<R>(
1502        &self,
1503        memory: MemAddr,
1504        accessor: impl FnOnce(&mut [u8]) -> R,
1505    ) -> R {
1506        // SAFETY: The caller ensures that the given memory address is valid in
1507        // the current store.
1508        let memory = unsafe { self.inner.memories.get(memory) };
1509        memory.mem.access_mut_slice(accessor)
1510    }
1511
1512    /// Returns all exports of a module instance by its module address.
1513    ///
1514    /// To get a single import by its known name, use
1515    /// [`Store::instance_export`].
1516    ///
1517    /// # Safety
1518    ///
1519    /// The caller has to guarantee that the given [`ModuleAddr`] came from the
1520    /// current [`Store`] object.
1521    pub unsafe fn instance_exports(&self, module_addr: ModuleAddr) -> Vec<(String, ExternVal)> {
1522        // SAFETY: The caller ensures that the given module address is valid in
1523        // the current store.
1524        let module = unsafe { self.modules.get(module_addr) };
1525
1526        module
1527            .exports
1528            .iter()
1529            .map(|(name, externval)| (name.clone(), *externval))
1530            .collect()
1531    }
1532}
1533
1534/// Represents a successful, possibly fueled instantiation of a module.
1535pub struct InstantiationOutcome {
1536    /// contains the store address of the module that has successfully instantiated.
1537    pub module_addr: ModuleAddr,
1538    /// contains `Some(remaining_fuel)` if instantiation was fuel-metered and `None` otherwise.
1539    pub maybe_remaining_fuel: Option<u64>,
1540}
1541
1542pub type Hostcode = usize;