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