1use crate::environ::ModuleEnvironment;
11use crate::wasm_unsupported;
12use crate::{
13 DataIndex, ElemIndex, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, Table,
14 TableIndex, Tag, TagIndex, TypeIndex, WasmError, WasmResult,
15};
16use cranelift_entity::packed_option::ReservedValue;
17use cranelift_entity::EntityRef;
18use std::boxed::Box;
19use std::vec::Vec;
20use wasmparser::{
21 self, Data, DataKind, DataSectionReader, Element, ElementItems, ElementKind,
22 ElementSectionReader, Export, ExportSectionReader, ExternalKind, FunctionSectionReader,
23 GlobalSectionReader, GlobalType, ImportSectionReader, MemorySectionReader, MemoryType,
24 NameSectionReader, Naming, Operator, TableSectionReader, TableType, TagSectionReader, TagType,
25 Type, TypeRef, TypeSectionReader,
26};
27
28fn memory(ty: MemoryType) -> Memory {
29 Memory {
30 minimum: ty.initial,
31 maximum: ty.maximum,
32 shared: ty.shared,
33 memory64: ty.memory64,
34 }
35}
36
37fn tag(e: TagType) -> Tag {
38 match e.kind {
39 wasmparser::TagKind::Exception => Tag {
40 ty: TypeIndex::from_u32(e.func_type_idx),
41 },
42 }
43}
44
45fn table(ty: TableType) -> WasmResult<Table> {
46 Ok(Table {
47 wasm_ty: ty.element_type.try_into()?,
48 minimum: ty.initial,
49 maximum: ty.maximum,
50 })
51}
52
53fn global(ty: GlobalType, initializer: GlobalInit) -> WasmResult<Global> {
54 Ok(Global {
55 wasm_ty: ty.content_type.try_into()?,
56 mutability: ty.mutable,
57 initializer,
58 })
59}
60
61pub fn parse_type_section<'a>(
63 types: TypeSectionReader<'a>,
64 environ: &mut dyn ModuleEnvironment<'a>,
65) -> WasmResult<()> {
66 let count = types.count();
67 environ.reserve_types(count)?;
68
69 for entry in types {
70 match entry? {
71 Type::Func(wasm_func_ty) => {
72 environ.declare_type_func(wasm_func_ty.clone().try_into()?)?;
73 }
74 }
75 }
76 Ok(())
77}
78
79pub fn parse_import_section<'data>(
81 imports: ImportSectionReader<'data>,
82 environ: &mut dyn ModuleEnvironment<'data>,
83) -> WasmResult<()> {
84 environ.reserve_imports(imports.count())?;
85
86 for entry in imports {
87 let import = entry?;
88 match import.ty {
89 TypeRef::Func(sig) => {
90 environ.declare_func_import(
91 TypeIndex::from_u32(sig),
92 import.module,
93 import.name,
94 )?;
95 }
96 TypeRef::Memory(ty) => {
97 environ.declare_memory_import(memory(ty), import.module, import.name)?;
98 }
99 TypeRef::Tag(e) => {
100 environ.declare_tag_import(tag(e), import.module, import.name)?;
101 }
102 TypeRef::Global(ty) => {
103 let ty = global(ty, GlobalInit::Import)?;
104 environ.declare_global_import(ty, import.module, import.name)?;
105 }
106 TypeRef::Table(ty) => {
107 let ty = table(ty)?;
108 environ.declare_table_import(ty, import.module, import.name)?;
109 }
110 }
111 }
112
113 environ.finish_imports()?;
114 Ok(())
115}
116
117pub fn parse_function_section(
119 functions: FunctionSectionReader,
120 environ: &mut dyn ModuleEnvironment,
121) -> WasmResult<()> {
122 let num_functions = functions.count();
123 if num_functions == std::u32::MAX {
124 return Err(WasmError::ImplLimitExceeded);
126 }
127
128 environ.reserve_func_types(num_functions)?;
129
130 for entry in functions {
131 let sigindex = entry?;
132 environ.declare_func_type(TypeIndex::from_u32(sigindex))?;
133 }
134
135 Ok(())
136}
137
138pub fn parse_table_section(
140 tables: TableSectionReader,
141 environ: &mut dyn ModuleEnvironment,
142) -> WasmResult<()> {
143 environ.reserve_tables(tables.count())?;
144
145 for entry in tables {
146 let ty = table(entry?.ty)?;
147 environ.declare_table(ty)?;
148 }
149
150 Ok(())
151}
152
153pub fn parse_memory_section(
155 memories: MemorySectionReader,
156 environ: &mut dyn ModuleEnvironment,
157) -> WasmResult<()> {
158 environ.reserve_memories(memories.count())?;
159
160 for entry in memories {
161 let memory = memory(entry?);
162 environ.declare_memory(memory)?;
163 }
164
165 Ok(())
166}
167
168pub fn parse_tag_section(
170 tags: TagSectionReader,
171 environ: &mut dyn ModuleEnvironment,
172) -> WasmResult<()> {
173 environ.reserve_tags(tags.count())?;
174
175 for entry in tags {
176 let tag = tag(entry?);
177 environ.declare_tag(tag)?;
178 }
179
180 Ok(())
181}
182
183pub fn parse_global_section(
185 globals: GlobalSectionReader,
186 environ: &mut dyn ModuleEnvironment,
187) -> WasmResult<()> {
188 environ.reserve_globals(globals.count())?;
189
190 for entry in globals {
191 let wasmparser::Global { ty, init_expr } = entry?;
192 let mut init_expr_reader = init_expr.get_binary_reader();
193 let initializer = match init_expr_reader.read_operator()? {
194 Operator::I32Const { value } => GlobalInit::I32Const(value),
195 Operator::I64Const { value } => GlobalInit::I64Const(value),
196 Operator::F32Const { value } => GlobalInit::F32Const(value.bits()),
197 Operator::F64Const { value } => GlobalInit::F64Const(value.bits()),
198 Operator::V128Const { value } => {
199 GlobalInit::V128Const(u128::from_le_bytes(*value.bytes()))
200 }
201 Operator::RefNull { hty: _ } => GlobalInit::RefNullConst,
202 Operator::RefFunc { function_index } => {
203 GlobalInit::RefFunc(FuncIndex::from_u32(function_index))
204 }
205 Operator::GlobalGet { global_index } => {
206 GlobalInit::GetGlobal(GlobalIndex::from_u32(global_index))
207 }
208 ref s => {
209 return Err(wasm_unsupported!(
210 "unsupported init expr in global section: {:?}",
211 s
212 ));
213 }
214 };
215 let ty = global(ty, initializer)?;
216 environ.declare_global(ty)?;
217 }
218
219 Ok(())
220}
221
222pub fn parse_export_section<'data>(
224 exports: ExportSectionReader<'data>,
225 environ: &mut dyn ModuleEnvironment<'data>,
226) -> WasmResult<()> {
227 environ.reserve_exports(exports.count())?;
228
229 for entry in exports {
230 let Export {
231 name,
232 ref kind,
233 index,
234 } = entry?;
235
236 let index = index as usize;
240 match *kind {
241 ExternalKind::Func => environ.declare_func_export(FuncIndex::new(index), name)?,
242 ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), name)?,
243 ExternalKind::Memory => environ.declare_memory_export(MemoryIndex::new(index), name)?,
244 ExternalKind::Tag => environ.declare_tag_export(TagIndex::new(index), name)?,
245 ExternalKind::Global => environ.declare_global_export(GlobalIndex::new(index), name)?,
246 }
247 }
248
249 environ.finish_exports()?;
250 Ok(())
251}
252
253pub fn parse_start_section(index: u32, environ: &mut dyn ModuleEnvironment) -> WasmResult<()> {
255 environ.declare_start_func(FuncIndex::from_u32(index))?;
256 Ok(())
257}
258
259fn read_elems(items: &ElementItems) -> WasmResult<Box<[FuncIndex]>> {
260 let mut elems = Vec::new();
261 match items {
262 ElementItems::Functions(funcs) => {
263 for func in funcs.clone() {
264 elems.push(FuncIndex::from_u32(func?));
265 }
266 }
267 ElementItems::Expressions(funcs) => {
268 for func in funcs.clone() {
269 let idx = match func?.get_binary_reader().read_operator()? {
270 Operator::RefNull { .. } => FuncIndex::reserved_value(),
271 Operator::RefFunc { function_index } => FuncIndex::from_u32(function_index),
272 s => {
273 return Err(WasmError::Unsupported(format!(
274 "unsupported init expr in element section: {:?}",
275 s
276 )));
277 }
278 };
279 elems.push(idx);
280 }
281 }
282 }
283 Ok(elems.into_boxed_slice())
284}
285
286pub fn parse_element_section<'data>(
288 elements: ElementSectionReader<'data>,
289 environ: &mut dyn ModuleEnvironment,
290) -> WasmResult<()> {
291 environ.reserve_table_elements(elements.count())?;
292
293 for (index, entry) in elements.into_iter().enumerate() {
294 let Element {
295 kind,
296 items,
297 ty: _,
298 range: _,
299 } = entry?;
300 let segments = read_elems(&items)?;
301 match kind {
302 ElementKind::Active {
303 table_index,
304 offset_expr,
305 } => {
306 let mut offset_expr_reader = offset_expr.get_binary_reader();
307 let (base, offset) = match offset_expr_reader.read_operator()? {
308 Operator::I32Const { value } => (None, value as u32),
309 Operator::GlobalGet { global_index } => {
310 (Some(GlobalIndex::from_u32(global_index)), 0)
311 }
312 ref s => {
313 return Err(wasm_unsupported!(
314 "unsupported init expr in element section: {:?}",
315 s
316 ));
317 }
318 };
319 environ.declare_table_elements(
320 TableIndex::from_u32(table_index),
321 base,
322 offset,
323 segments,
324 )?
325 }
326 ElementKind::Passive => {
327 let index = ElemIndex::from_u32(index as u32);
328 environ.declare_passive_element(index, segments)?;
329 }
330 ElementKind::Declared => {
331 environ.declare_elements(segments)?;
332 }
333 }
334 }
335 Ok(())
336}
337
338pub fn parse_data_section<'data>(
340 data: DataSectionReader<'data>,
341 environ: &mut dyn ModuleEnvironment<'data>,
342) -> WasmResult<()> {
343 environ.reserve_data_initializers(data.count())?;
344
345 for (index, entry) in data.into_iter().enumerate() {
346 let Data {
347 kind,
348 data,
349 range: _,
350 } = entry?;
351 match kind {
352 DataKind::Active {
353 memory_index,
354 offset_expr,
355 } => {
356 let mut offset_expr_reader = offset_expr.get_binary_reader();
357 let (base, offset) = match offset_expr_reader.read_operator()? {
358 Operator::I32Const { value } => (None, value as u64),
359 Operator::I64Const { value } => (None, value as u64),
360 Operator::GlobalGet { global_index } => {
361 (Some(GlobalIndex::from_u32(global_index)), 0)
362 }
363 ref s => {
364 return Err(wasm_unsupported!(
365 "unsupported init expr in data section: {:?}",
366 s
367 ))
368 }
369 };
370 environ.declare_data_initialization(
371 MemoryIndex::from_u32(memory_index),
372 base,
373 offset,
374 data,
375 )?;
376 }
377 DataKind::Passive => {
378 let index = DataIndex::from_u32(index as u32);
379 environ.declare_passive_data(index, data)?;
380 }
381 }
382 }
383
384 Ok(())
385}
386
387pub fn parse_name_section<'data>(
389 names: NameSectionReader<'data>,
390 environ: &mut dyn ModuleEnvironment<'data>,
391) -> WasmResult<()> {
392 for subsection in names {
393 match subsection? {
394 wasmparser::Name::Function(names) => {
395 for name in names {
396 let Naming { index, name } = name?;
397 if index != u32::max_value() {
399 environ.declare_func_name(FuncIndex::from_u32(index), name);
400 }
401 }
402 }
403 wasmparser::Name::Module { name, .. } => {
404 environ.declare_module_name(name);
405 }
406 wasmparser::Name::Local(reader) => {
407 for f in reader {
408 let f = f?;
409 if f.index == u32::max_value() {
410 continue;
411 }
412 for name in f.names {
413 let Naming { index, name } = name?;
414 environ.declare_local_name(FuncIndex::from_u32(f.index), index, name)
415 }
416 }
417 }
418 wasmparser::Name::Label(_)
419 | wasmparser::Name::Type(_)
420 | wasmparser::Name::Table(_)
421 | wasmparser::Name::Global(_)
422 | wasmparser::Name::Memory(_)
423 | wasmparser::Name::Element(_)
424 | wasmparser::Name::Data(_)
425 | wasmparser::Name::Unknown { .. } => {}
426 }
427 }
428 Ok(())
429}