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