From 1000f21338fa59f86a96fbcf20ba1ace6c34f60a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 13 Jul 2020 16:22:41 -0500 Subject: [PATCH] Update wasmparser to 0.59.0 (#2013) This commit is intended to update wasmparser to 0.59.0. This primarily includes bytecodealliance/wasm-tools#40 which is a large update to how parsing and validation works. The impact on Wasmtime is pretty small at this time, but over time I'd like to refactor the internals here to lean more heavily on that upstream wasmparser refactoring. For now, though, the intention is to get on the train of wasmparser's latest `main` branch to ensure we get bug fixes and such. As part of this update a few other crates and such were updated. This is primarily to handle the new encoding of `ref.is_null` where the type is not part of the instruction encoding any more. --- Cargo.lock | 42 ++-- cranelift/wasm/Cargo.toml | 2 +- cranelift/wasm/src/code_translator.rs | 2 +- cranelift/wasm/src/module_translator.rs | 87 ++++---- cranelift/wasm/src/sections_translator.rs | 25 +-- crates/debug/Cargo.toml | 2 +- crates/debug/src/read_debuginfo.rs | 58 +++--- crates/environ/Cargo.toml | 2 +- crates/fuzzing/Cargo.toml | 4 +- crates/fuzzing/src/generators/api.rs | 14 +- crates/jit/Cargo.toml | 2 +- crates/lightbeam/Cargo.toml | 2 +- crates/lightbeam/src/microwasm.rs | 2 +- crates/lightbeam/src/module.rs | 190 +++++------------- crates/lightbeam/src/translate_sections.rs | 1 + crates/wasmtime/Cargo.toml | 2 +- crates/wasmtime/src/instance.rs | 2 +- crates/wasmtime/src/module.rs | 7 +- crates/wasmtime/src/runtime.rs | 57 +++--- crates/wast/Cargo.toml | 2 +- crates/wast/src/wast.rs | 10 +- .../reference-types/simple_ref_is_null.wast | 4 +- tests/spec_testsuite | 2 +- 23 files changed, 205 insertions(+), 316 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7798fbb520..188ffad428 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -595,7 +595,7 @@ dependencies = [ "serde", "target-lexicon", "thiserror", - "wasmparser 0.58.0", + "wasmparser 0.59.0", "wat", ] @@ -1124,7 +1124,7 @@ dependencies = [ "staticvec", "thiserror", "typemap", - "wasmparser 0.58.0", + "wasmparser 0.59.0", "wat", ] @@ -2298,12 +2298,6 @@ dependencies = [ "yanix", ] -[[package]] -name = "wasmparser" -version = "0.55.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af931e2e1960c53f4a28b063fec4cacd036f35acbec8ff3a4739125b17382a87" - [[package]] name = "wasmparser" version = "0.57.0" @@ -2312,18 +2306,18 @@ checksum = "32fddd575d477c6e9702484139cf9f23dcd554b06d185ed0f56c857dd3a47aa6" [[package]] name = "wasmparser" -version = "0.58.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721a8d79483738d7aef6397edcf8f04cd862640b1ad5973adf5bb50fc10e86db" +checksum = "a950e6a618f62147fd514ff445b2a0b53120d382751960797f85f058c7eda9b9" [[package]] name = "wasmprinter" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c93ba310101ec5ee980db66b47b3d276577c8310df1570e19994347137650454" +checksum = "334551eb8b0b1be16cf366a54ce9b541ac32a96e9b51e67ebbae1696f108f112" dependencies = [ "anyhow", - "wasmparser 0.55.0", + "wasmparser 0.59.0", ] [[package]] @@ -2341,7 +2335,7 @@ dependencies = [ "smallvec", "target-lexicon", "tempfile", - "wasmparser 0.58.0", + "wasmparser 0.59.0", "wasmtime-environ", "wasmtime-jit", "wasmtime-profiling", @@ -2415,7 +2409,7 @@ dependencies = [ "object", "target-lexicon", "thiserror", - "wasmparser 0.58.0", + "wasmparser 0.59.0", "wasmtime-environ", ] @@ -2448,7 +2442,7 @@ dependencies = [ "tempfile", "thiserror", "toml", - "wasmparser 0.58.0", + "wasmparser 0.59.0", "winapi", "zstd", ] @@ -2477,7 +2471,7 @@ dependencies = [ "env_logger", "log", "rayon", - "wasmparser 0.58.0", + "wasmparser 0.59.0", "wasmprinter", "wasmtime", "wasmtime-wast", @@ -2502,7 +2496,7 @@ dependencies = [ "region", "target-lexicon", "thiserror", - "wasmparser 0.58.0", + "wasmparser 0.59.0", "wasmtime-debug", "wasmtime-environ", "wasmtime-obj", @@ -2599,7 +2593,7 @@ version = "0.18.0" dependencies = [ "anyhow", "wasmtime", - "wast 18.0.0", + "wast 21.0.0", ] [[package]] @@ -2643,20 +2637,20 @@ dependencies = [ [[package]] name = "wast" -version = "18.0.0" +version = "21.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b1f23531740a81f9300bd2febd397a95c76bfa4aa4bfaf4ca8b1ee3438f337" +checksum = "0b1844f66a2bc8526d71690104c0e78a8e59ffa1597b7245769d174ebb91deb5" dependencies = [ "leb128", ] [[package]] name = "wat" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4006d418d59293172aebfeeadb7673459dc151874a79135946ea7996b6a98515" +checksum = "ce85d72b74242c340e9e3492cfb602652d7bb324c3172dd441b5577e39a2e18c" dependencies = [ - "wast 18.0.0", + "wast 21.0.0", ] [[package]] diff --git a/cranelift/wasm/Cargo.toml b/cranelift/wasm/Cargo.toml index 4e8034979f..81fc0c69d7 100644 --- a/cranelift/wasm/Cargo.toml +++ b/cranelift/wasm/Cargo.toml @@ -12,7 +12,7 @@ keywords = ["webassembly", "wasm"] edition = "2018" [dependencies] -wasmparser = { version = "0.58.0", default-features = false } +wasmparser = { version = "0.59.0", default-features = false } cranelift-codegen = { path = "../codegen", version = "0.65.0", default-features = false } cranelift-entity = { path = "../entity", version = "0.65.0" } cranelift-frontend = { path = "../frontend", version = "0.65.0", default-features = false } diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index 800a793aab..64556bdddb 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -1043,7 +1043,7 @@ pub fn translate_operator( Operator::RefNull { ty } => { state.push1(environ.translate_ref_null(builder.cursor(), (*ty).try_into()?)?) } - Operator::RefIsNull { ty: _ } => { + Operator::RefIsNull => { let value = state.pop1(); state.push1(environ.translate_ref_is_null(builder.cursor(), value)?); } diff --git a/cranelift/wasm/src/module_translator.rs b/cranelift/wasm/src/module_translator.rs index d34a2c1557..9903a2979c 100644 --- a/cranelift/wasm/src/module_translator.rs +++ b/cranelift/wasm/src/module_translator.rs @@ -2,13 +2,13 @@ //! to deal with each part of it. use crate::environ::{ModuleEnvironment, WasmResult}; use crate::sections_translator::{ - parse_code_section, 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, + 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::{CustomSectionContent, ModuleReader, SectionContent}; +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). @@ -17,80 +17,85 @@ pub fn translate_module<'data>( environ: &mut dyn ModuleEnvironment<'data>, ) -> WasmResult { let _tt = timing::wasm_translate_module(); - let mut reader = ModuleReader::new(data)?; let mut module_translation_state = ModuleTranslationState::new(); - while !reader.eof() { - let section = reader.read()?; - match section.content()? { - SectionContent::Type(types) => { + 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)?; } - SectionContent::Import(imports) => { + Payload::ImportSection(imports) => { parse_import_section(imports, environ)?; } - SectionContent::Function(functions) => { + Payload::FunctionSection(functions) => { parse_function_section(functions, environ)?; } - SectionContent::Table(tables) => { + Payload::TableSection(tables) => { parse_table_section(tables, environ)?; } - SectionContent::Memory(memories) => { + Payload::MemorySection(memories) => { parse_memory_section(memories, environ)?; } - SectionContent::Global(globals) => { + Payload::GlobalSection(globals) => { parse_global_section(globals, environ)?; } - SectionContent::Export(exports) => { + Payload::ExportSection(exports) => { parse_export_section(exports, environ)?; } - SectionContent::Start(start) => { - parse_start_section(start, environ)?; + Payload::StartSection { func, .. } => { + parse_start_section(func, environ)?; } - SectionContent::Element(elements) => { + Payload::ElementSection(elements) => { parse_element_section(elements, environ)?; } - SectionContent::Code(code) => { - parse_code_section(code, &module_translation_state, environ)?; + Payload::CodeSectionStart { .. } => {} + 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, + )?; } - SectionContent::Data(data) => { + Payload::DataSection(data) => { parse_data_section(data, environ)?; } - SectionContent::DataCount(count) => { + Payload::DataCountSection { count, .. } => { environ.reserve_passive_data(count)?; } - SectionContent::Module(_) - | SectionContent::ModuleCode(_) - | SectionContent::Instance(_) - | SectionContent::Alias(_) => unimplemented!("module linking not implemented yet"), + Payload::ModuleSection(_) + | Payload::InstanceSection(_) + | Payload::AliasSection(_) + | Payload::ModuleCodeSectionStart { .. } + | Payload::ModuleCodeSectionEntry { .. } => { + unimplemented!("module linking not implemented yet") + } - SectionContent::Custom { - name, - binary, - content, - } => match content { - Some(CustomSectionContent::Name(names)) => { - parse_name_section(names, environ)?; - } - _ => { - let mut reader = binary.clone(); - let len = reader.bytes_remaining(); - let payload = reader.read_bytes(len)?; - environ.custom_section(name, payload)?; - } - }, + Payload::CustomSection { + name: "name", + data, + data_offset, + } => parse_name_section(NameSectionReader::new(data, data_offset)?, environ)?, + + Payload::CustomSection { name, data, .. } => environ.custom_section(name, data)?, + + Payload::UnknownSection { .. } => unreachable!(), } } diff --git a/cranelift/wasm/src/sections_translator.rs b/cranelift/wasm/src/sections_translator.rs index 36f93cda13..3bc4d7d144 100644 --- a/cranelift/wasm/src/sections_translator.rs +++ b/cranelift/wasm/src/sections_translator.rs @@ -23,11 +23,11 @@ use cranelift_entity::EntityRef; use std::boxed::Box; use std::vec::Vec; use wasmparser::{ - self, CodeSectionReader, Data, DataKind, DataSectionReader, Element, ElementItem, ElementItems, - ElementKind, ElementSectionReader, Export, ExportSectionReader, ExternalKind, - FunctionSectionReader, GlobalSectionReader, GlobalType, ImportSectionEntryType, - ImportSectionReader, MemorySectionReader, MemoryType, NameSectionReader, Naming, NamingReader, - Operator, TableSectionReader, Type, TypeDef, TypeSectionReader, + self, Data, DataKind, DataSectionReader, Element, ElementItem, ElementItems, ElementKind, + ElementSectionReader, Export, ExportSectionReader, ExternalKind, FunctionSectionReader, + GlobalSectionReader, GlobalType, ImportSectionEntryType, ImportSectionReader, + MemorySectionReader, MemoryType, NameSectionReader, Naming, NamingReader, Operator, + TableSectionReader, Type, TypeDef, TypeSectionReader, }; /// Parses the Type section of the wasm module. @@ -358,21 +358,6 @@ pub fn parse_element_section<'data>( Ok(()) } -/// Parses the Code section of the wasm module. -pub fn parse_code_section<'data>( - code: CodeSectionReader<'data>, - module_translation_state: &ModuleTranslationState, - environ: &mut dyn ModuleEnvironment<'data>, -) -> WasmResult<()> { - for body in code { - let mut reader = body?.get_binary_reader(); - let size = reader.bytes_remaining(); - let offset = reader.original_position(); - environ.define_function_body(module_translation_state, reader.read_bytes(size)?, offset)?; - } - Ok(()) -} - /// Parses the Data section of the wasm module. pub fn parse_data_section<'data>( data: DataSectionReader<'data>, diff --git a/crates/debug/Cargo.toml b/crates/debug/Cargo.toml index 4eb30caa96..8df3d12717 100644 --- a/crates/debug/Cargo.toml +++ b/crates/debug/Cargo.toml @@ -13,7 +13,7 @@ edition = "2018" [dependencies] gimli = "0.21.0" -wasmparser = "0.58.0" +wasmparser = "0.59.0" object = { version = "0.20", default-features = false, features = ["read", "write"] } wasmtime-environ = { path = "../environ", version = "0.18.0" } target-lexicon = { version = "0.10.0", default-features = false } diff --git a/crates/debug/src/read_debuginfo.rs b/crates/debug/src/read_debuginfo.rs index 6751fdfd40..ad28d9b1be 100644 --- a/crates/debug/src/read_debuginfo.rs +++ b/crates/debug/src/read_debuginfo.rs @@ -6,7 +6,7 @@ use gimli::{ }; use std::collections::HashMap; use std::path::PathBuf; -use wasmparser::{self, ModuleReader, SectionCode, TypeDef}; +use wasmparser::{self, NameSectionReader, Parser, Payload, TypeDef}; trait Reader: gimli::Reader {} @@ -155,7 +155,6 @@ fn read_name_section(reader: wasmparser::NameSectionReader) -> wasmparser::Resul } pub fn read_debuginfo(data: &[u8]) -> Result { - let mut reader = ModuleReader::new(data)?; let mut sections = HashMap::new(); let mut name_section = None; let mut code_section_offset = 0; @@ -165,26 +164,25 @@ pub fn read_debuginfo(data: &[u8]) -> Result { let mut func_params_refs: Vec = Vec::new(); let mut func_locals: Vec> = Vec::new(); - while !reader.eof() { - let section = reader.read()?; - match section.code { - SectionCode::Custom { name, .. } => { + for payload in Parser::new(0).parse_all(data) { + match payload? { + Payload::CustomSection { + name, + data, + data_offset, + } => { if name.starts_with(".debug_") { - let mut reader = section.get_binary_reader(); - let len = reader.bytes_remaining(); - sections.insert(name, reader.read_bytes(len)?); - } - if name == "name" { - if let Ok(reader) = section.get_name_section_reader() { + sections.insert(name, data); + } else if name == "name" { + if let Ok(reader) = NameSectionReader::new(data, data_offset) { if let Ok(section) = read_name_section(reader) { name_section = Some(section); } } } } - SectionCode::Type => { - signatures_params = section - .get_type_section_reader()? + Payload::TypeSection(s) => { + signatures_params = s .into_iter() .map(|ft| { if let Ok(TypeDef::Func(ft)) = ft { @@ -195,33 +193,29 @@ pub fn read_debuginfo(data: &[u8]) -> Result { }) .collect::>>()?; } - SectionCode::Import => { - for i in section.get_import_section_reader()? { + Payload::ImportSection(s) => { + for i in s { if let wasmparser::ImportSectionEntryType::Function(_) = i?.ty { imported_func_count += 1; } } } - SectionCode::Function => { - func_params_refs = section - .get_function_section_reader()? + Payload::FunctionSection(s) => { + func_params_refs = s .into_iter() .map(|index| Ok(index? as usize)) .collect::>>()?; } - SectionCode::Code => { - code_section_offset = section.range().start as u64; - func_locals = section - .get_code_section_reader()? + Payload::CodeSectionStart { range, .. } => { + code_section_offset = range.start as u64; + } + Payload::CodeSectionEntry(body) => { + let locals = body.get_locals_reader()?; + let locals = locals .into_iter() - .map(|body| { - let locals = body?.get_locals_reader()?; - Ok(locals - .into_iter() - .collect::, _>>()? - .into_boxed_slice()) - }) - .collect::>>()?; + .collect::, _>>()? + .into_boxed_slice(); + func_locals.push(locals); } _ => (), } diff --git a/crates/environ/Cargo.toml b/crates/environ/Cargo.toml index 73ddf7a2ae..a9f1761d91 100644 --- a/crates/environ/Cargo.toml +++ b/crates/environ/Cargo.toml @@ -17,7 +17,7 @@ cranelift-codegen = { path = "../../cranelift/codegen", version = "0.65.0", feat cranelift-entity = { path = "../../cranelift/entity", version = "0.65.0", features = ["enable-serde"] } cranelift-frontend = { path = "../../cranelift/frontend", version = "0.65.0" } cranelift-wasm = { path = "../../cranelift/wasm", version = "0.65.0", features = ["enable-serde"] } -wasmparser = "0.58.0" +wasmparser = "0.59.0" lightbeam = { path = "../lightbeam", optional = true, version = "0.18.0" } indexmap = { version = "1.0.2", features = ["serde-1"] } rayon = { version = "1.2.1", optional = true } diff --git a/crates/fuzzing/Cargo.toml b/crates/fuzzing/Cargo.toml index 24821f30d7..90ae4271dc 100644 --- a/crates/fuzzing/Cargo.toml +++ b/crates/fuzzing/Cargo.toml @@ -13,8 +13,8 @@ binaryen = { version = "0.10.0", optional = true } env_logger = "0.7.1" log = "0.4.8" rayon = "1.2.1" -wasmparser = "0.58.0" -wasmprinter = "0.2.5" +wasmparser = "0.59.0" +wasmprinter = "0.2.6" wasmtime = { path = "../wasmtime" } wasmtime-wast = { path = "../wast" } diff --git a/crates/fuzzing/src/generators/api.rs b/crates/fuzzing/src/generators/api.rs index 2a375bb9e6..db6474bf95 100644 --- a/crates/fuzzing/src/generators/api.rs +++ b/crates/fuzzing/src/generators/api.rs @@ -213,14 +213,12 @@ fn arbitrary_config( /// it'll free up new slots to start making new instances. fn predict_rss(wasm: &[u8]) -> Result { let mut prediction = 0; - let mut reader = ModuleReader::new(wasm)?; - while !reader.eof() { - let section = reader.read()?; - match section.code { + for payload in Parser::new(0).parse_all(wasm) { + match payload? { // For each declared memory we'll have to map that all in, so add in // the minimum amount of memory to our predicted rss. - SectionCode::Memory => { - for entry in section.get_memory_section_reader()? { + Payload::MemorySection(s) => { + for entry in s { let initial = entry?.limits.initial as usize; prediction += initial * 64 * 1024; } @@ -228,8 +226,8 @@ fn predict_rss(wasm: &[u8]) -> Result { // We'll need to allocate tables and space for table elements, and // currently this is 3 pointers per table entry. - SectionCode::Table => { - for entry in section.get_table_section_reader()? { + Payload::TableSection(s) => { + for entry in s { let initial = entry?.limits.initial as usize; prediction += initial * 3 * mem::size_of::(); } diff --git a/crates/jit/Cargo.toml b/crates/jit/Cargo.toml index 4e6509077d..a037f4d7f2 100644 --- a/crates/jit/Cargo.toml +++ b/crates/jit/Cargo.toml @@ -25,7 +25,7 @@ wasmtime-obj = { path = "../obj", version = "0.18.0" } region = "2.1.0" thiserror = "1.0.4" target-lexicon = { version = "0.10.0", default-features = false } -wasmparser = "0.58.0" +wasmparser = "0.59.0" more-asserts = "0.2.1" anyhow = "1.0" cfg-if = "0.1.9" diff --git a/crates/lightbeam/Cargo.toml b/crates/lightbeam/Cargo.toml index 953fa023ca..395e114f13 100644 --- a/crates/lightbeam/Cargo.toml +++ b/crates/lightbeam/Cargo.toml @@ -24,7 +24,7 @@ smallvec = "1.0.0" staticvec = "0.10" thiserror = "1.0.9" typemap = "0.3" -wasmparser = "0.58.0" +wasmparser = "0.59.0" [dev-dependencies] lazy_static = "1.2" diff --git a/crates/lightbeam/src/microwasm.rs b/crates/lightbeam/src/microwasm.rs index a33a695c13..20b9787008 100644 --- a/crates/lightbeam/src/microwasm.rs +++ b/crates/lightbeam/src/microwasm.rs @@ -2130,7 +2130,7 @@ where WasmOperator::RefNull { ty: _ } => { return Err(Error::Microwasm("RefNull unimplemented".into())) } - WasmOperator::RefIsNull { ty: _ } => { + WasmOperator::RefIsNull => { return Err(Error::Microwasm("RefIsNull unimplemented".into())) } WasmOperator::I32Eqz => one(Operator::Eqz(Size::_32)), diff --git a/crates/lightbeam/src/module.rs b/crates/lightbeam/src/module.rs index 7ee9d23ebf..7bd40bcff1 100644 --- a/crates/lightbeam/src/module.rs +++ b/crates/lightbeam/src/module.rs @@ -10,7 +10,7 @@ use memoffset::offset_of; use std::{convert::TryInto, mem}; use thiserror::Error; -use wasmparser::{FuncType, MemoryType, ModuleReader, SectionCode, Type}; +use wasmparser::{FuncType, MemoryType, Parser, Payload, Type}; pub trait AsValueType { const TYPE: Type; @@ -512,150 +512,58 @@ pub fn translate(data: &[u8]) -> Result { /// Translate from a slice of bytes holding a wasm module. pub fn translate_only(data: &[u8]) -> Result { - let mut reader = ModuleReader::new(data)?; let mut output = TranslatedModule::default(); - reader.skip_custom_sections()?; - if reader.eof() { - return Ok(output); - } - let mut section = reader.read()?; - - if let SectionCode::Type = section.code { - let types_reader = section.get_type_section_reader()?; - output.ctx.types = translate_sections::type_(types_reader)?; - - reader.skip_custom_sections()?; - if reader.eof() { - return Ok(output); - } - section = reader.read()?; - } - - if let SectionCode::Import = section.code { - let imports = section.get_import_section_reader()?; - translate_sections::import(imports)?; - - reader.skip_custom_sections()?; - if reader.eof() { - return Ok(output); - } - section = reader.read()?; - } - - if let SectionCode::Function = section.code { - let functions = section.get_function_section_reader()?; - output.ctx.func_ty_indices = translate_sections::function(functions)?; - - reader.skip_custom_sections()?; - if reader.eof() { - return Ok(output); - } - section = reader.read()?; - } - - if let SectionCode::Table = section.code { - let tables = section.get_table_section_reader()?; - translate_sections::table(tables)?; - - reader.skip_custom_sections()?; - if reader.eof() { - return Ok(output); - } - section = reader.read()?; - } - - if let SectionCode::Memory = section.code { - let memories = section.get_memory_section_reader()?; - let mem = translate_sections::memory(memories)?; - - if mem.len() > 1 { - return Err(Error::Input( - "Multiple memory sections not yet implemented".to_string(), - )); - } - - if !mem.is_empty() { - let mem = mem[0]; - if Some(mem.limits.initial) != mem.limits.maximum { - return Err(Error::Input( - "Custom memory limits not supported in lightbeam".to_string(), - )); + for payload in Parser::new(0).parse_all(data) { + match payload? { + Payload::TypeSection(s) => output.ctx.types = translate_sections::type_(s)?, + Payload::ImportSection(s) => translate_sections::import(s)?, + Payload::FunctionSection(s) => { + output.ctx.func_ty_indices = translate_sections::function(s)?; } - output.memory = Some(mem); + Payload::TableSection(s) => { + translate_sections::table(s)?; + } + Payload::MemorySection(s) => { + let mem = translate_sections::memory(s)?; + + if mem.len() > 1 { + return Err(Error::Input( + "Multiple memory sections not yet implemented".to_string(), + )); + } + + if !mem.is_empty() { + let mem = mem[0]; + if Some(mem.limits.initial) != mem.limits.maximum { + return Err(Error::Input( + "Custom memory limits not supported in lightbeam".to_string(), + )); + } + output.memory = Some(mem); + } + } + Payload::GlobalSection(s) => { + translate_sections::global(s)?; + } + Payload::ExportSection(s) => { + translate_sections::export(s)?; + } + Payload::StartSection { func, .. } => { + translate_sections::start(func)?; + } + Payload::ElementSection(s) => { + translate_sections::element(s)?; + } + Payload::DataSection(s) => { + translate_sections::data(s)?; + } + Payload::CodeSectionStart { .. } + | Payload::CustomSection { .. } + | Payload::Version { .. } => {} + + other => unimplemented!("can't translate {:?}", other), } - - reader.skip_custom_sections()?; - if reader.eof() { - return Ok(output); - } - section = reader.read()?; - } - - if let SectionCode::Global = section.code { - let globals = section.get_global_section_reader()?; - translate_sections::global(globals)?; - - reader.skip_custom_sections()?; - if reader.eof() { - return Ok(output); - } - section = reader.read()?; - } - - if let SectionCode::Export = section.code { - let exports = section.get_export_section_reader()?; - translate_sections::export(exports)?; - - reader.skip_custom_sections()?; - if reader.eof() { - return Ok(output); - } - section = reader.read()?; - } - - if let SectionCode::Start = section.code { - let start = section.get_start_section_content()?; - translate_sections::start(start)?; - - reader.skip_custom_sections()?; - if reader.eof() { - return Ok(output); - } - section = reader.read()?; - } - - if let SectionCode::Element = section.code { - let elements = section.get_element_section_reader()?; - translate_sections::element(elements)?; - - reader.skip_custom_sections()?; - if reader.eof() { - return Ok(output); - } - section = reader.read()?; - } - - if let SectionCode::Code = section.code { - let code = section.get_code_section_reader()?; - output.translated_code_section = Some(translate_sections::code(code, &output.ctx)?); - - reader.skip_custom_sections()?; - if reader.eof() { - return Ok(output); - } - section = reader.read()?; - } - - if let SectionCode::Data = section.code { - let data = section.get_data_section_reader()?; - translate_sections::data(data)?; - } - - if !reader.eof() { - return Err(Error::Input( - "Unexpected data found after the end of the module".to_string(), - )); } Ok(output) diff --git a/crates/lightbeam/src/translate_sections.rs b/crates/lightbeam/src/translate_sections.rs index ab769afca0..ad32936420 100644 --- a/crates/lightbeam/src/translate_sections.rs +++ b/crates/lightbeam/src/translate_sections.rs @@ -108,6 +108,7 @@ impl binemit::RelocSink for UnimplementedRelocSink { } /// Parses the Code section of the wasm module. +#[allow(dead_code)] pub fn code( _code: CodeSectionReader, _translation_ctx: &SimpleContext, diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml index e13c872cac..c49738e638 100644 --- a/crates/wasmtime/Cargo.toml +++ b/crates/wasmtime/Cargo.toml @@ -14,7 +14,7 @@ wasmtime-runtime = { path = "../runtime", version = "0.18.0" } wasmtime-environ = { path = "../environ", version = "0.18.0" } wasmtime-jit = { path = "../jit", version = "0.18.0" } wasmtime-profiling = { path = "../profiling", version = "0.18.0" } -wasmparser = "0.58.0" +wasmparser = "0.59.0" target-lexicon = { version = "0.10.0", default-features = false } anyhow = "1.0.19" region = "2.2.0" diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index f2ce4f6e6f..f4ecffe972 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -66,7 +66,7 @@ fn instantiate( let instance = store.add_instance(instance); instance .initialize( - config.validating_config.operator_config.enable_bulk_memory, + config.wasm_bulk_memory, &compiled_module.data_initializers(), ) .map_err(|e| -> Error { diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 391c3b63de..c3e7be1313 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -1,10 +1,9 @@ use crate::frame_info::GlobalFrameInfoRegistration; use crate::runtime::Engine; use crate::types::{EntityType, ExportType, ExternType, ImportType}; -use anyhow::{Error, Result}; +use anyhow::Result; use std::path::Path; use std::sync::{Arc, Mutex}; -use wasmparser::validate; use wasmtime_jit::CompiledModule; /// A compiled WebAssembly module, ready to be instantiated. @@ -296,8 +295,8 @@ impl Module { /// /// [binary]: https://webassembly.github.io/spec/core/binary/index.html pub fn validate(engine: &Engine, binary: &[u8]) -> Result<()> { - let config = engine.config().validating_config.clone(); - validate(binary, Some(config)).map_err(Error::new) + engine.config().validator().validate_all(binary)?; + Ok(()) } unsafe fn compile(engine: &Engine, binary: &[u8]) -> Result { diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index 9e6e690507..cbba86eafa 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -10,7 +10,7 @@ use std::hash::{Hash, Hasher}; use std::path::Path; use std::rc::{Rc, Weak}; use std::sync::Arc; -use wasmparser::{OperatorValidatorConfig, ValidatingParserConfig}; +use wasmparser::Validator; use wasmtime_environ::settings::{self, Configurable, SetError}; use wasmtime_environ::{ir, isa, isa::TargetIsa, wasm, CacheConfig, Tunables}; use wasmtime_jit::{native, CompilationStrategy, Compiler}; @@ -34,13 +34,17 @@ use wasmtime_runtime::{ pub struct Config { pub(crate) flags: settings::Builder, pub(crate) isa_flags: isa::Builder, - pub(crate) validating_config: ValidatingParserConfig, pub(crate) tunables: Tunables, pub(crate) strategy: CompilationStrategy, pub(crate) cache_config: CacheConfig, pub(crate) profiler: Arc, pub(crate) memory_creator: Option, pub(crate) max_wasm_stack: usize, + wasm_threads: bool, + wasm_reference_types: bool, + pub(crate) wasm_bulk_memory: bool, + wasm_simd: bool, + wasm_multi_value: bool, } impl Config { @@ -81,17 +85,6 @@ impl Config { Config { tunables, - validating_config: ValidatingParserConfig { - operator_config: OperatorValidatorConfig { - enable_threads: false, - enable_reference_types: false, - enable_bulk_memory: false, - enable_simd: false, - enable_multi_value: true, - enable_tail_call: false, - enable_module_linking: false, - }, - }, flags, isa_flags: native::builder(), strategy: CompilationStrategy::Auto, @@ -99,6 +92,11 @@ impl Config { profiler: Arc::new(NullProfilerAgent), memory_creator: None, max_wasm_stack: 1 << 20, + wasm_threads: false, + wasm_reference_types: false, + wasm_bulk_memory: false, + wasm_simd: false, + wasm_multi_value: true, } } @@ -163,7 +161,7 @@ impl Config { /// /// [threads]: https://github.com/webassembly/threads pub fn wasm_threads(&mut self, enable: bool) -> &mut Self { - self.validating_config.operator_config.enable_threads = enable; + self.wasm_threads = enable; // The threads proposal depends on the bulk memory proposal if enable { self.wasm_bulk_memory(true); @@ -193,9 +191,7 @@ impl Config { /// /// [proposal]: https://github.com/webassembly/reference-types pub fn wasm_reference_types(&mut self, enable: bool) -> &mut Self { - self.validating_config - .operator_config - .enable_reference_types = enable; + self.wasm_reference_types = enable; self.flags .set("enable_safepoints", if enable { "true" } else { "false" }) @@ -230,7 +226,7 @@ impl Config { /// /// [proposal]: https://github.com/webassembly/simd pub fn wasm_simd(&mut self, enable: bool) -> &mut Self { - self.validating_config.operator_config.enable_simd = enable; + self.wasm_simd = enable; let val = if enable { "true" } else { "false" }; self.flags .set("enable_simd", val) @@ -254,7 +250,7 @@ impl Config { /// /// [proposal]: https://github.com/webassembly/bulk-memory-operations pub fn wasm_bulk_memory(&mut self, enable: bool) -> &mut Self { - self.validating_config.operator_config.enable_bulk_memory = enable; + self.wasm_bulk_memory = enable; self } @@ -268,7 +264,7 @@ impl Config { /// /// [proposal]: https://github.com/webassembly/multi-value pub fn wasm_multi_value(&mut self, enable: bool) -> &mut Self { - self.validating_config.operator_config.enable_multi_value = enable; + self.wasm_multi_value = enable; self } @@ -613,6 +609,16 @@ impl Config { .finish(settings::Flags::new(self.flags.clone())) } + pub(crate) fn validator(&self) -> Validator { + let mut ret = Validator::new(); + ret.wasm_threads(self.wasm_threads) + .wasm_bulk_memory(self.wasm_bulk_memory) + .wasm_multi_value(self.wasm_multi_value) + .wasm_reference_types(self.wasm_reference_types) + .wasm_simd(self.wasm_simd); + return ret; + } + fn build_compiler(&self) -> Compiler { let isa = self.target_isa(); Compiler::new( @@ -640,15 +646,14 @@ impl Default for Config { impl fmt::Debug for Config { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let features = &self.validating_config.operator_config; f.debug_struct("Config") .field("debug_info", &self.tunables.debug_info) .field("strategy", &self.strategy) - .field("wasm_threads", &features.enable_threads) - .field("wasm_reference_types", &features.enable_reference_types) - .field("wasm_bulk_memory", &features.enable_bulk_memory) - .field("wasm_simd", &features.enable_simd) - .field("wasm_multi_value", &features.enable_multi_value) + .field("wasm_threads", &self.wasm_threads) + .field("wasm_reference_types", &self.wasm_reference_types) + .field("wasm_bulk_memory", &self.wasm_bulk_memory) + .field("wasm_simd", &self.wasm_simd) + .field("wasm_multi_value", &self.wasm_multi_value) .field( "flags", &settings::Flags::new(self.flags.clone()).to_string(), diff --git a/crates/wast/Cargo.toml b/crates/wast/Cargo.toml index e5d3ff9e07..1da22cd846 100644 --- a/crates/wast/Cargo.toml +++ b/crates/wast/Cargo.toml @@ -13,7 +13,7 @@ edition = "2018" [dependencies] anyhow = "1.0.19" wasmtime = { path = "../wasmtime", version = "0.18.0", default-features = false } -wast = "18.0.0" +wast = "21.0.0" [badges] maintenance = { status = "actively-developed" } diff --git a/crates/wast/src/wast.rs b/crates/wast/src/wast.rs index 92e68bb9eb..9315c19033 100644 --- a/crates/wast/src/wast.rs +++ b/crates/wast/src/wast.rs @@ -6,7 +6,7 @@ use wasmtime::*; use wast::Wat; use wast::{ parser::{self, ParseBuffer}, - RefType, + HeapType, }; /// Translate from a `script::Value` to a `RuntimeValue`. @@ -22,8 +22,8 @@ fn runtime_value(v: &wast::Expression<'_>) -> Result { F32Const(x) => Val::F32(x.bits), F64Const(x) => Val::F64(x.bits), V128Const(x) => Val::V128(u128::from_le_bytes(x.to_le_bytes())), - RefNull(RefType::Extern) => Val::ExternRef(None), - RefNull(RefType::Func) => Val::FuncRef(None), + RefNull(HeapType::Extern) => Val::ExternRef(None), + RefNull(HeapType::Func) => Val::FuncRef(None), RefExtern(x) => Val::ExternRef(Some(ExternRef::new(*x))), other => bail!("couldn't convert {:?} to a runtime value", other), }) @@ -409,7 +409,7 @@ fn val_matches(actual: &Val, expected: &wast::AssertExpression) -> Result (Val::F32(a), wast::AssertExpression::F32(b)) => f32_matches(*a, b), (Val::F64(a), wast::AssertExpression::F64(b)) => f64_matches(*a, b), (Val::V128(a), wast::AssertExpression::V128(b)) => v128_matches(*a, b), - (Val::ExternRef(x), wast::AssertExpression::RefNull(wast::RefType::Extern)) => x.is_none(), + (Val::ExternRef(x), wast::AssertExpression::RefNull(HeapType::Extern)) => x.is_none(), (Val::ExternRef(x), wast::AssertExpression::RefExtern(y)) => { if let Some(x) = x { let x = x @@ -421,7 +421,7 @@ fn val_matches(actual: &Val, expected: &wast::AssertExpression) -> Result false } } - (Val::FuncRef(x), wast::AssertExpression::RefNull(wast::RefType::Func)) => x.is_none(), + (Val::FuncRef(x), wast::AssertExpression::RefNull(HeapType::Func)) => x.is_none(), _ => bail!( "don't know how to compare {:?} and {:?} yet", actual, diff --git a/tests/misc_testsuite/reference-types/simple_ref_is_null.wast b/tests/misc_testsuite/reference-types/simple_ref_is_null.wast index 453aca48c4..47476e12db 100644 --- a/tests/misc_testsuite/reference-types/simple_ref_is_null.wast +++ b/tests/misc_testsuite/reference-types/simple_ref_is_null.wast @@ -1,12 +1,12 @@ (module (func (export "func_is_null") (param funcref) (result i32) - (ref.is_null func (local.get 0)) + (ref.is_null (local.get 0)) ) (func (export "func_is_null_with_non_null_funcref") (result i32) (call 0 (ref.func 0)) ) (func (export "extern_is_null") (param externref) (result i32) - (ref.is_null extern (local.get 0)) + (ref.is_null (local.get 0)) ) ) diff --git a/tests/spec_testsuite b/tests/spec_testsuite index 21a10bc594..d2163dace0 160000 --- a/tests/spec_testsuite +++ b/tests/spec_testsuite @@ -1 +1 @@ -Subproject commit 21a10bc5942aeb328a057fa54820d3ffb5e7f144 +Subproject commit d2163dace09d647bccf34b9b82a6f05a3b23cf29