Skip to content
Merged
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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ wasmtime-wasi = { workspace = true, features = ["exit"] }
wasmtime-wasi-nn = { workspace = true, optional = true }
wasmtime-wasi-threads = { workspace = true, optional = true }
wasmtime-wasi-http = { workspace = true, optional = true }
wasmtime-runtime = { workspace = true }
clap = { workspace = true, features = ["color", "suggestions", "derive"] }
anyhow = { workspace = true }
target-lexicon = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions ci/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ cargo test \
--features "test-programs/test_programs" \
--features wasi-threads \
--features wasi-http \
--features component-model \
--workspace \
--exclude 'wasmtime-wasi-*' \
--exclude wasi-tests \
Expand Down
2 changes: 1 addition & 1 deletion crates/test-programs/tests/wasi-http-modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl WasiHttpView for Ctx {
async fn instantiate_module(module: Module, ctx: Ctx) -> Result<(Store<Ctx>, Func), anyhow::Error> {
let mut linker = Linker::new(&ENGINE);
wasmtime_wasi_http::add_to_linker(&mut linker)?;
wasmtime_wasi::preview2::preview1::add_to_linker(&mut linker)?;
wasmtime_wasi::preview2::preview1::add_to_linker_async(&mut linker)?;

let mut store = Store::new(&ENGINE, ctx);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use tempfile::TempDir;
use wasmtime::{Config, Engine, Linker, Store};
use wasmtime_wasi::preview2::{
pipe::MemoryOutputPipe,
preview1::{add_to_linker, WasiPreview1Adapter, WasiPreview1View},
preview1::{add_to_linker_async, WasiPreview1Adapter, WasiPreview1View},
DirPerms, FilePerms, IsATTY, Table, WasiCtx, WasiCtxBuilder, WasiView,
};

Expand Down Expand Up @@ -34,7 +34,7 @@ async fn run(name: &str, inherit_stdio: bool) -> Result<()> {
let stderr = MemoryOutputPipe::new();
let r = {
let mut linker = Linker::new(&ENGINE);
add_to_linker(&mut linker)?;
add_to_linker_async(&mut linker)?;

// Create our wasi context.
// Additionally register any preopened directories if we have them.
Expand Down
4 changes: 4 additions & 0 deletions crates/wasi-nn/src/wit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ impl gen::inference::Host for WasiNnCtx {
}
}

impl gen::errors::Host for WasiNnCtx {}

impl gen::tensor::Host for WasiNnCtx {}

impl TryFrom<gen::graph::GraphEncoding> for crate::backend::BackendKind {
type Error = UsageError;
fn try_from(value: gen::graph::GraphEncoding) -> Result<Self, Self::Error> {
Expand Down
47 changes: 34 additions & 13 deletions crates/wasi/src/preview2/preview1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ impl WasiPreview1Adapter {

// Any context that needs to support preview 1 will impl this trait. They can
// construct the needed member with WasiPreview1Adapter::new().
pub trait WasiPreview1View: Send + Sync + WasiView {
pub trait WasiPreview1View: WasiView {
fn adapter(&self) -> &WasiPreview1Adapter;
fn adapter_mut(&mut self) -> &mut WasiPreview1Adapter;
}
Expand Down Expand Up @@ -390,23 +390,18 @@ trait WasiPreview1ViewExt:

impl<T: WasiPreview1View + preopens::Host> WasiPreview1ViewExt for T {}

pub fn add_to_linker<
T: WasiPreview1View
+ bindings::cli::environment::Host
+ bindings::cli::exit::Host
+ bindings::filesystem::types::Host
+ bindings::filesystem::preopens::Host
+ bindings::sync_io::poll::poll::Host
+ bindings::random::random::Host
+ bindings::io::streams::Host
+ bindings::clocks::monotonic_clock::Host
+ bindings::clocks::wall_clock::Host,
>(
pub fn add_to_linker_async<T: WasiPreview1View>(
linker: &mut wasmtime::Linker<T>,
) -> anyhow::Result<()> {
wasi_snapshot_preview1::add_to_linker(linker, |t| t)
}

pub fn add_to_linker_sync<T: WasiPreview1View>(
linker: &mut wasmtime::Linker<T>,
) -> anyhow::Result<()> {
sync::add_wasi_snapshot_preview1_to_linker(linker, |t| t)
}

// Generate the wasi_snapshot_preview1::WasiSnapshotPreview1 trait,
// and the module types.
// None of the generated modules, traits, or types should be used externally
Expand All @@ -425,6 +420,32 @@ wiggle::from_witx!({
errors: { errno => trappable Error },
});

mod sync {
use anyhow::Result;
use std::future::Future;

wiggle::wasmtime_integration!({
witx: ["$CARGO_MANIFEST_DIR/witx/wasi_snapshot_preview1.witx"],
target: super,
block_on[in_tokio]: {
wasi_snapshot_preview1::{
fd_advise, fd_close, fd_datasync, fd_fdstat_get, fd_filestat_get, fd_filestat_set_size,
fd_filestat_set_times, fd_read, fd_pread, fd_seek, fd_sync, fd_readdir, fd_write,
fd_pwrite, poll_oneoff, path_create_directory, path_filestat_get,
path_filestat_set_times, path_link, path_open, path_readlink, path_remove_directory,
path_rename, path_symlink, path_unlink_file
}
},
errors: { errno => trappable Error },
});

// Small wrapper around `in_tokio` to add a `Result` layer which is always
// `Ok`
fn in_tokio<F: Future>(future: F) -> Result<F::Output> {
Ok(crate::preview2::in_tokio(future))
}
}

impl wiggle::GuestErrorType for types::Errno {
fn success() -> Self {
Self::Success
Expand Down
6 changes: 6 additions & 0 deletions crates/wasi/src/preview2/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,9 @@ impl Table {
})
}
}

impl Default for Table {
fn default() -> Self {
Table::new()
}
}
80 changes: 23 additions & 57 deletions crates/wiggle/generate/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use {
proc_macro2::Span,
proc_macro2::{Span, TokenStream},
std::{collections::HashMap, iter::FromIterator, path::PathBuf},
syn::{
braced, bracketed,
Expand Down Expand Up @@ -61,14 +61,21 @@ impl Parse for ConfigField {
input.parse::<Token![async]>()?;
input.parse::<Token![:]>()?;
Ok(ConfigField::Async(AsyncConf {
blocking: false,
block_with: None,
functions: input.parse()?,
}))
} else if lookahead.peek(kw::block_on) {
input.parse::<kw::block_on>()?;
let block_with = if input.peek(syn::token::Bracket) {
let content;
let _ = bracketed!(content in input);
content.parse()?
} else {
quote::quote!(wiggle::run_in_dummy_executor)
};
input.parse::<Token![:]>()?;
Ok(ConfigField::Async(AsyncConf {
blocking: true,
block_with: Some(block_with),
functions: input.parse()?,
}))
} else if lookahead.peek(kw::wasmtime) {
Expand Down Expand Up @@ -381,16 +388,16 @@ impl std::fmt::Debug for UserErrorConfField {
#[derive(Clone, Default, Debug)]
/// Modules and funcs that have async signatures
pub struct AsyncConf {
blocking: bool,
block_with: Option<TokenStream>,
functions: AsyncFunctions,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug)]
pub enum Asyncness {
/// Wiggle function is synchronous, wasmtime Func is synchronous
Sync,
/// Wiggle function is asynchronous, but wasmtime Func is synchronous
Blocking,
Blocking { block_with: TokenStream },
/// Wiggle function and wasmtime Func are asynchronous.
Async,
}
Expand All @@ -402,10 +409,10 @@ impl Asyncness {
_ => false,
}
}
pub fn is_blocking(&self) -> bool {
pub fn blocking(&self) -> Option<&TokenStream> {
match self {
Self::Blocking => true,
_ => false,
Self::Blocking { block_with } => Some(block_with),
_ => None,
}
}
pub fn is_sync(&self) -> bool {
Expand All @@ -429,10 +436,11 @@ impl Default for AsyncFunctions {

impl AsyncConf {
pub fn get(&self, module: &str, function: &str) -> Asyncness {
let a = if self.blocking {
Asyncness::Blocking
} else {
Asyncness::Async
let a = match &self.block_with {
Some(block_with) => Asyncness::Blocking {
block_with: block_with.clone(),
},
None => Asyncness::Async,
};
match &self.functions {
AsyncFunctions::Some(fs) => {
Expand Down Expand Up @@ -577,54 +585,12 @@ impl Parse for WasmtimeConfig {

impl Parse for WasmtimeConfigField {
fn parse(input: ParseStream) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(kw::target) {
if input.peek(kw::target) {
input.parse::<kw::target>()?;
input.parse::<Token![:]>()?;
Ok(WasmtimeConfigField::Target(input.parse()?))

// The remainder of this function is the ConfigField impl, wrapped in
// WasmtimeConfigField::Core. This is required to get the correct lookahead error.
} else if lookahead.peek(kw::witx) {
input.parse::<kw::witx>()?;
input.parse::<Token![:]>()?;
Ok(WasmtimeConfigField::Core(ConfigField::Witx(
WitxConf::Paths(input.parse()?),
)))
} else if lookahead.peek(kw::witx_literal) {
input.parse::<kw::witx_literal>()?;
input.parse::<Token![:]>()?;
Ok(WasmtimeConfigField::Core(ConfigField::Witx(
WitxConf::Literal(input.parse()?),
)))
} else if lookahead.peek(kw::errors) {
input.parse::<kw::errors>()?;
input.parse::<Token![:]>()?;
Ok(WasmtimeConfigField::Core(ConfigField::Error(
input.parse()?,
)))
} else if lookahead.peek(Token![async]) {
input.parse::<Token![async]>()?;
input.parse::<Token![:]>()?;
Ok(WasmtimeConfigField::Core(ConfigField::Async(AsyncConf {
blocking: false,
functions: input.parse()?,
})))
} else if lookahead.peek(kw::block_on) {
input.parse::<kw::block_on>()?;
input.parse::<Token![:]>()?;
Ok(WasmtimeConfigField::Core(ConfigField::Async(AsyncConf {
blocking: true,
functions: input.parse()?,
})))
} else if lookahead.peek(kw::mutable) {
input.parse::<kw::mutable>()?;
input.parse::<Token![:]>()?;
Ok(WasmtimeConfigField::Core(ConfigField::Mutable(
input.parse::<syn::LitBool>()?.value,
)))
} else {
Err(lookahead.error())
Ok(WasmtimeConfigField::Core(input.parse()?))
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/wiggle/generate/src/wasmtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,14 @@ fn generate_func(
}
}

Asyncness::Blocking => {
Asyncness::Blocking { block_with } => {
quote! {
linker.func_wrap(
#module_str,
#field_str,
move |mut caller: wiggle::wasmtime_crate::Caller<'_, T> #(, #arg_decls)*| -> wiggle::anyhow::Result<#ret_ty> {
let result = async { #body };
wiggle::run_in_dummy_executor(result)?
#block_with(result)?
},
)?;
}
Expand Down
26 changes: 7 additions & 19 deletions src/commands/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,13 @@ impl CompileCommand {
output
});

// If the component-model proposal is enabled and the binary we're
// compiling looks like a component, tested by sniffing the first 8
// bytes with the current component model proposal.
#[cfg(feature = "component-model")]
{
if let Ok(wasmparser::Chunk::Parsed {
payload:
wasmparser::Payload::Version {
encoding: wasmparser::Encoding::Component,
..
},
..
}) = wasmparser::Parser::new(0).parse(&input, true)
{
fs::write(output, engine.precompile_component(&input)?)?;
return Ok(());
}
}
fs::write(output, engine.precompile_module(&input)?)?;
let output_bytes = if wasmparser::Parser::is_component(&input) {
engine.precompile_component(&input)?
} else {
engine.precompile_module(&input)?
};
fs::write(&output, output_bytes)
.with_context(|| format!("failed to write output: {}", output.display()))?;

Ok(())
}
Expand Down
Loading