wasm/execution/interpreter_loop/
reference.rs

1use core::ops::ControlFlow;
2
3use crate::{
4    assert_validated::UnwrapValidatedExt,
5    core::{indices::FuncIdx, reader::types::opcode},
6    execution::interpreter_loop::{define_instruction_fn, Args},
7    value::Ref,
8    RefType, Value,
9};
10
11define_instruction_fn! {
12    ref_null,
13    fuel_check = flat(opcode::REF_NULL),
14    |Args {
15         wasm, resumable, ..
16     }| {
17        let reftype = RefType::read(wasm).unwrap_validated();
18
19        resumable.stack.push_value(Value::Ref(Ref::Null(reftype)))?;
20        trace!("Instruction: ref.null '{:?}' -> [{:?}]", reftype, reftype);
21        Ok(ControlFlow::Continue(()))
22    }
23}
24
25define_instruction_fn! {
26    ref_is_null,
27    fuel_check = flat(opcode::REF_IS_NULL),
28    |Args { resumable, .. }| {
29        let rref: Ref = resumable.stack.pop_value().try_into().unwrap_validated();
30        let is_null = matches!(rref, Ref::Null(_));
31
32        let res = if is_null { 1 } else { 0 };
33        trace!("Instruction: ref.is_null [{}] -> [{}]", rref, res);
34        resumable.stack.push_value(Value::I32(res))?;
35        Ok(ControlFlow::Continue(()))
36    }
37}
38
39// https://webassembly.github.io/spec/core/exec/instructions.html#xref-syntax-instructions-syntax-instr-ref-mathsf-ref-func-x
40define_instruction_fn! {
41    ref_func,
42    fuel_check = flat(opcode::REF_FUNC),
43    |Args {
44         wasm,
45         resumable,
46         modules,
47         current_module,
48         ..
49     }| {
50        // SAFETY: Validation guarantees a valid function index to be
51        // next.
52        let func_idx = unsafe { FuncIdx::read_unchecked(wasm) };
53
54        // SAFETY: The current module address must come from the current
55        // store, because it is the only parameter to this function that
56        // can contain module addresses. All stores guarantee all
57        // addresses in them to be valid within themselves.
58        let current_module = unsafe { modules.get(*current_module) };
59        // SAFETY: Validation guarantees the function index to be valid
60        // in the current module.
61        let func_addr = unsafe { current_module.func_addrs.get(func_idx) };
62        resumable
63            .stack
64            .push_value(Value::Ref(Ref::Func(*func_addr)))?;
65        Ok(ControlFlow::Continue(()))
66    }
67}