diff --git a/cranelift/src/wasm.rs b/cranelift/src/wasm.rs index 5ef8e21f2e..4f44afa6f6 100644 --- a/cranelift/src/wasm.rs +++ b/cranelift/src/wasm.rs @@ -105,7 +105,9 @@ fn handle_module( } let mut dummy_environ = DummyEnvironment::with_flags(fisa.flags.clone()); - translate_module(&data, &mut dummy_environ)?; + translate_module(&data, &mut dummy_environ).map_err( + |e| e.to_string(), + )?; terminal.fg(term::color::GREEN).unwrap(); vprintln!(flag_verbose, "ok"); diff --git a/lib/codegen/src/result.rs b/lib/codegen/src/result.rs index 47047e2f4e..9d347e351a 100644 --- a/lib/codegen/src/result.rs +++ b/lib/codegen/src/result.rs @@ -7,13 +7,6 @@ use verifier; /// When Cretonne fails to compile a function, it will return one of these error codes. #[derive(Fail, Debug, PartialEq, Eq)] pub enum CtonError { - /// The input is invalid. - /// - /// This error code is used by a WebAssembly translator when it encounters invalid WebAssembly - /// code. This should never happen for validated WebAssembly code. - #[fail(display = "Invalid input code")] - InvalidInput, - /// An IR verifier error. /// /// This always represents a bug, either in the code that generated IR for Cretonne, or a bug diff --git a/lib/wasm/Cargo.toml b/lib/wasm/Cargo.toml index 62cfa3f872..f1ad6b726c 100644 --- a/lib/wasm/Cargo.toml +++ b/lib/wasm/Cargo.toml @@ -13,6 +13,8 @@ wasmparser = { version = "0.16.1", default-features = false } cretonne-codegen = { path = "../codegen", version = "0.8.0", default-features = false } cretonne-frontend = { path = "../frontend", version = "0.8.0", default-features = false } hashmap_core = { version = "0.1.4", optional = true } +failure = { version = "0.1.1", default-features = false, features = ["derive"] } +failure_derive = { version = "0.1.1", default-features = false } [dev-dependencies] tempdir = "0.3.5" diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index aea622cc34..dbe23c4d15 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -27,7 +27,7 @@ use cretonne_codegen::ir::types::*; use cretonne_codegen::ir::{self, InstBuilder, JumpTableData, MemFlags}; use cretonne_codegen::packed_option::ReservedValue; use cretonne_frontend::{FunctionBuilder, Variable}; -use environ::{FuncEnvironment, GlobalValue}; +use environ::{FuncEnvironment, GlobalValue, WasmResult}; use state::{ControlStackFrame, TranslationState}; use std::collections::{hash_map, HashMap}; use std::vec::Vec; @@ -45,13 +45,13 @@ pub fn translate_operator( builder: &mut FunctionBuilder, state: &mut TranslationState, environ: &mut FE, -) { +) -> WasmResult<()> { if !state.reachable { - return translate_unreachable_operator(&op, builder, state); + return Ok(translate_unreachable_operator(&op, builder, state)); } // This big match treats all Wasm code operators. - match op { + Ok(match op { /********************************** Locals **************************************** * `get_local` and `set_local` are treated as non-SSA variables and will completely * disappear in the Cretonne Code @@ -362,7 +362,7 @@ pub fn translate_operator( function_index as FunctionIndex, fref, state.peekn(num_args), - ); + )?; state.popn(num_args); state.pushn(builder.inst_results(call)); } @@ -378,7 +378,7 @@ pub fn translate_operator( sigref, callee, state.peekn(num_args), - ); + )?; state.popn(num_args); state.pushn(builder.inst_results(call)); } @@ -397,7 +397,7 @@ pub fn translate_operator( heap_index, heap, val, - )) + )?) } Operator::CurrentMemory { reserved } => { let heap_index = reserved as MemoryIndex; @@ -406,7 +406,7 @@ pub fn translate_operator( builder.cursor(), heap_index, heap, - )); + )?); } /******************************* Load instructions *********************************** * Wasm specifies an integer alignment flag but we drop it in Cretonne. @@ -857,7 +857,7 @@ pub fn translate_operator( Operator::I64AtomicRmw32UCmpxchg { .. } => { panic!("proposed thread operators not yet supported"); } - } + }) } // Clippy warns us of some fields we are deliberately ignoring diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index 68927101cf..90f1af3b5a 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -4,7 +4,7 @@ use cretonne_codegen::cursor::FuncCursor; use cretonne_codegen::ir::types::*; use cretonne_codegen::ir::{self, InstBuilder}; use cretonne_codegen::settings; -use environ::{FuncEnvironment, GlobalValue, ModuleEnvironment}; +use environ::{FuncEnvironment, GlobalValue, ModuleEnvironment, WasmResult}; use func_translator::FuncTranslator; use std::string::String; use std::vec::Vec; @@ -196,7 +196,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ sig_ref: ir::SigRef, callee: ir::Value, call_args: &[ir::Value], - ) -> ir::Inst { + ) -> WasmResult { // Pass the current function's vmctx parameter on to the callee. let vmctx = pos.func .special_param(ir::ArgumentPurpose::VMContext) @@ -224,9 +224,11 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ args.extend(call_args.iter().cloned(), &mut pos.func.dfg.value_lists); args.push(vmctx, &mut pos.func.dfg.value_lists); - pos.ins() - .CallIndirect(ir::Opcode::CallIndirect, VOID, sig_ref, args) - .0 + Ok( + pos.ins() + .CallIndirect(ir::Opcode::CallIndirect, VOID, sig_ref, args) + .0, + ) } fn translate_call( @@ -235,7 +237,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ _callee_index: FunctionIndex, callee: ir::FuncRef, call_args: &[ir::Value], - ) -> ir::Inst { + ) -> WasmResult { // Pass the current function's vmctx parameter on to the callee. let vmctx = pos.func .special_param(ir::ArgumentPurpose::VMContext) @@ -247,7 +249,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ args.extend(call_args.iter().cloned(), &mut pos.func.dfg.value_lists); args.push(vmctx, &mut pos.func.dfg.value_lists); - pos.ins().Call(ir::Opcode::Call, VOID, callee, args).0 + Ok(pos.ins().Call(ir::Opcode::Call, VOID, callee, args).0) } fn translate_grow_memory( @@ -256,8 +258,8 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ _index: MemoryIndex, _heap: ir::Heap, _val: ir::Value, - ) -> ir::Value { - pos.ins().iconst(I32, -1) + ) -> WasmResult { + Ok(pos.ins().iconst(I32, -1)) } fn translate_current_memory( @@ -265,8 +267,8 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ mut pos: FuncCursor, _index: MemoryIndex, _heap: ir::Heap, - ) -> ir::Value { - pos.ins().iconst(I32, -1) + ) -> WasmResult { + Ok(pos.ins().iconst(I32, -1)) } } @@ -385,7 +387,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { self.info.start_func = Some(func_index); } - fn define_function_body(&mut self, body_bytes: &'data [u8]) -> Result<(), String> { + fn define_function_body(&mut self, body_bytes: &'data [u8]) -> WasmResult<()> { let func = { let mut func_environ = DummyFuncEnvironment::new(&self.info); let function_index = self.get_num_func_imports() + self.info.function_bodies.len(); @@ -393,9 +395,11 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { let sig = func_environ.vmctx_sig(self.get_func_type(function_index)); let mut func = ir::Function::with_name_signature(name, sig); let reader = wasmparser::BinaryReader::new(body_bytes); - self.trans - .translate_from_reader(reader, &mut func, &mut func_environ) - .map_err(|e| format!("{}", e))?; + self.trans.translate_from_reader( + reader, + &mut func, + &mut func_environ, + )?; func }; self.func_bytecode_sizes.push(body_bytes.len()); diff --git a/lib/wasm/src/environ/mod.rs b/lib/wasm/src/environ/mod.rs index e89995d8f8..923d65be11 100644 --- a/lib/wasm/src/environ/mod.rs +++ b/lib/wasm/src/environ/mod.rs @@ -4,4 +4,4 @@ mod dummy; mod spec; pub use environ::dummy::DummyEnvironment; -pub use environ::spec::{FuncEnvironment, GlobalValue, ModuleEnvironment}; +pub use environ::spec::{FuncEnvironment, GlobalValue, ModuleEnvironment, WasmError, WasmResult}; diff --git a/lib/wasm/src/environ/spec.rs b/lib/wasm/src/environ/spec.rs index cc9e4eb771..6093203ff2 100644 --- a/lib/wasm/src/environ/spec.rs +++ b/lib/wasm/src/environ/spec.rs @@ -3,10 +3,10 @@ use cretonne_codegen::cursor::FuncCursor; use cretonne_codegen::ir::{self, InstBuilder}; use cretonne_codegen::settings::Flags; -use std::string::String; use std::vec::Vec; use translation_utils::{FunctionIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex}; +use wasmparser::BinaryReaderError; /// The value of a WebAssembly global variable. #[derive(Clone, Copy)] @@ -23,6 +23,49 @@ pub enum GlobalValue { }, } +/// A WebAssembly translation error. +/// +/// When a WebAssembly function can't be translated, one of these error codes will be returned +/// to describe the failure. +#[derive(Fail, Debug, PartialEq, Eq)] +pub enum WasmError { + /// The input WebAssembly code is invalid. + /// + /// This error code is used by a WebAssembly translator when it encounters invalid WebAssembly + /// code. This should never happen for validated WebAssembly code. + #[fail(display = "Invalid input WebAssembly code at offset {}: {}", _1, _0)] + InvalidWebAssembly { + message: &'static str, + offset: usize, + }, + + /// A feature used by the WebAssembly code is not supported by the embedding environment. + /// + /// Embedding environments may have their own limitations and feature restrictions. + #[fail(display = "Unsupported feature: {}", _0)] + Unsupported(&'static str), + + /// An implementation limit was exceeded. + /// + /// Cretonne can compile very large and complicated functions, but the [implementation has + /// limits][limits] that cause compilation to fail when they are exceeded. + /// + /// [limits]: https://cretonne.readthedocs.io/en/latest/langref.html#implementation-limits + #[fail(display = "Implementation limit exceeded")] + ImplLimitExceeded, +} + +impl WasmError { + /// Convert from a `BinaryReaderError` to a `WasmError`. + pub fn from_binary_reader_error(e: BinaryReaderError) -> Self { + let BinaryReaderError { message, offset } = e; + WasmError::InvalidWebAssembly { message, offset } + } +} + +/// A convenient alias for a `Result` that uses `WasmError` as the error type. +pub type WasmResult = Result; + /// Environment affecting the translation of a single WebAssembly function. /// /// A `FuncEnvironment` trait object is required to translate a WebAssembly function to Cretonne @@ -99,7 +142,7 @@ pub trait FuncEnvironment { sig_ref: ir::SigRef, callee: ir::Value, call_args: &[ir::Value], - ) -> ir::Inst; + ) -> WasmResult; /// Translate a `call` WebAssembly instruction at `pos`. /// @@ -114,8 +157,8 @@ pub trait FuncEnvironment { _callee_index: FunctionIndex, callee: ir::FuncRef, call_args: &[ir::Value], - ) -> ir::Inst { - pos.ins().call(callee, call_args) + ) -> WasmResult { + Ok(pos.ins().call(callee, call_args)) } /// Translate a `grow_memory` WebAssembly instruction. @@ -132,7 +175,7 @@ pub trait FuncEnvironment { index: MemoryIndex, heap: ir::Heap, val: ir::Value, - ) -> ir::Value; + ) -> WasmResult; /// Translates a `current_memory` WebAssembly instruction. /// @@ -145,7 +188,7 @@ pub trait FuncEnvironment { pos: FuncCursor, index: MemoryIndex, heap: ir::Heap, - ) -> ir::Value; + ) -> WasmResult; /// Emit code at the beginning of every wasm loop. /// @@ -229,5 +272,5 @@ pub trait ModuleEnvironment<'data> { fn declare_start_func(&mut self, index: FunctionIndex); /// Provides the contents of a function body. - fn define_function_body(&mut self, body_bytes: &'data [u8]) -> Result<(), String>; + fn define_function_body(&mut self, body_bytes: &'data [u8]) -> WasmResult<()>; } diff --git a/lib/wasm/src/func_translator.rs b/lib/wasm/src/func_translator.rs index 4801cccf11..ed693af4bf 100644 --- a/lib/wasm/src/func_translator.rs +++ b/lib/wasm/src/func_translator.rs @@ -7,10 +7,9 @@ use code_translator::translate_operator; use cretonne_codegen::entity::EntityRef; use cretonne_codegen::ir::{self, Ebb, InstBuilder}; -use cretonne_codegen::result::{CtonError, CtonResult}; use cretonne_codegen::timing; use cretonne_frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; -use environ::FuncEnvironment; +use environ::{FuncEnvironment, WasmError, WasmResult}; use state::TranslationState; use wasmparser::{self, BinaryReader}; @@ -56,7 +55,7 @@ impl FuncTranslator { code: &[u8], func: &mut ir::Function, environ: &mut FE, - ) -> CtonResult { + ) -> WasmResult<()> { self.translate_from_reader(BinaryReader::new(code), func, environ) } @@ -66,7 +65,7 @@ impl FuncTranslator { mut reader: BinaryReader, func: &mut ir::Function, environ: &mut FE, - ) -> CtonResult { + ) -> WasmResult<()> { let _tt = timing::wasm_translate_function(); dbg!( "translate({} bytes, {}{})", @@ -134,17 +133,17 @@ fn parse_local_decls( reader: &mut BinaryReader, builder: &mut FunctionBuilder, num_params: usize, -) -> CtonResult { +) -> WasmResult<()> { let mut next_local = num_params; - let local_count = reader.read_local_count().map_err( - |_| CtonError::InvalidInput, - )?; + let local_count = reader.read_local_count().map_err(|e| { + WasmError::from_binary_reader_error(e) + })?; let mut locals_total = 0; for _ in 0..local_count { builder.set_srcloc(cur_srcloc(reader)); - let (count, ty) = reader.read_local_decl(&mut locals_total).map_err(|_| { - CtonError::InvalidInput + let (count, ty) = reader.read_local_decl(&mut locals_total).map_err(|e| { + WasmError::from_binary_reader_error(e) })?; declare_locals(builder, count, ty, &mut next_local); } @@ -189,15 +188,17 @@ fn parse_function_body( builder: &mut FunctionBuilder, state: &mut TranslationState, environ: &mut FE, -) -> CtonResult { +) -> WasmResult<()> { // The control stack is initialized with a single block representing the whole function. debug_assert_eq!(state.control_stack.len(), 1, "State not initialized"); // Keep going until the final `End` operator which pops the outermost block. while !state.control_stack.is_empty() { builder.set_srcloc(cur_srcloc(&reader)); - let op = reader.read_operator().map_err(|_| CtonError::InvalidInput)?; - translate_operator(op, builder, state, environ); + let op = reader.read_operator().map_err(|e| { + WasmError::from_binary_reader_error(e) + })?; + translate_operator(op, builder, state, environ)?; } // The final `End` operator left us in the exit block where we need to manually add a return diff --git a/lib/wasm/src/lib.rs b/lib/wasm/src/lib.rs index e20e939ca8..d4caf9177c 100644 --- a/lib/wasm/src/lib.rs +++ b/lib/wasm/src/lib.rs @@ -42,6 +42,10 @@ extern crate cretonne_codegen; extern crate cretonne_frontend; extern crate wasmparser; +extern crate failure; +#[macro_use] +extern crate failure_derive; + mod code_translator; mod environ; mod func_translator; diff --git a/lib/wasm/src/module_translator.rs b/lib/wasm/src/module_translator.rs index f1092651d6..683517e7f5 100644 --- a/lib/wasm/src/module_translator.rs +++ b/lib/wasm/src/module_translator.rs @@ -1,14 +1,12 @@ //! Translation skeleton that traverses the whole WebAssembly module and call helper functions //! to deal with each part of it. use cretonne_codegen::timing; -use environ::ModuleEnvironment; +use environ::{ModuleEnvironment, WasmError, WasmResult}; use sections_translator::{parse_data_section, parse_elements_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, SectionParsingError}; -use wasmparser::{BinaryReaderError, Parser, ParserInput, ParserState, SectionCode, WasmDecoder}; - -use std::string::String; + parse_table_section}; +use wasmparser::{Parser, ParserInput, ParserState, SectionCode, WasmDecoder}; /// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IR /// [`Function`](../codegen/ir/function/struct.Function.html). @@ -17,13 +15,13 @@ use std::string::String; pub fn translate_module<'data>( data: &'data [u8], environ: &mut ModuleEnvironment<'data>, -) -> Result<(), String> { +) -> WasmResult<()> { let _tt = timing::wasm_translate_module(); let mut parser = Parser::new(data); match *parser.read() { ParserState::BeginWasm { .. } => {} - ParserState::Error(BinaryReaderError { message, offset }) => { - return Err(format!("at offset {}: {}", offset, message)); + ParserState::Error(e) => { + return Err(WasmError::from_binary_reader_error(e)); } ref s => panic!("modules should begin properly: {:?}", s), } @@ -31,83 +29,38 @@ pub fn translate_module<'data>( loop { match *parser.read_with_input(next_input) { ParserState::BeginSection { code: SectionCode::Type, .. } => { - match parse_function_signatures(&mut parser, environ) { - Ok(()) => (), - Err(SectionParsingError::WrongSectionContent(s)) => { - return Err(format!("wrong content in the type section: {}", s)) - } - }; + parse_function_signatures(&mut parser, environ)?; next_input = ParserInput::Default; } ParserState::BeginSection { code: SectionCode::Import, .. } => { - match parse_import_section(&mut parser, environ) { - Ok(()) => {} - Err(SectionParsingError::WrongSectionContent(s)) => { - return Err(format!("wrong content in the import section: {}", s)) - } - } + parse_import_section(&mut parser, environ)?; next_input = ParserInput::Default; } ParserState::BeginSection { code: SectionCode::Function, .. } => { - match parse_function_section(&mut parser, environ) { - Ok(()) => {} - Err(SectionParsingError::WrongSectionContent(s)) => { - return Err(format!("wrong content in the function section: {}", s)) - } - } + parse_function_section(&mut parser, environ)?; next_input = ParserInput::Default; } ParserState::BeginSection { code: SectionCode::Table, .. } => { - match parse_table_section(&mut parser, environ) { - Ok(()) => (), - Err(SectionParsingError::WrongSectionContent(s)) => { - return Err(format!("wrong content in the table section: {}", s)) - } - } + parse_table_section(&mut parser, environ)?; } ParserState::BeginSection { code: SectionCode::Memory, .. } => { - match parse_memory_section(&mut parser, environ) { - Ok(()) => {} - Err(SectionParsingError::WrongSectionContent(s)) => { - return Err(format!("wrong content in the memory section: {}", s)) - } - } + parse_memory_section(&mut parser, environ)?; next_input = ParserInput::Default; } ParserState::BeginSection { code: SectionCode::Global, .. } => { - match parse_global_section(&mut parser, environ) { - Ok(()) => {} - Err(SectionParsingError::WrongSectionContent(s)) => { - return Err(format!("wrong content in the global section: {}", s)) - } - } + parse_global_section(&mut parser, environ)?; next_input = ParserInput::Default; } ParserState::BeginSection { code: SectionCode::Export, .. } => { - match parse_export_section(&mut parser, environ) { - Ok(()) => {} - Err(SectionParsingError::WrongSectionContent(s)) => { - return Err(format!("wrong content in the export section: {}", s)) - } - } + parse_export_section(&mut parser, environ)?; next_input = ParserInput::Default; } ParserState::BeginSection { code: SectionCode::Start, .. } => { - match parse_start_section(&mut parser, environ) { - Ok(()) => (), - Err(SectionParsingError::WrongSectionContent(s)) => { - return Err(format!("wrong content in the start section: {}", s)) - } - } + parse_start_section(&mut parser, environ)?; next_input = ParserInput::Default; } ParserState::BeginSection { code: SectionCode::Element, .. } => { - match parse_elements_section(&mut parser, environ) { - Ok(()) => (), - Err(SectionParsingError::WrongSectionContent(s)) => { - return Err(format!("wrong content in the element section: {}", s)) - } - } + parse_elements_section(&mut parser, environ)?; next_input = ParserInput::Default; } ParserState::BeginSection { code: SectionCode::Code, .. } => { @@ -119,18 +72,14 @@ pub fn translate_module<'data>( } ParserState::EndWasm => return Ok(()), ParserState::BeginSection { code: SectionCode::Data, .. } => { - match parse_data_section(&mut parser, environ) { - Ok(()) => (), - Err(SectionParsingError::WrongSectionContent(s)) => { - return Err(format!("wrong content in the data section: {}", s)) - } - } + parse_data_section(&mut parser, environ)?; } ParserState::BeginSection { code: SectionCode::Custom { .. }, .. } => { // Ignore unknown custom sections. next_input = ParserInput::SkipSection; } - _ => return Err(String::from("wrong content in the preamble")), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + _ => panic!("wrong content in the preamble"), }; } // At this point we've entered the code section @@ -138,25 +87,21 @@ pub fn translate_module<'data>( match *parser.read() { ParserState::BeginFunctionBody { .. } => {} ParserState::EndSection => break, - _ => return Err(String::from("wrong content in code section")), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("wrong content in code section: {:?}", s), } let mut reader = parser.create_binary_reader(); let size = reader.bytes_remaining(); environ.define_function_body( reader.read_bytes(size).map_err(|e| { - format!("at offset {}: {}", e.offset, e.message) + WasmError::from_binary_reader_error(e) })?, )?; } loop { match *parser.read() { ParserState::BeginSection { code: SectionCode::Data, .. } => { - match parse_data_section(&mut parser, environ) { - Ok(()) => (), - Err(SectionParsingError::WrongSectionContent(s)) => { - return Err(format!("wrong content in the data section: {}", s)) - } - } + parse_data_section(&mut parser, environ)?; } ParserState::EndWasm => break, _ => (), diff --git a/lib/wasm/src/sections_translator.rs b/lib/wasm/src/sections_translator.rs index a9ca07a8df..222433fafb 100644 --- a/lib/wasm/src/sections_translator.rs +++ b/lib/wasm/src/sections_translator.rs @@ -8,9 +8,8 @@ //! is handled, according to the semantics of WebAssembly, to only specific expressions that are //! interpreted on the fly. use cretonne_codegen::ir::{self, AbiParam, Signature}; -use environ::ModuleEnvironment; +use environ::{ModuleEnvironment, WasmError, WasmResult}; use std::str::from_utf8; -use std::string::String; use std::vec::Vec; use translation_utils::{type_to_type, FunctionIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex, Table, TableElementType, TableIndex}; @@ -18,15 +17,11 @@ use wasmparser; use wasmparser::{ExternalKind, FuncType, ImportSectionEntryType, MemoryType, Operator, Parser, ParserState, WasmDecoder}; -pub enum SectionParsingError { - WrongSectionContent(String), -} - /// Reads the Type Section of the wasm module and returns the corresponding function signatures. pub fn parse_function_signatures( parser: &mut Parser, environ: &mut ModuleEnvironment, -) -> Result<(), SectionParsingError> { +) -> WasmResult<()> { loop { match *parser.read() { ParserState::EndSection => break, @@ -50,7 +45,8 @@ pub fn parse_function_signatures( })); environ.declare_signature(&sig); } - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), } } Ok(()) @@ -60,7 +56,7 @@ pub fn parse_function_signatures( pub fn parse_import_section<'data>( parser: &mut Parser<'data>, environ: &mut ModuleEnvironment<'data>, -) -> Result<(), SectionParsingError> { +) -> WasmResult<()> { loop { match *parser.read() { ParserState::ImportSectionEntry { @@ -110,7 +106,8 @@ pub fn parse_import_section<'data>( }) } ParserState::EndSection => break, - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; } Ok(()) @@ -120,14 +117,15 @@ pub fn parse_import_section<'data>( pub fn parse_function_section( parser: &mut Parser, environ: &mut ModuleEnvironment, -) -> Result<(), SectionParsingError> { +) -> WasmResult<()> { loop { match *parser.read() { ParserState::FunctionSectionEntry(sigindex) => { environ.declare_func_type(sigindex as SignatureIndex); } ParserState::EndSection => break, - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; } Ok(()) @@ -137,7 +135,7 @@ pub fn parse_function_section( pub fn parse_export_section<'data>( parser: &mut Parser<'data>, environ: &mut ModuleEnvironment<'data>, -) -> Result<(), SectionParsingError> { +) -> WasmResult<()> { loop { match *parser.read() { ParserState::ExportSectionEntry { @@ -158,24 +156,23 @@ pub fn parse_export_section<'data>( } } ParserState::EndSection => break, - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; } Ok(()) } /// Retrieves the start function index from the start section -pub fn parse_start_section( - parser: &mut Parser, - environ: &mut ModuleEnvironment, -) -> Result<(), SectionParsingError> { +pub fn parse_start_section(parser: &mut Parser, environ: &mut ModuleEnvironment) -> WasmResult<()> { loop { match *parser.read() { ParserState::StartSectionEntry(index) => { environ.declare_start_func(index as FunctionIndex); } ParserState::EndSection => break, - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; } Ok(()) @@ -185,7 +182,7 @@ pub fn parse_start_section( pub fn parse_memory_section( parser: &mut Parser, environ: &mut ModuleEnvironment, -) -> Result<(), SectionParsingError> { +) -> WasmResult<()> { loop { match *parser.read() { ParserState::MemorySectionEntry(ref ty) => { @@ -196,7 +193,8 @@ pub fn parse_memory_section( }); } ParserState::EndSection => break, - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; } Ok(()) @@ -206,16 +204,18 @@ pub fn parse_memory_section( pub fn parse_global_section( parser: &mut Parser, environ: &mut ModuleEnvironment, -) -> Result<(), SectionParsingError> { +) -> WasmResult<()> { loop { let (content_type, mutability) = match *parser.read() { ParserState::BeginGlobalSectionEntry(ref ty) => (ty.content_type, ty.mutable), ParserState::EndSection => break, - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; match *parser.read() { ParserState::BeginInitExpressionBody => (), - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), } let initializer = match *parser.read() { ParserState::InitExpressionOperator(Operator::I32Const { value }) => { @@ -233,11 +233,13 @@ pub fn parse_global_section( ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => { GlobalInit::GlobalRef(global_index as GlobalIndex) } - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; match *parser.read() { ParserState::EndInitExpressionBody => (), - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), } let global = Global { ty: type_to_type(&content_type).unwrap(), @@ -247,7 +249,8 @@ pub fn parse_global_section( environ.declare_global(global); match *parser.read() { ParserState::EndGlobalSectionEntry => (), - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), } } Ok(()) @@ -256,16 +259,18 @@ pub fn parse_global_section( pub fn parse_data_section<'data>( parser: &mut Parser<'data>, environ: &mut ModuleEnvironment<'data>, -) -> Result<(), SectionParsingError> { +) -> WasmResult<()> { loop { let memory_index = match *parser.read() { ParserState::BeginDataSectionEntry(memory_index) => memory_index, ParserState::EndSection => break, - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; match *parser.read() { ParserState::BeginInitExpressionBody => (), - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; let (base, offset) = match *parser.read() { ParserState::InitExpressionOperator(Operator::I32Const { value }) => { @@ -278,22 +283,26 @@ pub fn parse_data_section<'data>( _ => panic!("should not happen"), } } - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; match *parser.read() { ParserState::EndInitExpressionBody => (), - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; match *parser.read() { ParserState::BeginDataSectionEntryBody(_) => (), - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; let mut running_offset = offset; loop { let data = match *parser.read() { ParserState::DataSectionEntryBodyChunk(data) => data, ParserState::EndDataSectionEntryBody => break, - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; environ.declare_data_initialization( memory_index as MemoryIndex, @@ -305,17 +314,15 @@ pub fn parse_data_section<'data>( } match *parser.read() { ParserState::EndDataSectionEntry => (), - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; } Ok(()) } /// Retrieves the tables from the table section -pub fn parse_table_section( - parser: &mut Parser, - environ: &mut ModuleEnvironment, -) -> Result<(), SectionParsingError> { +pub fn parse_table_section(parser: &mut Parser, environ: &mut ModuleEnvironment) -> WasmResult<()> { loop { match *parser.read() { ParserState::TableSectionEntry(ref table) => { @@ -329,7 +336,8 @@ pub fn parse_table_section( }) } ParserState::EndSection => break, - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; } Ok(()) @@ -339,16 +347,18 @@ pub fn parse_table_section( pub fn parse_elements_section( parser: &mut Parser, environ: &mut ModuleEnvironment, -) -> Result<(), SectionParsingError> { +) -> WasmResult<()> { loop { let table_index = match *parser.read() { ParserState::BeginElementSectionEntry(table_index) => table_index as TableIndex, ParserState::EndSection => break, - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; match *parser.read() { ParserState::BeginInitExpressionBody => (), - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; let (base, offset) = match *parser.read() { ParserState::InitExpressionOperator(Operator::I32Const { value }) => { @@ -361,11 +371,13 @@ pub fn parse_elements_section( _ => panic!("should not happen"), } } - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; match *parser.read() { ParserState::EndInitExpressionBody => (), - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; match *parser.read() { ParserState::ElementSectionEntryBody(ref elements) => { @@ -373,11 +385,13 @@ pub fn parse_elements_section( elements.iter().map(|&x| x as FunctionIndex).collect(); environ.declare_table_elements(table_index, base, offset, elems) } - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; match *parser.read() { ParserState::EndElementSectionEntry => (), - ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), + ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)), + ref s => panic!("unexpected section content: {:?}", s), }; } Ok(())