wasm/execution/
const_interpreter_loop.rs1use crate::{
2 assert_validated::UnwrapValidatedExt,
3 core::{
4 indices::GlobalIdx,
5 reader::{span::Span, WasmReadable, WasmReader},
6 },
7 unreachable_validated,
8 value::{self, FuncAddr, Ref},
9 value_stack::Stack,
10 ModuleInst, RefType, RuntimeError, Store, Value,
11};
12
13pub(crate) fn run_const<T>(
25 wasm: &mut WasmReader,
26 stack: &mut Stack,
27 module: &ModuleInst,
28 store: &Store<T>,
29) -> Result<(), RuntimeError> {
30 use crate::core::reader::types::opcode::*;
31 loop {
32 let first_instr_byte = wasm.read_u8().unwrap_validated();
33
34 #[cfg(debug_assertions)]
35 crate::core::utils::print_beautiful_instruction_name_1_byte(first_instr_byte, wasm.pc);
36
37 #[cfg(not(debug_assertions))]
38 trace!("Read instruction byte {first_instr_byte:#04X?} ({first_instr_byte}) at wasm_binary[{}]", wasm.pc);
39
40 match first_instr_byte {
41 END => {
42 trace!("Constant instruction: END");
43 break;
44 }
45 GLOBAL_GET => {
46 let global_idx = wasm.read_var_u32().unwrap_validated() as GlobalIdx;
47
48 let global = &store.globals[module.global_addrs[global_idx]];
50
51 trace!(
52 "Constant instruction: global.get [{global_idx}] -> [{:?}]",
53 global
54 );
55 stack.push_value(global.value)?;
56 }
57 I32_CONST => {
58 let constant = wasm.read_var_i32().unwrap_validated();
59 trace!("Constant instruction: i32.const [] -> [{constant}]");
60 stack.push_value(constant.into())?;
61 }
62 F32_CONST => {
63 let constant = value::F32::from_bits(wasm.read_var_f32().unwrap_validated());
64 trace!("Constanting instruction: f32.const [] -> [{constant}]");
65 stack.push_value(constant.into())?;
66 }
67 F64_CONST => {
68 let constant = value::F64::from_bits(wasm.read_var_f64().unwrap_validated());
69 trace!("Constanting instruction: f64.const [] -> [{constant}]");
70 stack.push_value(constant.into())?;
71 }
72 I64_CONST => {
73 let constant = wasm.read_var_i64().unwrap_validated();
74 trace!("Constant instruction: i64.const [] -> [{constant}]");
75 stack.push_value(constant.into())?;
76 }
77 REF_NULL => {
78 let reftype = RefType::read(wasm).unwrap_validated();
79
80 stack.push_value(Value::Ref(Ref::Null(reftype)))?;
81 trace!("Instruction: ref.null '{:?}' -> [{:?}]", reftype, reftype);
82 }
83 REF_FUNC => {
84 let func_idx = wasm.read_var_u32().unwrap_validated() as usize;
86 let func_addr = *module.func_addrs.get(func_idx).unwrap_validated();
87 stack.push_value(Value::Ref(Ref::Func(FuncAddr(func_addr))))?;
88 }
89
90 FD_EXTENSIONS => {
91 use crate::core::reader::types::opcode::fd_extensions::*;
92
93 match wasm.read_var_u32().unwrap_validated() {
94 V128_CONST => {
95 let mut data = [0; 16];
96 for byte_ref in &mut data {
97 *byte_ref = wasm.read_u8().unwrap_validated();
98 }
99
100 stack.push_value(Value::V128(data))?;
101 }
102 0x00..=0x0B | 0x0D.. => unreachable_validated!(),
103 }
104 }
105
106 0x00..=0x0A
107 | 0x0C..=0x22
108 | 0x24..=0x40
109 | 0x45..=0xBF
110 | 0xC0..=0xCF
111 | 0xD1
112 | 0xD3..=0xFC
113 | 0xFE..=0xFF => {
114 unreachable_validated!();
115 }
116 }
117 }
118 Ok(())
119}
120
121pub(crate) fn run_const_span<T>(
122 wasm: &[u8],
123 span: &Span,
124 module: &ModuleInst,
125 store: &Store<T>,
126) -> Result<Option<Value>, RuntimeError> {
127 let mut wasm = WasmReader::new(wasm);
128
129 wasm.move_start_to(*span).unwrap_validated();
130
131 let mut stack = Stack::new();
132 run_const(&mut wasm, &mut stack, module, store)?;
133
134 Ok(stack.peek_value())
135}