Add wasm reference/pointers translation. (#1073)
This commit is contained in:
@@ -119,6 +119,12 @@ fn add_enable_multi_value<'a>() -> clap::Arg<'a, 'a> {
|
|||||||
.help("Enable WASM's multi-value support")
|
.help("Enable WASM's multi-value support")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_enable_reference_types_flag<'a>() -> clap::Arg<'a, 'a> {
|
||||||
|
Arg::with_name("enable-reference-types")
|
||||||
|
.long("enable-reference-types")
|
||||||
|
.help("Enable WASM's reference types operations")
|
||||||
|
}
|
||||||
|
|
||||||
fn add_just_decode_flag<'a>() -> clap::Arg<'a, 'a> {
|
fn add_just_decode_flag<'a>() -> clap::Arg<'a, 'a> {
|
||||||
Arg::with_name("just-decode")
|
Arg::with_name("just-decode")
|
||||||
.short("t")
|
.short("t")
|
||||||
@@ -163,6 +169,7 @@ fn add_wasm_or_compile<'a>(cmd: &str) -> clap::App<'a, 'a> {
|
|||||||
.arg(add_debug_flag())
|
.arg(add_debug_flag())
|
||||||
.arg(add_enable_simd_flag())
|
.arg(add_enable_simd_flag())
|
||||||
.arg(add_enable_multi_value())
|
.arg(add_enable_multi_value())
|
||||||
|
.arg(add_enable_reference_types_flag())
|
||||||
.arg(add_just_decode_flag())
|
.arg(add_just_decode_flag())
|
||||||
.arg(add_check_translation_flag())
|
.arg(add_check_translation_flag())
|
||||||
}
|
}
|
||||||
@@ -316,6 +323,7 @@ fn main() {
|
|||||||
rest_cmd.is_present("value-ranges"),
|
rest_cmd.is_present("value-ranges"),
|
||||||
rest_cmd.is_present("enable-simd"),
|
rest_cmd.is_present("enable-simd"),
|
||||||
rest_cmd.is_present("enable-multi-value"),
|
rest_cmd.is_present("enable-multi-value"),
|
||||||
|
rest_cmd.is_present("enable-reference-types"),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ pub fn run(
|
|||||||
flag_calc_value_ranges: bool,
|
flag_calc_value_ranges: bool,
|
||||||
flag_enable_simd: bool,
|
flag_enable_simd: bool,
|
||||||
flag_enable_multi_value: bool,
|
flag_enable_multi_value: bool,
|
||||||
|
flag_enable_reference_types: bool,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let parsed = parse_sets_and_triple(flag_set, flag_triple)?;
|
let parsed = parse_sets_and_triple(flag_set, flag_triple)?;
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ pub fn run(
|
|||||||
flag_calc_value_ranges,
|
flag_calc_value_ranges,
|
||||||
flag_enable_simd,
|
flag_enable_simd,
|
||||||
flag_enable_multi_value,
|
flag_enable_multi_value,
|
||||||
|
flag_enable_reference_types,
|
||||||
&path.to_path_buf(),
|
&path.to_path_buf(),
|
||||||
&name,
|
&name,
|
||||||
parsed.as_fisa(),
|
parsed.as_fisa(),
|
||||||
@@ -87,6 +89,7 @@ fn handle_module(
|
|||||||
flag_calc_value_ranges: bool,
|
flag_calc_value_ranges: bool,
|
||||||
flag_enable_simd: bool,
|
flag_enable_simd: bool,
|
||||||
flag_enable_multi_value: bool,
|
flag_enable_multi_value: bool,
|
||||||
|
flag_enable_reference_types: bool,
|
||||||
path: &PathBuf,
|
path: &PathBuf,
|
||||||
name: &str,
|
name: &str,
|
||||||
fisa: FlagsOrIsa,
|
fisa: FlagsOrIsa,
|
||||||
@@ -110,6 +113,9 @@ fn handle_module(
|
|||||||
if flag_enable_multi_value {
|
if flag_enable_multi_value {
|
||||||
features.enable_multi_value();
|
features.enable_multi_value();
|
||||||
}
|
}
|
||||||
|
if flag_enable_reference_types {
|
||||||
|
features.enable_reference_types();
|
||||||
|
}
|
||||||
|
|
||||||
module_binary = match wat2wasm_with_features(&module_binary, features) {
|
module_binary = match wat2wasm_with_features(&module_binary, features) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
environ: &mut FE,
|
environ: &mut FE,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
if !state.reachable {
|
if !state.reachable {
|
||||||
translate_unreachable_operator(module_translation_state, &op, builder, state)?;
|
translate_unreachable_operator(module_translation_state, &op, builder, state, environ)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,13 +139,13 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
***********************************************************************************/
|
***********************************************************************************/
|
||||||
Operator::Block { ty } => {
|
Operator::Block { ty } => {
|
||||||
let (params, results) = blocktype_params_results(module_translation_state, *ty)?;
|
let (params, results) = blocktype_params_results(module_translation_state, *ty)?;
|
||||||
let next = ebb_with_params(builder, results)?;
|
let next = ebb_with_params(builder, results, environ)?;
|
||||||
state.push_block(next, params.len(), results.len());
|
state.push_block(next, params.len(), results.len());
|
||||||
}
|
}
|
||||||
Operator::Loop { ty } => {
|
Operator::Loop { ty } => {
|
||||||
let (params, results) = blocktype_params_results(module_translation_state, *ty)?;
|
let (params, results) = blocktype_params_results(module_translation_state, *ty)?;
|
||||||
let loop_body = ebb_with_params(builder, params)?;
|
let loop_body = ebb_with_params(builder, params, environ)?;
|
||||||
let next = ebb_with_params(builder, results)?;
|
let next = ebb_with_params(builder, results, environ)?;
|
||||||
builder.ins().jump(loop_body, state.peekn(params.len()));
|
builder.ins().jump(loop_body, state.peekn(params.len()));
|
||||||
state.push_loop(loop_body, next, params.len(), results.len());
|
state.push_loop(loop_body, next, params.len(), results.len());
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
// destination ebb following the whole `if...end`. If we do end
|
// destination ebb following the whole `if...end`. If we do end
|
||||||
// up discovering an `else`, then we will allocate an ebb for it
|
// up discovering an `else`, then we will allocate an ebb for it
|
||||||
// and go back and patch the jump.
|
// and go back and patch the jump.
|
||||||
let destination = ebb_with_params(builder, results)?;
|
let destination = ebb_with_params(builder, results, environ)?;
|
||||||
let branch_inst = builder
|
let branch_inst = builder
|
||||||
.ins()
|
.ins()
|
||||||
.brz(val, destination, state.peekn(params.len()));
|
.brz(val, destination, state.peekn(params.len()));
|
||||||
@@ -176,8 +176,8 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
} else {
|
} else {
|
||||||
// The `if` type signature is not valid without an `else` block,
|
// The `if` type signature is not valid without an `else` block,
|
||||||
// so we eagerly allocate the `else` block here.
|
// so we eagerly allocate the `else` block here.
|
||||||
let destination = ebb_with_params(builder, results)?;
|
let destination = ebb_with_params(builder, results, environ)?;
|
||||||
let else_block = ebb_with_params(builder, params)?;
|
let else_block = ebb_with_params(builder, params, environ)?;
|
||||||
builder
|
builder
|
||||||
.ins()
|
.ins()
|
||||||
.brz(val, else_block, state.peekn(params.len()));
|
.brz(val, else_block, state.peekn(params.len()));
|
||||||
@@ -229,7 +229,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
let (params, _results) =
|
let (params, _results) =
|
||||||
blocktype_params_results(module_translation_state, blocktype)?;
|
blocktype_params_results(module_translation_state, blocktype)?;
|
||||||
debug_assert_eq!(params.len(), num_return_values);
|
debug_assert_eq!(params.len(), num_return_values);
|
||||||
let else_ebb = ebb_with_params(builder, params)?;
|
let else_ebb = ebb_with_params(builder, params, environ)?;
|
||||||
builder.ins().jump(destination, state.peekn(params.len()));
|
builder.ins().jump(destination, state.peekn(params.len()));
|
||||||
state.popn(params.len());
|
state.popn(params.len());
|
||||||
|
|
||||||
@@ -1352,11 +1352,12 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
/// Deals with a Wasm instruction located in an unreachable portion of the code. Most of them
|
/// Deals with a Wasm instruction located in an unreachable portion of the code. Most of them
|
||||||
/// are dropped but special ones like `End` or `Else` signal the potential end of the unreachable
|
/// are dropped but special ones like `End` or `Else` signal the potential end of the unreachable
|
||||||
/// portion so the translation state must be updated accordingly.
|
/// portion so the translation state must be updated accordingly.
|
||||||
fn translate_unreachable_operator(
|
fn translate_unreachable_operator<FE: FuncEnvironment + ?Sized>(
|
||||||
module_translation_state: &ModuleTranslationState,
|
module_translation_state: &ModuleTranslationState,
|
||||||
op: &Operator,
|
op: &Operator,
|
||||||
builder: &mut FunctionBuilder,
|
builder: &mut FunctionBuilder,
|
||||||
state: &mut FuncTranslationState,
|
state: &mut FuncTranslationState,
|
||||||
|
environ: &mut FE,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
debug_assert!(!state.reachable);
|
debug_assert!(!state.reachable);
|
||||||
match *op {
|
match *op {
|
||||||
@@ -1397,7 +1398,7 @@ fn translate_unreachable_operator(
|
|||||||
ElseData::NoElse { branch_inst } => {
|
ElseData::NoElse { branch_inst } => {
|
||||||
let (params, _results) =
|
let (params, _results) =
|
||||||
blocktype_params_results(module_translation_state, blocktype)?;
|
blocktype_params_results(module_translation_state, blocktype)?;
|
||||||
let else_ebb = ebb_with_params(builder, params)?;
|
let else_ebb = ebb_with_params(builder, params, environ)?;
|
||||||
|
|
||||||
// We change the target of the branch instruction.
|
// We change the target of the branch instruction.
|
||||||
builder.change_jump_destination(branch_inst, else_ebb);
|
builder.change_jump_destination(branch_inst, else_ebb);
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
//! [wasmtime-environ]: https://crates.io/crates/wasmtime-environ
|
//! [wasmtime-environ]: https://crates.io/crates/wasmtime-environ
|
||||||
//! [Wasmtime]: https://github.com/bytecodealliance/wasmtime
|
//! [Wasmtime]: https://github.com/bytecodealliance/wasmtime
|
||||||
|
|
||||||
use crate::environ::{FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, WasmResult};
|
use crate::environ::{
|
||||||
|
FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment, WasmResult,
|
||||||
|
};
|
||||||
use crate::func_translator::FuncTranslator;
|
use crate::func_translator::FuncTranslator;
|
||||||
use crate::state::ModuleTranslationState;
|
use crate::state::ModuleTranslationState;
|
||||||
use crate::translation_utils::{
|
use crate::translation_utils::{
|
||||||
@@ -192,11 +194,13 @@ impl<'dummy_environment> DummyFuncEnvironment<'dummy_environment> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environment> {
|
impl<'dummy_environment> TargetEnvironment for DummyFuncEnvironment<'dummy_environment> {
|
||||||
fn target_config(&self) -> TargetFrontendConfig {
|
fn target_config(&self) -> TargetFrontendConfig {
|
||||||
self.mod_info.config
|
self.mod_info.config
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environment> {
|
||||||
fn return_mode(&self) -> ReturnMode {
|
fn return_mode(&self) -> ReturnMode {
|
||||||
self.return_mode
|
self.return_mode
|
||||||
}
|
}
|
||||||
@@ -454,11 +458,13 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
impl TargetEnvironment for DummyEnvironment {
|
||||||
fn target_config(&self) -> TargetFrontendConfig {
|
fn target_config(&self) -> TargetFrontendConfig {
|
||||||
self.info.config
|
self.info.config
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
||||||
fn declare_signature(&mut self, sig: ir::Signature) -> WasmResult<()> {
|
fn declare_signature(&mut self, sig: ir::Signature) -> WasmResult<()> {
|
||||||
self.info.signatures.push(sig);
|
self.info.signatures.push(sig);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -6,5 +6,6 @@ mod spec;
|
|||||||
|
|
||||||
pub use crate::environ::dummy::DummyEnvironment;
|
pub use crate::environ::dummy::DummyEnvironment;
|
||||||
pub use crate::environ::spec::{
|
pub use crate::environ::spec::{
|
||||||
FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, WasmError, WasmResult,
|
FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment, WasmError,
|
||||||
|
WasmResult,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -103,12 +103,8 @@ pub enum ReturnMode {
|
|||||||
FallthroughReturn,
|
FallthroughReturn,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Environment affecting the translation of a single WebAssembly function.
|
/// Environment affecting the translation of a WebAssembly.
|
||||||
///
|
pub trait TargetEnvironment {
|
||||||
/// A `FuncEnvironment` trait object is required to translate a WebAssembly function to Cranelift
|
|
||||||
/// IR. The function environment provides information about the WebAssembly module as well as the
|
|
||||||
/// runtime environment.
|
|
||||||
pub trait FuncEnvironment {
|
|
||||||
/// Get the information needed to produce Cranelift IR for the given target.
|
/// Get the information needed to produce Cranelift IR for the given target.
|
||||||
fn target_config(&self) -> TargetFrontendConfig;
|
fn target_config(&self) -> TargetFrontendConfig;
|
||||||
|
|
||||||
@@ -124,13 +120,6 @@ pub trait FuncEnvironment {
|
|||||||
self.target_config().pointer_bytes()
|
self.target_config().pointer_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Should the code be structured to use a single `fallthrough_return` instruction at the end
|
|
||||||
/// of the function body, rather than `return` instructions as needed? This is used by VMs
|
|
||||||
/// to append custom epilogues.
|
|
||||||
fn return_mode(&self) -> ReturnMode {
|
|
||||||
ReturnMode::NormalReturns
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the Cranelift reference type to use for native references.
|
/// Get the Cranelift reference type to use for native references.
|
||||||
///
|
///
|
||||||
/// This returns `R64` for 64-bit architectures and `R32` for 32-bit architectures.
|
/// This returns `R64` for 64-bit architectures and `R32` for 32-bit architectures.
|
||||||
@@ -141,6 +130,20 @@ pub trait FuncEnvironment {
|
|||||||
_ => panic!("unsupported pointer type"),
|
_ => panic!("unsupported pointer type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Environment affecting the translation of a single WebAssembly function.
|
||||||
|
///
|
||||||
|
/// A `FuncEnvironment` trait object is required to translate a WebAssembly function to Cranelift
|
||||||
|
/// IR. The function environment provides information about the WebAssembly module as well as the
|
||||||
|
/// runtime environment.
|
||||||
|
pub trait FuncEnvironment: TargetEnvironment {
|
||||||
|
/// Should the code be structured to use a single `fallthrough_return` instruction at the end
|
||||||
|
/// of the function body, rather than `return` instructions as needed? This is used by VMs
|
||||||
|
/// to append custom epilogues.
|
||||||
|
fn return_mode(&self) -> ReturnMode {
|
||||||
|
ReturnMode::NormalReturns
|
||||||
|
}
|
||||||
|
|
||||||
/// Set up the necessary preamble definitions in `func` to access the global variable
|
/// Set up the necessary preamble definitions in `func` to access the global variable
|
||||||
/// identified by `index`.
|
/// identified by `index`.
|
||||||
@@ -384,10 +387,7 @@ pub trait FuncEnvironment {
|
|||||||
/// An object satisfying the `ModuleEnvironment` trait can be passed as argument to the
|
/// An object satisfying the `ModuleEnvironment` trait can be passed as argument to the
|
||||||
/// [`translate_module`](fn.translate_module.html) function. These methods should not be called
|
/// [`translate_module`](fn.translate_module.html) function. These methods should not be called
|
||||||
/// by the user, they are only for `cranelift-wasm` internal use.
|
/// by the user, they are only for `cranelift-wasm` internal use.
|
||||||
pub trait ModuleEnvironment<'data> {
|
pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
||||||
/// Get the information needed to produce Cranelift IR for the current target.
|
|
||||||
fn target_config(&self) -> TargetFrontendConfig;
|
|
||||||
|
|
||||||
/// 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) -> WasmResult<()> {
|
fn reserve_signatures(&mut self, _num: u32) -> WasmResult<()> {
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ fn declare_locals<FE: FuncEnvironment + ?Sized>(
|
|||||||
builder.ins().vconst(ir::types::I8X16, constant_handle)
|
builder.ins().vconst(ir::types::I8X16, constant_handle)
|
||||||
}
|
}
|
||||||
AnyRef => builder.ins().null(environ.reference_type()),
|
AnyRef => builder.ins().null(environ.reference_type()),
|
||||||
|
AnyFunc => builder.ins().null(environ.reference_type()),
|
||||||
ty => return Err(wasm_unsupported!("unsupported local type {:?}", ty)),
|
ty => return Err(wasm_unsupported!("unsupported local type {:?}", ty)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ mod state;
|
|||||||
mod translation_utils;
|
mod translation_utils;
|
||||||
|
|
||||||
pub use crate::environ::{
|
pub use crate::environ::{
|
||||||
DummyEnvironment, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, WasmError,
|
DummyEnvironment, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode,
|
||||||
WasmResult,
|
TargetEnvironment, WasmError, WasmResult,
|
||||||
};
|
};
|
||||||
pub use crate::func_translator::FuncTranslator;
|
pub use crate::func_translator::FuncTranslator;
|
||||||
pub use crate::module_translator::translate_module;
|
pub use crate::module_translator::translate_module;
|
||||||
|
|||||||
@@ -44,14 +44,15 @@ pub fn parse_type_section(
|
|||||||
params,
|
params,
|
||||||
returns,
|
returns,
|
||||||
} => {
|
} => {
|
||||||
let mut sig = Signature::new(environ.target_config().default_call_conv);
|
let mut sig =
|
||||||
|
Signature::new(ModuleEnvironment::target_config(environ).default_call_conv);
|
||||||
sig.params.extend(params.iter().map(|ty| {
|
sig.params.extend(params.iter().map(|ty| {
|
||||||
let cret_arg: ir::Type = type_to_type(*ty)
|
let cret_arg: ir::Type = type_to_type(*ty, environ)
|
||||||
.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)
|
||||||
}));
|
}));
|
||||||
sig.returns.extend(returns.iter().map(|ty| {
|
sig.returns.extend(returns.iter().map(|ty| {
|
||||||
let cret_arg: ir::Type = type_to_type(*ty)
|
let cret_arg: ir::Type = type_to_type(*ty, environ)
|
||||||
.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)
|
||||||
}));
|
}));
|
||||||
@@ -106,7 +107,7 @@ pub fn parse_import_section<'data>(
|
|||||||
ImportSectionEntryType::Global(ref ty) => {
|
ImportSectionEntryType::Global(ref ty) => {
|
||||||
environ.declare_global_import(
|
environ.declare_global_import(
|
||||||
Global {
|
Global {
|
||||||
ty: type_to_type(ty.content_type).unwrap(),
|
ty: type_to_type(ty.content_type, environ).unwrap(),
|
||||||
mutability: ty.mutable,
|
mutability: ty.mutable,
|
||||||
initializer: GlobalInit::Import,
|
initializer: GlobalInit::Import,
|
||||||
},
|
},
|
||||||
@@ -117,7 +118,7 @@ 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 tabletype_to_type(tab.element_type)? {
|
ty: match tabletype_to_type(tab.element_type, environ)? {
|
||||||
Some(t) => TableElementType::Val(t),
|
Some(t) => TableElementType::Val(t),
|
||||||
None => TableElementType::Func,
|
None => TableElementType::Func,
|
||||||
},
|
},
|
||||||
@@ -160,7 +161,7 @@ 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 tabletype_to_type(table.element_type)? {
|
ty: match tabletype_to_type(table.element_type, environ)? {
|
||||||
Some(t) => TableElementType::Val(t),
|
Some(t) => TableElementType::Val(t),
|
||||||
None => TableElementType::Func,
|
None => TableElementType::Func,
|
||||||
},
|
},
|
||||||
@@ -215,6 +216,7 @@ pub fn parse_global_section(
|
|||||||
Operator::V128Const { value } => {
|
Operator::V128Const { value } => {
|
||||||
GlobalInit::V128Const(V128Imm::from(value.bytes().to_vec().as_slice()))
|
GlobalInit::V128Const(V128Imm::from(value.bytes().to_vec().as_slice()))
|
||||||
}
|
}
|
||||||
|
Operator::RefNull => GlobalInit::RefNullConst,
|
||||||
Operator::GetGlobal { global_index } => {
|
Operator::GetGlobal { global_index } => {
|
||||||
GlobalInit::GetGlobal(GlobalIndex::from_u32(global_index))
|
GlobalInit::GetGlobal(GlobalIndex::from_u32(global_index))
|
||||||
}
|
}
|
||||||
@@ -226,7 +228,7 @@ pub fn parse_global_section(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let global = Global {
|
let global = Global {
|
||||||
ty: type_to_type(content_type).unwrap(),
|
ty: type_to_type(content_type, environ).unwrap(),
|
||||||
mutability: mutable,
|
mutability: mutable,
|
||||||
initializer,
|
initializer,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! Helper functions and structures for the translation.
|
//! Helper functions and structures for the translation.
|
||||||
use crate::environ::WasmResult;
|
use crate::environ::{TargetEnvironment, WasmResult};
|
||||||
use crate::state::ModuleTranslationState;
|
use crate::state::ModuleTranslationState;
|
||||||
use crate::wasm_unsupported;
|
use crate::wasm_unsupported;
|
||||||
use core::u32;
|
use core::u32;
|
||||||
@@ -83,6 +83,8 @@ pub enum GlobalInit {
|
|||||||
V128Const(V128Imm),
|
V128Const(V128Imm),
|
||||||
/// A `get_global` of another global.
|
/// A `get_global` of another global.
|
||||||
GetGlobal(GlobalIndex),
|
GetGlobal(GlobalIndex),
|
||||||
|
/// A `ref.null`.
|
||||||
|
RefNullConst,
|
||||||
///< The global is imported from, and thus initialized by, a different module.
|
///< The global is imported from, and thus initialized by, a different module.
|
||||||
Import,
|
Import,
|
||||||
}
|
}
|
||||||
@@ -119,26 +121,34 @@ 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) -> WasmResult<ir::Type> {
|
pub fn type_to_type<PE: TargetEnvironment + ?Sized>(
|
||||||
|
ty: wasmparser::Type,
|
||||||
|
environ: &PE,
|
||||||
|
) -> WasmResult<ir::Type> {
|
||||||
match ty {
|
match ty {
|
||||||
wasmparser::Type::I32 => Ok(ir::types::I32),
|
wasmparser::Type::I32 => Ok(ir::types::I32),
|
||||||
wasmparser::Type::I64 => Ok(ir::types::I64),
|
wasmparser::Type::I64 => Ok(ir::types::I64),
|
||||||
wasmparser::Type::F32 => Ok(ir::types::F32),
|
wasmparser::Type::F32 => Ok(ir::types::F32),
|
||||||
wasmparser::Type::F64 => Ok(ir::types::F64),
|
wasmparser::Type::F64 => Ok(ir::types::F64),
|
||||||
wasmparser::Type::V128 => Ok(ir::types::I8X16),
|
wasmparser::Type::V128 => Ok(ir::types::I8X16),
|
||||||
|
wasmparser::Type::AnyRef | wasmparser::Type::AnyFunc => Ok(environ.reference_type()),
|
||||||
ty => Err(wasm_unsupported!("type_to_type: wasm type {:?}", ty)),
|
ty => Err(wasm_unsupported!("type_to_type: wasm type {:?}", ty)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function translating wasmparser possible table types to Cranelift types when possible,
|
/// Helper function translating wasmparser possible table types to Cranelift types when possible,
|
||||||
/// or None for Func tables.
|
/// or None for Func tables.
|
||||||
pub fn tabletype_to_type(ty: wasmparser::Type) -> WasmResult<Option<ir::Type>> {
|
pub fn tabletype_to_type<PE: TargetEnvironment + ?Sized>(
|
||||||
|
ty: wasmparser::Type,
|
||||||
|
environ: &PE,
|
||||||
|
) -> WasmResult<Option<ir::Type>> {
|
||||||
match ty {
|
match ty {
|
||||||
wasmparser::Type::I32 => Ok(Some(ir::types::I32)),
|
wasmparser::Type::I32 => Ok(Some(ir::types::I32)),
|
||||||
wasmparser::Type::I64 => Ok(Some(ir::types::I64)),
|
wasmparser::Type::I64 => Ok(Some(ir::types::I64)),
|
||||||
wasmparser::Type::F32 => Ok(Some(ir::types::F32)),
|
wasmparser::Type::F32 => Ok(Some(ir::types::F32)),
|
||||||
wasmparser::Type::F64 => Ok(Some(ir::types::F64)),
|
wasmparser::Type::F64 => Ok(Some(ir::types::F64)),
|
||||||
wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)),
|
wasmparser::Type::V128 => Ok(Some(ir::types::I8X16)),
|
||||||
|
wasmparser::Type::AnyRef => Ok(Some(environ.reference_type())),
|
||||||
wasmparser::Type::AnyFunc => Ok(None),
|
wasmparser::Type::AnyFunc => Ok(None),
|
||||||
ty => Err(wasm_unsupported!(
|
ty => Err(wasm_unsupported!(
|
||||||
"tabletype_to_type: table wasm type {:?}",
|
"tabletype_to_type: table wasm type {:?}",
|
||||||
@@ -159,6 +169,8 @@ pub fn blocktype_params_results(
|
|||||||
wasmparser::Type::F32 => (&[], &[wasmparser::Type::F32]),
|
wasmparser::Type::F32 => (&[], &[wasmparser::Type::F32]),
|
||||||
wasmparser::Type::F64 => (&[], &[wasmparser::Type::F64]),
|
wasmparser::Type::F64 => (&[], &[wasmparser::Type::F64]),
|
||||||
wasmparser::Type::V128 => (&[], &[wasmparser::Type::V128]),
|
wasmparser::Type::V128 => (&[], &[wasmparser::Type::V128]),
|
||||||
|
wasmparser::Type::AnyRef => (&[], &[wasmparser::Type::AnyRef]),
|
||||||
|
wasmparser::Type::AnyFunc => (&[], &[wasmparser::Type::AnyFunc]),
|
||||||
wasmparser::Type::EmptyBlockType => (&[], &[]),
|
wasmparser::Type::EmptyBlockType => (&[], &[]),
|
||||||
ty => return Err(wasm_unsupported!("blocktype_params_results: type {:?}", ty)),
|
ty => return Err(wasm_unsupported!("blocktype_params_results: type {:?}", ty)),
|
||||||
},
|
},
|
||||||
@@ -171,9 +183,10 @@ pub fn blocktype_params_results(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create an `Ebb` with the given Wasm parameters.
|
/// Create an `Ebb` with the given Wasm parameters.
|
||||||
pub fn ebb_with_params(
|
pub fn ebb_with_params<PE: TargetEnvironment + ?Sized>(
|
||||||
builder: &mut FunctionBuilder,
|
builder: &mut FunctionBuilder,
|
||||||
params: &[wasmparser::Type],
|
params: &[wasmparser::Type],
|
||||||
|
environ: &PE,
|
||||||
) -> WasmResult<ir::Ebb> {
|
) -> WasmResult<ir::Ebb> {
|
||||||
let ebb = builder.create_ebb();
|
let ebb = builder.create_ebb();
|
||||||
for ty in params.iter() {
|
for ty in params.iter() {
|
||||||
@@ -190,6 +203,9 @@ pub fn ebb_with_params(
|
|||||||
wasmparser::Type::F64 => {
|
wasmparser::Type::F64 => {
|
||||||
builder.append_ebb_param(ebb, ir::types::F64);
|
builder.append_ebb_param(ebb, ir::types::F64);
|
||||||
}
|
}
|
||||||
|
wasmparser::Type::AnyRef | wasmparser::Type::AnyFunc => {
|
||||||
|
builder.append_ebb_param(ebb, environ.reference_type());
|
||||||
|
}
|
||||||
wasmparser::Type::V128 => {
|
wasmparser::Type::V128 => {
|
||||||
builder.append_ebb_param(ebb, ir::types::I8X16);
|
builder.append_ebb_param(ebb, ir::types::I8X16);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user