//! Conversions from `wasmparser` to `wasm-encoder` to [`Reencode`] parsed wasm. //! //! The [`RoundtripReencoder`] allows encoding identical wasm to the parsed //! input.
usecrate::CoreTypeEncoder; use core::convert::Infallible; use core::error::Error as StdError;
#[cfg(feature = "component-model")] mod component;
/// Parses the input `section` given from the `wasmparser` crate and /// adds the custom section to the `module`. fn parse_custom_section(
&mutself,
module: &mutcrate::Module,
section: wasmparser::CustomSectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_custom_section(self, module, section)
}
/// Converts the input `section` given from the `wasmparser` crate into an /// encoded custom section. fn custom_section<'a>(
&mutself,
section: wasmparser::CustomSectionReader<'a>,
) -> Result<crate::CustomSection<'a>, Error<Self::Error>> {
Ok(utils::custom_section(self, section))
}
/// Parses the input `section` given from the `wasmparser` crate and adds /// all the code to the `code` section. fn parse_code_section(
&mutself,
code: &mutcrate::CodeSection,
section: wasmparser::CodeSectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_code_section(self, code, section)
}
/// Parses a single [`wasmparser::FunctionBody`] and adds it to the `code` section. fn parse_function_body(
&mutself,
code: &mutcrate::CodeSection,
func: wasmparser::FunctionBody<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_function_body(self, code, func)
}
/// Create a new [`crate::Function`] by parsing the locals declarations from the /// provided [`wasmparser::FunctionBody`]. fn new_function_with_parsed_locals(
&mutself,
func: &wasmparser::FunctionBody<'_>,
) -> Result<crate::Function, Error<Self::Error>> {
utils::new_function_with_parsed_locals(self, func)
}
/// Parses a single instruction from `reader` and adds it to `function`. fn parse_instruction<'a>(
&mutself,
reader: &mut wasmparser::OperatorsReader<'a>,
) -> Result<crate::Instruction<'a>, Error<Self::Error>> {
utils::parse_instruction(self, reader)
}
/// Parses the input `section` given from the `wasmparser` crate and adds /// all the data to the `data` section. fn parse_data_section(
&mutself,
data: &mutcrate::DataSection,
section: wasmparser::DataSectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_data_section(self, data, section)
}
/// Parses a single [`wasmparser::Data`] and adds it to the `data` section. fn parse_data(
&mutself,
data: &mutcrate::DataSection,
datum: wasmparser::Data<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_data(self, data, datum)
}
/// Parses the input `section` given from the `wasmparser` crate and adds /// all the elements to the `element` section. fn parse_element_section(
&mutself,
elements: &mutcrate::ElementSection,
section: wasmparser::ElementSectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_element_section(self, elements, section)
}
/// Parses the single [`wasmparser::Element`] provided and adds it to the /// `element` section. fn parse_element(
&mutself,
elements: &mutcrate::ElementSection,
element: wasmparser::Element<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_element(self, elements, element)
}
/// Parses the input `section` given from the `wasmparser` crate and adds /// all the exports to the `exports` section. fn parse_export_section(
&mutself,
exports: &mutcrate::ExportSection,
section: wasmparser::ExportSectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_export_section(self, exports, section)
}
/// Parses the single [`wasmparser::Export`] provided and adds it to the /// `exports` section. fn parse_export(
&mutself,
exports: &mutcrate::ExportSection,
export: wasmparser::Export<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_export(self, exports, export)
}
/// Parses the input `section` given from the `wasmparser` crate and adds /// all the functions to the `functions` section. fn parse_function_section(
&mutself,
functions: &mutcrate::FunctionSection,
section: wasmparser::FunctionSectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_function_section(self, functions, section)
}
/// Parses the input `section` given from the `wasmparser` crate and adds /// all the globals to the `globals` section. fn parse_global_section(
&mutself,
globals: &mutcrate::GlobalSection,
section: wasmparser::GlobalSectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_global_section(self, globals, section)
}
/// Parses the single [`wasmparser::Global`] provided and adds it to the /// `globals` section. fn parse_global(
&mutself,
globals: &mutcrate::GlobalSection,
global: wasmparser::Global<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_global(self, globals, global)
}
/// Parses the input `section` given from the `wasmparser` crate and adds /// all the imports to the `import` section. fn parse_import_section(
&mutself,
imports: &mutcrate::ImportSection,
section: wasmparser::ImportSectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_import_section(self, imports, section)
}
/// Parses a [`wasmparser::Imports`] and adds all of its contents to the /// `import` section. fn parse_imports(
&mutself,
import_section: &mutcrate::ImportSection,
imports: wasmparser::Imports<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_imports(self, import_section, imports)
}
/// Parses the single [`wasmparser::Import`] provided and adds it to the /// `import` section. fn parse_import(
&mutself,
imports: &mutcrate::ImportSection,
import: wasmparser::Import<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_import(self, imports, import)
}
/// Parses the input `section` given from the `wasmparser` crate and adds /// all the memories to the `memories` section. fn parse_memory_section(
&mutself,
memories: &mutcrate::MemorySection,
section: wasmparser::MemorySectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_memory_section(self, memories, section)
}
/// Parses the input `section` given from the `wasmparser` crate and adds /// all the tables to the `tables` section. fn parse_table_section(
&mutself,
tables: &mutcrate::TableSection,
section: wasmparser::TableSectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_table_section(self, tables, section)
}
/// Parses a single [`wasmparser::Table`] and adds it to the `tables` section. fn parse_table(
&mutself,
tables: &mutcrate::TableSection,
table: wasmparser::Table<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_table(self, tables, table)
}
/// Parses the input `section` given from the `wasmparser` crate and adds /// all the tags to the `tags` section. fn parse_tag_section(
&mutself,
tags: &mutcrate::TagSection,
section: wasmparser::TagSectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_tag_section(self, tags, section)
}
/// Parses the input `section` given from the `wasmparser` crate and adds /// all the types to the `types` section. fn parse_type_section(
&mutself,
types: &mutcrate::TypeSection,
section: wasmparser::TypeSectionReader<'_>,
) -> Result<(), Error<Self::Error>> {
utils::parse_type_section(self, types, section)
}
/// Parses a single [`wasmparser::RecGroup`] and adds it to the `types` section. fn parse_recursive_type_group(
&mutself,
encoder: CoreTypeEncoder,
rec_group: wasmparser::RecGroup,
) -> Result<(), Error<Self::Error>> {
utils::parse_recursive_type_group(self, encoder, rec_group)
}
/// A hook method that is called inside [`Reencode::parse_core_module`] /// before and after every non-custom core wasm section. /// /// This method can be used to insert new custom sections in between those /// sections, or to detect when a non-custom section is missing and insert /// it in the [proper order]. /// /// The `after` parameter is `None` iff the hook is called before the first /// non-custom section, and `Some(s)` afterwards, where `s` is the /// [`SectionId`] of the previous non-custom section. /// /// The `before` parameter is `None` iff the hook is called after the last /// non-custom section, and `Some(s)` beforehand, where `s` is the /// [`SectionId`] of the following non-custom section. /// /// [proper order]: https://webassembly.github.io/spec/core/binary/modules.html#binary-module /// [`SectionId`]: crate::SectionId fn intersperse_section_hook(
&mutself,
module: &mutcrate::Module,
after: Option<crate::SectionId>,
before: Option<crate::SectionId>,
) -> Result<(), Error<Self::Error>> {
utils::intersperse_section_hook(self, module, after, before)
}
/// An error when re-encoding from `wasmparser` to `wasm-encoder`. #[derive(Debug)] pubenum Error<E = Infallible> { /// There was a type reference that was canonicalized and no longer /// references an index into a module's types space, so we cannot encode it /// into a Wasm binary again.
CanonicalizedHeapTypeReference, /// The const expression is invalid: not actually constant or something like /// that.
InvalidConstExpr, /// The code section size listed was not valid for the wasm binary provided.
InvalidCodeSectionSize, /// There was a section that does not belong in a core wasm module.
UnexpectedNonCoreModuleSection, /// There was a section that does not belong in a component module.
UnexpectedNonComponentSection, /// A core type definition was found in a component that's not supported.
UnsupportedCoreTypeInComponent, /// There was an error when parsing.
ParseError(wasmparser::BinaryReaderError), /// There was a user-defined error when re-encoding.
UserError(E),
}
impl<E: core::fmt::Display> core::fmt::Display for Error<E> { fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { matchself { Self::ParseError(_e) => {
write!(fmt, "There was an error when parsing")
} Self::UserError(e) => write!(fmt, "{e}"), Self::InvalidConstExpr => write!(fmt, "The const expression was invalid"), Self::UnexpectedNonCoreModuleSection => write!(
fmt, "There was a section that does not belong in a core wasm module"
), Self::UnexpectedNonComponentSection => write!(
fmt, "There was a section that does not belong in a component"
), Self::CanonicalizedHeapTypeReference => write!(
fmt, "There was a canonicalized heap type reference without type index information"
), Self::UnsupportedCoreTypeInComponent => {
fmt.write_str("unsupported core type in a component")
} Self::InvalidCodeSectionSize => fmt.write_str("invalid code section size"),
}
}
}
/// Reencodes `wasmparser` into `wasm-encoder` so that the encoded wasm is /// identical to the input and can be parsed and encoded again. #[derive(Debug)] pubstruct RoundtripReencoder;
impl Reencode for RoundtripReencoder { type Error = Infallible;
}
#[allow(missing_docs)] // FIXME pubmod utils { usesuper::{Error, Reencode}; usecrate::{CoreTypeEncoder, Encode, Imports}; use alloc::vec::Vec; use core::ops::Range;
// Convert from `range` to a byte range within `data` while // accounting for various offsets. Then create a // `CodeSectionReader` (which notably the payload does not // give us here) and recurse with that. This means that // users overriding `parse_code_section` always get that // function called. let orig_offset = parser.offset() as usize; let get_original_section = |range: Range<usize>| {
data.get(range.start - orig_offset..range.end - orig_offset)
.ok_or(Error::InvalidCodeSectionSize)
}; letmut last_section = None;
// Convert from `range` to a byte range within `data` while // accounting for various offsets. Then create a // `CodeSectionReader` (which notably the payload does not // give us here) and recurse with that. This means that // users overriding `parse_code_section` always get that // function called. let section = get_original_section(range.clone())?; let reader = wasmparser::BinaryReader::new(section, range.start); let section = wasmparser::CodeSectionReader::new(reader)?;
reencoder.parse_code_section(&mut codes, section)?;
module.section(&codes);
}
// Parsing of code section entries (function bodies) happens // above during the handling of the code section. That means // that we just skip all these payloads.
wasmparser::Payload::CodeSectionEntry(_) => {}
other => match other.as_section() {
Some((id, range)) => { let section = get_original_section(range)?;
reencoder.parse_unknown_section(module, id, section)?;
}
None => unreachable!(),
},
}
}
Ok(())
}
/// A hook method that is called inside [`Reencode::parse_core_module`]
/// before and after every non-custom core wasm section.
///
/// This method can be used to insert new custom sections in between those
/// sections, or to detect when a non-custom section is missing and insert
/// it in the [proper order].
///
/// The `after` parameter is `None` iff the hook is called before the first
/// non-custom section, and `Some(s)` afterwards, where `s` is the
/// [`SectionId`] of the previous non-custom section.
///
/// The `before` parameter is `None` iff the hook is called after the last
/// non-custom section, and `Some(s)` beforehand, where `s` is the
/// [`SectionId`] of the following non-custom section.
///
/// [proper order]: https://webassembly.github.io/spec/core/binary/modules.html#binary-module
/// [`SectionId`]: crate::SectionId
pub fn intersperse_section_hook<T: ?Sized + Reencode>(
_reencoder: &mut T,
_module: &mut crate::Module,
_after: Option<crate::SectionId>,
_before: Option<crate::SectionId>,
) -> Result<(), Error<T::Error>> {
Ok(())
}
/// Parses the input `section` given from the `wasmparser` crate and adds
/// all the types to the `types` section.
pub fn parse_type_section<T: ?Sized + Reencode>(
reencoder: &mut T,
types: &mut crate::TypeSection,
section: wasmparser::TypeSectionReader<'_>,
) -> Result<(), Error<T::Error>> {
for rec_group in section {
reencoder.parse_recursive_type_group(types.ty(), rec_group?)?;
}
Ok(())
}
/// Parses a single [`wasmparser::RecGroup`] and adds it to the `types` section.
pub fn parse_recursive_type_group<T: ?Sized + Reencode>(
reencoder: &mut T,
encoder: CoreTypeEncoder,
rec_group: wasmparser::RecGroup,
) -> Result<(), Error<T::Error>> {
if rec_group.is_explicit_rec_group() {
let subtypes = rec_group
.into_types()
.map(|t| reencoder.sub_type(t))
.collect::<Result<Vec<_>, _>>()?;
encoder.rec(subtypes);
} else {
let ty = rec_group.into_types().next().unwrap();
encoder.subtype(&reencoder.sub_type(ty)?);
}
Ok(())
}
/// Parses the input `section` given from the `wasmparser` crate and adds
/// all the tables to the `tables` section.
pub fn parse_table_section<T: ?Sized + Reencode>(
reencoder: &mut T,
tables: &mut crate::TableSection,
section: wasmparser::TableSectionReader<'_>,
) -> Result<(), Error<T::Error>> {
for table in section {
reencoder.parse_table(tables, table?)?;
}
Ok(())
}
/// Parses a single [`wasmparser::Table`] and adds it to the `tables` section.
pub fn parse_table<T: ?Sized + Reencode>(
reencoder: &mut T,
tables: &mut crate::TableSection,
table: wasmparser::Table<'_>,
) -> Result<(), Error<T::Error>> {
let ty = reencoder.table_type(table.ty)?;
match table.init {
wasmparser::TableInit::RefNull => {
tables.table(ty);
}
wasmparser::TableInit::Expr(e) => {
tables.table_with_init(ty, &reencoder.const_expr(e)?);
}
}
Ok(())
}
/// Parses the input `section` given from the `wasmparser` crate and adds
/// all the tags to the `tags` section.
pub fn parse_tag_section<T: ?Sized + Reencode>(
reencoder: &mut T,
tags: &mut crate::TagSection,
section: wasmparser::TagSectionReader<'_>,
) -> Result<(), Error<T::Error>> {
for tag in section {
let tag = tag?;
tags.tag(reencoder.tag_type(tag)?);
}
Ok(())
}
/// Parses the input `section` given from the `wasmparser` crate and adds
/// all the exports to the `exports` section.
pub fn parse_export_section<T: ?Sized + Reencode>(
reencoder: &mut T,
exports: &mut crate::ExportSection,
section: wasmparser::ExportSectionReader<'_>,
) -> Result<(), Error<T::Error>> {
for export in section {
reencoder.parse_export(exports, export?)?;
}
Ok(())
}
/// Parses the single [`wasmparser::Export`] provided and adds it to the
/// `exports` section.
pub fn parse_export<T: ?Sized + Reencode>(
reencoder: &mut T,
exports: &mut crate::ExportSection,
export: wasmparser::Export<'_>,
) -> Result<(), Error<T::Error>> {
exports.export(
export.name,
reencoder.export_kind(export.kind)?,
reencoder.external_index(export.kind, export.index)?,
);
Ok(())
}
/// Parses the input `section` given from the `wasmparser` crate and adds
/// all the globals to the `globals` section.
pub fn parse_global_section<T: ?Sized + Reencode>(
reencoder: &mut T,
globals: &mut crate::GlobalSection,
section: wasmparser::GlobalSectionReader<'_>,
) -> Result<(), Error<T::Error>> {
for global in section {
reencoder.parse_global(globals, global?)?;
}
Ok(())
}
/// Parses the single [`wasmparser::Global`] provided and adds it to the
/// `globals` section.
pub fn parse_global<T: ?Sized + Reencode>(
reencoder: &mut T,
globals: &mut crate::GlobalSection,
global: wasmparser::Global<'_>,
) -> Result<(), Error<T::Error>> {
globals.global(
reencoder.global_type(global.ty)?,
&reencoder.const_expr(global.init_expr)?,
);
Ok(())
}
/// Parses the input `section` given from the `wasmparser` crate and adds
/// all the imports to the `import` section.
pub fn parse_import_section<T: ?Sized + Reencode>(
reencoder: &mut T,
import_section: &mut crate::ImportSection,
section: wasmparser::ImportSectionReader<'_>,
) -> Result<(), Error<T::Error>> {
for imports in section {
let imports = imports?;
reencoder.parse_imports(import_section, imports)?;
}
Ok(())
}
/// Parses a [`wasmparser::Imports`] and adds all of its contents to the
/// `import` section.
pub fn parse_imports<T: ?Sized + Reencode>(
reencoder: &mut T,
import_section: &mut crate::ImportSection,
imports: wasmparser::Imports<'_>,
) -> Result<(), Error<T::Error>> {
import_section.imports(match imports {
wasmparser::Imports::Single(_, import) => Imports::Single(crate::Import {
module: import.module,
name: import.name,
ty: reencoder.entity_type(import.ty)?,
}),
wasmparser::Imports::Compact1 { module, items } => {
let mut new_items: Vec<crate::ImportCompact> = Vec::new();
for item in items {
let item = item?;
new_items.push(crate::ImportCompact {
name: item.name,
ty: reencoder.entity_type(item.ty)?,
})
}
Imports::Compact1 {
module: module,
items: new_items.into(),
}
}
wasmparser::Imports::Compact2 { module, ty, names } => {
let names = names.into_iter().collect::<wasmparser::Result<Vec<_>>>()?;
Imports::Compact2 {
module: module,
ty: reencoder.entity_type(ty)?,
names: names.into(),
}
}
});
Ok(())
}
/// Parses the single [`wasmparser::Import`] provided and adds it to the
/// `import` section.
pub fn parse_import<T: ?Sized + Reencode>(
reencoder: &mut T,
imports: &mut crate::ImportSection,
import: wasmparser::Import<'_>,
) -> Result<(), Error<T::Error>> {
reencoder.parse_imports(imports, wasmparser::Imports::Single(0, import))?;
Ok(())
}
/// Parses the input `section` given from the `wasmparser` crate and adds
/// all the memories to the `memories` section.
pub fn parse_memory_section<T: ?Sized + Reencode>(
reencoder: &mut T,
memories: &mut crate::MemorySection,
section: wasmparser::MemorySectionReader<'_>,
) -> Result<(), Error<T::Error>> {
for memory in section {
let memory = memory?;
memories.memory(reencoder.memory_type(memory)?);
}
Ok(())
}
/// Parses the input `section` given from the `wasmparser` crate and adds
/// all the functions to the `functions` section.
pub fn parse_function_section<T: ?Sized + Reencode>(
reencoder: &mut T,
functions: &mut crate::FunctionSection,
section: wasmparser::FunctionSectionReader<'_>,
) -> Result<(), Error<T::Error>> {
for func in section {
functions.function(reencoder.type_index(func?)?);
}
Ok(())
}
/// Parses the input `section` given from the `wasmparser` crate and adds
/// all the data to the `data` section.
pub fn parse_data_section<T: ?Sized + Reencode>(
reencoder: &mut T,
data: &mut crate::DataSection,
section: wasmparser::DataSectionReader<'_>,
) -> Result<(), Error<T::Error>> {
for datum in section {
reencoder.parse_data(data, datum?)?;
}
Ok(())
}
/// Parses a single [`wasmparser::Data`] and adds it to the `data` section.
pub fn parse_data<T: ?Sized + Reencode>(
reencoder: &mut T,
data: &mut crate::DataSection,
datum: wasmparser::Data<'_>,
) -> Result<(), Error<T::Error>> {
match datum.kind {
wasmparser::DataKind::Active {
memory_index,
offset_expr,
} => data.active(
reencoder.memory_index(memory_index)?,
&reencoder.const_expr(offset_expr)?,
datum.data.iter().copied(),
),
wasmparser::DataKind::Passive => data.passive(datum.data.iter().copied()),
};
Ok(())
}
/// Parses the input `section` given from the `wasmparser` crate and adds
/// all the elements to the `element` section.
pub fn parse_element_section<T: ?Sized + Reencode>(
reencoder: &mut T,
elements: &mut crate::ElementSection,
section: wasmparser::ElementSectionReader<'_>,
) -> Result<(), Error<T::Error>> {
for element in section {
reencoder.parse_element(elements, element?)?;
}
Ok(())
}
/// Parses the single [`wasmparser::Element`] provided and adds it to the
/// `element` section.
pub fn parse_element<T: ?Sized + Reencode>(
reencoder: &mut T,
elements: &mut crate::ElementSection,
element: wasmparser::Element<'_>,
) -> Result<(), Error<T::Error>> {
let elems = reencoder.element_items(element.items)?;
match element.kind {
wasmparser::ElementKind::Active {
table_index,
offset_expr,
} => elements.active(
// Inform the reencoder that a table index is being used even if
// it's not actually present here. That helps wasm-mutate for
// example which wants to track uses to know when it's ok to
// remove a table.
//
// If the table index started at `None` and is still zero then
// preserve this encoding and keep it at `None`. Otherwise if
// the result is nonzero or it was previously nonzero then keep
// that encoding too.
match (
table_index,
reencoder.table_index(table_index.unwrap_or(0))?,
) {
(None, 0) => None,
(_, n) => Some(n),
},
&reencoder.const_expr(offset_expr)?,
elems,
),
wasmparser::ElementKind::Passive => elements.passive(elems),
wasmparser::ElementKind::Declared => elements.declared(elems),
};
Ok(())
}
pub fn element_items<'a, T: ?Sized + Reencode>(
reencoder: &mut T,
items: wasmparser::ElementItems<'a>,
) -> Result<crate::Elements<'a>, Error<T::Error>> {
Ok(match items {
wasmparser::ElementItems::Functions(f) => {
let mut funcs = Vec::new();
for func in f {
funcs.push(reencoder.function_index(func?)?);
}
crate::Elements::Functions(funcs.into())
}
wasmparser::ElementItems::Expressions(ty, e) => {
let mut exprs = Vec::new();
for expr in e {
exprs.push(reencoder.const_expr(expr?)?);
}
crate::Elements::Expressions(reencoder.ref_type(ty)?, exprs.into())
}
})
}
// This case takes the arguments of a wasmparser instruction and creates
// a wasm-encoder instruction. There are a few special cases for where
// the structure of a wasmparser instruction differs from that of
// wasm-encoder.
(build $op:ident) => (Instruction::$op);
(build BrTable $arg:ident) => (Instruction::BrTable($arg.0, $arg.1));
(build TypedSelectMulti $arg:ident) => (Instruction::TypedSelectMulti(Cow::from($arg)));
(build I32Const $arg:ident) => (Instruction::I32Const($arg));
(build I64Const $arg:ident) => (Instruction::I64Const($arg));
(build F32Const $arg:ident) => (Instruction::F32Const($arg.into()));
(build F64Const $arg:ident) => (Instruction::F64Const($arg.into()));
(build V128Const $arg:ident) => (Instruction::V128Const($arg.i128()));
(build TryTable $table:ident) => (Instruction::TryTable(reencoder.block_type($table.ty)?, {
$table.catches.into_iter()
.map(|c| reencoder.catch(c))
.collect::<Result<Vec<_>, _>>()?
.into()
}));
(build $op:ident $arg:ident) => (Instruction::$op($arg));
(build $op:ident $($arg:ident)*) => (Instruction::$op { $($arg),* });
}
wasmparser::for_each_operator!(translate)
}
/// Parses the input `section` given from the `wasmparser` crate and adds
/// all the code to the `code` section.
pub fn parse_code_section<T: ?Sized + Reencode>(
reencoder: &mut T,
code: &mut crate::CodeSection,
section: wasmparser::CodeSectionReader<'_>,
) -> Result<(), Error<T::Error>> {
for func in section {
reencoder.parse_function_body(code, func?)?;
}
Ok(())
}
/// Parses a single [`wasmparser::FunctionBody`] and adds it to the `code` section.
pub fn parse_function_body<T: ?Sized + Reencode>(
reencoder: &mut T,
code: &mut crate::CodeSection,
func: wasmparser::FunctionBody<'_>,
) -> Result<(), Error<T::Error>> {
let mut f = reencoder.new_function_with_parsed_locals(&func)?;
let mut reader = func.get_operators_reader()?;
while !reader.eof() {
f.instruction(&reencoder.parse_instruction(&mut reader)?);
}
code.function(&f);
Ok(())
}
/// Create a new [`crate::Function`] by parsing the locals declarations from the
/// provided [`wasmparser::FunctionBody`].
pub fn new_function_with_parsed_locals<T: ?Sized + Reencode>(
reencoder: &mut T,
func: &wasmparser::FunctionBody<'_>,
) -> Result<crate::Function, Error<T::Error>> {
let mut locals = Vec::new();
for pair in func.get_locals_reader()? {
let (cnt, ty) = pair?;
locals.push((cnt, reencoder.val_type(ty)?));
}
Ok(crate::Function::new(locals))
}
/// Parses a single instruction from `reader` and adds it to `function`.
pub fn parse_instruction<'a, T: ?Sized + Reencode>(
reencoder: &mut T,
reader: &mut wasmparser::OperatorsReader<'a>,
) -> Result<crate::Instruction<'a>, Error<T::Error>> {
let instruction = reencoder.instruction(reader.read()?)?;
Ok(instruction)
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.