1 | //! Conversions from `wasmparser` to `wasm-encoder` to [`Reencode`] parsed wasm. |
2 | //! |
3 | //! The [`RoundtripReencoder`] allows encoding identical wasm to the parsed |
4 | //! input. |
5 | |
6 | #[cfg (all(not(feature = "std" ), core_error))] |
7 | use core::error::Error as StdError; |
8 | #[cfg (feature = "std" )] |
9 | use std::error::Error as StdError; |
10 | |
11 | use crate::CoreTypeEncoder; |
12 | use core::convert::Infallible; |
13 | |
14 | #[cfg (feature = "component-model" )] |
15 | mod component; |
16 | |
17 | #[cfg (feature = "component-model" )] |
18 | pub use self::component::*; |
19 | |
20 | #[allow (missing_docs)] // FIXME |
21 | pub trait Reencode { |
22 | type Error; |
23 | |
24 | fn data_index(&mut self, data: u32) -> u32 { |
25 | utils::data_index(self, data) |
26 | } |
27 | |
28 | fn element_index(&mut self, element: u32) -> u32 { |
29 | utils::element_index(self, element) |
30 | } |
31 | |
32 | fn function_index(&mut self, func: u32) -> u32 { |
33 | utils::function_index(self, func) |
34 | } |
35 | |
36 | fn global_index(&mut self, global: u32) -> u32 { |
37 | utils::global_index(self, global) |
38 | } |
39 | |
40 | fn memory_index(&mut self, memory: u32) -> u32 { |
41 | utils::memory_index(self, memory) |
42 | } |
43 | |
44 | fn table_index(&mut self, table: u32) -> u32 { |
45 | utils::table_index(self, table) |
46 | } |
47 | |
48 | fn tag_index(&mut self, tag: u32) -> u32 { |
49 | utils::tag_index(self, tag) |
50 | } |
51 | |
52 | fn type_index(&mut self, ty: u32) -> u32 { |
53 | utils::type_index(self, ty) |
54 | } |
55 | |
56 | fn type_index_unpacked( |
57 | &mut self, |
58 | ty: wasmparser::UnpackedIndex, |
59 | ) -> Result<u32, Error<Self::Error>> { |
60 | utils::type_index_unpacked(self, ty) |
61 | } |
62 | |
63 | fn external_index(&mut self, kind: wasmparser::ExternalKind, index: u32) -> u32 { |
64 | match kind { |
65 | wasmparser::ExternalKind::Func => self.function_index(index), |
66 | wasmparser::ExternalKind::Table => self.table_index(index), |
67 | wasmparser::ExternalKind::Memory => self.memory_index(index), |
68 | wasmparser::ExternalKind::Global => self.global_index(index), |
69 | wasmparser::ExternalKind::Tag => self.tag_index(index), |
70 | } |
71 | } |
72 | |
73 | fn abstract_heap_type( |
74 | &mut self, |
75 | value: wasmparser::AbstractHeapType, |
76 | ) -> crate::AbstractHeapType { |
77 | utils::abstract_heap_type(self, value) |
78 | } |
79 | |
80 | fn array_type( |
81 | &mut self, |
82 | array_ty: wasmparser::ArrayType, |
83 | ) -> Result<crate::ArrayType, Error<Self::Error>> { |
84 | utils::array_type(self, array_ty) |
85 | } |
86 | |
87 | fn block_type( |
88 | &mut self, |
89 | arg: wasmparser::BlockType, |
90 | ) -> Result<crate::BlockType, Error<Self::Error>> { |
91 | utils::block_type(self, arg) |
92 | } |
93 | |
94 | fn const_expr( |
95 | &mut self, |
96 | const_expr: wasmparser::ConstExpr, |
97 | ) -> Result<crate::ConstExpr, Error<Self::Error>> { |
98 | utils::const_expr(self, const_expr) |
99 | } |
100 | |
101 | fn catch(&mut self, arg: wasmparser::Catch) -> crate::Catch { |
102 | utils::catch(self, arg) |
103 | } |
104 | |
105 | fn composite_type( |
106 | &mut self, |
107 | composite_ty: wasmparser::CompositeType, |
108 | ) -> Result<crate::CompositeType, Error<Self::Error>> { |
109 | utils::composite_type(self, composite_ty) |
110 | } |
111 | |
112 | fn entity_type( |
113 | &mut self, |
114 | type_ref: wasmparser::TypeRef, |
115 | ) -> Result<crate::EntityType, Error<Self::Error>> { |
116 | utils::entity_type(self, type_ref) |
117 | } |
118 | |
119 | fn export_kind(&mut self, external_kind: wasmparser::ExternalKind) -> crate::ExportKind { |
120 | utils::export_kind(self, external_kind) |
121 | } |
122 | |
123 | fn field_type( |
124 | &mut self, |
125 | field_ty: wasmparser::FieldType, |
126 | ) -> Result<crate::FieldType, Error<Self::Error>> { |
127 | utils::field_type(self, field_ty) |
128 | } |
129 | |
130 | fn func_type( |
131 | &mut self, |
132 | func_ty: wasmparser::FuncType, |
133 | ) -> Result<crate::FuncType, Error<Self::Error>> { |
134 | utils::func_type(self, func_ty) |
135 | } |
136 | |
137 | fn cont_type( |
138 | &mut self, |
139 | cont_ty: wasmparser::ContType, |
140 | ) -> Result<crate::ContType, Error<Self::Error>> { |
141 | utils::cont_type(self, cont_ty) |
142 | } |
143 | |
144 | fn global_type( |
145 | &mut self, |
146 | global_ty: wasmparser::GlobalType, |
147 | ) -> Result<crate::GlobalType, Error<Self::Error>> { |
148 | utils::global_type(self, global_ty) |
149 | } |
150 | |
151 | fn handle(&mut self, on: wasmparser::Handle) -> crate::Handle { |
152 | utils::handle(self, on) |
153 | } |
154 | |
155 | fn heap_type( |
156 | &mut self, |
157 | heap_type: wasmparser::HeapType, |
158 | ) -> Result<crate::HeapType, Error<Self::Error>> { |
159 | utils::heap_type(self, heap_type) |
160 | } |
161 | |
162 | fn instruction<'a>( |
163 | &mut self, |
164 | arg: wasmparser::Operator<'a>, |
165 | ) -> Result<crate::Instruction<'a>, Error<Self::Error>> { |
166 | utils::instruction(self, arg) |
167 | } |
168 | |
169 | fn memory_type(&mut self, memory_ty: wasmparser::MemoryType) -> crate::MemoryType { |
170 | utils::memory_type(self, memory_ty) |
171 | } |
172 | |
173 | fn mem_arg(&mut self, arg: wasmparser::MemArg) -> crate::MemArg { |
174 | utils::mem_arg(self, arg) |
175 | } |
176 | |
177 | fn ordering(&mut self, arg: wasmparser::Ordering) -> crate::Ordering { |
178 | utils::ordering(self, arg) |
179 | } |
180 | |
181 | fn ref_type( |
182 | &mut self, |
183 | ref_type: wasmparser::RefType, |
184 | ) -> Result<crate::RefType, Error<Self::Error>> { |
185 | utils::ref_type(self, ref_type) |
186 | } |
187 | |
188 | fn storage_type( |
189 | &mut self, |
190 | storage_ty: wasmparser::StorageType, |
191 | ) -> Result<crate::StorageType, Error<Self::Error>> { |
192 | utils::storage_type(self, storage_ty) |
193 | } |
194 | |
195 | fn struct_type( |
196 | &mut self, |
197 | struct_ty: wasmparser::StructType, |
198 | ) -> Result<crate::StructType, Error<Self::Error>> { |
199 | utils::struct_type(self, struct_ty) |
200 | } |
201 | |
202 | fn sub_type( |
203 | &mut self, |
204 | sub_ty: wasmparser::SubType, |
205 | ) -> Result<crate::SubType, Error<Self::Error>> { |
206 | utils::sub_type(self, sub_ty) |
207 | } |
208 | |
209 | fn table_type( |
210 | &mut self, |
211 | table_ty: wasmparser::TableType, |
212 | ) -> Result<crate::TableType, Error<Self::Error>> { |
213 | utils::table_type(self, table_ty) |
214 | } |
215 | |
216 | fn tag_kind(&mut self, kind: wasmparser::TagKind) -> crate::TagKind { |
217 | utils::tag_kind(self, kind) |
218 | } |
219 | |
220 | fn tag_type(&mut self, tag_ty: wasmparser::TagType) -> crate::TagType { |
221 | utils::tag_type(self, tag_ty) |
222 | } |
223 | |
224 | fn val_type( |
225 | &mut self, |
226 | val_ty: wasmparser::ValType, |
227 | ) -> Result<crate::ValType, Error<Self::Error>> { |
228 | utils::val_type(self, val_ty) |
229 | } |
230 | |
231 | /// Parses the input `section` given from the `wasmparser` crate and |
232 | /// adds the custom section to the `module`. |
233 | fn parse_custom_section( |
234 | &mut self, |
235 | module: &mut crate::Module, |
236 | section: wasmparser::CustomSectionReader<'_>, |
237 | ) -> Result<(), Error<Self::Error>> { |
238 | utils::parse_custom_section(self, module, section) |
239 | } |
240 | |
241 | /// Converts the input `section` given from the `wasmparser` crate into an |
242 | /// encoded custom section. |
243 | fn custom_section<'a>( |
244 | &mut self, |
245 | section: wasmparser::CustomSectionReader<'a>, |
246 | ) -> crate::CustomSection<'a> { |
247 | utils::custom_section(self, section) |
248 | } |
249 | |
250 | /// Parses the input `section` given from the `wasmparser` crate and adds |
251 | /// all the code to the `code` section. |
252 | fn parse_code_section( |
253 | &mut self, |
254 | code: &mut crate::CodeSection, |
255 | section: wasmparser::CodeSectionReader<'_>, |
256 | ) -> Result<(), Error<Self::Error>> { |
257 | utils::parse_code_section(self, code, section) |
258 | } |
259 | |
260 | /// Parses a single [`wasmparser::FunctionBody`] and adds it to the `code` section. |
261 | fn parse_function_body( |
262 | &mut self, |
263 | code: &mut crate::CodeSection, |
264 | func: wasmparser::FunctionBody<'_>, |
265 | ) -> Result<(), Error<Self::Error>> { |
266 | utils::parse_function_body(self, code, func) |
267 | } |
268 | |
269 | /// Create a new [`crate::Function`] by parsing the locals declarations from the |
270 | /// provided [`wasmparser::FunctionBody`]. |
271 | fn new_function_with_parsed_locals( |
272 | &mut self, |
273 | func: &wasmparser::FunctionBody<'_>, |
274 | ) -> Result<crate::Function, Error<Self::Error>> { |
275 | utils::new_function_with_parsed_locals(self, func) |
276 | } |
277 | |
278 | /// Parses a single instruction from `reader` and adds it to `function`. |
279 | fn parse_instruction<'a>( |
280 | &mut self, |
281 | reader: &mut wasmparser::OperatorsReader<'a>, |
282 | ) -> Result<crate::Instruction<'a>, Error<Self::Error>> { |
283 | utils::parse_instruction(self, reader) |
284 | } |
285 | |
286 | /// Parses the input `section` given from the `wasmparser` crate and adds |
287 | /// all the data to the `data` section. |
288 | fn parse_data_section( |
289 | &mut self, |
290 | data: &mut crate::DataSection, |
291 | section: wasmparser::DataSectionReader<'_>, |
292 | ) -> Result<(), Error<Self::Error>> { |
293 | utils::parse_data_section(self, data, section) |
294 | } |
295 | |
296 | /// Parses a single [`wasmparser::Data`] and adds it to the `data` section. |
297 | fn parse_data( |
298 | &mut self, |
299 | data: &mut crate::DataSection, |
300 | datum: wasmparser::Data<'_>, |
301 | ) -> Result<(), Error<Self::Error>> { |
302 | utils::parse_data(self, data, datum) |
303 | } |
304 | |
305 | /// Parses the input `section` given from the `wasmparser` crate and adds |
306 | /// all the elements to the `element` section. |
307 | fn parse_element_section( |
308 | &mut self, |
309 | elements: &mut crate::ElementSection, |
310 | section: wasmparser::ElementSectionReader<'_>, |
311 | ) -> Result<(), Error<Self::Error>> { |
312 | utils::parse_element_section(self, elements, section) |
313 | } |
314 | |
315 | /// Parses the single [`wasmparser::Element`] provided and adds it to the |
316 | /// `element` section. |
317 | fn parse_element( |
318 | &mut self, |
319 | elements: &mut crate::ElementSection, |
320 | element: wasmparser::Element<'_>, |
321 | ) -> Result<(), Error<Self::Error>> { |
322 | utils::parse_element(self, elements, element) |
323 | } |
324 | |
325 | fn element_items<'a>( |
326 | &mut self, |
327 | items: wasmparser::ElementItems<'a>, |
328 | ) -> Result<crate::Elements<'a>, Error<Self::Error>> { |
329 | utils::element_items(self, items) |
330 | } |
331 | |
332 | /// Parses the input `section` given from the `wasmparser` crate and adds |
333 | /// all the exports to the `exports` section. |
334 | fn parse_export_section( |
335 | &mut self, |
336 | exports: &mut crate::ExportSection, |
337 | section: wasmparser::ExportSectionReader<'_>, |
338 | ) -> Result<(), Error<Self::Error>> { |
339 | utils::parse_export_section(self, exports, section) |
340 | } |
341 | |
342 | /// Parses the single [`wasmparser::Export`] provided and adds it to the |
343 | /// `exports` section. |
344 | fn parse_export(&mut self, exports: &mut crate::ExportSection, export: wasmparser::Export<'_>) { |
345 | utils::parse_export(self, exports, export) |
346 | } |
347 | |
348 | /// Parses the input `section` given from the `wasmparser` crate and adds |
349 | /// all the functions to the `functions` section. |
350 | fn parse_function_section( |
351 | &mut self, |
352 | functions: &mut crate::FunctionSection, |
353 | section: wasmparser::FunctionSectionReader<'_>, |
354 | ) -> Result<(), Error<Self::Error>> { |
355 | utils::parse_function_section(self, functions, section) |
356 | } |
357 | |
358 | /// Parses the input `section` given from the `wasmparser` crate and adds |
359 | /// all the globals to the `globals` section. |
360 | fn parse_global_section( |
361 | &mut self, |
362 | globals: &mut crate::GlobalSection, |
363 | section: wasmparser::GlobalSectionReader<'_>, |
364 | ) -> Result<(), Error<Self::Error>> { |
365 | utils::parse_global_section(self, globals, section) |
366 | } |
367 | |
368 | /// Parses the single [`wasmparser::Global`] provided and adds it to the |
369 | /// `globals` section. |
370 | fn parse_global( |
371 | &mut self, |
372 | globals: &mut crate::GlobalSection, |
373 | global: wasmparser::Global<'_>, |
374 | ) -> Result<(), Error<Self::Error>> { |
375 | utils::parse_global(self, globals, global) |
376 | } |
377 | |
378 | /// Parses the input `section` given from the `wasmparser` crate and adds |
379 | /// all the imports to the `import` section. |
380 | fn parse_import_section( |
381 | &mut self, |
382 | imports: &mut crate::ImportSection, |
383 | section: wasmparser::ImportSectionReader<'_>, |
384 | ) -> Result<(), Error<Self::Error>> { |
385 | utils::parse_import_section(self, imports, section) |
386 | } |
387 | |
388 | /// Parses the single [`wasmparser::Import`] provided and adds it to the |
389 | /// `import` section. |
390 | fn parse_import( |
391 | &mut self, |
392 | imports: &mut crate::ImportSection, |
393 | import: wasmparser::Import<'_>, |
394 | ) -> Result<(), Error<Self::Error>> { |
395 | utils::parse_import(self, imports, import) |
396 | } |
397 | |
398 | /// Parses the input `section` given from the `wasmparser` crate and adds |
399 | /// all the memories to the `memories` section. |
400 | fn parse_memory_section( |
401 | &mut self, |
402 | memories: &mut crate::MemorySection, |
403 | section: wasmparser::MemorySectionReader<'_>, |
404 | ) -> Result<(), Error<Self::Error>> { |
405 | utils::parse_memory_section(self, memories, section) |
406 | } |
407 | |
408 | /// Parses the input `section` given from the `wasmparser` crate and adds |
409 | /// all the tables to the `tables` section. |
410 | fn parse_table_section( |
411 | &mut self, |
412 | tables: &mut crate::TableSection, |
413 | section: wasmparser::TableSectionReader<'_>, |
414 | ) -> Result<(), Error<Self::Error>> { |
415 | utils::parse_table_section(self, tables, section) |
416 | } |
417 | |
418 | /// Parses a single [`wasmparser::Table`] and adds it to the `tables` section. |
419 | fn parse_table( |
420 | &mut self, |
421 | tables: &mut crate::TableSection, |
422 | table: wasmparser::Table<'_>, |
423 | ) -> Result<(), Error<Self::Error>> { |
424 | utils::parse_table(self, tables, table) |
425 | } |
426 | |
427 | /// Parses the input `section` given from the `wasmparser` crate and adds |
428 | /// all the tags to the `tags` section. |
429 | fn parse_tag_section( |
430 | &mut self, |
431 | tags: &mut crate::TagSection, |
432 | section: wasmparser::TagSectionReader<'_>, |
433 | ) -> Result<(), Error<Self::Error>> { |
434 | utils::parse_tag_section(self, tags, section) |
435 | } |
436 | |
437 | /// Parses the input `section` given from the `wasmparser` crate and adds |
438 | /// all the types to the `types` section. |
439 | fn parse_type_section( |
440 | &mut self, |
441 | types: &mut crate::TypeSection, |
442 | section: wasmparser::TypeSectionReader<'_>, |
443 | ) -> Result<(), Error<Self::Error>> { |
444 | utils::parse_type_section(self, types, section) |
445 | } |
446 | |
447 | /// Parses a single [`wasmparser::RecGroup`] and adds it to the `types` section. |
448 | fn parse_recursive_type_group( |
449 | &mut self, |
450 | encoder: CoreTypeEncoder, |
451 | rec_group: wasmparser::RecGroup, |
452 | ) -> Result<(), Error<Self::Error>> { |
453 | utils::parse_recursive_type_group(self, encoder, rec_group) |
454 | } |
455 | |
456 | fn parse_unknown_section( |
457 | &mut self, |
458 | module: &mut crate::Module, |
459 | id: u8, |
460 | contents: &[u8], |
461 | ) -> Result<(), Error<Self::Error>> { |
462 | utils::parse_unknown_section(self, module, id, contents) |
463 | } |
464 | |
465 | /// A hook method that is called inside [`Reencode::parse_core_module`] |
466 | /// before and after every non-custom core wasm section. |
467 | /// |
468 | /// This method can be used to insert new custom sections in between those |
469 | /// sections, or to detect when a non-custom section is missing and insert |
470 | /// it in the [proper order]. |
471 | /// |
472 | /// The `after` parameter is `None` iff the hook is called before the first |
473 | /// non-custom section, and `Some(s)` afterwards, where `s` is the |
474 | /// [`SectionId`] of the previous non-custom section. |
475 | /// |
476 | /// The `before` parameter is `None` iff the hook is called after the last |
477 | /// non-custom section, and `Some(s)` beforehand, where `s` is the |
478 | /// [`SectionId`] of the following non-custom section. |
479 | /// |
480 | /// [proper order]: https://webassembly.github.io/spec/core/binary/modules.html#binary-module |
481 | /// [`SectionId`]: crate::SectionId |
482 | fn intersperse_section_hook( |
483 | &mut self, |
484 | module: &mut crate::Module, |
485 | after: Option<crate::SectionId>, |
486 | before: Option<crate::SectionId>, |
487 | ) -> Result<(), Error<Self::Error>> { |
488 | utils::intersperse_section_hook(self, module, after, before) |
489 | } |
490 | |
491 | fn parse_core_module( |
492 | &mut self, |
493 | module: &mut crate::Module, |
494 | parser: wasmparser::Parser, |
495 | data: &[u8], |
496 | ) -> Result<(), Error<Self::Error>> { |
497 | utils::parse_core_module(self, module, parser, data) |
498 | } |
499 | |
500 | fn custom_name_section( |
501 | &mut self, |
502 | section: wasmparser::NameSectionReader<'_>, |
503 | ) -> Result<crate::NameSection, Error<Self::Error>> { |
504 | utils::custom_name_section(self, section) |
505 | } |
506 | |
507 | fn parse_custom_name_subsection( |
508 | &mut self, |
509 | names: &mut crate::NameSection, |
510 | section: wasmparser::Name<'_>, |
511 | ) -> Result<(), Error<Self::Error>> { |
512 | utils::parse_custom_name_subsection(self, names, section) |
513 | } |
514 | |
515 | fn data_count(&mut self, count: u32) -> u32 { |
516 | count |
517 | } |
518 | |
519 | fn start_section(&mut self, start: u32) -> u32 { |
520 | self.function_index(start) |
521 | } |
522 | } |
523 | |
524 | /// An error when re-encoding from `wasmparser` to `wasm-encoder`. |
525 | #[derive (Debug)] |
526 | pub enum Error<E = Infallible> { |
527 | /// There was a type reference that was canonicalized and no longer |
528 | /// references an index into a module's types space, so we cannot encode it |
529 | /// into a Wasm binary again. |
530 | CanonicalizedHeapTypeReference, |
531 | /// The const expression is invalid: not actually constant or something like |
532 | /// that. |
533 | InvalidConstExpr, |
534 | /// The code section size listed was not valid for the wasm binary provided. |
535 | InvalidCodeSectionSize, |
536 | /// There was a section that does not belong into a core wasm module. |
537 | UnexpectedNonCoreModuleSection, |
538 | /// There was a section that does not belong into a compoennt module. |
539 | UnexpectedNonComponentSection, |
540 | /// A core type definition was found in a component that's not supported. |
541 | UnsupportedCoreTypeInComponent, |
542 | /// There was an error when parsing. |
543 | ParseError(wasmparser::BinaryReaderError), |
544 | /// There was a user-defined error when re-encoding. |
545 | UserError(E), |
546 | } |
547 | |
548 | impl<E> From<wasmparser::BinaryReaderError> for Error<E> { |
549 | fn from(err: wasmparser::BinaryReaderError) -> Self { |
550 | Self::ParseError(err) |
551 | } |
552 | } |
553 | |
554 | impl<E: core::fmt::Display> core::fmt::Display for Error<E> { |
555 | fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { |
556 | match self { |
557 | Self::ParseError(_e) => { |
558 | write!(fmt, "There was an error when parsing" ) |
559 | } |
560 | Self::UserError(e) => write!(fmt, " {e}" ), |
561 | Self::InvalidConstExpr => write!(fmt, "The const expression was invalid" ), |
562 | Self::UnexpectedNonCoreModuleSection => write!( |
563 | fmt, |
564 | "There was a section that does not belong into a core wasm module" |
565 | ), |
566 | Self::UnexpectedNonComponentSection => write!( |
567 | fmt, |
568 | "There was a section that does not belong into a component" |
569 | ), |
570 | Self::CanonicalizedHeapTypeReference => write!( |
571 | fmt, |
572 | "There was a canonicalized heap type reference without type index information" |
573 | ), |
574 | Self::UnsupportedCoreTypeInComponent => { |
575 | fmt.write_str("unsupported core type in a component" ) |
576 | } |
577 | Self::InvalidCodeSectionSize => fmt.write_str("invalid code section size" ), |
578 | } |
579 | } |
580 | } |
581 | |
582 | #[cfg (any(feature = "std" , core_error))] |
583 | impl<E: 'static + StdError> StdError for Error<E> { |
584 | fn source(&self) -> Option<&(dyn StdError + 'static)> { |
585 | match self { |
586 | Self::ParseError(e: &BinaryReaderError) => Some(e), |
587 | Self::UserError(e: &E) => Some(e), |
588 | Self::InvalidConstExpr |
589 | | Self::CanonicalizedHeapTypeReference |
590 | | Self::UnexpectedNonCoreModuleSection |
591 | | Self::UnexpectedNonComponentSection |
592 | | Self::UnsupportedCoreTypeInComponent |
593 | | Self::InvalidCodeSectionSize => None, |
594 | } |
595 | } |
596 | } |
597 | |
598 | /// Reencodes `wasmparser` into `wasm-encoder` so that the encoded wasm is |
599 | /// identical to the input and can be parsed and encoded again. |
600 | #[derive (Debug)] |
601 | pub struct RoundtripReencoder; |
602 | |
603 | impl Reencode for RoundtripReencoder { |
604 | type Error = Infallible; |
605 | } |
606 | |
607 | #[allow (missing_docs)] // FIXME |
608 | pub mod utils { |
609 | use super::{Error, Reencode}; |
610 | use crate::{CoreTypeEncoder, Encode}; |
611 | use alloc::vec::Vec; |
612 | use core::ops::Range; |
613 | |
614 | pub fn parse_core_module<T: ?Sized + Reencode>( |
615 | reencoder: &mut T, |
616 | module: &mut crate::Module, |
617 | parser: wasmparser::Parser, |
618 | data: &[u8], |
619 | ) -> Result<(), Error<T::Error>> { |
620 | fn handle_intersperse_section_hook<T: ?Sized + Reencode>( |
621 | reencoder: &mut T, |
622 | module: &mut crate::Module, |
623 | last_section: &mut Option<crate::SectionId>, |
624 | next_section: Option<crate::SectionId>, |
625 | ) -> Result<(), Error<T::Error>> { |
626 | let after = core::mem::replace(last_section, next_section); |
627 | let before = next_section; |
628 | reencoder.intersperse_section_hook(module, after, before) |
629 | } |
630 | |
631 | // Convert from `range` to a byte range within `data` while |
632 | // accounting for various offsets. Then create a |
633 | // `CodeSectionReader` (which notably the payload does not |
634 | // give us here) and recurse with that. This means that |
635 | // users overridding `parse_code_section` always get that |
636 | // function called. |
637 | let orig_offset = parser.offset() as usize; |
638 | let get_original_section = |range: Range<usize>| { |
639 | data.get(range.start - orig_offset..range.end - orig_offset) |
640 | .ok_or(Error::InvalidCodeSectionSize) |
641 | }; |
642 | let mut last_section = None; |
643 | |
644 | for section in parser.parse_all(data) { |
645 | match section? { |
646 | wasmparser::Payload::Version { |
647 | encoding: wasmparser::Encoding::Module, |
648 | .. |
649 | } => (), |
650 | wasmparser::Payload::Version { .. } => { |
651 | return Err(Error::UnexpectedNonCoreModuleSection) |
652 | } |
653 | wasmparser::Payload::TypeSection(section) => { |
654 | handle_intersperse_section_hook( |
655 | reencoder, |
656 | module, |
657 | &mut last_section, |
658 | Some(crate::SectionId::Type), |
659 | )?; |
660 | let mut types = crate::TypeSection::new(); |
661 | reencoder.parse_type_section(&mut types, section)?; |
662 | module.section(&types); |
663 | } |
664 | wasmparser::Payload::ImportSection(section) => { |
665 | handle_intersperse_section_hook( |
666 | reencoder, |
667 | module, |
668 | &mut last_section, |
669 | Some(crate::SectionId::Import), |
670 | )?; |
671 | let mut imports = crate::ImportSection::new(); |
672 | reencoder.parse_import_section(&mut imports, section)?; |
673 | module.section(&imports); |
674 | } |
675 | wasmparser::Payload::FunctionSection(section) => { |
676 | handle_intersperse_section_hook( |
677 | reencoder, |
678 | module, |
679 | &mut last_section, |
680 | Some(crate::SectionId::Function), |
681 | )?; |
682 | let mut functions = crate::FunctionSection::new(); |
683 | reencoder.parse_function_section(&mut functions, section)?; |
684 | module.section(&functions); |
685 | } |
686 | wasmparser::Payload::TableSection(section) => { |
687 | handle_intersperse_section_hook( |
688 | reencoder, |
689 | module, |
690 | &mut last_section, |
691 | Some(crate::SectionId::Table), |
692 | )?; |
693 | let mut tables = crate::TableSection::new(); |
694 | reencoder.parse_table_section(&mut tables, section)?; |
695 | module.section(&tables); |
696 | } |
697 | wasmparser::Payload::MemorySection(section) => { |
698 | handle_intersperse_section_hook( |
699 | reencoder, |
700 | module, |
701 | &mut last_section, |
702 | Some(crate::SectionId::Memory), |
703 | )?; |
704 | let mut memories = crate::MemorySection::new(); |
705 | reencoder.parse_memory_section(&mut memories, section)?; |
706 | module.section(&memories); |
707 | } |
708 | wasmparser::Payload::TagSection(section) => { |
709 | handle_intersperse_section_hook( |
710 | reencoder, |
711 | module, |
712 | &mut last_section, |
713 | Some(crate::SectionId::Tag), |
714 | )?; |
715 | let mut tags = crate::TagSection::new(); |
716 | reencoder.parse_tag_section(&mut tags, section)?; |
717 | module.section(&tags); |
718 | } |
719 | wasmparser::Payload::GlobalSection(section) => { |
720 | handle_intersperse_section_hook( |
721 | reencoder, |
722 | module, |
723 | &mut last_section, |
724 | Some(crate::SectionId::Global), |
725 | )?; |
726 | let mut globals = crate::GlobalSection::new(); |
727 | reencoder.parse_global_section(&mut globals, section)?; |
728 | module.section(&globals); |
729 | } |
730 | wasmparser::Payload::ExportSection(section) => { |
731 | handle_intersperse_section_hook( |
732 | reencoder, |
733 | module, |
734 | &mut last_section, |
735 | Some(crate::SectionId::Export), |
736 | )?; |
737 | let mut exports = crate::ExportSection::new(); |
738 | reencoder.parse_export_section(&mut exports, section)?; |
739 | module.section(&exports); |
740 | } |
741 | wasmparser::Payload::StartSection { func, .. } => { |
742 | handle_intersperse_section_hook( |
743 | reencoder, |
744 | module, |
745 | &mut last_section, |
746 | Some(crate::SectionId::Start), |
747 | )?; |
748 | module.section(&crate::StartSection { |
749 | function_index: reencoder.start_section(func), |
750 | }); |
751 | } |
752 | wasmparser::Payload::ElementSection(section) => { |
753 | handle_intersperse_section_hook( |
754 | reencoder, |
755 | module, |
756 | &mut last_section, |
757 | Some(crate::SectionId::Element), |
758 | )?; |
759 | let mut elements = crate::ElementSection::new(); |
760 | reencoder.parse_element_section(&mut elements, section)?; |
761 | module.section(&elements); |
762 | } |
763 | wasmparser::Payload::DataCountSection { count, .. } => { |
764 | handle_intersperse_section_hook( |
765 | reencoder, |
766 | module, |
767 | &mut last_section, |
768 | Some(crate::SectionId::DataCount), |
769 | )?; |
770 | let count = reencoder.data_count(count); |
771 | module.section(&crate::DataCountSection { count }); |
772 | } |
773 | wasmparser::Payload::DataSection(section) => { |
774 | handle_intersperse_section_hook( |
775 | reencoder, |
776 | module, |
777 | &mut last_section, |
778 | Some(crate::SectionId::Data), |
779 | )?; |
780 | let mut data = crate::DataSection::new(); |
781 | reencoder.parse_data_section(&mut data, section)?; |
782 | module.section(&data); |
783 | } |
784 | wasmparser::Payload::CodeSectionStart { range, .. } => { |
785 | handle_intersperse_section_hook( |
786 | reencoder, |
787 | module, |
788 | &mut last_section, |
789 | Some(crate::SectionId::Code), |
790 | )?; |
791 | let mut codes = crate::CodeSection::new(); |
792 | |
793 | // Convert from `range` to a byte range within `data` while |
794 | // accounting for various offsets. Then create a |
795 | // `CodeSectionReader` (which notably the payload does not |
796 | // give us here) and recurse with that. This means that |
797 | // users overridding `parse_code_section` always get that |
798 | // function called. |
799 | let section = get_original_section(range.clone())?; |
800 | let reader = wasmparser::BinaryReader::new(section, range.start); |
801 | let section = wasmparser::CodeSectionReader::new(reader)?; |
802 | reencoder.parse_code_section(&mut codes, section)?; |
803 | module.section(&codes); |
804 | } |
805 | |
806 | // Parsing of code section entries (function bodies) happens |
807 | // above during the handling of the code section. That means |
808 | // that we just skip all these payloads. |
809 | wasmparser::Payload::CodeSectionEntry(_) => {} |
810 | |
811 | #[cfg (feature = "component-model" )] |
812 | wasmparser::Payload::ModuleSection { .. } |
813 | | wasmparser::Payload::InstanceSection(_) |
814 | | wasmparser::Payload::CoreTypeSection(_) |
815 | | wasmparser::Payload::ComponentSection { .. } |
816 | | wasmparser::Payload::ComponentInstanceSection(_) |
817 | | wasmparser::Payload::ComponentAliasSection(_) |
818 | | wasmparser::Payload::ComponentTypeSection(_) |
819 | | wasmparser::Payload::ComponentCanonicalSection(_) |
820 | | wasmparser::Payload::ComponentStartSection { .. } |
821 | | wasmparser::Payload::ComponentImportSection(_) |
822 | | wasmparser::Payload::ComponentExportSection(_) => { |
823 | return Err(Error::UnexpectedNonCoreModuleSection) |
824 | } |
825 | wasmparser::Payload::CustomSection(section) => { |
826 | reencoder.parse_custom_section(module, section)?; |
827 | } |
828 | wasmparser::Payload::End(_) => { |
829 | handle_intersperse_section_hook(reencoder, module, &mut last_section, None)?; |
830 | } |
831 | |
832 | other => match other.as_section() { |
833 | Some((id, range)) => { |
834 | let section = get_original_section(range)?; |
835 | reencoder.parse_unknown_section(module, id, section)?; |
836 | } |
837 | None => unreachable!(), |
838 | }, |
839 | } |
840 | } |
841 | |
842 | Ok(()) |
843 | } |
844 | |
845 | /// A hook method that is called inside [`Reencode::parse_core_module`] |
846 | /// before and after every non-custom core wasm section. |
847 | /// |
848 | /// This method can be used to insert new custom sections in between those |
849 | /// sections, or to detect when a non-custom section is missing and insert |
850 | /// it in the [proper order]. |
851 | /// |
852 | /// The `after` parameter is `None` iff the hook is called before the first |
853 | /// non-custom section, and `Some(s)` afterwards, where `s` is the |
854 | /// [`SectionId`] of the previous non-custom section. |
855 | /// |
856 | /// The `before` parameter is `None` iff the hook is called after the last |
857 | /// non-custom section, and `Some(s)` beforehand, where `s` is the |
858 | /// [`SectionId`] of the following non-custom section. |
859 | /// |
860 | /// [proper order]: https://webassembly.github.io/spec/core/binary/modules.html#binary-module |
861 | /// [`SectionId`]: crate::SectionId |
862 | pub fn intersperse_section_hook<T: ?Sized + Reencode>( |
863 | _reencoder: &mut T, |
864 | _module: &mut crate::Module, |
865 | _after: Option<crate::SectionId>, |
866 | _before: Option<crate::SectionId>, |
867 | ) -> Result<(), Error<T::Error>> { |
868 | Ok(()) |
869 | } |
870 | |
871 | pub fn memory_index<T: ?Sized + Reencode>(_reencoder: &mut T, memory: u32) -> u32 { |
872 | memory |
873 | } |
874 | |
875 | pub fn mem_arg<T: ?Sized + Reencode>( |
876 | reencoder: &mut T, |
877 | arg: wasmparser::MemArg, |
878 | ) -> crate::MemArg { |
879 | crate::MemArg { |
880 | offset: arg.offset, |
881 | align: arg.align.into(), |
882 | memory_index: reencoder.memory_index(arg.memory), |
883 | } |
884 | } |
885 | |
886 | pub fn ordering<T: ?Sized + Reencode>( |
887 | _reencoder: &mut T, |
888 | arg: wasmparser::Ordering, |
889 | ) -> crate::Ordering { |
890 | match arg { |
891 | wasmparser::Ordering::SeqCst => crate::Ordering::SeqCst, |
892 | wasmparser::Ordering::AcqRel => crate::Ordering::AcqRel, |
893 | } |
894 | } |
895 | |
896 | pub fn function_index<T: ?Sized + Reencode>(_reencoder: &mut T, func: u32) -> u32 { |
897 | func |
898 | } |
899 | |
900 | pub fn tag_index<T: ?Sized + Reencode>(_reencoder: &mut T, tag: u32) -> u32 { |
901 | tag |
902 | } |
903 | |
904 | pub fn catch<T: ?Sized + Reencode>(reencoder: &mut T, arg: wasmparser::Catch) -> crate::Catch { |
905 | match arg { |
906 | wasmparser::Catch::One { tag, label } => crate::Catch::One { |
907 | tag: reencoder.tag_index(tag), |
908 | label, |
909 | }, |
910 | wasmparser::Catch::OneRef { tag, label } => crate::Catch::OneRef { |
911 | tag: reencoder.tag_index(tag), |
912 | label, |
913 | }, |
914 | wasmparser::Catch::All { label } => crate::Catch::All { label }, |
915 | wasmparser::Catch::AllRef { label } => crate::Catch::AllRef { label }, |
916 | } |
917 | } |
918 | |
919 | pub fn handle<T: ?Sized + Reencode>( |
920 | reencoder: &mut T, |
921 | arg: wasmparser::Handle, |
922 | ) -> crate::Handle { |
923 | match arg { |
924 | wasmparser::Handle::OnLabel { tag, label } => crate::Handle::OnLabel { |
925 | tag: reencoder.tag_index(tag), |
926 | label, |
927 | }, |
928 | wasmparser::Handle::OnSwitch { tag } => crate::Handle::OnSwitch { |
929 | tag: reencoder.tag_index(tag), |
930 | }, |
931 | } |
932 | } |
933 | |
934 | /// Parses the input `section` given from the `wasmparser` crate and |
935 | /// adds the custom section to the `module`. |
936 | pub fn parse_custom_section<T: ?Sized + Reencode>( |
937 | reencoder: &mut T, |
938 | module: &mut crate::Module, |
939 | section: wasmparser::CustomSectionReader<'_>, |
940 | ) -> Result<(), Error<T::Error>> { |
941 | match section.as_known() { |
942 | wasmparser::KnownCustom::Name(name) => { |
943 | module.section(&reencoder.custom_name_section(name)?); |
944 | } |
945 | _ => { |
946 | module.section(&reencoder.custom_section(section)); |
947 | } |
948 | } |
949 | Ok(()) |
950 | } |
951 | |
952 | /// Converts the input `section` given from the `wasmparser` crate into an |
953 | /// encoded custom section. |
954 | pub fn custom_section<'a, T: ?Sized + Reencode>( |
955 | _reencoder: &mut T, |
956 | section: wasmparser::CustomSectionReader<'a>, |
957 | ) -> crate::CustomSection<'a> { |
958 | crate::CustomSection { |
959 | data: section.data().into(), |
960 | name: section.name().into(), |
961 | } |
962 | } |
963 | |
964 | pub fn export_kind<T: ?Sized + Reencode>( |
965 | _reencoder: &mut T, |
966 | external_kind: wasmparser::ExternalKind, |
967 | ) -> crate::ExportKind { |
968 | match external_kind { |
969 | wasmparser::ExternalKind::Func => crate::ExportKind::Func, |
970 | wasmparser::ExternalKind::Table => crate::ExportKind::Table, |
971 | wasmparser::ExternalKind::Memory => crate::ExportKind::Memory, |
972 | wasmparser::ExternalKind::Global => crate::ExportKind::Global, |
973 | wasmparser::ExternalKind::Tag => crate::ExportKind::Tag, |
974 | } |
975 | } |
976 | |
977 | pub fn memory_type<T: ?Sized + Reencode>( |
978 | _reencoder: &mut T, |
979 | memory_ty: wasmparser::MemoryType, |
980 | ) -> crate::MemoryType { |
981 | crate::MemoryType { |
982 | minimum: memory_ty.initial, |
983 | maximum: memory_ty.maximum, |
984 | memory64: memory_ty.memory64, |
985 | shared: memory_ty.shared, |
986 | page_size_log2: memory_ty.page_size_log2, |
987 | } |
988 | } |
989 | |
990 | pub fn tag_kind<T: ?Sized + Reencode>( |
991 | _reencoder: &mut T, |
992 | kind: wasmparser::TagKind, |
993 | ) -> crate::TagKind { |
994 | match kind { |
995 | wasmparser::TagKind::Exception => crate::TagKind::Exception, |
996 | } |
997 | } |
998 | |
999 | pub fn type_index<T: ?Sized + Reencode>(_reencoder: &mut T, ty: u32) -> u32 { |
1000 | ty |
1001 | } |
1002 | |
1003 | pub fn type_index_unpacked<T: ?Sized + Reencode>( |
1004 | reencoder: &mut T, |
1005 | ty: wasmparser::UnpackedIndex, |
1006 | ) -> Result<u32, Error<T::Error>> { |
1007 | ty.as_module_index() |
1008 | .map(|ty| reencoder.type_index(ty)) |
1009 | .ok_or(Error::CanonicalizedHeapTypeReference) |
1010 | } |
1011 | |
1012 | pub fn tag_type<T: ?Sized + Reencode>( |
1013 | reencoder: &mut T, |
1014 | tag_ty: wasmparser::TagType, |
1015 | ) -> crate::TagType { |
1016 | crate::TagType { |
1017 | kind: reencoder.tag_kind(tag_ty.kind), |
1018 | func_type_idx: reencoder.type_index(tag_ty.func_type_idx), |
1019 | } |
1020 | } |
1021 | |
1022 | pub fn abstract_heap_type<T: ?Sized + Reencode>( |
1023 | _reencoder: &mut T, |
1024 | value: wasmparser::AbstractHeapType, |
1025 | ) -> crate::AbstractHeapType { |
1026 | use wasmparser::AbstractHeapType::*; |
1027 | match value { |
1028 | Func => crate::AbstractHeapType::Func, |
1029 | Extern => crate::AbstractHeapType::Extern, |
1030 | Any => crate::AbstractHeapType::Any, |
1031 | None => crate::AbstractHeapType::None, |
1032 | NoExtern => crate::AbstractHeapType::NoExtern, |
1033 | NoFunc => crate::AbstractHeapType::NoFunc, |
1034 | Eq => crate::AbstractHeapType::Eq, |
1035 | Struct => crate::AbstractHeapType::Struct, |
1036 | Array => crate::AbstractHeapType::Array, |
1037 | I31 => crate::AbstractHeapType::I31, |
1038 | Exn => crate::AbstractHeapType::Exn, |
1039 | NoExn => crate::AbstractHeapType::NoExn, |
1040 | Cont => crate::AbstractHeapType::Cont, |
1041 | NoCont => crate::AbstractHeapType::NoCont, |
1042 | } |
1043 | } |
1044 | |
1045 | /// Parses the input `section` given from the `wasmparser` crate and adds |
1046 | /// all the types to the `types` section. |
1047 | pub fn parse_type_section<T: ?Sized + Reencode>( |
1048 | reencoder: &mut T, |
1049 | types: &mut crate::TypeSection, |
1050 | section: wasmparser::TypeSectionReader<'_>, |
1051 | ) -> Result<(), Error<T::Error>> { |
1052 | for rec_group in section { |
1053 | reencoder.parse_recursive_type_group(types.ty(), rec_group?)?; |
1054 | } |
1055 | Ok(()) |
1056 | } |
1057 | |
1058 | /// Parses a single [`wasmparser::RecGroup`] and adds it to the `types` section. |
1059 | pub fn parse_recursive_type_group<T: ?Sized + Reencode>( |
1060 | reencoder: &mut T, |
1061 | encoder: CoreTypeEncoder, |
1062 | rec_group: wasmparser::RecGroup, |
1063 | ) -> Result<(), Error<T::Error>> { |
1064 | if rec_group.is_explicit_rec_group() { |
1065 | let subtypes = rec_group |
1066 | .into_types() |
1067 | .map(|t| reencoder.sub_type(t)) |
1068 | .collect::<Result<Vec<_>, _>>()?; |
1069 | encoder.rec(subtypes); |
1070 | } else { |
1071 | let ty = rec_group.into_types().next().unwrap(); |
1072 | encoder.subtype(&reencoder.sub_type(ty)?); |
1073 | } |
1074 | Ok(()) |
1075 | } |
1076 | |
1077 | pub fn sub_type<T: ?Sized + Reencode>( |
1078 | reencoder: &mut T, |
1079 | sub_ty: wasmparser::SubType, |
1080 | ) -> Result<crate::SubType, Error<T::Error>> { |
1081 | Ok(crate::SubType { |
1082 | is_final: sub_ty.is_final, |
1083 | supertype_idx: sub_ty |
1084 | .supertype_idx |
1085 | .map(|i| reencoder.type_index_unpacked(i.unpack())) |
1086 | .transpose()?, |
1087 | composite_type: reencoder.composite_type(sub_ty.composite_type)?, |
1088 | }) |
1089 | } |
1090 | |
1091 | pub fn composite_type<T: ?Sized + Reencode>( |
1092 | reencoder: &mut T, |
1093 | composite_ty: wasmparser::CompositeType, |
1094 | ) -> Result<crate::CompositeType, Error<T::Error>> { |
1095 | let inner = match composite_ty.inner { |
1096 | wasmparser::CompositeInnerType::Func(f) => { |
1097 | crate::CompositeInnerType::Func(reencoder.func_type(f)?) |
1098 | } |
1099 | wasmparser::CompositeInnerType::Array(a) => { |
1100 | crate::CompositeInnerType::Array(reencoder.array_type(a)?) |
1101 | } |
1102 | wasmparser::CompositeInnerType::Struct(s) => { |
1103 | crate::CompositeInnerType::Struct(reencoder.struct_type(s)?) |
1104 | } |
1105 | wasmparser::CompositeInnerType::Cont(c) => { |
1106 | crate::CompositeInnerType::Cont(reencoder.cont_type(c)?) |
1107 | } |
1108 | }; |
1109 | Ok(crate::CompositeType { |
1110 | inner, |
1111 | shared: composite_ty.shared, |
1112 | }) |
1113 | } |
1114 | |
1115 | pub fn func_type<T: ?Sized + Reencode>( |
1116 | reencoder: &mut T, |
1117 | func_ty: wasmparser::FuncType, |
1118 | ) -> Result<crate::FuncType, Error<T::Error>> { |
1119 | let mut buf = Vec::with_capacity(func_ty.params().len() + func_ty.results().len()); |
1120 | for ty in func_ty.params().iter().chain(func_ty.results()).copied() { |
1121 | buf.push(reencoder.val_type(ty)?); |
1122 | } |
1123 | Ok(crate::FuncType::from_parts( |
1124 | buf.into(), |
1125 | func_ty.params().len(), |
1126 | )) |
1127 | } |
1128 | |
1129 | pub fn array_type<T: ?Sized + Reencode>( |
1130 | reencoder: &mut T, |
1131 | array_ty: wasmparser::ArrayType, |
1132 | ) -> Result<crate::ArrayType, Error<T::Error>> { |
1133 | Ok(crate::ArrayType(reencoder.field_type(array_ty.0)?)) |
1134 | } |
1135 | |
1136 | pub fn struct_type<T: ?Sized + Reencode>( |
1137 | reencoder: &mut T, |
1138 | struct_ty: wasmparser::StructType, |
1139 | ) -> Result<crate::StructType, Error<T::Error>> { |
1140 | Ok(crate::StructType { |
1141 | fields: struct_ty |
1142 | .fields |
1143 | .iter() |
1144 | .map(|field_ty| reencoder.field_type(*field_ty)) |
1145 | .collect::<Result<_, _>>()?, |
1146 | }) |
1147 | } |
1148 | |
1149 | pub fn field_type<T: ?Sized + Reencode>( |
1150 | reencoder: &mut T, |
1151 | field_ty: wasmparser::FieldType, |
1152 | ) -> Result<crate::FieldType, Error<T::Error>> { |
1153 | Ok(crate::FieldType { |
1154 | element_type: reencoder.storage_type(field_ty.element_type)?, |
1155 | mutable: field_ty.mutable, |
1156 | }) |
1157 | } |
1158 | |
1159 | pub fn storage_type<T: ?Sized + Reencode>( |
1160 | reencoder: &mut T, |
1161 | storage_ty: wasmparser::StorageType, |
1162 | ) -> Result<crate::StorageType, Error<T::Error>> { |
1163 | Ok(match storage_ty { |
1164 | wasmparser::StorageType::I8 => crate::StorageType::I8, |
1165 | wasmparser::StorageType::I16 => crate::StorageType::I16, |
1166 | wasmparser::StorageType::Val(v) => crate::StorageType::Val(reencoder.val_type(v)?), |
1167 | }) |
1168 | } |
1169 | |
1170 | pub fn cont_type<T: ?Sized + Reencode>( |
1171 | reencoder: &mut T, |
1172 | cont_ty: wasmparser::ContType, |
1173 | ) -> Result<crate::ContType, Error<T::Error>> { |
1174 | Ok(crate::ContType( |
1175 | reencoder.type_index_unpacked(cont_ty.0.unpack())?, |
1176 | )) |
1177 | } |
1178 | |
1179 | pub fn val_type<T: ?Sized + Reencode>( |
1180 | reencoder: &mut T, |
1181 | val_ty: wasmparser::ValType, |
1182 | ) -> Result<crate::ValType, Error<T::Error>> { |
1183 | Ok(match val_ty { |
1184 | wasmparser::ValType::I32 => crate::ValType::I32, |
1185 | wasmparser::ValType::I64 => crate::ValType::I64, |
1186 | wasmparser::ValType::F32 => crate::ValType::F32, |
1187 | wasmparser::ValType::F64 => crate::ValType::F64, |
1188 | wasmparser::ValType::V128 => crate::ValType::V128, |
1189 | wasmparser::ValType::Ref(r) => crate::ValType::Ref(reencoder.ref_type(r)?), |
1190 | }) |
1191 | } |
1192 | |
1193 | pub fn ref_type<T: ?Sized + Reencode>( |
1194 | reencoder: &mut T, |
1195 | ref_type: wasmparser::RefType, |
1196 | ) -> Result<crate::RefType, Error<T::Error>> { |
1197 | Ok(crate::RefType { |
1198 | nullable: ref_type.is_nullable(), |
1199 | heap_type: reencoder.heap_type(ref_type.heap_type())?, |
1200 | }) |
1201 | } |
1202 | |
1203 | pub fn heap_type<T: ?Sized + Reencode>( |
1204 | reencoder: &mut T, |
1205 | heap_type: wasmparser::HeapType, |
1206 | ) -> Result<crate::HeapType, Error<T::Error>> { |
1207 | Ok(match heap_type { |
1208 | wasmparser::HeapType::Concrete(i) => { |
1209 | crate::HeapType::Concrete(reencoder.type_index_unpacked(i)?) |
1210 | } |
1211 | wasmparser::HeapType::Abstract { shared, ty } => crate::HeapType::Abstract { |
1212 | shared, |
1213 | ty: reencoder.abstract_heap_type(ty), |
1214 | }, |
1215 | }) |
1216 | } |
1217 | |
1218 | /// Parses the input `section` given from the `wasmparser` crate and adds |
1219 | /// all the tables to the `tables` section. |
1220 | pub fn parse_table_section<T: ?Sized + Reencode>( |
1221 | reencoder: &mut T, |
1222 | tables: &mut crate::TableSection, |
1223 | section: wasmparser::TableSectionReader<'_>, |
1224 | ) -> Result<(), Error<T::Error>> { |
1225 | for table in section { |
1226 | reencoder.parse_table(tables, table?)?; |
1227 | } |
1228 | Ok(()) |
1229 | } |
1230 | |
1231 | /// Parses a single [`wasmparser::Table`] and adds it to the `tables` section. |
1232 | pub fn parse_table<T: ?Sized + Reencode>( |
1233 | reencoder: &mut T, |
1234 | tables: &mut crate::TableSection, |
1235 | table: wasmparser::Table<'_>, |
1236 | ) -> Result<(), Error<T::Error>> { |
1237 | let ty = reencoder.table_type(table.ty)?; |
1238 | match table.init { |
1239 | wasmparser::TableInit::RefNull => { |
1240 | tables.table(ty); |
1241 | } |
1242 | wasmparser::TableInit::Expr(e) => { |
1243 | tables.table_with_init(ty, &reencoder.const_expr(e)?); |
1244 | } |
1245 | } |
1246 | Ok(()) |
1247 | } |
1248 | |
1249 | pub fn table_type<T: ?Sized + Reencode>( |
1250 | reencoder: &mut T, |
1251 | table_ty: wasmparser::TableType, |
1252 | ) -> Result<crate::TableType, Error<T::Error>> { |
1253 | Ok(crate::TableType { |
1254 | element_type: reencoder.ref_type(table_ty.element_type)?, |
1255 | minimum: table_ty.initial, |
1256 | maximum: table_ty.maximum, |
1257 | table64: table_ty.table64, |
1258 | shared: table_ty.shared, |
1259 | }) |
1260 | } |
1261 | |
1262 | /// Parses the input `section` given from the `wasmparser` crate and adds |
1263 | /// all the tags to the `tags` section. |
1264 | pub fn parse_tag_section<T: ?Sized + Reencode>( |
1265 | reencoder: &mut T, |
1266 | tags: &mut crate::TagSection, |
1267 | section: wasmparser::TagSectionReader<'_>, |
1268 | ) -> Result<(), Error<T::Error>> { |
1269 | for tag in section { |
1270 | let tag = tag?; |
1271 | tags.tag(reencoder.tag_type(tag)); |
1272 | } |
1273 | Ok(()) |
1274 | } |
1275 | |
1276 | /// Parses the input `section` given from the `wasmparser` crate and adds |
1277 | /// all the exports to the `exports` section. |
1278 | pub fn parse_export_section<T: ?Sized + Reencode>( |
1279 | reencoder: &mut T, |
1280 | exports: &mut crate::ExportSection, |
1281 | section: wasmparser::ExportSectionReader<'_>, |
1282 | ) -> Result<(), Error<T::Error>> { |
1283 | for export in section { |
1284 | reencoder.parse_export(exports, export?); |
1285 | } |
1286 | Ok(()) |
1287 | } |
1288 | |
1289 | /// Parses the single [`wasmparser::Export`] provided and adds it to the |
1290 | /// `exports` section. |
1291 | pub fn parse_export<T: ?Sized + Reencode>( |
1292 | reencoder: &mut T, |
1293 | exports: &mut crate::ExportSection, |
1294 | export: wasmparser::Export<'_>, |
1295 | ) { |
1296 | exports.export( |
1297 | export.name, |
1298 | reencoder.export_kind(export.kind), |
1299 | reencoder.external_index(export.kind, export.index), |
1300 | ); |
1301 | } |
1302 | |
1303 | /// Parses the input `section` given from the `wasmparser` crate and adds |
1304 | /// all the globals to the `globals` section. |
1305 | pub fn parse_global_section<T: ?Sized + Reencode>( |
1306 | reencoder: &mut T, |
1307 | globals: &mut crate::GlobalSection, |
1308 | section: wasmparser::GlobalSectionReader<'_>, |
1309 | ) -> Result<(), Error<T::Error>> { |
1310 | for global in section { |
1311 | reencoder.parse_global(globals, global?)?; |
1312 | } |
1313 | Ok(()) |
1314 | } |
1315 | |
1316 | /// Parses the single [`wasmparser::Global`] provided and adds it to the |
1317 | /// `globals` section. |
1318 | pub fn parse_global<T: ?Sized + Reencode>( |
1319 | reencoder: &mut T, |
1320 | globals: &mut crate::GlobalSection, |
1321 | global: wasmparser::Global<'_>, |
1322 | ) -> Result<(), Error<T::Error>> { |
1323 | globals.global( |
1324 | reencoder.global_type(global.ty)?, |
1325 | &reencoder.const_expr(global.init_expr)?, |
1326 | ); |
1327 | Ok(()) |
1328 | } |
1329 | |
1330 | pub fn global_type<T: ?Sized + Reencode>( |
1331 | reencoder: &mut T, |
1332 | global_ty: wasmparser::GlobalType, |
1333 | ) -> Result<crate::GlobalType, Error<T::Error>> { |
1334 | Ok(crate::GlobalType { |
1335 | val_type: reencoder.val_type(global_ty.content_type)?, |
1336 | mutable: global_ty.mutable, |
1337 | shared: global_ty.shared, |
1338 | }) |
1339 | } |
1340 | |
1341 | pub fn entity_type<T: ?Sized + Reencode>( |
1342 | reencoder: &mut T, |
1343 | type_ref: wasmparser::TypeRef, |
1344 | ) -> Result<crate::EntityType, Error<T::Error>> { |
1345 | Ok(match type_ref { |
1346 | wasmparser::TypeRef::Func(i) => crate::EntityType::Function(reencoder.type_index(i)), |
1347 | wasmparser::TypeRef::Table(t) => crate::EntityType::Table(reencoder.table_type(t)?), |
1348 | wasmparser::TypeRef::Memory(m) => crate::EntityType::Memory(reencoder.memory_type(m)), |
1349 | wasmparser::TypeRef::Global(g) => crate::EntityType::Global(reencoder.global_type(g)?), |
1350 | wasmparser::TypeRef::Tag(t) => crate::EntityType::Tag(reencoder.tag_type(t)), |
1351 | }) |
1352 | } |
1353 | |
1354 | /// Parses the input `section` given from the `wasmparser` crate and adds |
1355 | /// all the imports to the `import` section. |
1356 | pub fn parse_import_section<T: ?Sized + Reencode>( |
1357 | reencoder: &mut T, |
1358 | imports: &mut crate::ImportSection, |
1359 | section: wasmparser::ImportSectionReader<'_>, |
1360 | ) -> Result<(), Error<T::Error>> { |
1361 | for import in section { |
1362 | reencoder.parse_import(imports, import?)?; |
1363 | } |
1364 | Ok(()) |
1365 | } |
1366 | |
1367 | /// Parses the single [`wasmparser::Import`] provided and adds it to the |
1368 | /// `import` section. |
1369 | pub fn parse_import<T: ?Sized + Reencode>( |
1370 | reencoder: &mut T, |
1371 | imports: &mut crate::ImportSection, |
1372 | import: wasmparser::Import<'_>, |
1373 | ) -> Result<(), Error<T::Error>> { |
1374 | imports.import( |
1375 | import.module, |
1376 | import.name, |
1377 | reencoder.entity_type(import.ty)?, |
1378 | ); |
1379 | Ok(()) |
1380 | } |
1381 | |
1382 | /// Parses the input `section` given from the `wasmparser` crate and adds |
1383 | /// all the memories to the `memories` section. |
1384 | pub fn parse_memory_section<T: ?Sized + Reencode>( |
1385 | reencoder: &mut T, |
1386 | memories: &mut crate::MemorySection, |
1387 | section: wasmparser::MemorySectionReader<'_>, |
1388 | ) -> Result<(), Error<T::Error>> { |
1389 | for memory in section { |
1390 | let memory = memory?; |
1391 | memories.memory(reencoder.memory_type(memory)); |
1392 | } |
1393 | Ok(()) |
1394 | } |
1395 | |
1396 | /// Parses the input `section` given from the `wasmparser` crate and adds |
1397 | /// all the functions to the `functions` section. |
1398 | pub fn parse_function_section<T: ?Sized + Reencode>( |
1399 | reencoder: &mut T, |
1400 | functions: &mut crate::FunctionSection, |
1401 | section: wasmparser::FunctionSectionReader<'_>, |
1402 | ) -> Result<(), Error<T::Error>> { |
1403 | for func in section { |
1404 | functions.function(reencoder.type_index(func?)); |
1405 | } |
1406 | Ok(()) |
1407 | } |
1408 | |
1409 | /// Parses the input `section` given from the `wasmparser` crate and adds |
1410 | /// all the data to the `data` section. |
1411 | pub fn parse_data_section<T: ?Sized + Reencode>( |
1412 | reencoder: &mut T, |
1413 | data: &mut crate::DataSection, |
1414 | section: wasmparser::DataSectionReader<'_>, |
1415 | ) -> Result<(), Error<T::Error>> { |
1416 | for datum in section { |
1417 | reencoder.parse_data(data, datum?)?; |
1418 | } |
1419 | Ok(()) |
1420 | } |
1421 | |
1422 | /// Parses a single [`wasmparser::Data`] and adds it to the `data` section. |
1423 | pub fn parse_data<T: ?Sized + Reencode>( |
1424 | reencoder: &mut T, |
1425 | data: &mut crate::DataSection, |
1426 | datum: wasmparser::Data<'_>, |
1427 | ) -> Result<(), Error<T::Error>> { |
1428 | match datum.kind { |
1429 | wasmparser::DataKind::Active { |
1430 | memory_index, |
1431 | offset_expr, |
1432 | } => data.active( |
1433 | reencoder.memory_index(memory_index), |
1434 | &reencoder.const_expr(offset_expr)?, |
1435 | datum.data.iter().copied(), |
1436 | ), |
1437 | wasmparser::DataKind::Passive => data.passive(datum.data.iter().copied()), |
1438 | }; |
1439 | Ok(()) |
1440 | } |
1441 | |
1442 | /// Parses the input `section` given from the `wasmparser` crate and adds |
1443 | /// all the elements to the `element` section. |
1444 | pub fn parse_element_section<T: ?Sized + Reencode>( |
1445 | reencoder: &mut T, |
1446 | elements: &mut crate::ElementSection, |
1447 | section: wasmparser::ElementSectionReader<'_>, |
1448 | ) -> Result<(), Error<T::Error>> { |
1449 | for element in section { |
1450 | reencoder.parse_element(elements, element?)?; |
1451 | } |
1452 | Ok(()) |
1453 | } |
1454 | |
1455 | /// Parses the single [`wasmparser::Element`] provided and adds it to the |
1456 | /// `element` section. |
1457 | pub fn parse_element<T: ?Sized + Reencode>( |
1458 | reencoder: &mut T, |
1459 | elements: &mut crate::ElementSection, |
1460 | element: wasmparser::Element<'_>, |
1461 | ) -> Result<(), Error<T::Error>> { |
1462 | let elems = reencoder.element_items(element.items)?; |
1463 | match element.kind { |
1464 | wasmparser::ElementKind::Active { |
1465 | table_index, |
1466 | offset_expr, |
1467 | } => elements.active( |
1468 | // Inform the reencoder that a table index is being used even if |
1469 | // it's not actually present here. That helps wasm-mutate for |
1470 | // example which wants to track uses to know when it's ok to |
1471 | // remove a table. |
1472 | // |
1473 | // If the table index started at `None` and is still zero then |
1474 | // preserve this encoding and keep it at `None`. Otherwise if |
1475 | // the result is nonzero or it was previously nonzero then keep |
1476 | // that encoding too. |
1477 | match (table_index, reencoder.table_index(table_index.unwrap_or(0))) { |
1478 | (None, 0) => None, |
1479 | (_, n) => Some(n), |
1480 | }, |
1481 | &reencoder.const_expr(offset_expr)?, |
1482 | elems, |
1483 | ), |
1484 | wasmparser::ElementKind::Passive => elements.passive(elems), |
1485 | wasmparser::ElementKind::Declared => elements.declared(elems), |
1486 | }; |
1487 | Ok(()) |
1488 | } |
1489 | |
1490 | pub fn element_items<'a, T: ?Sized + Reencode>( |
1491 | reencoder: &mut T, |
1492 | items: wasmparser::ElementItems<'a>, |
1493 | ) -> Result<crate::Elements<'a>, Error<T::Error>> { |
1494 | Ok(match items { |
1495 | wasmparser::ElementItems::Functions(f) => { |
1496 | let mut funcs = Vec::new(); |
1497 | for func in f { |
1498 | funcs.push(reencoder.function_index(func?)); |
1499 | } |
1500 | crate::Elements::Functions(funcs.into()) |
1501 | } |
1502 | wasmparser::ElementItems::Expressions(ty, e) => { |
1503 | let mut exprs = Vec::new(); |
1504 | for expr in e { |
1505 | exprs.push(reencoder.const_expr(expr?)?); |
1506 | } |
1507 | crate::Elements::Expressions(reencoder.ref_type(ty)?, exprs.into()) |
1508 | } |
1509 | }) |
1510 | } |
1511 | |
1512 | pub fn table_index<T: ?Sized + Reencode>(_reencoder: &mut T, table: u32) -> u32 { |
1513 | table |
1514 | } |
1515 | |
1516 | pub fn global_index<T: ?Sized + Reencode>(_reencoder: &mut T, global: u32) -> u32 { |
1517 | global |
1518 | } |
1519 | |
1520 | pub fn data_index<T: ?Sized + Reencode>(_reencoder: &mut T, data: u32) -> u32 { |
1521 | data |
1522 | } |
1523 | |
1524 | pub fn element_index<T: ?Sized + Reencode>(_reencoder: &mut T, element: u32) -> u32 { |
1525 | element |
1526 | } |
1527 | |
1528 | pub fn const_expr<T: ?Sized + Reencode>( |
1529 | reencoder: &mut T, |
1530 | const_expr: wasmparser::ConstExpr, |
1531 | ) -> Result<crate::ConstExpr, Error<T::Error>> { |
1532 | let mut ops = const_expr.get_operators_reader(); |
1533 | let mut bytes = Vec::new(); |
1534 | |
1535 | while !ops.is_end_then_eof() { |
1536 | let insn = reencoder.parse_instruction(&mut ops)?; |
1537 | insn.encode(&mut bytes); |
1538 | } |
1539 | |
1540 | Ok(crate::ConstExpr::raw(bytes)) |
1541 | } |
1542 | |
1543 | pub fn block_type<T: ?Sized + Reencode>( |
1544 | reencoder: &mut T, |
1545 | arg: wasmparser::BlockType, |
1546 | ) -> Result<crate::BlockType, Error<T::Error>> { |
1547 | match arg { |
1548 | wasmparser::BlockType::Empty => Ok(crate::BlockType::Empty), |
1549 | wasmparser::BlockType::FuncType(n) => { |
1550 | Ok(crate::BlockType::FunctionType(reencoder.type_index(n))) |
1551 | } |
1552 | wasmparser::BlockType::Type(t) => Ok(crate::BlockType::Result(reencoder.val_type(t)?)), |
1553 | } |
1554 | } |
1555 | |
1556 | pub fn instruction<'a, T: ?Sized + Reencode>( |
1557 | reencoder: &mut T, |
1558 | arg: wasmparser::Operator<'a>, |
1559 | ) -> Result<crate::Instruction<'a>, Error<T::Error>> { |
1560 | use crate::Instruction; |
1561 | |
1562 | macro_rules! translate { |
1563 | ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => { |
1564 | Ok(match arg { |
1565 | $( |
1566 | wasmparser::Operator::$op $({ $($arg),* })? => { |
1567 | $( |
1568 | $(let $arg = translate!(map $arg $arg);)* |
1569 | )? |
1570 | translate!(build $op $($($arg)*)?) |
1571 | } |
1572 | )* |
1573 | unexpected => unreachable!("encountered unexpected Wasm operator: {unexpected:?}" ), |
1574 | }) |
1575 | }; |
1576 | |
1577 | // This case is used to map, based on the name of the field, from the |
1578 | // wasmparser payload type to the wasm-encoder payload type through |
1579 | // `Translator` as applicable. |
1580 | (map $arg:ident tag_index) => (reencoder.tag_index($arg)); |
1581 | (map $arg:ident function_index) => (reencoder.function_index($arg)); |
1582 | (map $arg:ident table) => (reencoder.table_index($arg)); |
1583 | (map $arg:ident table_index) => (reencoder.table_index($arg)); |
1584 | (map $arg:ident dst_table) => (reencoder.table_index($arg)); |
1585 | (map $arg:ident src_table) => (reencoder.table_index($arg)); |
1586 | (map $arg:ident type_index) => (reencoder.type_index($arg)); |
1587 | (map $arg:ident array_type_index) => (reencoder.type_index($arg)); |
1588 | (map $arg:ident array_type_index_dst) => (reencoder.type_index($arg)); |
1589 | (map $arg:ident array_type_index_src) => (reencoder.type_index($arg)); |
1590 | (map $arg:ident struct_type_index) => (reencoder.type_index($arg)); |
1591 | (map $arg:ident global_index) => (reencoder.global_index($arg)); |
1592 | (map $arg:ident mem) => (reencoder.memory_index($arg)); |
1593 | (map $arg:ident src_mem) => (reencoder.memory_index($arg)); |
1594 | (map $arg:ident dst_mem) => (reencoder.memory_index($arg)); |
1595 | (map $arg:ident data_index) => (reencoder.data_index($arg)); |
1596 | (map $arg:ident elem_index) => (reencoder.element_index($arg)); |
1597 | (map $arg:ident array_data_index) => (reencoder.data_index($arg)); |
1598 | (map $arg:ident array_elem_index) => (reencoder.element_index($arg)); |
1599 | (map $arg:ident blockty) => (reencoder.block_type($arg)?); |
1600 | (map $arg:ident relative_depth) => ($arg); |
1601 | (map $arg:ident targets) => (( |
1602 | $arg |
1603 | .targets() |
1604 | .collect::<Result<Vec<_>, wasmparser::BinaryReaderError>>()? |
1605 | .into(), |
1606 | $arg.default(), |
1607 | )); |
1608 | (map $arg:ident ty) => (reencoder.val_type($arg)?); |
1609 | (map $arg:ident hty) => (reencoder.heap_type($arg)?); |
1610 | (map $arg:ident from_ref_type) => (reencoder.ref_type($arg)?); |
1611 | (map $arg:ident to_ref_type) => (reencoder.ref_type($arg)?); |
1612 | (map $arg:ident memarg) => (reencoder.mem_arg($arg)); |
1613 | (map $arg:ident ordering) => (reencoder.ordering($arg)); |
1614 | (map $arg:ident local_index) => ($arg); |
1615 | (map $arg:ident value) => ($arg); |
1616 | (map $arg:ident lane) => ($arg); |
1617 | (map $arg:ident lanes) => ($arg); |
1618 | (map $arg:ident array_size) => ($arg); |
1619 | (map $arg:ident field_index) => ($arg); |
1620 | (map $arg:ident try_table) => ($arg); |
1621 | (map $arg:ident argument_index) => (reencoder.type_index($arg)); |
1622 | (map $arg:ident result_index) => (reencoder.type_index($arg)); |
1623 | (map $arg:ident cont_type_index) => (reencoder.type_index($arg)); |
1624 | (map $arg:ident resume_table) => (( |
1625 | $arg.handlers.into_iter().map(|h| reencoder.handle(h)).collect::<Vec<_>>().into() |
1626 | )); |
1627 | |
1628 | // This case takes the arguments of a wasmparser instruction and creates |
1629 | // a wasm-encoder instruction. There are a few special cases for where |
1630 | // the structure of a wasmparser instruction differs from that of |
1631 | // wasm-encoder. |
1632 | (build $op:ident) => (Instruction::$op); |
1633 | (build BrTable $arg:ident) => (Instruction::BrTable($arg.0, $arg.1)); |
1634 | (build I32Const $arg:ident) => (Instruction::I32Const($arg)); |
1635 | (build I64Const $arg:ident) => (Instruction::I64Const($arg)); |
1636 | (build F32Const $arg:ident) => (Instruction::F32Const(f32::from_bits($arg.bits()))); |
1637 | (build F64Const $arg:ident) => (Instruction::F64Const(f64::from_bits($arg.bits()))); |
1638 | (build V128Const $arg:ident) => (Instruction::V128Const($arg.i128())); |
1639 | (build TryTable $table:ident) => (Instruction::TryTable(reencoder.block_type($table.ty)?, { |
1640 | $table.catches.into_iter().map(|c| reencoder.catch(c)).collect::<Vec<_>>().into() |
1641 | })); |
1642 | (build $op:ident $arg:ident) => (Instruction::$op($arg)); |
1643 | (build $op:ident $($arg:ident)*) => (Instruction::$op { $($arg),* }); |
1644 | } |
1645 | |
1646 | wasmparser::for_each_operator!(translate) |
1647 | } |
1648 | |
1649 | /// Parses the input `section` given from the `wasmparser` crate and adds |
1650 | /// all the code to the `code` section. |
1651 | pub fn parse_code_section<T: ?Sized + Reencode>( |
1652 | reencoder: &mut T, |
1653 | code: &mut crate::CodeSection, |
1654 | section: wasmparser::CodeSectionReader<'_>, |
1655 | ) -> Result<(), Error<T::Error>> { |
1656 | for func in section { |
1657 | reencoder.parse_function_body(code, func?)?; |
1658 | } |
1659 | Ok(()) |
1660 | } |
1661 | |
1662 | /// Parses a single [`wasmparser::FunctionBody`] and adds it to the `code` section. |
1663 | pub fn parse_function_body<T: ?Sized + Reencode>( |
1664 | reencoder: &mut T, |
1665 | code: &mut crate::CodeSection, |
1666 | func: wasmparser::FunctionBody<'_>, |
1667 | ) -> Result<(), Error<T::Error>> { |
1668 | let mut f = reencoder.new_function_with_parsed_locals(&func)?; |
1669 | let mut reader = func.get_operators_reader()?; |
1670 | while !reader.eof() { |
1671 | f.instruction(&reencoder.parse_instruction(&mut reader)?); |
1672 | } |
1673 | code.function(&f); |
1674 | Ok(()) |
1675 | } |
1676 | |
1677 | /// Create a new [`crate::Function`] by parsing the locals declarations from the |
1678 | /// provided [`wasmparser::FunctionBody`]. |
1679 | pub fn new_function_with_parsed_locals<T: ?Sized + Reencode>( |
1680 | reencoder: &mut T, |
1681 | func: &wasmparser::FunctionBody<'_>, |
1682 | ) -> Result<crate::Function, Error<T::Error>> { |
1683 | let mut locals = Vec::new(); |
1684 | for pair in func.get_locals_reader()? { |
1685 | let (cnt, ty) = pair?; |
1686 | locals.push((cnt, reencoder.val_type(ty)?)); |
1687 | } |
1688 | Ok(crate::Function::new(locals)) |
1689 | } |
1690 | |
1691 | /// Parses a single instruction from `reader` and adds it to `function`. |
1692 | pub fn parse_instruction<'a, T: ?Sized + Reencode>( |
1693 | reencoder: &mut T, |
1694 | reader: &mut wasmparser::OperatorsReader<'a>, |
1695 | ) -> Result<crate::Instruction<'a>, Error<T::Error>> { |
1696 | let instruction = reencoder.instruction(reader.read()?)?; |
1697 | Ok(instruction) |
1698 | } |
1699 | |
1700 | pub fn parse_unknown_section<T: ?Sized + Reencode>( |
1701 | _reencoder: &mut T, |
1702 | module: &mut crate::Module, |
1703 | id: u8, |
1704 | contents: &[u8], |
1705 | ) -> Result<(), Error<T::Error>> { |
1706 | module.section(&crate::RawSection { id, data: contents }); |
1707 | Ok(()) |
1708 | } |
1709 | |
1710 | pub fn custom_name_section<T: ?Sized + Reencode>( |
1711 | reencoder: &mut T, |
1712 | section: wasmparser::NameSectionReader<'_>, |
1713 | ) -> Result<crate::NameSection, Error<T::Error>> { |
1714 | let mut ret = crate::NameSection::new(); |
1715 | for subsection in section { |
1716 | reencoder.parse_custom_name_subsection(&mut ret, subsection?)?; |
1717 | } |
1718 | Ok(ret) |
1719 | } |
1720 | |
1721 | pub fn parse_custom_name_subsection<T: ?Sized + Reencode>( |
1722 | reencoder: &mut T, |
1723 | names: &mut crate::NameSection, |
1724 | section: wasmparser::Name<'_>, |
1725 | ) -> Result<(), Error<T::Error>> { |
1726 | match section { |
1727 | wasmparser::Name::Module { name, .. } => { |
1728 | names.module(name); |
1729 | } |
1730 | wasmparser::Name::Function(map) => { |
1731 | names.functions(&name_map(map, |i| reencoder.function_index(i))?); |
1732 | } |
1733 | wasmparser::Name::Type(map) => { |
1734 | names.types(&name_map(map, |i| reencoder.type_index(i))?); |
1735 | } |
1736 | wasmparser::Name::Local(map) => { |
1737 | names.locals(&indirect_name_map(map, |i| reencoder.function_index(i))?); |
1738 | } |
1739 | wasmparser::Name::Label(map) => { |
1740 | names.labels(&indirect_name_map(map, |i| reencoder.function_index(i))?); |
1741 | } |
1742 | wasmparser::Name::Table(map) => { |
1743 | names.tables(&name_map(map, |i| reencoder.table_index(i))?); |
1744 | } |
1745 | wasmparser::Name::Memory(map) => { |
1746 | names.memories(&name_map(map, |i| reencoder.memory_index(i))?); |
1747 | } |
1748 | wasmparser::Name::Global(map) => { |
1749 | names.globals(&name_map(map, |i| reencoder.global_index(i))?); |
1750 | } |
1751 | wasmparser::Name::Element(map) => { |
1752 | names.elements(&name_map(map, |i| reencoder.element_index(i))?); |
1753 | } |
1754 | wasmparser::Name::Data(map) => { |
1755 | names.data(&name_map(map, |i| reencoder.data_index(i))?); |
1756 | } |
1757 | wasmparser::Name::Tag(map) => { |
1758 | names.tags(&name_map(map, |i| reencoder.tag_index(i))?); |
1759 | } |
1760 | wasmparser::Name::Field(map) => { |
1761 | names.fields(&indirect_name_map(map, |i| reencoder.type_index(i))?); |
1762 | } |
1763 | wasmparser::Name::Unknown { ty, data, .. } => { |
1764 | names.raw(ty, data); |
1765 | } |
1766 | } |
1767 | Ok(()) |
1768 | } |
1769 | |
1770 | pub fn name_map( |
1771 | map: wasmparser::NameMap<'_>, |
1772 | mut map_index: impl FnMut(u32) -> u32, |
1773 | ) -> wasmparser::Result<crate::NameMap> { |
1774 | let mut ret = crate::NameMap::new(); |
1775 | for naming in map { |
1776 | let naming = naming?; |
1777 | ret.append(map_index(naming.index), naming.name); |
1778 | } |
1779 | Ok(ret) |
1780 | } |
1781 | |
1782 | pub fn indirect_name_map( |
1783 | map: wasmparser::IndirectNameMap<'_>, |
1784 | mut map_index: impl FnMut(u32) -> u32, |
1785 | ) -> wasmparser::Result<crate::IndirectNameMap> { |
1786 | let mut ret = crate::IndirectNameMap::new(); |
1787 | for naming in map { |
1788 | let naming = naming?; |
1789 | ret.append(map_index(naming.index), &name_map(naming.names, |i| i)?); |
1790 | } |
1791 | Ok(ret) |
1792 | } |
1793 | } |
1794 | |
1795 | impl From<wasmparser::MemArg> for crate::MemArg { |
1796 | fn from(arg: wasmparser::MemArg) -> Self { |
1797 | RoundtripReencoder.mem_arg(arg) |
1798 | } |
1799 | } |
1800 | |
1801 | impl From<wasmparser::Ordering> for crate::Ordering { |
1802 | fn from(arg: wasmparser::Ordering) -> Self { |
1803 | RoundtripReencoder.ordering(arg) |
1804 | } |
1805 | } |
1806 | |
1807 | impl TryFrom<wasmparser::BlockType> for crate::BlockType { |
1808 | type Error = Error; |
1809 | |
1810 | fn try_from(arg: wasmparser::BlockType) -> Result<Self, Self::Error> { |
1811 | RoundtripReencoder.block_type(arg) |
1812 | } |
1813 | } |
1814 | |
1815 | impl<'a> TryFrom<wasmparser::Operator<'a>> for crate::Instruction<'a> { |
1816 | type Error = Error; |
1817 | |
1818 | fn try_from(arg: wasmparser::Operator<'a>) -> Result<Self, Self::Error> { |
1819 | RoundtripReencoder.instruction(arg) |
1820 | } |
1821 | } |
1822 | |
1823 | impl From<wasmparser::Catch> for crate::Catch { |
1824 | fn from(arg: wasmparser::Catch) -> Self { |
1825 | RoundtripReencoder.catch(arg) |
1826 | } |
1827 | } |
1828 | |
1829 | impl<'a> TryFrom<wasmparser::ConstExpr<'a>> for crate::ConstExpr { |
1830 | type Error = Error; |
1831 | |
1832 | fn try_from(const_expr: wasmparser::ConstExpr) -> Result<Self, Self::Error> { |
1833 | RoundtripReencoder.const_expr(const_expr) |
1834 | } |
1835 | } |
1836 | |
1837 | impl<'a> From<wasmparser::CustomSectionReader<'a>> for crate::CustomSection<'a> { |
1838 | fn from(section: wasmparser::CustomSectionReader<'a>) -> Self { |
1839 | RoundtripReencoder.custom_section(section) |
1840 | } |
1841 | } |
1842 | |
1843 | impl From<wasmparser::ExternalKind> for crate::ExportKind { |
1844 | fn from(external_kind: wasmparser::ExternalKind) -> Self { |
1845 | RoundtripReencoder.export_kind(external_kind) |
1846 | } |
1847 | } |
1848 | |
1849 | impl TryFrom<wasmparser::GlobalType> for crate::GlobalType { |
1850 | type Error = Error; |
1851 | |
1852 | fn try_from(global_ty: wasmparser::GlobalType) -> Result<Self, Self::Error> { |
1853 | RoundtripReencoder.global_type(global_ty) |
1854 | } |
1855 | } |
1856 | |
1857 | impl From<wasmparser::Handle> for crate::Handle { |
1858 | fn from(arg: wasmparser::Handle) -> Self { |
1859 | RoundtripReencoder.handle(on:arg) |
1860 | } |
1861 | } |
1862 | |
1863 | impl TryFrom<wasmparser::TypeRef> for crate::EntityType { |
1864 | type Error = Error; |
1865 | |
1866 | fn try_from(type_ref: wasmparser::TypeRef) -> Result<Self, Self::Error> { |
1867 | RoundtripReencoder.entity_type(type_ref) |
1868 | } |
1869 | } |
1870 | |
1871 | impl From<wasmparser::MemoryType> for crate::MemoryType { |
1872 | fn from(memory_ty: wasmparser::MemoryType) -> Self { |
1873 | RoundtripReencoder.memory_type(memory_ty) |
1874 | } |
1875 | } |
1876 | |
1877 | impl TryFrom<wasmparser::TableType> for crate::TableType { |
1878 | type Error = Error; |
1879 | |
1880 | fn try_from(table_ty: wasmparser::TableType) -> Result<Self, Self::Error> { |
1881 | RoundtripReencoder.table_type(table_ty) |
1882 | } |
1883 | } |
1884 | |
1885 | impl From<wasmparser::TagKind> for crate::TagKind { |
1886 | fn from(kind: wasmparser::TagKind) -> Self { |
1887 | RoundtripReencoder.tag_kind(kind) |
1888 | } |
1889 | } |
1890 | |
1891 | impl From<wasmparser::TagType> for crate::TagType { |
1892 | fn from(tag_ty: wasmparser::TagType) -> Self { |
1893 | RoundtripReencoder.tag_type(tag_ty) |
1894 | } |
1895 | } |
1896 | |
1897 | impl TryFrom<wasmparser::SubType> for crate::SubType { |
1898 | type Error = Error; |
1899 | |
1900 | fn try_from(sub_ty: wasmparser::SubType) -> Result<Self, Self::Error> { |
1901 | RoundtripReencoder.sub_type(sub_ty) |
1902 | } |
1903 | } |
1904 | |
1905 | impl TryFrom<wasmparser::CompositeType> for crate::CompositeType { |
1906 | type Error = Error; |
1907 | |
1908 | fn try_from(composite_ty: wasmparser::CompositeType) -> Result<Self, Self::Error> { |
1909 | RoundtripReencoder.composite_type(composite_ty) |
1910 | } |
1911 | } |
1912 | |
1913 | impl TryFrom<wasmparser::FuncType> for crate::FuncType { |
1914 | type Error = Error; |
1915 | |
1916 | fn try_from(func_ty: wasmparser::FuncType) -> Result<Self, Self::Error> { |
1917 | RoundtripReencoder.func_type(func_ty) |
1918 | } |
1919 | } |
1920 | |
1921 | impl TryFrom<wasmparser::ArrayType> for crate::ArrayType { |
1922 | type Error = Error; |
1923 | |
1924 | fn try_from(array_ty: wasmparser::ArrayType) -> Result<Self, Self::Error> { |
1925 | RoundtripReencoder.array_type(array_ty) |
1926 | } |
1927 | } |
1928 | |
1929 | impl TryFrom<wasmparser::StructType> for crate::StructType { |
1930 | type Error = Error; |
1931 | |
1932 | fn try_from(struct_ty: wasmparser::StructType) -> Result<Self, Self::Error> { |
1933 | RoundtripReencoder.struct_type(struct_ty) |
1934 | } |
1935 | } |
1936 | |
1937 | impl TryFrom<wasmparser::FieldType> for crate::FieldType { |
1938 | type Error = Error; |
1939 | |
1940 | fn try_from(field_ty: wasmparser::FieldType) -> Result<Self, Self::Error> { |
1941 | RoundtripReencoder.field_type(field_ty) |
1942 | } |
1943 | } |
1944 | |
1945 | impl TryFrom<wasmparser::StorageType> for crate::StorageType { |
1946 | type Error = Error; |
1947 | |
1948 | fn try_from(storage_ty: wasmparser::StorageType) -> Result<Self, Self::Error> { |
1949 | RoundtripReencoder.storage_type(storage_ty) |
1950 | } |
1951 | } |
1952 | |
1953 | impl TryFrom<wasmparser::ValType> for crate::ValType { |
1954 | type Error = Error; |
1955 | |
1956 | fn try_from(val_ty: wasmparser::ValType) -> Result<Self, Self::Error> { |
1957 | RoundtripReencoder.val_type(val_ty) |
1958 | } |
1959 | } |
1960 | |
1961 | impl TryFrom<wasmparser::RefType> for crate::RefType { |
1962 | type Error = Error; |
1963 | |
1964 | fn try_from(ref_type: wasmparser::RefType) -> Result<Self, Self::Error> { |
1965 | RoundtripReencoder.ref_type(ref_type) |
1966 | } |
1967 | } |
1968 | |
1969 | impl TryFrom<wasmparser::HeapType> for crate::HeapType { |
1970 | type Error = Error; |
1971 | |
1972 | fn try_from(heap_type: wasmparser::HeapType) -> Result<Self, Self::Error> { |
1973 | crate::reencode::utils::heap_type(&mut crate::reencode::RoundtripReencoder, heap_type) |
1974 | } |
1975 | } |
1976 | |
1977 | impl From<wasmparser::AbstractHeapType> for crate::AbstractHeapType { |
1978 | fn from(value: wasmparser::AbstractHeapType) -> Self { |
1979 | RoundtripReencoder.abstract_heap_type(value) |
1980 | } |
1981 | } |
1982 | |