Enable SIMD instructions from the command line (#232)
This change adds an `--enable-simd` flag to the binaries in this project. This allows the ISA `enable_simd` flag to be set and to configure the validation configuration used by wasmparser to allow SIMD instructions.
This commit is contained in:
committed by
Yury Delendik
parent
fff0198fb7
commit
5873f697fc
@@ -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] <file> -o <output>
|
||||
wasm2obj [--target TARGET] [-cdg] [--enable-simd] <file> -o <output>
|
||||
wasm2obj --help | --version
|
||||
|
||||
Options:
|
||||
@@ -71,6 +72,7 @@ Options:
|
||||
--target <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<Vec<u8>, 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<String>,
|
||||
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));
|
||||
|
||||
@@ -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=<wasm>...] [--env=<env>...] [--dir=<dir>...] [--mapdir=<mapping>...] <file> [<arg>...]
|
||||
wasmtime [-ocdg] [--wasi-c] [--preload=<wasm>...] [--env=<env>...] [--dir=<dir>...] [--mapdir=<mapping>...] --invoke=<fn> <file> [<arg>...]
|
||||
wasmtime [-ocdg] [--enable-simd] [--wasi-c] [--preload=<wasm>...] [--env=<env>...] [--dir=<dir>...] [--mapdir=<mapping>...] <file> [<arg>...]
|
||||
wasmtime [-ocdg] [--enable-simd] [--wasi-c] [--preload=<wasm>...] [--env=<env>...] [--dir=<dir>...] [--mapdir=<mapping>...] --invoke=<fn> <file> [<arg>...]
|
||||
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=<wasm> load an additional wasm module before loading the main module
|
||||
--env=<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<String>,
|
||||
flag_preload: Vec<String>,
|
||||
flag_env: Vec<String>,
|
||||
@@ -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(
|
||||
|
||||
15
src/wast.rs
15
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] <file>...
|
||||
run_wast [-cdo] [--enable-simd] <file>...
|
||||
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<String>,
|
||||
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()
|
||||
|
||||
@@ -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<ValidatingParserConfig> 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<Compiler>,
|
||||
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
||||
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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>,
|
||||
|
||||
Reference in New Issue
Block a user