1use super::state::ModuleTranslationState;
4use crate::lib::std::borrow::ToOwned;
5use crate::lib::std::string::ToString;
6use crate::lib::std::{boxed::Box, string::String, vec::Vec};
7use crate::translate_module;
8use crate::{WasmError, WasmResult};
9use near_vm_types::FunctionType;
10use near_vm_types::entity::PrimaryMap;
11use near_vm_types::{
12 CustomSectionIndex, DataIndex, DataInitializer, DataInitializerLocation, ElemIndex,
13 ExportIndex, FunctionIndex, GlobalIndex, GlobalInit, GlobalType, ImportIndex,
14 LocalFunctionIndex, MemoryIndex, MemoryType, ModuleInfo, OwnedTableInitializer, SignatureIndex,
15 TableIndex, TableType,
16};
17use std::convert::{TryFrom, TryInto};
18use std::sync::Arc;
19pub use wasmparser::FunctionBody as FunctionReader;
20
21#[derive(Hash)]
23pub struct FunctionBodyData<'a> {
24 pub data: &'a [u8],
26
27 pub module_offset: usize,
29}
30
31pub struct ModuleEnvironment<'data> {
36 pub module: ModuleInfo,
38
39 pub function_body_inputs: PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
41
42 pub data_initializers: Vec<DataInitializer<'data>>,
44
45 pub module_translation_state: Option<ModuleTranslationState>,
47}
48
49impl<'data> ModuleEnvironment<'data> {
50 pub fn new() -> Self {
52 Self {
53 module: ModuleInfo::new(),
54 function_body_inputs: PrimaryMap::new(),
55 data_initializers: Vec::new(),
56 module_translation_state: None,
57 }
58 }
59
60 #[tracing::instrument(target = "near_vm", level = "trace", skip_all)]
63 pub fn translate(mut self, data: &'data [u8]) -> WasmResult<Self> {
64 assert!(self.module_translation_state.is_none());
65 let module_translation_state = translate_module(data, &mut self)?;
66 self.module_translation_state = Some(module_translation_state);
67 Ok(self)
68 }
69
70 pub(crate) fn declare_export(&mut self, export: ExportIndex, name: &str) -> WasmResult<()> {
71 self.module.exports.insert(String::from(name), export);
72 Ok(())
73 }
74
75 pub(crate) fn declare_import(
76 &mut self,
77 import: ImportIndex,
78 module: &str,
79 field: &str,
80 ) -> WasmResult<()> {
81 self.module.imports.insert(
82 (
83 String::from(module),
84 String::from(field),
85 self.module.imports.len().try_into().unwrap(),
86 ),
87 import,
88 );
89 Ok(())
90 }
91
92 pub(crate) fn reserve_signatures(&mut self, num: u32) -> WasmResult<()> {
93 self.module.signatures.reserve_exact(usize::try_from(num).unwrap());
94 Ok(())
95 }
96
97 pub(crate) fn declare_signature(&mut self, sig: FunctionType) -> WasmResult<()> {
98 self.module.signatures.push(sig);
100 Ok(())
101 }
102
103 pub(crate) fn declare_func_import(
104 &mut self,
105 sig_index: SignatureIndex,
106 module: &str,
107 field: &str,
108 ) -> WasmResult<()> {
109 debug_assert_eq!(
110 self.module.functions.len(),
111 self.module.import_counts.functions as usize,
112 "Imported functions must be declared first"
113 );
114 self.declare_import(
115 ImportIndex::Function(FunctionIndex::from_u32(self.module.import_counts.functions)),
116 module,
117 field,
118 )?;
119 self.module.functions.push(sig_index);
120 self.module.import_counts.functions += 1;
121 Ok(())
122 }
123
124 pub(crate) fn declare_table_import(
125 &mut self,
126 table: TableType,
127 module: &str,
128 field: &str,
129 ) -> WasmResult<()> {
130 debug_assert_eq!(
131 self.module.tables.len(),
132 self.module.import_counts.tables as usize,
133 "Imported tables must be declared first"
134 );
135 self.declare_import(
136 ImportIndex::Table(TableIndex::from_u32(self.module.import_counts.tables)),
137 module,
138 field,
139 )?;
140 self.module.tables.push(table);
141 self.module.import_counts.tables += 1;
142 Ok(())
143 }
144
145 pub(crate) fn declare_memory_import(
146 &mut self,
147 memory: MemoryType,
148 module: &str,
149 field: &str,
150 ) -> WasmResult<()> {
151 debug_assert_eq!(
152 self.module.memories.len(),
153 self.module.import_counts.memories as usize,
154 "Imported memories must be declared first"
155 );
156 self.declare_import(
157 ImportIndex::Memory(MemoryIndex::from_u32(self.module.import_counts.memories)),
158 module,
159 field,
160 )?;
161 self.module.memories.push(memory);
162 self.module.import_counts.memories += 1;
163 Ok(())
164 }
165
166 pub(crate) fn declare_global_import(
167 &mut self,
168 global: GlobalType,
169 module: &str,
170 field: &str,
171 ) -> WasmResult<()> {
172 debug_assert_eq!(
173 self.module.globals.len(),
174 self.module.import_counts.globals as usize,
175 "Imported globals must be declared first"
176 );
177 self.declare_import(
178 ImportIndex::Global(GlobalIndex::from_u32(self.module.import_counts.globals)),
179 module,
180 field,
181 )?;
182 self.module.globals.push(global);
183 self.module.import_counts.globals += 1;
184 Ok(())
185 }
186
187 pub(crate) fn finish_imports(&self) -> WasmResult<()> {
188 Ok(())
189 }
190
191 pub(crate) fn reserve_func_types(&mut self, num: u32) -> WasmResult<()> {
192 self.module.functions.reserve_exact(usize::try_from(num).unwrap());
193 self.function_body_inputs.reserve_exact(usize::try_from(num).unwrap());
194 Ok(())
195 }
196
197 pub(crate) fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()> {
198 self.module.functions.push(sig_index);
199 Ok(())
200 }
201
202 pub(crate) fn reserve_tables(&mut self, num: u32) -> WasmResult<()> {
203 self.module.tables.reserve_exact(usize::try_from(num).unwrap());
204 Ok(())
205 }
206
207 pub(crate) fn declare_table(&mut self, table: TableType) -> WasmResult<()> {
208 self.module.tables.push(table);
209 Ok(())
210 }
211
212 pub(crate) fn reserve_memories(&mut self, num: u32) -> WasmResult<()> {
213 self.module.memories.reserve_exact(usize::try_from(num).unwrap());
214 Ok(())
215 }
216
217 pub(crate) fn declare_memory(&mut self, memory: MemoryType) -> WasmResult<()> {
218 if memory.shared {
219 return Err(WasmError::Unsupported("shared memories are not supported yet".to_owned()));
220 }
221 self.module.memories.push(memory);
222 Ok(())
223 }
224
225 pub(crate) fn reserve_globals(&mut self, num: u32) -> WasmResult<()> {
226 self.module.globals.reserve_exact(usize::try_from(num).unwrap());
227 Ok(())
228 }
229
230 pub(crate) fn declare_global(
231 &mut self,
232 global: GlobalType,
233 initializer: GlobalInit,
234 ) -> WasmResult<()> {
235 self.module.globals.push(global);
236 self.module.global_initializers.push(initializer);
237 Ok(())
238 }
239
240 pub(crate) fn reserve_exports(&mut self, num: u32) -> WasmResult<()> {
241 self.module.exports.reserve(usize::try_from(num).unwrap());
242 Ok(())
243 }
244
245 pub(crate) fn declare_func_export(
246 &mut self,
247 func_index: FunctionIndex,
248 name: &str,
249 ) -> WasmResult<()> {
250 self.declare_export(ExportIndex::Function(func_index), name)
251 }
252
253 pub(crate) fn declare_table_export(
254 &mut self,
255 table_index: TableIndex,
256 name: &str,
257 ) -> WasmResult<()> {
258 self.declare_export(ExportIndex::Table(table_index), name)
259 }
260
261 pub(crate) fn declare_memory_export(
262 &mut self,
263 memory_index: MemoryIndex,
264 name: &str,
265 ) -> WasmResult<()> {
266 self.declare_export(ExportIndex::Memory(memory_index), name)
267 }
268
269 pub(crate) fn declare_global_export(
270 &mut self,
271 global_index: GlobalIndex,
272 name: &str,
273 ) -> WasmResult<()> {
274 self.declare_export(ExportIndex::Global(global_index), name)
275 }
276
277 pub(crate) fn declare_start_function(&mut self, func_index: FunctionIndex) -> WasmResult<()> {
278 debug_assert!(self.module.start_function.is_none());
279 self.module.start_function = Some(func_index);
280 Ok(())
281 }
282
283 pub(crate) fn reserve_table_initializers(&mut self, num: u32) -> WasmResult<()> {
284 self.module.table_initializers.reserve_exact(usize::try_from(num).unwrap());
285 Ok(())
286 }
287
288 pub(crate) fn declare_table_initializers(
289 &mut self,
290 table_index: TableIndex,
291 base: Option<GlobalIndex>,
292 offset: usize,
293 elements: Box<[FunctionIndex]>,
294 ) -> WasmResult<()> {
295 self.module.table_initializers.push(OwnedTableInitializer {
296 table_index,
297 base,
298 offset,
299 elements,
300 });
301 Ok(())
302 }
303
304 pub(crate) fn declare_passive_element(
305 &mut self,
306 elem_index: ElemIndex,
307 segments: Box<[FunctionIndex]>,
308 ) -> WasmResult<()> {
309 let old = self.module.passive_elements.insert(elem_index, segments);
310 debug_assert!(
311 old.is_none(),
312 "should never get duplicate element indices, that would be a bug in `near_vm_compiler`'s \
313 translation"
314 );
315 Ok(())
316 }
317
318 pub(crate) fn define_function_body(
319 &mut self,
320 _module_translation_state: &ModuleTranslationState,
321 body_bytes: &'data [u8],
322 body_offset: usize,
323 ) -> WasmResult<()> {
324 self.function_body_inputs
325 .push(FunctionBodyData { data: body_bytes, module_offset: body_offset });
326 Ok(())
327 }
328
329 pub(crate) fn reserve_data_initializers(&mut self, num: u32) -> WasmResult<()> {
330 self.data_initializers.reserve_exact(usize::try_from(num).unwrap());
331 Ok(())
332 }
333
334 pub(crate) fn declare_data_initialization(
335 &mut self,
336 memory_index: MemoryIndex,
337 base: Option<GlobalIndex>,
338 offset: usize,
339 data: &'data [u8],
340 ) -> WasmResult<()> {
341 self.data_initializers.push(DataInitializer {
342 location: DataInitializerLocation { memory_index, base, offset },
343 data,
344 });
345 Ok(())
346 }
347
348 pub(crate) fn reserve_passive_data(&self, _count: u32) -> WasmResult<()> {
349 Ok(())
351 }
352
353 pub(crate) fn declare_passive_data(
354 &mut self,
355 data_index: DataIndex,
356 data: &'data [u8],
357 ) -> WasmResult<()> {
358 let old = self.module.passive_data.insert(data_index, Arc::from(data));
359 debug_assert!(
360 old.is_none(),
361 "a module can't have duplicate indices, this would be a near_vm-compiler bug"
362 );
363 Ok(())
364 }
365
366 pub(crate) fn declare_module_name(&mut self, name: &'data str) -> WasmResult<()> {
367 self.module.name = Some(name.to_string());
368 Ok(())
369 }
370
371 pub(crate) fn declare_function_name(
372 &mut self,
373 func_index: FunctionIndex,
374 name: &'data str,
375 ) -> WasmResult<()> {
376 self.module.function_names.insert(func_index, name.to_string());
377 Ok(())
378 }
379
380 pub(crate) fn reserve_imports(&self, _num: u32) -> WasmResult<()> {
383 Ok(())
384 }
385
386 pub(crate) fn finish_exports(&self) -> WasmResult<()> {
388 Ok(())
389 }
390
391 pub(crate) fn custom_section(&mut self, name: &'data str, data: &'data [u8]) -> WasmResult<()> {
393 let custom_section = CustomSectionIndex::from_u32(
394 self.module.custom_sections_data.len().try_into().unwrap(),
395 );
396 self.module.custom_sections.insert(String::from(name), custom_section);
397 self.module.custom_sections_data.push(Arc::from(data));
398 Ok(())
399 }
400}