diff --git a/src/wasm2obj.rs b/src/wasm2obj.rs index 754efdc174..bc99441bd8 100644 --- a/src/wasm2obj.rs +++ b/src/wasm2obj.rs @@ -31,6 +31,7 @@ use cranelift_codegen::isa; use cranelift_codegen::settings; +use cranelift_codegen::settings::Configurable; use cranelift_native; use docopt::Docopt; use faerie::Artifact; @@ -62,7 +63,7 @@ The translation is dependent on the environment chosen. The default is a dummy environment that produces placeholder values. Usage: - wasm2obj [--target TARGET] [-cdg] -o + wasm2obj [--target TARGET] [-cdg] [--enable-simd] -o wasm2obj --help | --version Options: @@ -71,6 +72,7 @@ Options: --target build for the target triple; default is the host machine -g generate debug information -c, --cache enable caching system + --enable-simd enable proposed SIMD instructions --version print the Cranelift version -d, --debug enable debug output on stderr/stdout "; @@ -83,6 +85,7 @@ struct Args { flag_g: bool, flag_debug: bool, flag_cache: bool, + flag_enable_simd: bool, } fn read_wasm_file(path: PathBuf) -> Result, io::Error> { @@ -116,6 +119,7 @@ fn main() { &args.arg_target, &args.arg_output, args.flag_g, + args.flag_enable_simd, ) { Ok(()) => {} Err(message) => { @@ -130,6 +134,7 @@ fn handle_module( target: &Option, output: &str, generate_debug_info: bool, + enable_simd: bool, ) -> Result<(), String> { let data = match read_wasm_file(path) { Ok(data) => data, @@ -152,7 +157,10 @@ fn handle_module( panic!("host machine is not a supported target"); }), }; - let flag_builder = settings::builder(); + let mut flag_builder = settings::builder(); + if enable_simd { + flag_builder.enable("enable_simd").unwrap(); + } let isa = isa_builder.finish(settings::Flags::new(flag_builder)); let mut obj = Artifact::new(isa.triple().clone(), String::from(output)); diff --git a/src/wasmtime.rs b/src/wasmtime.rs index 479efd2915..08b33150b4 100644 --- a/src/wasmtime.rs +++ b/src/wasmtime.rs @@ -47,7 +47,7 @@ use std::process::exit; use wabt; use wasi_common::preopen_dir; use wasmtime_environ::cache_conf; -use wasmtime_jit::{ActionOutcome, Context}; +use wasmtime_jit::{ActionOutcome, Context, Features}; use wasmtime_wasi::instantiate_wasi; use wasmtime_wast::instantiate_spectest; @@ -66,8 +66,8 @@ including calling the start function if one is present. Additional functions given with --invoke are then called. Usage: - wasmtime [-ocdg] [--wasi-c] [--preload=...] [--env=...] [--dir=...] [--mapdir=...] [...] - wasmtime [-ocdg] [--wasi-c] [--preload=...] [--env=...] [--dir=...] [--mapdir=...] --invoke= [...] + wasmtime [-ocdg] [--enable-simd] [--wasi-c] [--preload=...] [--env=...] [--dir=...] [--mapdir=...] [...] + wasmtime [-ocdg] [--enable-simd] [--wasi-c] [--preload=...] [--env=...] [--dir=...] [--mapdir=...] --invoke= [...] wasmtime --help | --version Options: @@ -76,6 +76,7 @@ Options: -c, --cache enable caching system -g generate debug information -d, --debug enable debug output on stderr/stdout + --enable-simd enable proposed SIMD instructions --wasi-c enable the wasi-c implementation of WASI --preload= load an additional wasm module before loading the main module --env= pass an environment variable (\"key=value\") to the program @@ -94,6 +95,7 @@ struct Args { flag_cache: bool, flag_debug: bool, flag_g: bool, + flag_enable_simd: bool, flag_invoke: Option, flag_preload: Vec, flag_env: Vec, @@ -214,19 +216,26 @@ fn main() { panic!("host machine is not a supported target"); }); let mut flag_builder = settings::builder(); + let mut features: Features = Default::default(); // Enable verifier passes in debug mode. if cfg!(debug_assertions) { flag_builder.enable("enable_verifier").unwrap(); } + // Enable SIMD if requested + if args.flag_enable_simd { + flag_builder.enable("enable_simd").unwrap(); + features.simd = true; + } + // Enable optimization if requested. if args.flag_optimize { flag_builder.set("opt_level", "best").unwrap(); } let isa = isa_builder.finish(settings::Flags::new(flag_builder)); - let mut context = Context::with_isa(isa); + let mut context = Context::with_isa(isa).with_features(features); // Make spectest available by default. context.name_instance( diff --git a/src/wast.rs b/src/wast.rs index a2af79b87e..49d2ae2b98 100644 --- a/src/wast.rs +++ b/src/wast.rs @@ -34,7 +34,7 @@ use serde::Deserialize; use std::path::Path; use std::process; use wasmtime_environ::cache_conf; -use wasmtime_jit::Compiler; +use wasmtime_jit::{Compiler, Features}; use wasmtime_wast::WastContext; mod utils; @@ -45,7 +45,7 @@ const USAGE: &str = " Wast test runner. Usage: - run_wast [-cdo] ... + run_wast [-cdo] [--enable-simd] ... run_wast --help | --version Options: @@ -54,6 +54,7 @@ Options: -o, --optimize runs optimization passes on the translated functions -c, --cache enable caching system -d, --debug enable debug output on stderr/stdout + --enable-simd enable proposed SIMD instructions "; #[derive(Deserialize, Debug, Clone)] @@ -63,6 +64,7 @@ struct Args { flag_function: Option, flag_optimize: bool, flag_cache: bool, + flag_enable_simd: bool, } fn main() { @@ -87,6 +89,7 @@ fn main() { panic!("host machine is not a supported target"); }); let mut flag_builder = settings::builder(); + let mut features: Features = Default::default(); // Enable verifier passes in debug mode. if cfg!(debug_assertions) { @@ -98,9 +101,15 @@ fn main() { flag_builder.set("opt_level", "best").unwrap(); } + // Enable SIMD if requested + if args.flag_enable_simd { + flag_builder.enable("enable_simd").unwrap(); + features.simd = true; + } + let isa = isa_builder.finish(settings::Flags::new(flag_builder)); let engine = Compiler::new(isa); - let mut wast_context = WastContext::new(Box::new(engine)); + let mut wast_context = WastContext::new(Box::new(engine)).with_features(features); wast_context .register_spectest() diff --git a/wasmtime-jit/src/context.rs b/wasmtime-jit/src/context.rs index 12e710f866..0e2940d678 100644 --- a/wasmtime-jit/src/context.rs +++ b/wasmtime-jit/src/context.rs @@ -43,12 +43,43 @@ impl fmt::Display for ContextError { } } +/// The collection of features configurable during compilation +#[derive(Clone, Default)] +pub struct Features { + /// marks whether the proposed thread feature is enabled or disabled + pub threads: bool, + /// marks whether the proposed reference type feature is enabled or disabled + pub reference_types: bool, + /// marks whether the proposed SIMD feature is enabled or disabled + pub simd: bool, + /// marks whether the proposed bulk memory feature is enabled or disabled + pub bulk_memory: bool, + /// marks whether the proposed multi-value feature is enabled or disabled + pub multi_value: bool, +} + +impl Into for Features { + fn into(self) -> ValidatingParserConfig { + ValidatingParserConfig { + operator_config: OperatorValidatorConfig { + enable_threads: self.threads, + enable_reference_types: self.reference_types, + enable_bulk_memory: self.bulk_memory, + enable_simd: self.simd, + enable_multi_value: self.multi_value, + }, + mutable_global_imports: true, + } + } +} + /// A convenient context for compiling and executing WebAssembly instances. pub struct Context { namespace: Namespace, compiler: Box, global_exports: Rc>>>, debug_info: bool, + features: Features, } impl Context { @@ -59,6 +90,7 @@ impl Context { compiler, global_exports: Rc::new(RefCell::new(HashMap::new())), debug_info: false, + features: Default::default(), } } @@ -77,21 +109,15 @@ impl Context { Self::new(Box::new(Compiler::new(isa))) } - fn validate(&mut self, data: &[u8]) -> Result<(), String> { - let config = ValidatingParserConfig { - operator_config: OperatorValidatorConfig { - enable_threads: false, - enable_reference_types: false, - enable_bulk_memory: false, - enable_simd: false, - enable_multi_value: false, - }, - mutable_global_imports: true, - }; + /// Construct a new instance with the given features from the current `Context` + pub fn with_features(self, features: Features) -> Self { + Self { features, ..self } + } + fn validate(&mut self, data: &[u8]) -> Result<(), String> { // TODO: Fix Cranelift to be able to perform validation itself, rather // than calling into wasmparser ourselves here. - if validate(data, Some(config)) { + if validate(data, Some(self.features.clone().into())) { Ok(()) } else { // TODO: Work with wasmparser to get better error messages. diff --git a/wasmtime-jit/src/lib.rs b/wasmtime-jit/src/lib.rs index 9c878c6b21..3e9dc53b4e 100644 --- a/wasmtime-jit/src/lib.rs +++ b/wasmtime-jit/src/lib.rs @@ -51,7 +51,7 @@ mod target_tunables; pub use crate::action::{ActionError, ActionOutcome, RuntimeValue}; pub use crate::compiler::Compiler; -pub use crate::context::{Context, ContextError, UnknownInstance}; +pub use crate::context::{Context, ContextError, Features, UnknownInstance}; pub use crate::instantiate::{instantiate, CompiledModule, SetupError}; pub use crate::link::link_module; pub use crate::namespace::Namespace; diff --git a/wasmtime-wast/src/wast.rs b/wasmtime-wast/src/wast.rs index cf3a10c2eb..2213bdd7ff 100644 --- a/wasmtime-wast/src/wast.rs +++ b/wasmtime-wast/src/wast.rs @@ -4,7 +4,7 @@ use std::path::Path; use std::{fmt, fs, io, str}; use wabt::script::{Action, Command, CommandKind, ModuleBinary, ScriptParser, Value}; use wasmtime_jit::{ - ActionError, ActionOutcome, Compiler, Context, InstanceHandle, InstantiationError, + ActionError, ActionOutcome, Compiler, Context, Features, InstanceHandle, InstantiationError, RuntimeValue, UnknownInstance, }; @@ -85,6 +85,14 @@ impl WastContext { } } + /// Construct a new instance with the given features using the current `Context` + pub fn with_features(self, features: Features) -> Self { + Self { + context: self.context.with_features(features), + ..self + } + } + fn get_instance( &mut self, instance_name: Option<&str>,