Merge remote-tracking branch 'origin/main' into pch/wiggle_sync_shimming

This commit is contained in:
Pat Hickey
2021-05-06 17:54:03 -07:00
142 changed files with 4443 additions and 1771 deletions

View File

@@ -28,7 +28,7 @@ lazy_static::lazy_static! {
Compiling for a specific platform (Linux) and CPU preset (Skylake):\n\
\n \
wasmtime compile --target x86_64-unknown-linux --cranelift-enable skylake foo.wasm\n",
crate::WASM_FEATURES.as_str()
crate::FLAG_EXPLANATIONS.as_str()
)
};
}
@@ -126,7 +126,8 @@ mod test {
command.execute()?;
let engine = Engine::default();
let module = Module::from_file(&engine, output_path)?;
let contents = std::fs::read(output_path)?;
let module = unsafe { Module::deserialize(&engine, contents)? };
let store = Store::new(&engine);
let instance = Instance::new(&store, &module, &[])?;
let f = instance.get_typed_func::<i32, i32>("f")?;

View File

@@ -1,6 +1,6 @@
//! The module that implements the `wasmtime run` command.
use crate::CommonOptions;
use crate::{CommonOptions, WasiModules};
use anyhow::{bail, Context as _, Result};
use std::thread;
use std::time::Duration;
@@ -67,7 +67,7 @@ fn parse_preloads(s: &str) -> Result<(String, PathBuf)> {
lazy_static::lazy_static! {
static ref AFTER_HELP: String = {
crate::WASM_FEATURES.to_string()
crate::FLAG_EXPLANATIONS.to_string()
};
}
@@ -143,7 +143,13 @@ impl RunCommand {
let argv = self.compute_argv();
let mut linker = Linker::new(&store);
populate_with_wasi(&mut linker, preopen_dirs, &argv, &self.vars)?;
populate_with_wasi(
&mut linker,
preopen_dirs,
&argv,
&self.vars,
&self.common.wasi_modules.unwrap_or(WasiModules::default()),
)?;
// Load the preload wasm modules.
for (name, path) in self.preloads.iter() {
@@ -348,6 +354,7 @@ fn populate_with_wasi(
preopen_dirs: Vec<(String, Dir)>,
argv: &[String],
vars: &[(String, String)],
wasi_modules: &WasiModules,
) -> Result<()> {
// Add the current snapshot to the linker.
let mut builder = WasiCtxBuilder::new();
@@ -357,25 +364,40 @@ fn populate_with_wasi(
builder = builder.preopened_dir(dir, name)?;
}
Wasi::new(linker.store(), builder.build()?).add_to_linker(linker)?;
#[cfg(feature = "wasi-nn")]
{
use std::cell::RefCell;
use std::rc::Rc;
let wasi_nn = WasiNn::new(linker.store(), Rc::new(RefCell::new(WasiNnCtx::new()?)));
wasi_nn.add_to_linker(linker)?;
if wasi_modules.wasi_common {
Wasi::new(linker.store(), builder.build()?).add_to_linker(linker)?;
}
#[cfg(feature = "wasi-crypto")]
{
use std::cell::RefCell;
use std::rc::Rc;
let cx_crypto = Rc::new(RefCell::new(WasiCryptoCtx::new()));
WasiCryptoCommon::new(linker.store(), cx_crypto.clone()).add_to_linker(linker)?;
WasiCryptoAsymmetricCommon::new(linker.store(), cx_crypto.clone()).add_to_linker(linker)?;
WasiCryptoSignatures::new(linker.store(), cx_crypto.clone()).add_to_linker(linker)?;
WasiCryptoSymmetric::new(linker.store(), cx_crypto).add_to_linker(linker)?;
if wasi_modules.wasi_nn {
#[cfg(not(feature = "wasi-nn"))]
{
bail!("Cannot enable wasi-nn when the binary is not compiled with this feature.");
}
#[cfg(feature = "wasi-nn")]
{
use std::cell::RefCell;
use std::rc::Rc;
let wasi_nn = WasiNn::new(linker.store(), Rc::new(RefCell::new(WasiNnCtx::new()?)));
wasi_nn.add_to_linker(linker)?;
}
}
if wasi_modules.wasi_crypto {
#[cfg(not(feature = "wasi-crypto"))]
{
bail!("Cannot enable wasi-crypto when the binary is not compiled with this feature.");
}
#[cfg(feature = "wasi-crypto")]
{
use std::cell::RefCell;
use std::rc::Rc;
let cx_crypto = Rc::new(RefCell::new(WasiCryptoCtx::new()));
WasiCryptoCommon::new(linker.store(), cx_crypto.clone()).add_to_linker(linker)?;
WasiCryptoAsymmetricCommon::new(linker.store(), cx_crypto.clone())
.add_to_linker(linker)?;
WasiCryptoSignatures::new(linker.store(), cx_crypto.clone()).add_to_linker(linker)?;
WasiCryptoSymmetric::new(linker.store(), cx_crypto).add_to_linker(linker)?;
}
}
Ok(())

View File

@@ -18,7 +18,7 @@ lazy_static::lazy_static! {
The default is a dummy environment that produces placeholder values.\n\
\n\
{}",
crate::WASM_FEATURES.as_str()
crate::FLAG_EXPLANATIONS.as_str()
)
};
}

View File

@@ -9,7 +9,7 @@ use wasmtime_wast::WastContext;
lazy_static::lazy_static! {
static ref AFTER_HELP: String = {
crate::WASM_FEATURES.to_string()
crate::FLAG_EXPLANATIONS.to_string()
};
}

View File

@@ -43,19 +43,47 @@ const SUPPORTED_WASM_FEATURES: &[(&str, &str)] = &[
("threads", "enables support for WebAssembly threads"),
];
const SUPPORTED_WASI_MODULES: &[(&str, &str)] = &[
(
"default",
"enables all stable WASI modules (no experimental modules)",
),
(
"wasi-common",
"enables support for the WASI common APIs, see https://github.com/WebAssembly/WASI",
),
(
"experimental-wasi-nn",
"enables support for the WASI neural network API (experimental), see https://github.com/WebAssembly/wasi-nn",
),
(
"experimental-wasi-crypto",
"enables support for the WASI cryptography APIs (experimental), see https://github.com/WebAssembly/wasi-crypto",
),
];
lazy_static::lazy_static! {
static ref WASM_FEATURES: String = {
static ref FLAG_EXPLANATIONS: String = {
use std::fmt::Write;
let mut s = String::new();
// Explain --wasm-features.
writeln!(&mut s, "Supported values for `--wasm-features`:").unwrap();
writeln!(&mut s).unwrap();
let max = SUPPORTED_WASM_FEATURES.iter().max_by_key(|(name, _)| name.len()).unwrap();
for (name, desc) in SUPPORTED_WASM_FEATURES.iter() {
writeln!(&mut s, "{:width$} {}", name, desc, width = max.0.len() + 2).unwrap();
}
writeln!(&mut s).unwrap();
// Explain --wasi-modules.
writeln!(&mut s, "Supported values for `--wasi-modules`:").unwrap();
writeln!(&mut s).unwrap();
let max = SUPPORTED_WASI_MODULES.iter().max_by_key(|(name, _)| name.len()).unwrap();
for (name, desc) in SUPPORTED_WASI_MODULES.iter() {
writeln!(&mut s, "{:width$} {}", name, desc, width = max.0.len() + 2).unwrap();
}
writeln!(&mut s).unwrap();
writeln!(&mut s, "Features prefixed with '-' will be disabled.").unwrap();
@@ -186,6 +214,10 @@ struct CommonOptions {
#[structopt(long, value_name = "FEATURE,FEATURE,...", parse(try_from_str = parse_wasm_features))]
wasm_features: Option<wasmparser::WasmFeatures>,
/// Enables or disables WASI modules
#[structopt(long, value_name = "MODULE,MODULE,...", parse(try_from_str = parse_wasi_modules))]
wasi_modules: Option<WasiModules>,
/// Use Lightbeam for all compilation
#[structopt(long, conflicts_with = "cranelift")]
lightbeam: bool,
@@ -408,6 +440,75 @@ fn parse_wasm_features(features: &str) -> Result<wasmparser::WasmFeatures> {
memory64: false,
})
}
fn parse_wasi_modules(modules: &str) -> Result<WasiModules> {
let modules = modules.trim();
match modules {
"default" => Ok(WasiModules::default()),
"-default" => Ok(WasiModules::none()),
_ => {
// Starting from the default set of WASI modules, enable or disable a list of
// comma-separated modules.
let mut wasi_modules = WasiModules::default();
let mut set = |module: &str, enable: bool| match module {
"" => Ok(()),
"wasi-common" => Ok(wasi_modules.wasi_common = enable),
"experimental-wasi-nn" => Ok(wasi_modules.wasi_nn = enable),
"experimental-wasi-crypto" => Ok(wasi_modules.wasi_crypto = enable),
"default" => bail!("'default' cannot be specified with other WASI modules"),
_ => bail!("unsupported WASI module '{}'", module),
};
for module in modules.split(',') {
let module = module.trim();
let (module, value) = if module.starts_with('-') {
(&module[1..], false)
} else {
(module, true)
};
set(module, value)?;
}
Ok(wasi_modules)
}
}
}
/// Select which WASI modules are available at runtime for use by Wasm programs.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct WasiModules {
/// Enable the wasi-common implementation; eventually this should be split into its separate
/// parts once the implementation allows for it (e.g. wasi-fs, wasi-clocks, etc.).
pub wasi_common: bool,
/// Enable the experimental wasi-nn implementation.
pub wasi_nn: bool,
/// Enable the experimental wasi-crypto implementation.
pub wasi_crypto: bool,
}
impl Default for WasiModules {
fn default() -> Self {
Self {
wasi_common: true,
wasi_nn: false,
wasi_crypto: false,
}
}
}
impl WasiModules {
/// Enable no modules.
pub fn none() -> Self {
Self {
wasi_common: false,
wasi_nn: false,
wasi_crypto: false,
}
}
}
fn parse_cranelift_flag(name_and_value: &str) -> Result<(String, String)> {
let mut split = name_and_value.splitn(2, '=');
let name = if let Some(name) = split.next() {
@@ -574,4 +675,61 @@ mod test {
feature_test!(test_simd_feature, simd, "simd");
feature_test!(test_threads_feature, threads, "threads");
feature_test!(test_multi_memory_feature, multi_memory, "multi-memory");
#[test]
fn test_default_modules() {
let options = CommonOptions::from_iter_safe(vec!["foo", "--wasi-modules=default"]).unwrap();
assert_eq!(
options.wasi_modules.unwrap(),
WasiModules {
wasi_common: true,
wasi_nn: false,
wasi_crypto: false
}
);
}
#[test]
fn test_empty_modules() {
let options = CommonOptions::from_iter_safe(vec!["foo", "--wasi-modules="]).unwrap();
assert_eq!(
options.wasi_modules.unwrap(),
WasiModules {
wasi_common: true,
wasi_nn: false,
wasi_crypto: false
}
);
}
#[test]
fn test_some_modules() {
let options = CommonOptions::from_iter_safe(vec![
"foo",
"--wasi-modules=experimental-wasi-nn,-wasi-common",
])
.unwrap();
assert_eq!(
options.wasi_modules.unwrap(),
WasiModules {
wasi_common: false,
wasi_nn: true,
wasi_crypto: false
}
);
}
#[test]
fn test_no_modules() {
let options =
CommonOptions::from_iter_safe(vec!["foo", "--wasi-modules=-default"]).unwrap();
assert_eq!(
options.wasi_modules.unwrap(),
WasiModules {
wasi_common: false,
wasi_nn: false,
wasi_crypto: false
}
);
}
}