diff options
Diffstat (limited to 'third_party/rust/cranelift-wasm/src/module_translator.rs')
-rw-r--r-- | third_party/rust/cranelift-wasm/src/module_translator.rs | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/third_party/rust/cranelift-wasm/src/module_translator.rs b/third_party/rust/cranelift-wasm/src/module_translator.rs new file mode 100644 index 0000000000..0b1794158f --- /dev/null +++ b/third_party/rust/cranelift-wasm/src/module_translator.rs @@ -0,0 +1,159 @@ +//! 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 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(); + validator.wasm_features(environ.wasm_features()); + let mut stack = Vec::new(); + let mut modules = 1; + let mut cur_module = 0; + + for payload in Parser::new(0).parse_all(data) { + match payload? { + Payload::Version { num, range } => { + validator.version(num, &range)?; + environ.module_start(cur_module); + } + Payload::End => { + validator.end()?; + environ.module_end(cur_module); + if let Some((other, other_index)) = stack.pop() { + validator = other; + cur_module = other_index; + } + } + + 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::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()?; + 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)?; + environ.reserve_passive_data(count)?; + } + + Payload::ModuleSection(s) => { + validator.module_section(&s)?; + environ.reserve_modules(s.get_count()); + } + Payload::InstanceSection(s) => { + validator.instance_section(&s)?; + unimplemented!("module linking not implemented yet") + } + Payload::AliasSection(s) => { + validator.alias_section(&s)?; + unimplemented!("module linking not implemented yet") + } + Payload::ModuleCodeSectionStart { + count, + range, + size: _, + } => { + validator.module_code_section_start(count, &range)?; + } + + Payload::ModuleCodeSectionEntry { .. } => { + let subvalidator = validator.module_code_section_entry(); + stack.push((validator, cur_module)); + validator = subvalidator; + cur_module = modules; + modules += 1; + } + + 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 { id, range, .. } => { + validator.unknown_section(id, &range)?; + unreachable!(); + } + } + } + + Ok(module_translation_state) +} |