Update to the new wasmparser and port to the new readers API.

The new wasmparser API provides dedicated reader types for each section
type, which significantly simplifies the code.

This also changes WasmError::from_binary_reader_error into a From
trait so that we don't have to do .map_err(from_binary_reader_error)
throughout the code.
This commit is contained in:
Dan Gohman
2018-10-23 16:34:29 -07:00
parent 9e084dbadc
commit 5ea6c57b95
6 changed files with 319 additions and 430 deletions

View File

@@ -1,119 +1,143 @@
//! Translation skeleton that traverses the whole WebAssembly module and call helper functions
//! to deal with each part of it.
use cranelift_codegen::timing;
use environ::{ModuleEnvironment, WasmError, WasmResult};
use environ::{ModuleEnvironment, WasmResult};
use sections_translator::{
parse_code_section, parse_data_section, parse_element_section, parse_export_section,
parse_function_section, parse_function_signatures, parse_global_section, parse_import_section,
parse_memory_section, parse_start_section, parse_table_section,
parse_function_section, parse_global_section, parse_import_section, parse_memory_section,
parse_start_section, parse_table_section, parse_type_section,
};
use wasmparser::{Parser, ParserInput, ParserState, SectionCode, WasmDecoder};
use wasmparser::{ModuleReader, SectionCode};
/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cranelift IR
/// [`Function`](../codegen/ir/function/struct.Function.html).
/// Returns the functions and also the mappings for imported functions and signature between the
/// indexes in the wasm module and the indexes inside each functions.
pub fn translate_module<'data>(
data: &'data [u8],
environ: &mut ModuleEnvironment<'data>,
) -> WasmResult<()> {
let _tt = timing::wasm_translate_module();
let mut parser = Parser::new(data);
match *parser.read() {
ParserState::BeginWasm { .. } => {}
ParserState::Error(e) => {
return Err(WasmError::from_binary_reader_error(e));
let mut reader = ModuleReader::new(data)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
let mut section = reader.read()?;
if let SectionCode::Type = section.code {
let types = section.get_type_section_reader()?;
parse_type_section(types, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
ref s => panic!("modules should begin properly: {:?}", s),
section = reader.read()?;
}
let mut next_input = ParserInput::Default;
loop {
match *parser.read_with_input(next_input) {
ParserState::BeginSection {
code: SectionCode::Type,
..
} => {
parse_function_signatures(&mut parser, environ)?;
next_input = ParserInput::Default;
}
ParserState::BeginSection {
code: SectionCode::Import,
..
} => {
parse_import_section(&mut parser, environ)?;
next_input = ParserInput::Default;
}
ParserState::BeginSection {
code: SectionCode::Function,
..
} => {
parse_function_section(&mut parser, environ)?;
next_input = ParserInput::Default;
}
ParserState::BeginSection {
code: SectionCode::Table,
..
} => {
parse_table_section(&mut parser, environ)?;
}
ParserState::BeginSection {
code: SectionCode::Memory,
..
} => {
parse_memory_section(&mut parser, environ)?;
next_input = ParserInput::Default;
}
ParserState::BeginSection {
code: SectionCode::Global,
..
} => {
parse_global_section(&mut parser, environ)?;
next_input = ParserInput::Default;
}
ParserState::BeginSection {
code: SectionCode::Export,
..
} => {
parse_export_section(&mut parser, environ)?;
next_input = ParserInput::Default;
}
ParserState::BeginSection {
code: SectionCode::Start,
..
} => {
parse_start_section(&mut parser, environ)?;
next_input = ParserInput::Default;
}
ParserState::BeginSection {
code: SectionCode::Element,
..
} => {
parse_element_section(&mut parser, environ)?;
next_input = ParserInput::Default;
}
ParserState::BeginSection {
code: SectionCode::Code,
..
} => parse_code_section(&mut parser, environ)?,
ParserState::EndSection => {
next_input = ParserInput::Default;
}
ParserState::EndWasm => return Ok(()),
ParserState::BeginSection {
code: SectionCode::Data,
..
} => {
parse_data_section(&mut parser, environ)?;
}
ParserState::BeginSection {
code: SectionCode::Custom { .. },
..
} => {
// Ignore unknown custom sections.
next_input = ParserInput::SkipSection;
}
ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)),
_ => panic!("wrong content in the preamble"),
};
if let SectionCode::Import = section.code {
let imports = section.get_import_section_reader()?;
parse_import_section(imports, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
}
if let SectionCode::Function = section.code {
let functions = section.get_function_section_reader()?;
parse_function_section(functions, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
}
if let SectionCode::Table = section.code {
let tables = section.get_table_section_reader()?;
parse_table_section(tables, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
}
if let SectionCode::Memory = section.code {
let memories = section.get_memory_section_reader()?;
parse_memory_section(memories, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
}
if let SectionCode::Global = section.code {
let globals = section.get_global_section_reader()?;
parse_global_section(globals, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
}
if let SectionCode::Export = section.code {
let exports = section.get_export_section_reader()?;
parse_export_section(exports, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
}
if let SectionCode::Start = section.code {
let start = section.get_start_section_content()?;
parse_start_section(start, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
}
if let SectionCode::Element = section.code {
let elements = section.get_element_section_reader()?;
parse_element_section(elements, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
}
if let SectionCode::Code = section.code {
let code = section.get_code_section_reader()?;
parse_code_section(code, environ)?;
reader.skip_custom_sections()?;
if reader.eof() {
return Ok(());
}
section = reader.read()?;
}
if let SectionCode::Data = section.code {
let data = section.get_data_section_reader()?;
parse_data_section(data, environ)?;
}
Ok(())
}