Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various WASM tweaks and cleanups #2059

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions radix-engine/src/vm/scrypto_vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ use radix_engine_profiling_derive::trace_resources;

pub struct ScryptoVm<W: WasmEngine> {
pub wasm_engine: W,
pub wasm_validator_config: WasmValidatorConfigV1,
}

impl<W: WasmEngine + Default> Default for ScryptoVm<W> {
fn default() -> Self {
Self {
wasm_engine: W::default(),
wasm_validator_config: WasmValidatorConfigV1::new(),
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions radix-engine/src/vm/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod constants;
mod errors;
mod prepare;
mod traits;
mod wasm_features_config;
mod wasm_validator;
mod wasm_validator_config;
mod wasmi;
Expand All @@ -12,6 +13,7 @@ pub use constants::*;
pub use errors::*;
pub use prepare::*;
pub use traits::*;
pub use wasm_features_config::*;
pub use wasm_validator::*;
pub use wasm_validator_config::*;
pub use weights::*;
Expand Down
36 changes: 12 additions & 24 deletions radix-engine/src/vm/wasm/prepare.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate radix_wasm_instrument as wasm_instrument;

use crate::internal_prelude::*;
use crate::vm::wasm::{constants::*, errors::*, PrepareError};
use crate::vm::wasm::{constants::*, errors::*, PrepareError, WasmFeaturesConfig};
use num_traits::CheckedAdd;
use radix_engine_interface::blueprints::package::BlueprintDefinitionInit;
use syn::Ident;
Expand All @@ -10,7 +10,7 @@ use wasm_instrument::{
inject_stack_limiter,
utils::module_info::ModuleInfo,
};
use wasmparser::{ExternalKind, FuncType, Operator, Type, TypeRef, ValType, WasmFeatures};
use wasmparser::{ExternalKind, FuncType, Operator, Type, TypeRef, ValType};

use super::WasmiModule;
use crate::vm::ScryptoVmVersion;
Expand All @@ -25,28 +25,7 @@ impl WasmModule {
// deserialize
let module = ModuleInfo::new(code).map_err(|_| PrepareError::DeserializationError)?;

// Radix Engine supports MVP + proposals: mutable globals and sign-extension-ops
let features = WasmFeatures {
mutable_global: true,
saturating_float_to_int: false,
sign_extension: true,
reference_types: false,
multi_value: false,
bulk_memory: false,
simd: false,
relaxed_simd: false,
threads: false,
tail_call: false,
floats: false,
multi_memory: false,
exceptions: false,
memory64: false,
extended_const: false,
component_model: false,
function_references: false,
memory_control: false,
gc: false,
};
let features = WasmFeaturesConfig::default().features;

module
.validate(features)
Expand Down Expand Up @@ -1082,6 +1061,15 @@ impl WasmModule {
InvalidTable::InitialTableSizeLimitExceeded,
));
}
// As of now (Jan 17, 2025) tables are not growable, because TableGrow operator is disabled
// in `wasmparser`, but let's add below check in case it is enabled in the future.
if let Some(maximum) = table.ty.maximum {
if maximum > max_initial_table_size {
return Err(PrepareError::InvalidTable(
InvalidTable::InitialTableSizeLimitExceeded,
));
}
}
}
}

Expand Down
76 changes: 76 additions & 0 deletions radix-engine/src/vm/wasm/wasm_features_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use radix_rust::prelude::String;
use wasmparser::WasmFeatures;

#[derive(Debug, Clone)]
pub struct WasmFeaturesConfig {
pub features: WasmFeatures,
}

impl Default for WasmFeaturesConfig {
fn default() -> Self {
Self {
// The Radix Engine supports the MVP and additional proposals, specifically:
// - mutable-globals and sign-extension-ops
// - reference-types and multi-value returns
// These features have been enabled by default in LLVM version 19, which Rust has used starting from version 1.82.
// To ensure compatibility with Rust versions 1.82 and later, both features must be enabled.
//
// - Reference types
// Enabling this is safe since Rust does not support `externref`.
// Regarding indirect function calls—which are common in Rust code—there is no issue with the 5-byte LEB128 encoding.
// The proposal has been around for a while, and WebAssembly engines, including `wasmi`, have had sufficient time to stabilize it.
// - Multi-value returns
// This is also safe to enable because the Radix Engine has never used the Nightly `extern "wasm"` feature.
// You can find more details here: https://blog.rust-lang.org/2024/09/24/webassembly-targets-change-in-default-target-features.html
features: WasmFeatures {
mutable_global: true,
sign_extension: true,
reference_types: true,
multi_value: true,
saturating_float_to_int: false,
bulk_memory: false,
simd: false,
relaxed_simd: false,
threads: false,
tail_call: false,
floats: false,
multi_memory: false,
exceptions: false,
memory64: false,
extended_const: false,
component_model: false,
function_references: false,
memory_control: false,
gc: false,
},
}
}
}

macro_rules! cflag {
($flag:expr, $name:expr) => {
if $flag {
concat!(" -m", $name)
} else {
concat!(" -mno-", $name)
}
};
}

impl WasmFeaturesConfig {
pub fn new() -> Self {
Self::default()
}

// More on CFLAGS for WASM: https://clang.llvm.org/docs/ClangCommandLineReference.html#webassembly
pub fn into_target_cflags(&self) -> String {
let mut cflags = String::from("-mcpu=mvp");
// Assuming that remaining options have sensible defaults
cflags += cflag!(self.features.mutable_global, "mutable-globals");
cflags += cflag!(self.features.sign_extension, "sign-ext");
cflags += cflag!(self.features.reference_types, "reference-types");
cflags += cflag!(self.features.multi_value, "multivalue");

cflags
}
}
22 changes: 22 additions & 0 deletions radix-engine/src/vm/wasm/wasmi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use radix_engine_interface::blueprints::package::CodeHash;
use sbor::rust::mem::MaybeUninit;
#[cfg(not(feature = "fuzzing"))]
use sbor::rust::sync::Arc;
use wasm::WasmFeaturesConfig;
use wasmi::core::HostError;
use wasmi::errors::InstantiationError;
use wasmi::*;
Expand Down Expand Up @@ -961,6 +962,27 @@ impl WasmiModule {
pub fn new(code: &[u8]) -> Result<Self, WasmiInstantiationError> {
let mut config = wasmi::Config::default();

let features = WasmFeaturesConfig::default().features;

config.wasm_mutable_global(features.mutable_global);
config.wasm_sign_extension(features.sign_extension);
config.wasm_saturating_float_to_int(features.saturating_float_to_int);
config.wasm_multi_value(features.multi_value);
config.wasm_multi_memory(features.multi_memory);
config.wasm_bulk_memory(features.bulk_memory);
config.wasm_reference_types(features.reference_types);
config.wasm_tail_call(features.tail_call);
config.wasm_extended_const(features.extended_const);
config.floats(features.floats);
// Below features are not configurable in `wasmi`
// component_model,
// simd
// relaxed_simd
// threads
// exceptions
// memory64
// memory_control

// In order to speed compilation we deliberately
// - use LazyTranslation compilation mode
// - compiling without WASM validation (Module::new_checked())
Expand Down
Loading
Loading