1use super::environ::ModuleEnvironment;
15use super::error::from_binaryreadererror_wasmerror;
16use super::state::ModuleTranslationState;
17use crate::wasm_unsupported;
18use std::boxed::Box;
19use std::vec::Vec;
20use wasmer_types::entity::packed_option::ReservedValue;
21use wasmer_types::entity::EntityRef;
22use wasmer_types::{
23 DataIndex, ElemIndex, FunctionIndex, FunctionType, GlobalIndex, GlobalInit, GlobalType,
24 MemoryIndex, MemoryType, Pages, SignatureIndex, TableIndex, TableType, Type, V128,
25};
26use wasmer_types::{WasmError, WasmResult};
27use wasmparser::{
28 self, Data, DataKind, DataSectionReader, Element, ElementItems, ElementKind,
29 ElementSectionReader, Export, ExportSectionReader, ExternalKind, FunctionSectionReader,
30 GlobalSectionReader, GlobalType as WPGlobalType, ImportSectionReader, MemorySectionReader,
31 MemoryType as WPMemoryType, NameSectionReader, Operator, TableSectionReader, TypeRef,
32 TypeSectionReader,
33};
34
35pub fn wptype_to_type(ty: wasmparser::ValType) -> WasmResult<Type> {
37 match ty {
38 wasmparser::ValType::I32 => Ok(Type::I32),
39 wasmparser::ValType::I64 => Ok(Type::I64),
40 wasmparser::ValType::F32 => Ok(Type::F32),
41 wasmparser::ValType::F64 => Ok(Type::F64),
42 wasmparser::ValType::V128 => Ok(Type::V128),
43 wasmparser::ValType::Ref(ty) => wpreftype_to_type(ty),
44 }
45}
46
47pub fn wpreftype_to_type(ty: wasmparser::RefType) -> WasmResult<Type> {
49 if ty.is_extern_ref() {
50 Ok(Type::ExternRef)
51 } else if ty.is_func_ref() {
52 Ok(Type::FuncRef)
53 } else {
54 Err(wasm_unsupported!("unsupported reference type: {:?}", ty))
55 }
56}
57
58pub fn wpheaptype_to_type(ty: wasmparser::HeapType) -> WasmResult<Type> {
60 match ty {
61 wasmparser::HeapType::Func => Ok(Type::FuncRef),
62 wasmparser::HeapType::Extern => Ok(Type::ExternRef),
63 other => Err(wasm_unsupported!("unsupported reference type: {other:?}")),
64 }
65}
66
67pub fn parse_type_section(
69 types: TypeSectionReader,
70 module_translation_state: &mut ModuleTranslationState,
71 environ: &mut ModuleEnvironment,
72) -> WasmResult<()> {
73 let count = types.count();
74 environ.reserve_signatures(count)?;
75
76 for res in types.into_iter_err_on_gc_types() {
77 let functype = res.map_err(from_binaryreadererror_wasmerror)?;
78
79 let params = functype.params();
80 let returns = functype.results();
81 let sig_params: Box<[Type]> = params
82 .iter()
83 .map(|ty| {
84 wptype_to_type(*ty)
85 .expect("only numeric types are supported in function signatures")
86 })
87 .collect();
88 let sig_returns: Box<[Type]> = returns
89 .iter()
90 .map(|ty| {
91 wptype_to_type(*ty)
92 .expect("only numeric types are supported in function signatures")
93 })
94 .collect();
95 let sig = FunctionType::new(sig_params, sig_returns);
96 environ.declare_signature(sig)?;
97 module_translation_state
98 .wasm_types
99 .push((params.to_vec().into(), returns.to_vec().into()));
100 }
101
102 Ok(())
103}
104
105pub fn parse_import_section<'data>(
107 imports: ImportSectionReader<'data>,
108 environ: &mut ModuleEnvironment<'data>,
109) -> WasmResult<()> {
110 environ.reserve_imports(imports.count())?;
111
112 for entry in imports {
113 let import = entry.map_err(from_binaryreadererror_wasmerror)?;
114 let module_name = import.module;
115 let field_name = import.name;
116
117 match import.ty {
118 TypeRef::Func(sig) => {
119 environ.declare_func_import(
120 SignatureIndex::from_u32(sig),
121 module_name,
122 field_name,
123 )?;
124 }
125 TypeRef::Tag(_) => {
126 unimplemented!("exception handling not implemented yet")
127 }
128 TypeRef::Memory(WPMemoryType {
129 shared,
130 memory64,
131 initial,
132 maximum,
133 }) => {
134 if memory64 {
135 unimplemented!("64bit memory not implemented yet");
136 }
137 environ.declare_memory_import(
138 MemoryType {
139 minimum: Pages(initial as u32),
140 maximum: maximum.map(|p| Pages(p as u32)),
141 shared,
142 },
143 module_name,
144 field_name,
145 )?;
146 }
147 TypeRef::Global(ref ty) => {
148 environ.declare_global_import(
149 GlobalType {
150 ty: wptype_to_type(ty.content_type)?,
151 mutability: ty.mutable.into(),
152 },
153 module_name,
154 field_name,
155 )?;
156 }
157 TypeRef::Table(ref tab) => {
158 environ.declare_table_import(
159 TableType {
160 ty: wpreftype_to_type(tab.element_type)?,
161 minimum: tab.initial,
162 maximum: tab.maximum,
163 },
164 module_name,
165 field_name,
166 )?;
167 }
168 }
169 }
170
171 environ.finish_imports()?;
172 Ok(())
173}
174
175pub fn parse_function_section(
177 functions: FunctionSectionReader,
178 environ: &mut ModuleEnvironment,
179) -> WasmResult<()> {
180 let num_functions = functions.count();
181 if num_functions == std::u32::MAX {
182 return Err(WasmError::ImplLimitExceeded);
184 }
185
186 environ.reserve_func_types(num_functions)?;
187
188 for entry in functions {
189 let sigindex = entry.map_err(from_binaryreadererror_wasmerror)?;
190 environ.declare_func_type(SignatureIndex::from_u32(sigindex))?;
191 }
192
193 Ok(())
194}
195
196pub fn parse_table_section(
198 tables: TableSectionReader,
199 environ: &mut ModuleEnvironment,
200) -> WasmResult<()> {
201 environ.reserve_tables(tables.count())?;
202
203 for entry in tables {
204 let table = entry.map_err(from_binaryreadererror_wasmerror)?;
205 environ.declare_table(TableType {
206 ty: wpreftype_to_type(table.ty.element_type).unwrap(),
207 minimum: table.ty.initial,
208 maximum: table.ty.maximum,
209 })?;
210 }
211
212 Ok(())
213}
214
215pub fn parse_memory_section(
217 memories: MemorySectionReader,
218 environ: &mut ModuleEnvironment,
219) -> WasmResult<()> {
220 environ.reserve_memories(memories.count())?;
221
222 for entry in memories {
223 let WPMemoryType {
224 shared,
225 memory64,
226 initial,
227 maximum,
228 } = entry.map_err(from_binaryreadererror_wasmerror)?;
229 if memory64 {
230 unimplemented!("64bit memory not implemented yet");
231 }
232 environ.declare_memory(MemoryType {
233 minimum: Pages(initial as u32),
234 maximum: maximum.map(|p| Pages(p as u32)),
235 shared,
236 })?;
237 }
238
239 Ok(())
240}
241
242pub fn parse_global_section(
244 globals: GlobalSectionReader,
245 environ: &mut ModuleEnvironment,
246) -> WasmResult<()> {
247 environ.reserve_globals(globals.count())?;
248
249 for entry in globals {
250 let wasmparser::Global {
251 ty: WPGlobalType {
252 content_type,
253 mutable,
254 },
255 init_expr,
256 } = entry.map_err(from_binaryreadererror_wasmerror)?;
257 let mut init_expr_reader = init_expr.get_binary_reader();
258 let initializer = match init_expr_reader
259 .read_operator()
260 .map_err(from_binaryreadererror_wasmerror)?
261 {
262 Operator::I32Const { value } => GlobalInit::I32Const(value),
263 Operator::I64Const { value } => GlobalInit::I64Const(value),
264 Operator::F32Const { value } => GlobalInit::F32Const(f32::from_bits(value.bits())),
265 Operator::F64Const { value } => GlobalInit::F64Const(f64::from_bits(value.bits())),
266 Operator::V128Const { value } => GlobalInit::V128Const(V128::from(*value.bytes())),
267 Operator::RefNull { hty: _ } => {
268 GlobalInit::RefNullConst
270 }
271 Operator::RefFunc { function_index } => {
272 GlobalInit::RefFunc(FunctionIndex::from_u32(function_index))
273 }
274 Operator::GlobalGet { global_index } => {
275 GlobalInit::GetGlobal(GlobalIndex::from_u32(global_index))
276 }
277 ref s => {
278 return Err(wasm_unsupported!(
279 "unsupported init expr in global section: {:?}",
280 s
281 ));
282 }
283 };
284 let global = GlobalType {
285 ty: wptype_to_type(content_type).unwrap(),
286 mutability: mutable.into(),
287 };
288 environ.declare_global(global, initializer)?;
289 }
290
291 Ok(())
292}
293
294pub fn parse_export_section<'data>(
296 exports: ExportSectionReader<'data>,
297 environ: &mut ModuleEnvironment<'data>,
298) -> WasmResult<()> {
299 environ.reserve_exports(exports.count())?;
300
301 for entry in exports {
302 let Export {
303 name: field,
304 ref kind,
305 index,
306 } = entry.map_err(from_binaryreadererror_wasmerror)?;
307
308 let index = index as usize;
312 match *kind {
313 ExternalKind::Func => environ.declare_func_export(FunctionIndex::new(index), field)?,
314 ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), field)?,
315 ExternalKind::Memory => {
316 environ.declare_memory_export(MemoryIndex::new(index), field)?
317 }
318 ExternalKind::Global => {
319 environ.declare_global_export(GlobalIndex::new(index), field)?
320 }
321 ExternalKind::Tag => {
322 unimplemented!("exception handling not implemented yet")
323 }
324 }
325 }
326
327 environ.finish_exports()?;
328 Ok(())
329}
330
331pub fn parse_start_section(index: u32, environ: &mut ModuleEnvironment) -> WasmResult<()> {
333 environ.declare_start_function(FunctionIndex::from_u32(index))?;
334 Ok(())
335}
336
337fn read_elems(items: &ElementItems) -> WasmResult<Box<[FunctionIndex]>> {
338 let mut out = Vec::new();
339
340 match items {
341 ElementItems::Functions(funcs) => {
342 for res in funcs.clone().into_iter() {
343 let func_index = res.map_err(from_binaryreadererror_wasmerror)?;
344 out.push(FunctionIndex::from_u32(func_index));
345 }
346 }
347 ElementItems::Expressions(ty, section) => {
348 if !(ty.is_extern_ref() || ty.is_func_ref()) {
350 return Err(wasm_unsupported!(
351 "unsupported element type in element section: {:?}",
352 ty
353 ));
354 }
355
356 for res in section.clone().into_iter() {
357 let expr = res.map_err(from_binaryreadererror_wasmerror)?;
358
359 let op = expr
360 .get_binary_reader()
361 .read_operator()
362 .map_err(from_binaryreadererror_wasmerror)?;
363 match op {
364 Operator::RefNull { .. } => out.push(FunctionIndex::reserved_value()),
365 Operator::RefFunc { function_index } => {
366 out.push(FunctionIndex::from_u32(function_index))
367 }
368 other => {
369 return Err(WasmError::Unsupported(format!(
370 "unsupported init expr in element section: {other:?}",
371 )));
372 }
373 }
374 }
375 }
376 }
377
378 Ok(out.into_boxed_slice())
379}
380
381pub fn parse_element_section(
383 elements: ElementSectionReader<'_>,
384 environ: &mut ModuleEnvironment,
385) -> WasmResult<()> {
386 environ.reserve_table_initializers(elements.count())?;
387
388 for (index, elem) in elements.into_iter().enumerate() {
389 let Element {
390 kind,
391 items,
392 range: _,
393 } = elem.map_err(from_binaryreadererror_wasmerror)?;
394
395 let segments = read_elems(&items)?;
396 match kind {
397 ElementKind::Active {
398 table_index,
399 offset_expr,
400 } => {
401 let table_index = TableIndex::from_u32(table_index.unwrap_or(0));
402
403 let mut init_expr_reader = offset_expr.get_binary_reader();
404 let (base, offset) = match init_expr_reader
405 .read_operator()
406 .map_err(from_binaryreadererror_wasmerror)?
407 {
408 Operator::I32Const { value } => (None, value as u32 as usize),
409 Operator::GlobalGet { global_index } => {
410 (Some(GlobalIndex::from_u32(global_index)), 0)
411 }
412 ref s => {
413 return Err(wasm_unsupported!(
414 "unsupported init expr in element section: {:?}",
415 s
416 ));
417 }
418 };
419 environ.declare_table_initializers(table_index, base, offset, segments)?
420 }
421 ElementKind::Passive => {
422 let index = ElemIndex::from_u32(index as u32);
423 environ.declare_passive_element(index, segments)?;
424 }
425 ElementKind::Declared => (),
426 }
427 }
428 Ok(())
429}
430
431pub fn parse_data_section<'data>(
433 data: DataSectionReader<'data>,
434 environ: &mut ModuleEnvironment<'data>,
435) -> WasmResult<()> {
436 environ.reserve_data_initializers(data.count())?;
437
438 for (index, entry) in data.into_iter().enumerate() {
439 let Data {
440 kind,
441 data,
442 range: _,
443 } = entry.map_err(from_binaryreadererror_wasmerror)?;
444 match kind {
445 DataKind::Active {
446 memory_index,
447 offset_expr,
448 } => {
449 let mut init_expr_reader = offset_expr.get_binary_reader();
450 let (base, offset) = match init_expr_reader
451 .read_operator()
452 .map_err(from_binaryreadererror_wasmerror)?
453 {
454 Operator::I32Const { value } => (None, value as u32 as usize),
455 Operator::GlobalGet { global_index } => {
456 (Some(GlobalIndex::from_u32(global_index)), 0)
457 }
458 ref s => {
459 return Err(wasm_unsupported!(
460 "unsupported init expr in data section: {:?}",
461 s
462 ))
463 }
464 };
465 environ.declare_data_initialization(
466 MemoryIndex::from_u32(memory_index),
467 base,
468 offset,
469 data,
470 )?;
471 }
472 DataKind::Passive => {
473 let index = DataIndex::from_u32(index as u32);
474 environ.declare_passive_data(index, data)?;
475 }
476 }
477 }
478
479 Ok(())
480}
481
482pub fn parse_name_section<'data>(
484 names: NameSectionReader<'data>,
485 environ: &mut ModuleEnvironment<'data>,
486) -> WasmResult<()> {
487 for res in names {
488 let subsection = if let Ok(subsection) = res {
489 subsection
490 } else {
491 continue;
493 };
494 match subsection {
495 wasmparser::Name::Function(function_subsection) => {
496 for naming in function_subsection.into_iter().flatten() {
497 if naming.index != std::u32::MAX {
498 environ.declare_function_name(
499 FunctionIndex::from_u32(naming.index),
500 naming.name,
501 )?;
502 }
503 }
504 }
505 wasmparser::Name::Module {
506 name,
507 name_range: _,
508 } => {
509 environ.declare_module_name(name)?;
510 }
511 wasmparser::Name::Local(_) => {}
512 wasmparser::Name::Label(_)
513 | wasmparser::Name::Type(_)
514 | wasmparser::Name::Table(_)
515 | wasmparser::Name::Memory(_)
516 | wasmparser::Name::Global(_)
517 | wasmparser::Name::Element(_)
518 | wasmparser::Name::Data(_)
519 | wasmparser::Name::Unknown { .. }
520 | wasmparser::Name::Tag(..) => {}
521 }
522 }
523
524 Ok(())
525}