Skip to content

Commit

Permalink
Add extended-const Wasm proposal support (#707)
Browse files Browse the repository at this point in the history
* add extended-const Wasm proposal to config

* add Wasm spec tests for extended-const

* enable extended-const for tests

* apply rustfmt

* add ConstExpr to support extended const

* fix no_std build

* rename func_ref

* add module docs
  • Loading branch information
Robbepop committed Mar 17, 2023
1 parent 6dbbada commit eb8d73f
Show file tree
Hide file tree
Showing 13 changed files with 416 additions and 227 deletions.
1 change: 1 addition & 0 deletions crates/wasmi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ spin = { version = "0.9", default-features = false, features = [
"spin_mutex",
"rwlock",
] }
smallvec = { version = "1.10.0", features = ["union"] }

[dev-dependencies]
wat = "1"
Expand Down
17 changes: 16 additions & 1 deletion crates/wasmi/src/engine/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub struct Config {
reference_types: bool,
/// Is `true` if the [`tail-call`] Wasm proposal is enabled.
tail_call: bool,
/// Is `true` if the [`extended-const`] Wasm proposal is enabled.
extended_const: bool,
/// Is `true` if Wasm instructions on `f32` and `f64` types are allowed.
floats: bool,
/// Is `true` if `wasmi` executions shall consume fuel.
Expand Down Expand Up @@ -201,6 +203,7 @@ impl Default for Config {
bulk_memory: true,
reference_types: true,
tail_call: false,
extended_const: false,
floats: true,
consume_fuel: false,
fuel_costs: FuelCosts::default(),
Expand Down Expand Up @@ -321,6 +324,18 @@ impl Config {
self
}

/// Enable or disable the [`extended-const`] Wasm proposal for the [`Config`].
///
/// # Note
///
/// Disabled by default.
///
/// [`tail-call`]: https://github.com/WebAssembly/extended-const
pub fn wasm_extended_const(&mut self, enable: bool) -> &mut Self {
self.extended_const = enable;
self
}

/// Enable or disable Wasm floating point (`f32` and `f64`) instructions and types.
///
/// Enabled by default.
Expand Down Expand Up @@ -395,6 +410,7 @@ impl Config {
bulk_memory: self.bulk_memory,
reference_types: self.reference_types,
tail_call: self.tail_call,
extended_const: self.extended_const,
floats: self.floats,
component_model: false,
simd: false,
Expand All @@ -403,7 +419,6 @@ impl Config {
multi_memory: false,
exceptions: false,
memory64: false,
extended_const: false,
memory_control: false,
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/wasmi/src/engine/func_builder/translator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ use crate::{
},
module::{
BlockType,
ConstExpr,
FuncIdx,
FuncTypeIdx,
GlobalIdx,
InitExpr,
MemoryIdx,
ModuleResources,
DEFAULT_MEMORY_INDEX,
Expand Down Expand Up @@ -416,14 +416,14 @@ impl<'parser> FuncTranslator<'parser> {
/// have a chance to be optimized to more efficient instructions.
fn optimize_global_get(
global_type: &GlobalType,
init_value: Option<&InitExpr>,
init_value: Option<&ConstExpr>,
) -> Option<Instruction> {
if let (Mutability::Const, Some(init_expr)) = (global_type.mutability(), init_value) {
if let Some(value) = init_expr.to_const() {
if let Some(value) = init_expr.eval_const() {
// We can optimize `global.get` to the constant value.
return Some(Instruction::constant(value));
}
if let Some(func_index) = init_expr.func_ref() {
if let Some(func_index) = init_expr.funcref() {
// We can optimize `global.get` to the equivalent `ref.func x` instruction.
let func_index = bytecode::FuncIdx::from(func_index.into_u32());
return Some(Instruction::RefFunc { func_index });
Expand Down
6 changes: 3 additions & 3 deletions crates/wasmi/src/module/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::{
export::ExternIdx,
import::FuncTypeIdx,
ConstExpr,
DataSegment,
ElementSegment,
ExternTypeIdx,
Expand All @@ -9,7 +10,6 @@ use super::{
GlobalIdx,
Import,
ImportName,
InitExpr,
Module,
};
use crate::{
Expand All @@ -33,7 +33,7 @@ pub struct ModuleBuilder<'engine> {
pub tables: Vec<TableType>,
pub memories: Vec<MemoryType>,
pub globals: Vec<GlobalType>,
pub globals_init: Vec<InitExpr>,
pub globals_init: Vec<ConstExpr>,
pub exports: BTreeMap<Box<str>, ExternIdx>,
pub start: Option<FuncIdx>,
pub func_bodies: Vec<FuncBody>,
Expand Down Expand Up @@ -90,7 +90,7 @@ impl<'a> ModuleResources<'a> {
}

/// Returns the global variable type and optional initial value.
pub fn get_global(&self, global_idx: GlobalIdx) -> (GlobalType, Option<&InitExpr>) {
pub fn get_global(&self, global_idx: GlobalIdx) -> (GlobalType, Option<&ConstExpr>) {
let index = global_idx.into_u32() as usize;
let len_imports = self.res.imports.len_globals();
let global_type = self.get_type_of_global(global_idx);
Expand Down
8 changes: 4 additions & 4 deletions crates/wasmi/src/module/data.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{InitExpr, MemoryIdx};
use super::{ConstExpr, MemoryIdx};
use alloc::sync::Arc;

/// A Wasm [`Module`] data segment.
Expand Down Expand Up @@ -27,7 +27,7 @@ pub struct ActiveDataSegment {
/// The linear memory that is to be initialized with this active segment.
memory_index: MemoryIdx,
/// The offset at which the data segment is initialized.
offset: InitExpr,
offset: ConstExpr,
}

impl ActiveDataSegment {
Expand All @@ -37,7 +37,7 @@ impl ActiveDataSegment {
}

/// Returns the offset expression of the [`ActiveDataSegment`].
pub fn offset(&self) -> &InitExpr {
pub fn offset(&self) -> &ConstExpr {
&self.offset
}
}
Expand All @@ -50,7 +50,7 @@ impl From<wasmparser::DataKind<'_>> for DataSegmentKind {
offset_expr,
} => {
let memory_index = MemoryIdx::from(memory_index);
let offset = InitExpr::new(offset_expr);
let offset = ConstExpr::new(offset_expr);
Self::Active(ActiveDataSegment {
memory_index,
offset,
Expand Down
16 changes: 8 additions & 8 deletions crates/wasmi/src/module/element.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{InitExpr, TableIdx};
use super::{ConstExpr, TableIdx};
use crate::module::utils::WasmiValueType;
use alloc::sync::Arc;
use wasmi_core::ValueType;
Expand All @@ -19,7 +19,7 @@ pub struct ElementSegment {
/// The items of an [`ElementSegment`].
#[derive(Debug, Clone)]
pub struct ElementSegmentItems {
exprs: Arc<[InitExpr]>,
exprs: Arc<[ConstExpr]>,
}

impl ElementSegmentItems {
Expand All @@ -36,22 +36,22 @@ impl ElementSegmentItems {
.map(|item| {
item.unwrap_or_else(|error| panic!("failed to parse element item: {error}"))
})
.map(InitExpr::new_funcref)
.map(ConstExpr::new_funcref)
.collect::<Arc<[_]>>(),
wasmparser::ElementItems::Expressions(items) => items
.clone()
.into_iter()
.map(|item| {
item.unwrap_or_else(|error| panic!("failed to parse element item: {error}"))
})
.map(InitExpr::new)
.map(ConstExpr::new)
.collect::<Arc<[_]>>(),
};
Self { exprs }
}

/// Returns a shared reference to the items of the [`ElementSegmentItems`].
pub fn items(&self) -> &[InitExpr] {
pub fn items(&self) -> &[ConstExpr] {
&self.exprs
}
}
Expand All @@ -73,7 +73,7 @@ pub struct ActiveElementSegment {
/// The index of the Wasm table that is to be initialized.
table_index: TableIdx,
/// The offset where the Wasm table is to be initialized.
offset: InitExpr,
offset: ConstExpr,
}

impl ActiveElementSegment {
Expand All @@ -83,7 +83,7 @@ impl ActiveElementSegment {
}

/// Returns the offset expression of the [`ActiveElementSegment`].
pub fn offset(&self) -> &InitExpr {
pub fn offset(&self) -> &ConstExpr {
&self.offset
}
}
Expand All @@ -96,7 +96,7 @@ impl From<wasmparser::ElementKind<'_>> for ElementSegmentKind {
offset_expr,
} => {
let table_index = TableIdx::from(table_index);
let offset = InitExpr::new(offset_expr);
let offset = ConstExpr::new(offset_expr);
Self::Active(ActiveElementSegment {
table_index,
offset,
Expand Down
8 changes: 4 additions & 4 deletions crates/wasmi/src/module/global.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::InitExpr;
use super::ConstExpr;
use crate::GlobalType;

/// The index of a global variable within a [`Module`].
Expand Down Expand Up @@ -33,13 +33,13 @@ pub struct Global {
///
/// This is represented by a so called initializer expression
/// that is run at module instantiation time.
init_expr: InitExpr,
init_expr: ConstExpr,
}

impl From<wasmparser::Global<'_>> for Global {
fn from(global: wasmparser::Global<'_>) -> Self {
let global_type = GlobalType::from_wasmparser(global.ty);
let init_expr = InitExpr::new(global.init_expr);
let init_expr = ConstExpr::new(global.init_expr);
Self {
global_type,
init_expr,
Expand All @@ -49,7 +49,7 @@ impl From<wasmparser::Global<'_>> for Global {

impl Global {
/// Splits the [`Global`] into its global type and its global initializer.
pub fn into_type_and_init(self) -> (GlobalType, InitExpr) {
pub fn into_type_and_init(self) -> (GlobalType, ConstExpr) {
(self.global_type, self.init_expr)
}
}

0 comments on commit eb8d73f

Please sign in to comment.