wasm/execution/
const_interpreter_loop.rs1use alloc::vec::Vec;
2
3use crate::{
4 addrs::ModuleAddr,
5 assert_validated::UnwrapValidatedExt,
6 config::Config,
7 core::{
8 indices::{FuncIdx, GlobalIdx},
9 reader::{
10 span::Span,
11 types::{FuncType, ResultType},
12 WasmReader,
13 },
14 },
15 unreachable_validated,
16 value::{self, Ref},
17 value_stack::Stack,
18 RefType, RuntimeError, Store, Value,
19};
20
21pub(crate) unsafe fn run_const<T: Config>(
35 wasm: &mut WasmReader,
36 stack: &mut Stack,
37 module: ModuleAddr,
38 store: &Store<T>,
39) -> Result<(), RuntimeError> {
40 use crate::core::reader::types::opcode::*;
41 loop {
42 let first_instr_byte = wasm.read_u8().unwrap_validated();
43
44 #[cfg(debug_assertions)]
45 crate::core::utils::print_beautiful_instruction_name_1_byte(first_instr_byte, wasm.pc);
46
47 #[cfg(not(debug_assertions))]
48 trace!("Read instruction byte {first_instr_byte:#04X?} ({first_instr_byte}) at wasm_binary[{}]", wasm.pc);
49
50 match first_instr_byte {
51 END => {
52 trace!("Constant instruction: END");
53 break;
54 }
55 GLOBAL_GET => {
56 let global_idx = unsafe { GlobalIdx::read_unchecked(wasm) };
59
60 let module_instance = unsafe { store.modules.get(module) };
63
64 let global_addr = *unsafe { module_instance.global_addrs.get(global_idx) };
67
68 let global = unsafe { store.globals.get(global_addr) };
71
72 trace!(
73 "Constant instruction: global.get [{global_idx}] -> [{:?}]",
74 global
75 );
76 stack.push_value::<T>(global.value)?;
77 }
78 I32_CONST => {
79 let constant = wasm.read_var_i32().unwrap_validated();
80 trace!("Constant instruction: i32.const [] -> [{constant}]");
81 stack.push_value::<T>(constant.into())?;
82 }
83 F32_CONST => {
84 let constant = value::F32::from_bits(wasm.read_f32().unwrap_validated());
85 trace!("Constanting instruction: f32.const [] -> [{constant}]");
86 stack.push_value::<T>(constant.into())?;
87 }
88 F64_CONST => {
89 let constant = value::F64::from_bits(wasm.read_f64().unwrap_validated());
90 trace!("Constanting instruction: f64.const [] -> [{constant}]");
91 stack.push_value::<T>(constant.into())?;
92 }
93 I64_CONST => {
94 let constant = wasm.read_var_i64().unwrap_validated();
95 trace!("Constant instruction: i64.const [] -> [{constant}]");
96 stack.push_value::<T>(constant.into())?;
97 }
98 REF_NULL => {
99 let reftype = RefType::read(wasm).unwrap_validated();
100
101 stack.push_value::<T>(Value::Ref(Ref::Null(reftype)))?;
102 trace!("Instruction: ref.null '{:?}' -> [{:?}]", reftype, reftype);
103 }
104 REF_FUNC => {
105 let func_idx = unsafe { FuncIdx::read_unchecked(wasm) };
108 let func_addr = unsafe { store.modules.get(module).func_addrs.get(func_idx) };
111 stack.push_value::<T>(Value::Ref(Ref::Func(*func_addr)))?;
112 }
113
114 FD_EXTENSIONS => {
115 use crate::core::reader::types::opcode::fd_extensions::*;
116
117 match wasm.read_var_u32().unwrap_validated() {
118 V128_CONST => {
119 let mut data = [0; 16];
120 for byte_ref in &mut data {
121 *byte_ref = wasm.read_u8().unwrap_validated();
122 }
123
124 stack.push_value::<T>(Value::V128(data))?;
125 }
126 0x00..=0x0B | 0x0D.. => unreachable_validated!(),
127 }
128 }
129
130 0x00..=0x0A
131 | 0x0C..=0x22
132 | 0x24..=0x40
133 | 0x45..=0xBF
134 | 0xC0..=0xCF
135 | 0xD1
136 | 0xD3..=0xFC
137 | 0xFE..=0xFF => {
138 unreachable_validated!();
139 }
140 }
141 }
142 Ok(())
143}
144
145pub(crate) unsafe fn run_const_span<T: Config>(
150 wasm: &[u8],
151 span: &Span,
152 module: ModuleAddr,
153 store: &Store<T>,
154) -> Result<Option<Value>, RuntimeError> {
155 let mut wasm = WasmReader::new(wasm);
156
157 wasm.move_start_to(*span).unwrap_validated();
158
159 let mut stack = Stack::new::<T>(
160 Vec::new(),
161 &FuncType {
162 params: ResultType {
163 valtypes: Vec::new(),
164 },
165 returns: ResultType {
166 valtypes: Vec::new(),
167 },
168 },
169 &[],
170 )?;
171 unsafe { run_const(&mut wasm, &mut stack, module, store)? };
173
174 Ok(stack.peek_value())
175}