wasm/execution/
const_interpreter_loop.rs1use crate::{
2 assert_validated::UnwrapValidatedExt,
3 core::{
4 indices::GlobalIdx,
5 reader::{span::Span, WasmReadable, WasmReader},
6 },
7 value::{self, FuncAddr, Ref},
8 value_stack::Stack,
9 ModuleInst, RefType, RuntimeError, Store, Value,
10};
11
12pub(crate) fn run_const(
24 wasm: &mut WasmReader,
25 stack: &mut Stack,
26 module: &ModuleInst,
27 store: &Store,
28) -> Result<(), RuntimeError> {
29 use crate::core::reader::types::opcode::*;
30 loop {
31 let first_instr_byte = wasm.read_u8().unwrap_validated();
32
33 #[cfg(debug_assertions)]
34 crate::core::utils::print_beautiful_instruction_name_1_byte(first_instr_byte, wasm.pc);
35
36 #[cfg(not(debug_assertions))]
37 trace!("Read instruction byte {first_instr_byte:#04X?} ({first_instr_byte}) at wasm_binary[{}]", wasm.pc);
38
39 match first_instr_byte {
40 END => {
41 trace!("Constant instruction: END");
42 break;
43 }
44 GLOBAL_GET => {
45 let global_idx = wasm.read_var_u32().unwrap_validated() as GlobalIdx;
46
47 let global = &store.globals[module.global_addrs[global_idx]];
49
50 trace!(
51 "Constant instruction: global.get [{global_idx}] -> [{:?}]",
52 global
53 );
54 stack.push_value(global.value)?;
55 }
56 I32_CONST => {
57 let constant = wasm.read_var_i32().unwrap_validated();
58 trace!("Constant instruction: i32.const [] -> [{constant}]");
59 stack.push_value(constant.into())?;
60 }
61 F32_CONST => {
62 let constant = value::F32::from_bits(wasm.read_var_f32().unwrap_validated());
63 trace!("Constanting instruction: f32.const [] -> [{constant}]");
64 stack.push_value(constant.into())?;
65 }
66 F64_CONST => {
67 let constant = value::F64::from_bits(wasm.read_var_f64().unwrap_validated());
68 trace!("Constanting instruction: f64.const [] -> [{constant}]");
69 stack.push_value(constant.into())?;
70 }
71 I64_CONST => {
72 let constant = wasm.read_var_i64().unwrap_validated();
73 trace!("Constant instruction: i64.const [] -> [{constant}]");
74 stack.push_value(constant.into())?;
75 }
76 REF_NULL => {
77 let reftype = RefType::read_unvalidated(wasm);
78
79 stack.push_value(Value::Ref(reftype.to_null_ref()))?;
80 trace!("Instruction: ref.null '{:?}' -> [{:?}]", reftype, reftype);
81 }
82 REF_FUNC => {
83 let func_idx = wasm.read_var_u32().unwrap_validated() as usize;
85 stack.push_value(Value::Ref(Ref::Func(FuncAddr::new(Some(
87 module.func_addrs[func_idx],
88 )))))?;
89 }
90 other => {
91 unreachable!("Unknown constant instruction {other:#x}, validation allowed an unimplemented instruction.");
92 }
93 }
94 }
95 Ok(())
96}
97
98pub(crate) fn run_const_span(
99 wasm: &[u8],
100 span: &Span,
101 module: &ModuleInst,
102 store: &Store,
103) -> Result<Option<Value>, RuntimeError> {
104 let mut wasm = WasmReader::new(wasm);
105
106 wasm.move_start_to(*span).unwrap_validated();
107
108 let mut stack = Stack::new();
109 run_const(&mut wasm, &mut stack, module, store)?;
110
111 Ok(stack.peek_unknown_value())
112}