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