Make wasmtime_environ::Module serializable (#2005)
* Define WasmType/WasmFuncType in the Cranelift * Make `Module` serializable
This commit is contained in:
@@ -30,6 +30,7 @@ use crate::translation_utils::{
|
||||
};
|
||||
use crate::translation_utils::{FuncIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex};
|
||||
use crate::wasm_unsupported;
|
||||
use core::convert::TryInto;
|
||||
use core::{i32, u32};
|
||||
use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
|
||||
use cranelift_codegen::ir::immediates::Offset32;
|
||||
@@ -1039,7 +1040,9 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
Operator::F32Le | Operator::F64Le => {
|
||||
translate_fcmp(FloatCC::LessThanOrEqual, builder, state)
|
||||
}
|
||||
Operator::RefNull { ty } => state.push1(environ.translate_ref_null(builder.cursor(), *ty)?),
|
||||
Operator::RefNull { ty } => {
|
||||
state.push1(environ.translate_ref_null(builder.cursor(), (*ty).try_into()?)?)
|
||||
}
|
||||
Operator::RefIsNull { ty: _ } => {
|
||||
let value = state.pop1();
|
||||
state.push1(environ.translate_ref_is_null(builder.cursor(), value)?);
|
||||
|
||||
@@ -547,7 +547,7 @@ impl TargetEnvironment for DummyEnvironment {
|
||||
}
|
||||
|
||||
impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
||||
fn declare_signature(&mut self, _wasm: &WasmFuncType, sig: ir::Signature) -> WasmResult<()> {
|
||||
fn declare_signature(&mut self, _wasm: WasmFuncType, sig: ir::Signature) -> WasmResult<()> {
|
||||
self.info.signatures.push(sig);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -12,22 +12,89 @@ use crate::translation_utils::{
|
||||
Table, TableIndex,
|
||||
};
|
||||
use core::convert::From;
|
||||
use core::convert::TryFrom;
|
||||
use cranelift_codegen::cursor::FuncCursor;
|
||||
use cranelift_codegen::ir::immediates::Offset32;
|
||||
use cranelift_codegen::ir::{self, InstBuilder};
|
||||
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||
use cranelift_frontend::FunctionBuilder;
|
||||
#[cfg(feature = "enable-serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::boxed::Box;
|
||||
use std::string::ToString;
|
||||
use thiserror::Error;
|
||||
use wasmparser::BinaryReaderError;
|
||||
use wasmparser::Operator;
|
||||
|
||||
// Re-export `wasmparser`'s function and value types so that consumers can
|
||||
// associate this the original Wasm signature with each compiled function. This
|
||||
// is often necessary because while each Wasm signature gets compiled down into
|
||||
// a single native signature, multiple Wasm signatures might compile down into
|
||||
// the same native signature.
|
||||
pub use wasmparser::{FuncType as WasmFuncType, Type as WasmType};
|
||||
/// WebAssembly value type -- equivalent of `wasmparser`'s Type.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub enum WasmType {
|
||||
/// I32 type
|
||||
I32,
|
||||
/// I64 type
|
||||
I64,
|
||||
/// F32 type
|
||||
F32,
|
||||
/// F64 type
|
||||
F64,
|
||||
/// V128 type
|
||||
V128,
|
||||
/// FuncRef type
|
||||
FuncRef,
|
||||
/// ExternRef type
|
||||
ExternRef,
|
||||
}
|
||||
|
||||
impl TryFrom<wasmparser::Type> for WasmType {
|
||||
type Error = WasmError;
|
||||
fn try_from(ty: wasmparser::Type) -> Result<Self, Self::Error> {
|
||||
use wasmparser::Type::*;
|
||||
match ty {
|
||||
I32 => Ok(WasmType::I32),
|
||||
I64 => Ok(WasmType::I64),
|
||||
F32 => Ok(WasmType::F32),
|
||||
F64 => Ok(WasmType::F64),
|
||||
V128 => Ok(WasmType::V128),
|
||||
FuncRef => Ok(WasmType::FuncRef),
|
||||
ExternRef => Ok(WasmType::ExternRef),
|
||||
EmptyBlockType | Func => Err(WasmError::InvalidWebAssembly {
|
||||
message: "unexpected value type".to_string(),
|
||||
offset: 0,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// WebAssembly function type -- equivalent of `wasmparser`'s FuncType.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct WasmFuncType {
|
||||
/// Function params types.
|
||||
pub params: Box<[WasmType]>,
|
||||
/// Returns params types.
|
||||
pub returns: Box<[WasmType]>,
|
||||
}
|
||||
|
||||
impl TryFrom<wasmparser::FuncType> for WasmFuncType {
|
||||
type Error = WasmError;
|
||||
fn try_from(ty: wasmparser::FuncType) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
params: ty
|
||||
.params
|
||||
.into_vec()
|
||||
.into_iter()
|
||||
.map(WasmType::try_from)
|
||||
.collect::<Result<_, Self::Error>>()?,
|
||||
returns: ty
|
||||
.returns
|
||||
.into_vec()
|
||||
.into_iter()
|
||||
.map(WasmType::try_from)
|
||||
.collect::<Result<_, Self::Error>>()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The value of a WebAssembly global variable.
|
||||
#[derive(Clone, Copy)]
|
||||
@@ -524,7 +591,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
||||
/// Declares a function signature to the environment.
|
||||
fn declare_signature(
|
||||
&mut self,
|
||||
wasm_func_type: &WasmFuncType,
|
||||
wasm_func_type: WasmFuncType,
|
||||
sig: ir::Signature,
|
||||
) -> WasmResult<()>;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::environ::{FuncEnvironment, ReturnMode, WasmResult};
|
||||
use crate::state::{FuncTranslationState, ModuleTranslationState};
|
||||
use crate::translation_utils::get_vmctx_value_label;
|
||||
use crate::wasm_unsupported;
|
||||
use core::convert::TryInto;
|
||||
use cranelift_codegen::entity::EntityRef;
|
||||
use cranelift_codegen::ir::{self, Block, InstBuilder, ValueLabel};
|
||||
use cranelift_codegen::timing;
|
||||
@@ -196,7 +197,9 @@ fn declare_locals<FE: FuncEnvironment + ?Sized>(
|
||||
let constant_handle = builder.func.dfg.constants.insert([0; 16].to_vec().into());
|
||||
builder.ins().vconst(ir::types::I8X16, constant_handle)
|
||||
}
|
||||
ExternRef | FuncRef => environ.translate_ref_null(builder.cursor(), wasm_type)?,
|
||||
ExternRef | FuncRef => {
|
||||
environ.translate_ref_null(builder.cursor(), wasm_type.try_into()?)?
|
||||
}
|
||||
ty => return Err(wasm_unsupported!("unsupported local type {:?}", ty)),
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ use crate::translation_utils::{
|
||||
};
|
||||
use crate::{wasm_unsupported, HashMap};
|
||||
use core::convert::TryFrom;
|
||||
use core::convert::TryInto;
|
||||
use cranelift_codegen::ir::immediates::V128Imm;
|
||||
use cranelift_codegen::ir::{self, AbiParam, Signature};
|
||||
use cranelift_entity::packed_option::ReservedValue;
|
||||
@@ -53,7 +54,7 @@ pub fn parse_type_section(
|
||||
.expect("only numeric types are supported in function signatures");
|
||||
AbiParam::new(cret_arg)
|
||||
}));
|
||||
environ.declare_signature(&wasm_func_ty, sig)?;
|
||||
environ.declare_signature(wasm_func_ty.clone().try_into()?, sig)?;
|
||||
module_translation_state
|
||||
.wasm_types
|
||||
.push((wasm_func_ty.params, wasm_func_ty.returns));
|
||||
@@ -104,7 +105,7 @@ pub fn parse_import_section<'data>(
|
||||
ImportSectionEntryType::Global(ref ty) => {
|
||||
environ.declare_global_import(
|
||||
Global {
|
||||
wasm_ty: ty.content_type,
|
||||
wasm_ty: ty.content_type.try_into()?,
|
||||
ty: type_to_type(ty.content_type, environ).unwrap(),
|
||||
mutability: ty.mutable,
|
||||
initializer: GlobalInit::Import,
|
||||
@@ -116,7 +117,7 @@ pub fn parse_import_section<'data>(
|
||||
ImportSectionEntryType::Table(ref tab) => {
|
||||
environ.declare_table_import(
|
||||
Table {
|
||||
wasm_ty: tab.element_type,
|
||||
wasm_ty: tab.element_type.try_into()?,
|
||||
ty: match tabletype_to_type(tab.element_type, environ)? {
|
||||
Some(t) => TableElementType::Val(t),
|
||||
None => TableElementType::Func,
|
||||
@@ -166,7 +167,7 @@ pub fn parse_table_section(
|
||||
for entry in tables {
|
||||
let table = entry?;
|
||||
environ.declare_table(Table {
|
||||
wasm_ty: table.element_type,
|
||||
wasm_ty: table.element_type.try_into()?,
|
||||
ty: match tabletype_to_type(table.element_type, environ)? {
|
||||
Some(t) => TableElementType::Val(t),
|
||||
None => TableElementType::Func,
|
||||
@@ -237,7 +238,7 @@ pub fn parse_global_section(
|
||||
}
|
||||
};
|
||||
let global = Global {
|
||||
wasm_ty: content_type,
|
||||
wasm_ty: content_type.try_into()?,
|
||||
ty: type_to_type(content_type, environ).unwrap(),
|
||||
mutability: mutable,
|
||||
initializer,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
use crate::environ::{TargetEnvironment, WasmResult, WasmType};
|
||||
use crate::state::ModuleTranslationState;
|
||||
use crate::wasm_unsupported;
|
||||
use core::convert::TryInto;
|
||||
use core::u32;
|
||||
use cranelift_codegen::entity::entity_impl;
|
||||
use cranelift_codegen::ir;
|
||||
@@ -39,31 +40,37 @@ entity_impl!(DefinedGlobalIndex);
|
||||
|
||||
/// Index type of a table (imported or defined) inside the WebAssembly module.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct TableIndex(u32);
|
||||
entity_impl!(TableIndex);
|
||||
|
||||
/// Index type of a global variable (imported or defined) inside the WebAssembly module.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct GlobalIndex(u32);
|
||||
entity_impl!(GlobalIndex);
|
||||
|
||||
/// Index type of a linear memory (imported or defined) inside the WebAssembly module.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct MemoryIndex(u32);
|
||||
entity_impl!(MemoryIndex);
|
||||
|
||||
/// Index type of a signature (imported or defined) inside the WebAssembly module.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct SignatureIndex(u32);
|
||||
entity_impl!(SignatureIndex);
|
||||
|
||||
/// Index type of a passive data segment inside the WebAssembly module.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct DataIndex(u32);
|
||||
entity_impl!(DataIndex);
|
||||
|
||||
/// Index type of a passive element segment inside the WebAssembly module.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct ElemIndex(u32);
|
||||
entity_impl!(ElemIndex);
|
||||
|
||||
@@ -75,6 +82,7 @@ entity_impl!(ElemIndex);
|
||||
/// Wasm `i64` and a `funcref` might be represented with a Cranelift `i64` on
|
||||
/// 64-bit architectures, and when GC is not required for func refs.
|
||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct Global {
|
||||
/// The Wasm type of the value stored in the global.
|
||||
pub wasm_ty: crate::WasmType,
|
||||
@@ -88,6 +96,7 @@ pub struct Global {
|
||||
|
||||
/// Globals are initialized via the `const` operators or by referring to another import.
|
||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub enum GlobalInit {
|
||||
/// An `i32.const`.
|
||||
I32Const(i32),
|
||||
@@ -111,6 +120,7 @@ pub enum GlobalInit {
|
||||
|
||||
/// WebAssembly table.
|
||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct Table {
|
||||
/// The table elements' Wasm type.
|
||||
pub wasm_ty: WasmType,
|
||||
@@ -124,6 +134,7 @@ pub struct Table {
|
||||
|
||||
/// WebAssembly table element. Can be a function or a scalar type.
|
||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub enum TableElementType {
|
||||
/// A scalar type.
|
||||
Val(ir::Type),
|
||||
@@ -133,6 +144,7 @@ pub enum TableElementType {
|
||||
|
||||
/// WebAssembly linear memory.
|
||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||
pub struct Memory {
|
||||
/// The minimum number of pages in the memory.
|
||||
pub minimum: u32,
|
||||
@@ -153,7 +165,9 @@ pub fn type_to_type<PE: TargetEnvironment + ?Sized>(
|
||||
wasmparser::Type::F32 => Ok(ir::types::F32),
|
||||
wasmparser::Type::F64 => Ok(ir::types::F64),
|
||||
wasmparser::Type::V128 => Ok(ir::types::I8X16),
|
||||
wasmparser::Type::ExternRef | wasmparser::Type::FuncRef => Ok(environ.reference_type(ty)),
|
||||
wasmparser::Type::ExternRef | wasmparser::Type::FuncRef => {
|
||||
Ok(environ.reference_type(ty.try_into()?))
|
||||
}
|
||||
ty => Err(wasm_unsupported!("type_to_type: wasm type {:?}", ty)),
|
||||
}
|
||||
}
|
||||
@@ -170,7 +184,7 @@ pub fn tabletype_to_type<PE: TargetEnvironment + ?Sized>(
|
||||
wasmparser::Type::F32 => Ok(Some(ir::types::F32)),
|
||||
wasmparser::Type::F64 => Ok(Some(ir::types::F64)),
|
||||
wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)),
|
||||
wasmparser::Type::ExternRef => Ok(Some(environ.reference_type(ty))),
|
||||
wasmparser::Type::ExternRef => Ok(Some(environ.reference_type(ty.try_into()?))),
|
||||
wasmparser::Type::FuncRef => Ok(None),
|
||||
ty => Err(wasm_unsupported!(
|
||||
"tabletype_to_type: table wasm type {:?}",
|
||||
@@ -226,7 +240,7 @@ pub fn block_with_params<PE: TargetEnvironment + ?Sized>(
|
||||
builder.append_block_param(block, ir::types::F64);
|
||||
}
|
||||
wasmparser::Type::ExternRef | wasmparser::Type::FuncRef => {
|
||||
builder.append_block_param(block, environ.reference_type(*ty));
|
||||
builder.append_block_param(block, environ.reference_type((*ty).try_into()?));
|
||||
}
|
||||
wasmparser::Type::V128 => {
|
||||
builder.append_block_param(block, ir::types::I8X16);
|
||||
|
||||
Reference in New Issue
Block a user