Return a WasmResult from ModuleEnvironment methods (#886)
* [wasm] return a WasmResult from `declare_table_elements` This method in particular needs to accommodate failure because any table index other than zero is currently invalid. * [wasm] additional failure handling improvements - Adds `WasmResult<()>` as the return type for most of the `ModuleEnvironment` methods that previously returned nothing. - Replaces some panics with `WasmError::Unsupported` now that the methods can return a result. - Adds a `wasm_unsupported!()` macro for early returns with a formatted unsupported message.
This commit is contained in:
@@ -23,12 +23,13 @@
|
|||||||
//! That is why `translate_function_body` takes an object having the `WasmRuntime` trait as
|
//! That is why `translate_function_body` takes an object having the `WasmRuntime` trait as
|
||||||
//! argument.
|
//! argument.
|
||||||
use super::{hash_map, HashMap};
|
use super::{hash_map, HashMap};
|
||||||
use crate::environ::{FuncEnvironment, GlobalVariable, ReturnMode, WasmError, WasmResult};
|
use crate::environ::{FuncEnvironment, GlobalVariable, ReturnMode, WasmResult};
|
||||||
use crate::state::{ControlStackFrame, TranslationState};
|
use crate::state::{ControlStackFrame, TranslationState};
|
||||||
use crate::translation_utils::{
|
use crate::translation_utils::{
|
||||||
blocktype_to_type, f32_translation, f64_translation, num_return_values,
|
blocktype_to_type, f32_translation, f64_translation, num_return_values,
|
||||||
};
|
};
|
||||||
use crate::translation_utils::{FuncIndex, MemoryIndex, SignatureIndex, TableIndex};
|
use crate::translation_utils::{FuncIndex, MemoryIndex, SignatureIndex, TableIndex};
|
||||||
|
use crate::wasm_unsupported;
|
||||||
use core::{i32, u32};
|
use core::{i32, u32};
|
||||||
use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
|
use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
|
||||||
use cranelift_codegen::ir::types::*;
|
use cranelift_codegen::ir::types::*;
|
||||||
@@ -899,10 +900,10 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
| Operator::I64AtomicRmw8UCmpxchg { .. }
|
| Operator::I64AtomicRmw8UCmpxchg { .. }
|
||||||
| Operator::I64AtomicRmw16UCmpxchg { .. }
|
| Operator::I64AtomicRmw16UCmpxchg { .. }
|
||||||
| Operator::I64AtomicRmw32UCmpxchg { .. } => {
|
| Operator::I64AtomicRmw32UCmpxchg { .. } => {
|
||||||
return Err(WasmError::Unsupported("proposed thread operators"));
|
wasm_unsupported!("proposed thread operator {:?}", op);
|
||||||
}
|
}
|
||||||
Operator::RefNull | Operator::RefIsNull { .. } => {
|
Operator::RefNull | Operator::RefIsNull { .. } => {
|
||||||
return Err(WasmError::Unsupported("proposed reference-type operators"));
|
wasm_unsupported!("proposed reference-type operator {:?}", op);
|
||||||
}
|
}
|
||||||
Operator::MemoryInit { .. }
|
Operator::MemoryInit { .. }
|
||||||
| Operator::DataDrop { .. }
|
| Operator::DataDrop { .. }
|
||||||
@@ -915,7 +916,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
| Operator::TableSet { .. }
|
| Operator::TableSet { .. }
|
||||||
| Operator::TableGrow { .. }
|
| Operator::TableGrow { .. }
|
||||||
| Operator::TableSize { .. } => {
|
| Operator::TableSize { .. } => {
|
||||||
return Err(WasmError::Unsupported("proposed bulk memory operators"));
|
wasm_unsupported!("proposed bulk memory operator {:?}", op);
|
||||||
}
|
}
|
||||||
Operator::V128Load { .. }
|
Operator::V128Load { .. }
|
||||||
| Operator::V128Store { .. }
|
| Operator::V128Store { .. }
|
||||||
@@ -1059,7 +1060,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
| Operator::F64x2ConvertUI64x2
|
| Operator::F64x2ConvertUI64x2
|
||||||
| Operator::V8x16Shuffle1
|
| Operator::V8x16Shuffle1
|
||||||
| Operator::V8x16Shuffle2Imm { .. } => {
|
| Operator::V8x16Shuffle2Imm { .. } => {
|
||||||
return Err(WasmError::Unsupported("proposed SIMD operators"));
|
wasm_unsupported!("proposed SIMD operator {:?}", op);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -367,8 +367,9 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
|||||||
self.info.config
|
self.info.config
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_signature(&mut self, sig: ir::Signature) {
|
fn declare_signature(&mut self, sig: ir::Signature) -> WasmResult<()> {
|
||||||
self.info.signatures.push(sig);
|
self.info.signatures.push(sig);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_func_import(
|
fn declare_func_import(
|
||||||
@@ -376,7 +377,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
|||||||
sig_index: SignatureIndex,
|
sig_index: SignatureIndex,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: &'data str,
|
||||||
) {
|
) -> WasmResult<()> {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
self.info.functions.len(),
|
self.info.functions.len(),
|
||||||
self.info.imported_funcs.len(),
|
self.info.imported_funcs.len(),
|
||||||
@@ -386,32 +387,48 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
|||||||
self.info
|
self.info
|
||||||
.imported_funcs
|
.imported_funcs
|
||||||
.push((String::from(module), String::from(field)));
|
.push((String::from(module), String::from(field)));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_func_type(&mut self, sig_index: SignatureIndex) {
|
fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()> {
|
||||||
self.info.functions.push(Exportable::new(sig_index));
|
self.info.functions.push(Exportable::new(sig_index));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_global(&mut self, global: Global) {
|
fn declare_global(&mut self, global: Global) -> WasmResult<()> {
|
||||||
self.info.globals.push(Exportable::new(global));
|
self.info.globals.push(Exportable::new(global));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_global_import(&mut self, global: Global, module: &'data str, field: &'data str) {
|
fn declare_global_import(
|
||||||
|
&mut self,
|
||||||
|
global: Global,
|
||||||
|
module: &'data str,
|
||||||
|
field: &'data str,
|
||||||
|
) -> WasmResult<()> {
|
||||||
self.info.globals.push(Exportable::new(global));
|
self.info.globals.push(Exportable::new(global));
|
||||||
self.info
|
self.info
|
||||||
.imported_globals
|
.imported_globals
|
||||||
.push((String::from(module), String::from(field)));
|
.push((String::from(module), String::from(field)));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_table(&mut self, table: Table) {
|
fn declare_table(&mut self, table: Table) -> WasmResult<()> {
|
||||||
self.info.tables.push(Exportable::new(table));
|
self.info.tables.push(Exportable::new(table));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_table_import(&mut self, table: Table, module: &'data str, field: &'data str) {
|
fn declare_table_import(
|
||||||
|
&mut self,
|
||||||
|
table: Table,
|
||||||
|
module: &'data str,
|
||||||
|
field: &'data str,
|
||||||
|
) -> WasmResult<()> {
|
||||||
self.info.tables.push(Exportable::new(table));
|
self.info.tables.push(Exportable::new(table));
|
||||||
self.info
|
self.info
|
||||||
.imported_tables
|
.imported_tables
|
||||||
.push((String::from(module), String::from(field)));
|
.push((String::from(module), String::from(field)));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_table_elements(
|
fn declare_table_elements(
|
||||||
@@ -420,19 +437,27 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
|||||||
_base: Option<GlobalIndex>,
|
_base: Option<GlobalIndex>,
|
||||||
_offset: usize,
|
_offset: usize,
|
||||||
_elements: Box<[FuncIndex]>,
|
_elements: Box<[FuncIndex]>,
|
||||||
) {
|
) -> WasmResult<()> {
|
||||||
// We do nothing
|
// We do nothing
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_memory(&mut self, memory: Memory) {
|
fn declare_memory(&mut self, memory: Memory) -> WasmResult<()> {
|
||||||
self.info.memories.push(Exportable::new(memory));
|
self.info.memories.push(Exportable::new(memory));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_memory_import(&mut self, memory: Memory, module: &'data str, field: &'data str) {
|
fn declare_memory_import(
|
||||||
|
&mut self,
|
||||||
|
memory: Memory,
|
||||||
|
module: &'data str,
|
||||||
|
field: &'data str,
|
||||||
|
) -> WasmResult<()> {
|
||||||
self.info.memories.push(Exportable::new(memory));
|
self.info.memories.push(Exportable::new(memory));
|
||||||
self.info
|
self.info
|
||||||
.imported_memories
|
.imported_memories
|
||||||
.push((String::from(module), String::from(field)));
|
.push((String::from(module), String::from(field)));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_data_initialization(
|
fn declare_data_initialization(
|
||||||
@@ -441,37 +466,55 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
|||||||
_base: Option<GlobalIndex>,
|
_base: Option<GlobalIndex>,
|
||||||
_offset: usize,
|
_offset: usize,
|
||||||
_data: &'data [u8],
|
_data: &'data [u8],
|
||||||
) {
|
) -> WasmResult<()> {
|
||||||
// We do nothing
|
// We do nothing
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) {
|
fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()> {
|
||||||
self.info.functions[func_index]
|
self.info.functions[func_index]
|
||||||
.export_names
|
.export_names
|
||||||
.push(String::from(name));
|
.push(String::from(name));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_table_export(&mut self, table_index: TableIndex, name: &'data str) {
|
fn declare_table_export(
|
||||||
|
&mut self,
|
||||||
|
table_index: TableIndex,
|
||||||
|
name: &'data str,
|
||||||
|
) -> WasmResult<()> {
|
||||||
self.info.tables[table_index]
|
self.info.tables[table_index]
|
||||||
.export_names
|
.export_names
|
||||||
.push(String::from(name));
|
.push(String::from(name));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_memory_export(&mut self, memory_index: MemoryIndex, name: &'data str) {
|
fn declare_memory_export(
|
||||||
|
&mut self,
|
||||||
|
memory_index: MemoryIndex,
|
||||||
|
name: &'data str,
|
||||||
|
) -> WasmResult<()> {
|
||||||
self.info.memories[memory_index]
|
self.info.memories[memory_index]
|
||||||
.export_names
|
.export_names
|
||||||
.push(String::from(name));
|
.push(String::from(name));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_global_export(&mut self, global_index: GlobalIndex, name: &'data str) {
|
fn declare_global_export(
|
||||||
|
&mut self,
|
||||||
|
global_index: GlobalIndex,
|
||||||
|
name: &'data str,
|
||||||
|
) -> WasmResult<()> {
|
||||||
self.info.globals[global_index]
|
self.info.globals[global_index]
|
||||||
.export_names
|
.export_names
|
||||||
.push(String::from(name));
|
.push(String::from(name));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_start_func(&mut self, func_index: FuncIndex) {
|
fn declare_start_func(&mut self, func_index: FuncIndex) -> WasmResult<()> {
|
||||||
debug_assert!(self.info.start_func.is_none());
|
debug_assert!(self.info.start_func.is_none());
|
||||||
self.info.start_func = Some(func_index);
|
self.info.start_func = Some(func_index);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn define_function_body(
|
fn define_function_body(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
//! Support for configurable wasm translation.
|
//! Support for configurable wasm translation.
|
||||||
|
|
||||||
mod dummy;
|
mod dummy;
|
||||||
|
#[macro_use]
|
||||||
mod spec;
|
mod spec;
|
||||||
|
|
||||||
pub use crate::environ::dummy::DummyEnvironment;
|
pub use crate::environ::dummy::DummyEnvironment;
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ pub enum WasmError {
|
|||||||
///
|
///
|
||||||
/// Embedding environments may have their own limitations and feature restrictions.
|
/// Embedding environments may have their own limitations and feature restrictions.
|
||||||
#[fail(display = "Unsupported feature: {}", _0)]
|
#[fail(display = "Unsupported feature: {}", _0)]
|
||||||
Unsupported(&'static str),
|
Unsupported(std::string::String),
|
||||||
|
|
||||||
/// An implementation limit was exceeded.
|
/// An implementation limit was exceeded.
|
||||||
///
|
///
|
||||||
@@ -76,6 +76,13 @@ pub enum WasmError {
|
|||||||
User(std::string::String),
|
User(std::string::String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return an `Err(WasmError::Unsupported(msg))` where `msg` the string built by calling `format!`
|
||||||
|
/// on the arguments to this macro.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! wasm_unsupported {
|
||||||
|
($($arg:tt)*) => { return Err($crate::environ::WasmError::Unsupported(format!($($arg)*))) }
|
||||||
|
}
|
||||||
|
|
||||||
impl From<BinaryReaderError> for WasmError {
|
impl From<BinaryReaderError> for WasmError {
|
||||||
/// Convert from a `BinaryReaderError` to a `WasmError`.
|
/// Convert from a `BinaryReaderError` to a `WasmError`.
|
||||||
fn from(e: BinaryReaderError) -> Self {
|
fn from(e: BinaryReaderError) -> Self {
|
||||||
@@ -289,14 +296,18 @@ pub trait ModuleEnvironment<'data> {
|
|||||||
|
|
||||||
/// Provides the number of signatures up front. By default this does nothing, but
|
/// Provides the number of signatures up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
fn reserve_signatures(&mut self, _num: u32) {}
|
fn reserve_signatures(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Declares a function signature to the environment.
|
/// Declares a function signature to the environment.
|
||||||
fn declare_signature(&mut self, sig: ir::Signature);
|
fn declare_signature(&mut self, sig: ir::Signature) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Provides the number of imports up front. By default this does nothing, but
|
/// Provides the number of imports up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
fn reserve_imports(&mut self, _num: u32) {}
|
fn reserve_imports(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Declares a function import to the environment.
|
/// Declares a function import to the environment.
|
||||||
fn declare_func_import(
|
fn declare_func_import(
|
||||||
@@ -304,73 +315,113 @@ pub trait ModuleEnvironment<'data> {
|
|||||||
sig_index: SignatureIndex,
|
sig_index: SignatureIndex,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: &'data str,
|
||||||
);
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Declares a table import to the environment.
|
/// Declares a table import to the environment.
|
||||||
fn declare_table_import(&mut self, table: Table, module: &'data str, field: &'data str);
|
fn declare_table_import(
|
||||||
|
&mut self,
|
||||||
|
table: Table,
|
||||||
|
module: &'data str,
|
||||||
|
field: &'data str,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Declares a memory import to the environment.
|
/// Declares a memory import to the environment.
|
||||||
fn declare_memory_import(&mut self, memory: Memory, module: &'data str, field: &'data str);
|
fn declare_memory_import(
|
||||||
|
&mut self,
|
||||||
|
memory: Memory,
|
||||||
|
module: &'data str,
|
||||||
|
field: &'data str,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Declares a global import to the environment.
|
/// Declares a global import to the environment.
|
||||||
fn declare_global_import(&mut self, global: Global, module: &'data str, field: &'data str);
|
fn declare_global_import(
|
||||||
|
&mut self,
|
||||||
|
global: Global,
|
||||||
|
module: &'data str,
|
||||||
|
field: &'data str,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Notifies the implementation that all imports have been declared.
|
/// Notifies the implementation that all imports have been declared.
|
||||||
fn finish_imports(&mut self) {}
|
fn finish_imports(&mut self) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Provides the number of defined functions up front. By default this does nothing, but
|
/// Provides the number of defined functions up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
fn reserve_func_types(&mut self, _num: u32) {}
|
fn reserve_func_types(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Declares the type (signature) of a local function in the module.
|
/// Declares the type (signature) of a local function in the module.
|
||||||
fn declare_func_type(&mut self, sig_index: SignatureIndex);
|
fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Provides the number of defined tables up front. By default this does nothing, but
|
/// Provides the number of defined tables up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
fn reserve_tables(&mut self, _num: u32) {}
|
fn reserve_tables(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Declares a table to the environment.
|
/// Declares a table to the environment.
|
||||||
fn declare_table(&mut self, table: Table);
|
fn declare_table(&mut self, table: Table) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Provides the number of defined memories up front. By default this does nothing, but
|
/// Provides the number of defined memories up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
fn reserve_memories(&mut self, _num: u32) {}
|
fn reserve_memories(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Declares a memory to the environment
|
/// Declares a memory to the environment
|
||||||
fn declare_memory(&mut self, memory: Memory);
|
fn declare_memory(&mut self, memory: Memory) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Provides the number of defined globals up front. By default this does nothing, but
|
/// Provides the number of defined globals up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
fn reserve_globals(&mut self, _num: u32) {}
|
fn reserve_globals(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Declares a global to the environment.
|
/// Declares a global to the environment.
|
||||||
fn declare_global(&mut self, global: Global);
|
fn declare_global(&mut self, global: Global) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Provides the number of exports up front. By default this does nothing, but
|
/// Provides the number of exports up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
fn reserve_exports(&mut self, _num: u32) {}
|
fn reserve_exports(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Declares a function export to the environment.
|
/// Declares a function export to the environment.
|
||||||
fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str);
|
fn declare_func_export(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Declares a table export to the environment.
|
/// Declares a table export to the environment.
|
||||||
fn declare_table_export(&mut self, table_index: TableIndex, name: &'data str);
|
fn declare_table_export(&mut self, table_index: TableIndex, name: &'data str)
|
||||||
|
-> WasmResult<()>;
|
||||||
|
|
||||||
/// Declares a memory export to the environment.
|
/// Declares a memory export to the environment.
|
||||||
fn declare_memory_export(&mut self, memory_index: MemoryIndex, name: &'data str);
|
fn declare_memory_export(
|
||||||
|
&mut self,
|
||||||
|
memory_index: MemoryIndex,
|
||||||
|
name: &'data str,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Declares a global export to the environment.
|
/// Declares a global export to the environment.
|
||||||
fn declare_global_export(&mut self, global_index: GlobalIndex, name: &'data str);
|
fn declare_global_export(
|
||||||
|
&mut self,
|
||||||
|
global_index: GlobalIndex,
|
||||||
|
name: &'data str,
|
||||||
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Notifies the implementation that all exports have been declared.
|
/// Notifies the implementation that all exports have been declared.
|
||||||
fn finish_exports(&mut self) {}
|
fn finish_exports(&mut self) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Declares the optional start function.
|
/// Declares the optional start function.
|
||||||
fn declare_start_func(&mut self, index: FuncIndex);
|
fn declare_start_func(&mut self, index: FuncIndex) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Provides the number of element initializers up front. By default this does nothing, but
|
/// Provides the number of element initializers up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
fn reserve_table_elements(&mut self, _num: u32) {}
|
fn reserve_table_elements(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Fills a declared table with references to functions in the module.
|
/// Fills a declared table with references to functions in the module.
|
||||||
fn declare_table_elements(
|
fn declare_table_elements(
|
||||||
@@ -379,7 +430,7 @@ pub trait ModuleEnvironment<'data> {
|
|||||||
base: Option<GlobalIndex>,
|
base: Option<GlobalIndex>,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
elements: Box<[FuncIndex]>,
|
elements: Box<[FuncIndex]>,
|
||||||
);
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Provides the contents of a function body.
|
/// Provides the contents of a function body.
|
||||||
///
|
///
|
||||||
@@ -393,7 +444,9 @@ pub trait ModuleEnvironment<'data> {
|
|||||||
|
|
||||||
/// Provides the number of data initializers up front. By default this does nothing, but
|
/// Provides the number of data initializers up front. By default this does nothing, but
|
||||||
/// implementations can use this to preallocate memory if desired.
|
/// implementations can use this to preallocate memory if desired.
|
||||||
fn reserve_data_initializers(&mut self, _num: u32) {}
|
fn reserve_data_initializers(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Fills a declared memory with bytes at module instantiation.
|
/// Fills a declared memory with bytes at module instantiation.
|
||||||
fn declare_data_initialization(
|
fn declare_data_initialization(
|
||||||
@@ -402,5 +455,5 @@ pub trait ModuleEnvironment<'data> {
|
|||||||
base: Option<GlobalIndex>,
|
base: Option<GlobalIndex>,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
data: &'data [u8],
|
data: &'data [u8],
|
||||||
);
|
) -> WasmResult<()>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,10 @@
|
|||||||
//! WebAssembly module and the runtime environment.
|
//! WebAssembly module and the runtime environment.
|
||||||
|
|
||||||
use crate::code_translator::translate_operator;
|
use crate::code_translator::translate_operator;
|
||||||
use crate::environ::{FuncEnvironment, ReturnMode, WasmError, WasmResult};
|
use crate::environ::{FuncEnvironment, ReturnMode, WasmResult};
|
||||||
use crate::state::{TranslationState, VisibleTranslationState};
|
use crate::state::{TranslationState, VisibleTranslationState};
|
||||||
use crate::translation_utils::get_vmctx_value_label;
|
use crate::translation_utils::get_vmctx_value_label;
|
||||||
|
use crate::wasm_unsupported;
|
||||||
use cranelift_codegen::entity::EntityRef;
|
use cranelift_codegen::entity::EntityRef;
|
||||||
use cranelift_codegen::ir::{self, Ebb, InstBuilder, ValueLabel};
|
use cranelift_codegen::ir::{self, Ebb, InstBuilder, ValueLabel};
|
||||||
use cranelift_codegen::timing;
|
use cranelift_codegen::timing;
|
||||||
@@ -176,7 +177,7 @@ fn declare_locals(
|
|||||||
I64 => builder.ins().iconst(ir::types::I64, 0),
|
I64 => builder.ins().iconst(ir::types::I64, 0),
|
||||||
F32 => builder.ins().f32const(ir::immediates::Ieee32::with_bits(0)),
|
F32 => builder.ins().f32const(ir::immediates::Ieee32::with_bits(0)),
|
||||||
F64 => builder.ins().f64const(ir::immediates::Ieee64::with_bits(0)),
|
F64 => builder.ins().f64const(ir::immediates::Ieee64::with_bits(0)),
|
||||||
_ => return Err(WasmError::Unsupported("unsupported local type")),
|
ty => wasm_unsupported!("unsupported local type {:?}", ty),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ty = builder.func.dfg.value_type(zeroval);
|
let ty = builder.func.dfg.value_type(zeroval);
|
||||||
|
|||||||
@@ -7,11 +7,12 @@
|
|||||||
//! The special case of the initialize expressions for table elements offsets or global variables
|
//! The special case of the initialize expressions for table elements offsets or global variables
|
||||||
//! is handled, according to the semantics of WebAssembly, to only specific expressions that are
|
//! is handled, according to the semantics of WebAssembly, to only specific expressions that are
|
||||||
//! interpreted on the fly.
|
//! interpreted on the fly.
|
||||||
use crate::environ::{ModuleEnvironment, WasmError, WasmResult};
|
use crate::environ::{ModuleEnvironment, WasmResult};
|
||||||
use crate::translation_utils::{
|
use crate::translation_utils::{
|
||||||
tabletype_to_type, type_to_type, FuncIndex, Global, GlobalIndex, GlobalInit, Memory,
|
tabletype_to_type, type_to_type, FuncIndex, Global, GlobalIndex, GlobalInit, Memory,
|
||||||
MemoryIndex, SignatureIndex, Table, TableElementType, TableIndex,
|
MemoryIndex, SignatureIndex, Table, TableElementType, TableIndex,
|
||||||
};
|
};
|
||||||
|
use crate::wasm_unsupported;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use cranelift_codegen::ir::{self, AbiParam, Signature};
|
use cranelift_codegen::ir::{self, AbiParam, Signature};
|
||||||
use cranelift_entity::EntityRef;
|
use cranelift_entity::EntityRef;
|
||||||
@@ -29,7 +30,7 @@ pub fn parse_type_section(
|
|||||||
types: TypeSectionReader,
|
types: TypeSectionReader,
|
||||||
environ: &mut dyn ModuleEnvironment,
|
environ: &mut dyn ModuleEnvironment,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
environ.reserve_signatures(types.get_count());
|
environ.reserve_signatures(types.get_count())?;
|
||||||
|
|
||||||
for entry in types {
|
for entry in types {
|
||||||
match entry? {
|
match entry? {
|
||||||
@@ -49,9 +50,9 @@ pub fn parse_type_section(
|
|||||||
.expect("only numeric types are supported in function signatures");
|
.expect("only numeric types are supported in function signatures");
|
||||||
AbiParam::new(cret_arg)
|
AbiParam::new(cret_arg)
|
||||||
}));
|
}));
|
||||||
environ.declare_signature(sig);
|
environ.declare_signature(sig)?;
|
||||||
}
|
}
|
||||||
_ => return Err(WasmError::Unsupported("unsupported type in type section")),
|
ty => wasm_unsupported!("unsupported type in type section: {:?}", ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -62,7 +63,7 @@ pub fn parse_import_section<'data>(
|
|||||||
imports: ImportSectionReader<'data>,
|
imports: ImportSectionReader<'data>,
|
||||||
environ: &mut dyn ModuleEnvironment<'data>,
|
environ: &mut dyn ModuleEnvironment<'data>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
environ.reserve_imports(imports.get_count());
|
environ.reserve_imports(imports.get_count())?;
|
||||||
|
|
||||||
for entry in imports {
|
for entry in imports {
|
||||||
let import = entry?;
|
let import = entry?;
|
||||||
@@ -71,7 +72,11 @@ pub fn parse_import_section<'data>(
|
|||||||
|
|
||||||
match import.ty {
|
match import.ty {
|
||||||
ImportSectionEntryType::Function(sig) => {
|
ImportSectionEntryType::Function(sig) => {
|
||||||
environ.declare_func_import(SignatureIndex::from_u32(sig), module_name, field_name);
|
environ.declare_func_import(
|
||||||
|
SignatureIndex::from_u32(sig),
|
||||||
|
module_name,
|
||||||
|
field_name,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
ImportSectionEntryType::Memory(MemoryType {
|
ImportSectionEntryType::Memory(MemoryType {
|
||||||
limits: ref memlimits,
|
limits: ref memlimits,
|
||||||
@@ -85,7 +90,7 @@ pub fn parse_import_section<'data>(
|
|||||||
},
|
},
|
||||||
module_name,
|
module_name,
|
||||||
field_name,
|
field_name,
|
||||||
);
|
)?;
|
||||||
}
|
}
|
||||||
ImportSectionEntryType::Global(ref ty) => {
|
ImportSectionEntryType::Global(ref ty) => {
|
||||||
environ.declare_global_import(
|
environ.declare_global_import(
|
||||||
@@ -96,7 +101,7 @@ pub fn parse_import_section<'data>(
|
|||||||
},
|
},
|
||||||
module_name,
|
module_name,
|
||||||
field_name,
|
field_name,
|
||||||
);
|
)?;
|
||||||
}
|
}
|
||||||
ImportSectionEntryType::Table(ref tab) => {
|
ImportSectionEntryType::Table(ref tab) => {
|
||||||
environ.declare_table_import(
|
environ.declare_table_import(
|
||||||
@@ -110,12 +115,12 @@ pub fn parse_import_section<'data>(
|
|||||||
},
|
},
|
||||||
module_name,
|
module_name,
|
||||||
field_name,
|
field_name,
|
||||||
);
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
environ.finish_imports();
|
environ.finish_imports()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,11 +129,11 @@ pub fn parse_function_section(
|
|||||||
functions: FunctionSectionReader,
|
functions: FunctionSectionReader,
|
||||||
environ: &mut dyn ModuleEnvironment,
|
environ: &mut dyn ModuleEnvironment,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
environ.reserve_func_types(functions.get_count());
|
environ.reserve_func_types(functions.get_count())?;
|
||||||
|
|
||||||
for entry in functions {
|
for entry in functions {
|
||||||
let sigindex = entry?;
|
let sigindex = entry?;
|
||||||
environ.declare_func_type(SignatureIndex::from_u32(sigindex));
|
environ.declare_func_type(SignatureIndex::from_u32(sigindex))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -139,7 +144,7 @@ pub fn parse_table_section(
|
|||||||
tables: TableSectionReader,
|
tables: TableSectionReader,
|
||||||
environ: &mut dyn ModuleEnvironment,
|
environ: &mut dyn ModuleEnvironment,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
environ.reserve_tables(tables.get_count());
|
environ.reserve_tables(tables.get_count())?;
|
||||||
|
|
||||||
for entry in tables {
|
for entry in tables {
|
||||||
let table = entry?;
|
let table = entry?;
|
||||||
@@ -150,7 +155,7 @@ pub fn parse_table_section(
|
|||||||
},
|
},
|
||||||
minimum: table.limits.initial,
|
minimum: table.limits.initial,
|
||||||
maximum: table.limits.maximum,
|
maximum: table.limits.maximum,
|
||||||
});
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -161,7 +166,7 @@ pub fn parse_memory_section(
|
|||||||
memories: MemorySectionReader,
|
memories: MemorySectionReader,
|
||||||
environ: &mut dyn ModuleEnvironment,
|
environ: &mut dyn ModuleEnvironment,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
environ.reserve_memories(memories.get_count());
|
environ.reserve_memories(memories.get_count())?;
|
||||||
|
|
||||||
for entry in memories {
|
for entry in memories {
|
||||||
let memory = entry?;
|
let memory = entry?;
|
||||||
@@ -169,7 +174,7 @@ pub fn parse_memory_section(
|
|||||||
minimum: memory.limits.initial,
|
minimum: memory.limits.initial,
|
||||||
maximum: memory.limits.maximum,
|
maximum: memory.limits.maximum,
|
||||||
shared: memory.shared,
|
shared: memory.shared,
|
||||||
});
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -180,7 +185,7 @@ pub fn parse_global_section(
|
|||||||
globals: GlobalSectionReader,
|
globals: GlobalSectionReader,
|
||||||
environ: &mut dyn ModuleEnvironment,
|
environ: &mut dyn ModuleEnvironment,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
environ.reserve_globals(globals.get_count());
|
environ.reserve_globals(globals.get_count())?;
|
||||||
|
|
||||||
for entry in globals {
|
for entry in globals {
|
||||||
let wasmparser::Global {
|
let wasmparser::Global {
|
||||||
@@ -199,14 +204,16 @@ pub fn parse_global_section(
|
|||||||
Operator::GetGlobal { global_index } => {
|
Operator::GetGlobal { global_index } => {
|
||||||
GlobalInit::GetGlobal(GlobalIndex::from_u32(global_index))
|
GlobalInit::GetGlobal(GlobalIndex::from_u32(global_index))
|
||||||
}
|
}
|
||||||
ref s => panic!("unsupported init expr in global section: {:?}", s),
|
ref s => {
|
||||||
|
wasm_unsupported!("unsupported init expr in global section: {:?}", s);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let global = Global {
|
let global = Global {
|
||||||
ty: type_to_type(content_type).unwrap(),
|
ty: type_to_type(content_type).unwrap(),
|
||||||
mutability: mutable,
|
mutability: mutable,
|
||||||
initializer,
|
initializer,
|
||||||
};
|
};
|
||||||
environ.declare_global(global);
|
environ.declare_global(global)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -217,7 +224,7 @@ pub fn parse_export_section<'data>(
|
|||||||
exports: ExportSectionReader<'data>,
|
exports: ExportSectionReader<'data>,
|
||||||
environ: &mut dyn ModuleEnvironment<'data>,
|
environ: &mut dyn ModuleEnvironment<'data>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
environ.reserve_exports(exports.get_count());
|
environ.reserve_exports(exports.get_count())?;
|
||||||
|
|
||||||
for entry in exports {
|
for entry in exports {
|
||||||
let Export {
|
let Export {
|
||||||
@@ -231,20 +238,24 @@ pub fn parse_export_section<'data>(
|
|||||||
// becomes a concern here.
|
// becomes a concern here.
|
||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
match *kind {
|
match *kind {
|
||||||
ExternalKind::Function => environ.declare_func_export(FuncIndex::new(index), field),
|
ExternalKind::Function => environ.declare_func_export(FuncIndex::new(index), field)?,
|
||||||
ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), field),
|
ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), field)?,
|
||||||
ExternalKind::Memory => environ.declare_memory_export(MemoryIndex::new(index), field),
|
ExternalKind::Memory => {
|
||||||
ExternalKind::Global => environ.declare_global_export(GlobalIndex::new(index), field),
|
environ.declare_memory_export(MemoryIndex::new(index), field)?
|
||||||
|
}
|
||||||
|
ExternalKind::Global => {
|
||||||
|
environ.declare_global_export(GlobalIndex::new(index), field)?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
environ.finish_exports();
|
environ.finish_exports()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the Start section of the wasm module.
|
/// Parses the Start section of the wasm module.
|
||||||
pub fn parse_start_section(index: u32, environ: &mut dyn ModuleEnvironment) -> WasmResult<()> {
|
pub fn parse_start_section(index: u32, environ: &mut dyn ModuleEnvironment) -> WasmResult<()> {
|
||||||
environ.declare_start_func(FuncIndex::from_u32(index));
|
environ.declare_start_func(FuncIndex::from_u32(index))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +264,7 @@ pub fn parse_element_section<'data>(
|
|||||||
elements: ElementSectionReader<'data>,
|
elements: ElementSectionReader<'data>,
|
||||||
environ: &mut dyn ModuleEnvironment,
|
environ: &mut dyn ModuleEnvironment,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
environ.reserve_table_elements(elements.get_count());
|
environ.reserve_table_elements(elements.get_count())?;
|
||||||
|
|
||||||
for entry in elements {
|
for entry in elements {
|
||||||
let Element { kind, items } = entry?;
|
let Element { kind, items } = entry?;
|
||||||
@@ -268,7 +279,9 @@ pub fn parse_element_section<'data>(
|
|||||||
Operator::GetGlobal { global_index } => {
|
Operator::GetGlobal { global_index } => {
|
||||||
(Some(GlobalIndex::from_u32(global_index)), 0)
|
(Some(GlobalIndex::from_u32(global_index)), 0)
|
||||||
}
|
}
|
||||||
ref s => panic!("unsupported init expr in element section: {:?}", s),
|
ref s => {
|
||||||
|
wasm_unsupported!("unsupported init expr in element section: {:?}", s);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let items_reader = items.get_items_reader()?;
|
let items_reader = items.get_items_reader()?;
|
||||||
let mut elems = Vec::with_capacity(usize::try_from(items_reader.get_count()).unwrap());
|
let mut elems = Vec::with_capacity(usize::try_from(items_reader.get_count()).unwrap());
|
||||||
@@ -281,9 +294,9 @@ pub fn parse_element_section<'data>(
|
|||||||
base,
|
base,
|
||||||
offset,
|
offset,
|
||||||
elems.into_boxed_slice(),
|
elems.into_boxed_slice(),
|
||||||
)
|
)?
|
||||||
} else {
|
} else {
|
||||||
panic!("unsupported passive elements section");
|
wasm_unsupported!("unsupported passive elements section: {:?}", kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -308,7 +321,7 @@ pub fn parse_data_section<'data>(
|
|||||||
data: DataSectionReader<'data>,
|
data: DataSectionReader<'data>,
|
||||||
environ: &mut dyn ModuleEnvironment<'data>,
|
environ: &mut dyn ModuleEnvironment<'data>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
environ.reserve_data_initializers(data.get_count());
|
environ.reserve_data_initializers(data.get_count())?;
|
||||||
|
|
||||||
for entry in data {
|
for entry in data {
|
||||||
let Data { kind, data } = entry?;
|
let Data { kind, data } = entry?;
|
||||||
@@ -323,16 +336,16 @@ pub fn parse_data_section<'data>(
|
|||||||
Operator::GetGlobal { global_index } => {
|
Operator::GetGlobal { global_index } => {
|
||||||
(Some(GlobalIndex::from_u32(global_index)), 0)
|
(Some(GlobalIndex::from_u32(global_index)), 0)
|
||||||
}
|
}
|
||||||
ref s => panic!("unsupported init expr in data section: {:?}", s),
|
ref s => wasm_unsupported!("unsupported init expr in data section: {:?}", s),
|
||||||
};
|
};
|
||||||
environ.declare_data_initialization(
|
environ.declare_data_initialization(
|
||||||
MemoryIndex::from_u32(memory_index),
|
MemoryIndex::from_u32(memory_index),
|
||||||
base,
|
base,
|
||||||
offset,
|
offset,
|
||||||
data,
|
data,
|
||||||
);
|
)?;
|
||||||
} else {
|
} else {
|
||||||
panic!("unsupported passive data section");
|
wasm_unsupported!("unsupported passive data section: {:?}", kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
//! Helper functions and structures for the translation.
|
//! Helper functions and structures for the translation.
|
||||||
use crate::environ::{WasmError, WasmResult};
|
use crate::environ::WasmResult;
|
||||||
|
use crate::wasm_unsupported;
|
||||||
use core::u32;
|
use core::u32;
|
||||||
use cranelift_codegen::entity::entity_impl;
|
use cranelift_codegen::entity::entity_impl;
|
||||||
use cranelift_codegen::ir;
|
use cranelift_codegen::ir;
|
||||||
@@ -119,7 +120,7 @@ pub fn type_to_type(ty: wasmparser::Type) -> WasmResult<ir::Type> {
|
|||||||
wasmparser::Type::I64 => ir::types::I64,
|
wasmparser::Type::I64 => ir::types::I64,
|
||||||
wasmparser::Type::F32 => ir::types::F32,
|
wasmparser::Type::F32 => ir::types::F32,
|
||||||
wasmparser::Type::F64 => ir::types::F64,
|
wasmparser::Type::F64 => ir::types::F64,
|
||||||
_ => return Err(WasmError::Unsupported("unsupported wasm type")),
|
ty => wasm_unsupported!("unsupported wasm type {:?}", ty),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +133,7 @@ pub fn tabletype_to_type(ty: wasmparser::Type) -> WasmResult<Option<ir::Type>> {
|
|||||||
wasmparser::Type::F32 => Some(ir::types::F32),
|
wasmparser::Type::F32 => Some(ir::types::F32),
|
||||||
wasmparser::Type::F64 => Some(ir::types::F64),
|
wasmparser::Type::F64 => Some(ir::types::F64),
|
||||||
wasmparser::Type::AnyFunc => None,
|
wasmparser::Type::AnyFunc => None,
|
||||||
_ => return Err(WasmError::Unsupported("unsupported table wasm type")),
|
ty => wasm_unsupported!("unsupported table wasm type {:?}", ty),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +142,7 @@ pub fn blocktype_to_type(ty: wasmparser::TypeOrFuncType) -> WasmResult<ir::Type>
|
|||||||
match ty {
|
match ty {
|
||||||
wasmparser::TypeOrFuncType::Type(ty) => type_to_type(ty),
|
wasmparser::TypeOrFuncType::Type(ty) => type_to_type(ty),
|
||||||
wasmparser::TypeOrFuncType::FuncType(_) => {
|
wasmparser::TypeOrFuncType::FuncType(_) => {
|
||||||
Err(WasmError::Unsupported("multi-value block signatures"))
|
wasm_unsupported!("multi-value block signature {:?}", ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,10 +166,10 @@ pub fn num_return_values(ty: wasmparser::TypeOrFuncType) -> WasmResult<usize> {
|
|||||||
| wasmparser::Type::F32
|
| wasmparser::Type::F32
|
||||||
| wasmparser::Type::I64
|
| wasmparser::Type::I64
|
||||||
| wasmparser::Type::F64 => Ok(1),
|
| wasmparser::Type::F64 => Ok(1),
|
||||||
_ => Err(WasmError::Unsupported("unsupported return value type")),
|
ty => wasm_unsupported!("unsupported return value type {:?}", ty),
|
||||||
},
|
},
|
||||||
wasmparser::TypeOrFuncType::FuncType(_) => {
|
wasmparser::TypeOrFuncType::FuncType(_) => {
|
||||||
Err(WasmError::Unsupported("multi-value block signatures"))
|
wasm_unsupported!("multi-value block signature {:?}", ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user