[wasm] Don't panic when seeing unexpected types but properly fail instead;

This commit is contained in:
Benjamin Bouvier
2019-07-01 12:23:14 +02:00
parent 460fdaa34d
commit f6ac165ff6
3 changed files with 40 additions and 22 deletions

View File

@@ -135,7 +135,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
if let Ok(ty_cre) = blocktype_to_type(ty) { if let Ok(ty_cre) = blocktype_to_type(ty) {
builder.append_ebb_param(next, ty_cre); builder.append_ebb_param(next, ty_cre);
} }
state.push_block(next, num_return_values(ty)); state.push_block(next, num_return_values(ty)?);
} }
Operator::Loop { ty } => { Operator::Loop { ty } => {
let loop_body = builder.create_ebb(); let loop_body = builder.create_ebb();
@@ -144,7 +144,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
builder.append_ebb_param(next, ty_cre); builder.append_ebb_param(next, ty_cre);
} }
builder.ins().jump(loop_body, &[]); builder.ins().jump(loop_body, &[]);
state.push_loop(loop_body, next, num_return_values(ty)); state.push_loop(loop_body, next, num_return_values(ty)?);
builder.switch_to_block(loop_body); builder.switch_to_block(loop_body);
environ.translate_loop_header(builder.cursor())?; environ.translate_loop_header(builder.cursor())?;
} }
@@ -161,7 +161,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
if let Ok(ty_cre) = blocktype_to_type(ty) { if let Ok(ty_cre) = blocktype_to_type(ty) {
builder.append_ebb_param(if_not, ty_cre); builder.append_ebb_param(if_not, ty_cre);
} }
state.push_if(jump_inst, if_not, num_return_values(ty)); state.push_if(jump_inst, if_not, num_return_values(ty)?);
} }
Operator::Else => { Operator::Else => {
// We take the control frame pushed by the if, use its ebb as the else body // We take the control frame pushed by the if, use its ebb as the else body

View File

@@ -7,10 +7,10 @@
//! 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, WasmResult}; use crate::environ::{ModuleEnvironment, WasmError, WasmResult};
use crate::translation_utils::{ use crate::translation_utils::{
type_to_type, FuncIndex, Global, GlobalIndex, GlobalInit, Memory, MemoryIndex, SignatureIndex, tabletype_to_type, type_to_type, FuncIndex, Global, GlobalIndex, GlobalInit, Memory,
Table, TableElementType, TableIndex, MemoryIndex, SignatureIndex, Table, TableElementType, TableIndex,
}; };
use core::convert::TryFrom; use core::convert::TryFrom;
use cranelift_codegen::ir::{self, AbiParam, Signature}; use cranelift_codegen::ir::{self, AbiParam, Signature};
@@ -51,7 +51,7 @@ pub fn parse_type_section(
})); }));
environ.declare_signature(sig); environ.declare_signature(sig);
} }
ref s => panic!("unsupported type: {:?}", s), _ => return Err(WasmError::Unsupported("unsupported type in type section")),
} }
} }
Ok(()) Ok(())
@@ -101,9 +101,9 @@ pub fn parse_import_section<'data>(
ImportSectionEntryType::Table(ref tab) => { ImportSectionEntryType::Table(ref tab) => {
environ.declare_table_import( environ.declare_table_import(
Table { Table {
ty: match type_to_type(tab.element_type) { ty: match tabletype_to_type(tab.element_type)? {
Ok(t) => TableElementType::Val(t), Some(t) => TableElementType::Val(t),
Err(()) => TableElementType::Func, None => TableElementType::Func,
}, },
minimum: tab.limits.initial, minimum: tab.limits.initial,
maximum: tab.limits.maximum, maximum: tab.limits.maximum,
@@ -144,9 +144,9 @@ pub fn parse_table_section(
for entry in tables { for entry in tables {
let table = entry?; let table = entry?;
environ.declare_table(Table { environ.declare_table(Table {
ty: match type_to_type(table.element_type) { ty: match tabletype_to_type(table.element_type)? {
Ok(t) => TableElementType::Val(t), Some(t) => TableElementType::Val(t),
Err(()) => TableElementType::Func, None => TableElementType::Func,
}, },
minimum: table.limits.initial, minimum: table.limits.initial,
maximum: table.limits.maximum, maximum: table.limits.maximum,

View File

@@ -1,4 +1,5 @@
//! Helper functions and structures for the translation. //! Helper functions and structures for the translation.
use crate::environ::{WasmError, WasmResult};
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;
@@ -109,21 +110,36 @@ pub struct Memory {
} }
/// Helper function translating wasmparser types to Cranelift types when possible. /// Helper function translating wasmparser types to Cranelift types when possible.
pub fn type_to_type(ty: wasmparser::Type) -> Result<ir::Type, ()> { pub fn type_to_type(ty: wasmparser::Type) -> WasmResult<ir::Type> {
Ok(match ty { Ok(match ty {
wasmparser::Type::I32 => ir::types::I32, wasmparser::Type::I32 => ir::types::I32,
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(()), _ => return Err(WasmError::Unsupported("unsupported wasm type")),
})
}
/// Helper function translating wasmparser possible table types to Cranelift types when possible,
/// or None for Func tables.
pub fn tabletype_to_type(ty: wasmparser::Type) -> WasmResult<Option<ir::Type>> {
Ok(match ty {
wasmparser::Type::I32 => Some(ir::types::I32),
wasmparser::Type::I64 => Some(ir::types::I64),
wasmparser::Type::F32 => Some(ir::types::F32),
wasmparser::Type::F64 => Some(ir::types::F64),
wasmparser::Type::AnyFunc => None,
_ => return Err(WasmError::Unsupported("unsupported table wasm type")),
}) })
} }
/// Helper function translating wasmparser block signatures to Cranelift types when possible. /// Helper function translating wasmparser block signatures to Cranelift types when possible.
pub fn blocktype_to_type(ty: wasmparser::TypeOrFuncType) -> Result<ir::Type, ()> { 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(_) => unimplemented!("multi-value block signatures"), wasmparser::TypeOrFuncType::FuncType(_) => {
Err(WasmError::Unsupported("multi-value block signatures"))
}
} }
} }
@@ -138,17 +154,19 @@ pub fn f64_translation(x: wasmparser::Ieee64) -> ir::immediates::Ieee64 {
} }
/// Translate a `wasmparser` type into its `Cranelift` equivalent, when possible /// Translate a `wasmparser` type into its `Cranelift` equivalent, when possible
pub fn num_return_values(ty: wasmparser::TypeOrFuncType) -> usize { pub fn num_return_values(ty: wasmparser::TypeOrFuncType) -> WasmResult<usize> {
match ty { match ty {
wasmparser::TypeOrFuncType::Type(ty) => match ty { wasmparser::TypeOrFuncType::Type(ty) => match ty {
wasmparser::Type::EmptyBlockType => 0, wasmparser::Type::EmptyBlockType => Ok(0),
wasmparser::Type::I32 wasmparser::Type::I32
| wasmparser::Type::F32 | wasmparser::Type::F32
| wasmparser::Type::I64 | wasmparser::Type::I64
| wasmparser::Type::F64 => 1, | wasmparser::Type::F64 => Ok(1),
_ => panic!("unsupported return value type"), _ => Err(WasmError::Unsupported("unsupported return value type")),
}, },
wasmparser::TypeOrFuncType::FuncType(_) => unimplemented!("multi-value block signatures"), wasmparser::TypeOrFuncType::FuncType(_) => {
Err(WasmError::Unsupported("multi-value block signatures"))
}
} }
} }