Files
wasmtime/cranelift/wasm/src/module_translator.rs
Alex Crichton 026fb8d388 Don't re-parse wasm for debuginfo (#2085)
* Don't re-parse wasm for debuginfo

This commit updates debuginfo parsing to happen during the main
translation of the original wasm module. This avoid re-parsing the wasm
module twice (at least the section-level headers). Additionally this
ties debuginfo directly to a `ModuleTranslation` which makes it easier
to process debuginfo for nested modules in the upcoming module linking
proposal.

The changes here are summarized by taking the `read_debuginfo` function
and merging it with the main module translation that happens which is
driven by cranelift. Some new hooks were added to the module environment
trait to support this, but most of it was integrating with existing hooks.

* Fix tests in debug crate
2020-08-03 09:59:20 -05:00

114 lines
4.0 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, WasmResult};
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_type_section,
};
use crate::state::ModuleTranslationState;
use cranelift_codegen::timing;
use wasmparser::{NameSectionReader, Parser, Payload};
/// 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();
for payload in Parser::new(0).parse_all(data) {
match payload? {
Payload::Version { .. } | Payload::End => {}
Payload::TypeSection(types) => {
parse_type_section(types, &mut module_translation_state, environ)?;
}
Payload::ImportSection(imports) => {
parse_import_section(imports, environ)?;
}
Payload::FunctionSection(functions) => {
parse_function_section(functions, environ)?;
}
Payload::TableSection(tables) => {
parse_table_section(tables, environ)?;
}
Payload::MemorySection(memories) => {
parse_memory_section(memories, environ)?;
}
Payload::GlobalSection(globals) => {
parse_global_section(globals, environ)?;
}
Payload::ExportSection(exports) => {
parse_export_section(exports, environ)?;
}
Payload::StartSection { func, .. } => {
parse_start_section(func, environ)?;
}
Payload::ElementSection(elements) => {
parse_element_section(elements, environ)?;
}
Payload::CodeSectionStart { count, range, .. } => {
environ.reserve_function_bodies(count, range.start as u64);
}
Payload::CodeSectionEntry(code) => {
let mut code = code.get_binary_reader();
let size = code.bytes_remaining();
let offset = code.original_position();
environ.define_function_body(
&module_translation_state,
code.read_bytes(size)?,
offset,
)?;
}
Payload::DataSection(data) => {
parse_data_section(data, environ)?;
}
Payload::DataCountSection { count, .. } => {
environ.reserve_passive_data(count)?;
}
Payload::ModuleSection(_)
| Payload::InstanceSection(_)
| Payload::AliasSection(_)
| Payload::ModuleCodeSectionStart { .. }
| Payload::ModuleCodeSectionEntry { .. } => {
unimplemented!("module linking not implemented yet")
}
Payload::CustomSection {
name: "name",
data,
data_offset,
} => {
let result = NameSectionReader::new(data, 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 { name, data, .. } => environ.custom_section(name, data)?,
Payload::UnknownSection { .. } => unreachable!(),
}
}
Ok(module_translation_state)
}