summaryrefslogtreecommitdiffstats
path: root/third_party/rust/cranelift-wasm/src/module_translator.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/cranelift-wasm/src/module_translator.rs')
-rw-r--r--third_party/rust/cranelift-wasm/src/module_translator.rs159
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)
+}