Files
wasmtime/cranelift/wasm/src/module_translator.rs
Alex Crichton 29c7de7340 Update wasm-tools dependencies (#4970)
* Update wasm-tools dependencies

This update brings in a number of features such as:

* The component model binary format and AST has been slightly adjusted
  in a few locations. Names are dropped from parameters/results now in
  the internal representation since they were not used anyway. At this
  time the ability to bind a multi-return function has not been exposed.

* The `wasmparser` validator pass will now share allocations with prior
  functions, providing what's probably a very minor speedup for Wasmtime
  itself.

* The text format for many component-related tests now requires named
  parameters.

* Some new relaxed-simd instructions are updated to be ignored.

I hope to have a follow-up to expose the multi-return ability to the
embedding API of components.

* Update audit information for new crates
2022-09-27 13:12:34 -05:00

132 lines
4.8 KiB
Rust

//! Translation skeleton that traverses the whole WebAssembly module and call helper functions
//! to deal with each part of it.
use crate::environ::ModuleEnvironment;
use crate::sections_translator::{
parse_data_section, parse_element_section, parse_export_section, parse_function_section,
parse_global_section, parse_import_section, parse_memory_section, parse_name_section,
parse_start_section, parse_table_section, parse_tag_section, parse_type_section,
};
use crate::state::ModuleTranslationState;
use crate::WasmResult;
use cranelift_codegen::timing;
use std::prelude::v1::*;
use wasmparser::{NameSectionReader, Parser, Payload, Validator};
/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cranelift IR
/// [`Function`](cranelift_codegen::ir::Function).
pub fn translate_module<'data>(
data: &'data [u8],
environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<ModuleTranslationState> {
let _tt = timing::wasm_translate_module();
let mut module_translation_state = ModuleTranslationState::new();
let mut validator = Validator::new_with_features(environ.wasm_features());
for payload in Parser::new(0).parse_all(data) {
match payload? {
Payload::Version {
num,
encoding,
range,
} => {
validator.version(num, encoding, &range)?;
}
Payload::End(offset) => {
validator.end(offset)?;
}
Payload::TypeSection(types) => {
validator.type_section(&types)?;
parse_type_section(types, &mut module_translation_state, environ)?;
}
Payload::ImportSection(imports) => {
validator.import_section(&imports)?;
parse_import_section(imports, environ)?;
}
Payload::FunctionSection(functions) => {
validator.function_section(&functions)?;
parse_function_section(functions, environ)?;
}
Payload::TableSection(tables) => {
validator.table_section(&tables)?;
parse_table_section(tables, environ)?;
}
Payload::MemorySection(memories) => {
validator.memory_section(&memories)?;
parse_memory_section(memories, environ)?;
}
Payload::TagSection(tags) => {
validator.tag_section(&tags)?;
parse_tag_section(tags, environ)?;
}
Payload::GlobalSection(globals) => {
validator.global_section(&globals)?;
parse_global_section(globals, environ)?;
}
Payload::ExportSection(exports) => {
validator.export_section(&exports)?;
parse_export_section(exports, environ)?;
}
Payload::StartSection { func, range } => {
validator.start_section(func, &range)?;
parse_start_section(func, environ)?;
}
Payload::ElementSection(elements) => {
validator.element_section(&elements)?;
parse_element_section(elements, environ)?;
}
Payload::CodeSectionStart { count, range, .. } => {
validator.code_section_start(count, &range)?;
environ.reserve_function_bodies(count, range.start as u64);
}
Payload::CodeSectionEntry(body) => {
let func_validator = validator
.code_section_entry(&body)?
.into_validator(Default::default());
environ.define_function_body(func_validator, body)?;
}
Payload::DataSection(data) => {
validator.data_section(&data)?;
parse_data_section(data, environ)?;
}
Payload::DataCountSection { count, range } => {
validator.data_count_section(count, &range)?;
// NOTE: the count here is the total segment count, not the passive segment count
environ.reserve_passive_data(count)?;
}
Payload::CustomSection(s) if s.name() == "name" => {
let result = NameSectionReader::new(s.data(), s.data_offset())
.map_err(|e| e.into())
.and_then(|s| parse_name_section(s, environ));
if let Err(e) = result {
log::warn!("failed to parse name section {:?}", e);
}
}
Payload::CustomSection(s) => environ.custom_section(s.name(), s.data())?,
other => {
validator.payload(&other)?;
panic!("unimplemented section {:?}", other);
}
}
}
Ok(module_translation_state)
}