From f21b07e8e64f9301c8c60387fe34edfbc98a7c25 Mon Sep 17 00:00:00 2001 From: Michael-F-Bryan Date: Wed, 8 Mar 2023 17:38:44 +0800 Subject: [PATCH] Wasmer run for wasm32-unknown-unknown --- lib/cli/src/commands/run2.rs | 78 +++++++++++++++++++++++++++-- tests/integration/cli/tests/run2.rs | 2 - 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/lib/cli/src/commands/run2.rs b/lib/cli/src/commands/run2.rs index f115ed95c..414046c85 100644 --- a/lib/cli/src/commands/run2.rs +++ b/lib/cli/src/commands/run2.rs @@ -13,7 +13,7 @@ use anyhow::{Context, Error}; use clap::Parser; use tempfile::NamedTempFile; use url::Url; -use wasmer::{Module, Store, TypedFunction}; +use wasmer::{Function, Imports, Instance, Module, Store, Type, TypedFunction, Value}; use wasmer_compiler::ArtifactBuild; use wasmer_registry::Package; use wasmer_wasix::runners::{Runner, WapmContainer}; @@ -84,7 +84,7 @@ impl Run2 { } else if wasmer_wasix::is_wasi_module(module) || wasmer_wasix::is_wasix_module(module) { self.execute_wasi_module(target.path(), module, store) } else { - self.execute_pure_wasm_module() + self.execute_pure_wasm_module(module, store) } } @@ -145,8 +145,35 @@ impl Run2 { } #[tracing::instrument(skip_all)] - fn execute_pure_wasm_module(&self) -> Result<(), Error> { - todo!() + fn execute_pure_wasm_module(&self, module: &Module, store: &mut Store) -> Result<(), Error> { + let imports = Imports::default(); + let instance = Instance::new(store, module, &imports) + .context("Unable to instantiate the WebAssembly module")?; + + let entrypoint = match &self.entrypoint { + Some(entry) => { + instance.exports + .get_function(entry) + .with_context(|| format!("The module doesn't contain a \"{entry}\" function"))? + }, + None => { + instance.exports.get_function("_start") + .context("The module doesn't contain a \"_start\" function. Either implement it or specify an entrypoint function.")? + } + }; + + let return_values = invoke_function(&instance, store, entrypoint, &self.args)?; + + println!( + "{}", + return_values + .iter() + .map(|val| val.to_string()) + .collect::>() + .join(" ") + ); + + Ok(()) } #[tracing::instrument(skip_all)] @@ -171,6 +198,49 @@ impl Run2 { } } +fn invoke_function( + instance: &Instance, + store: &mut Store, + func: &Function, + args: &[String], +) -> Result, Error> { + let func_ty = func.ty(store); + let required_arguments = func_ty.params().len(); + let provided_arguments = args.len(); + + anyhow::ensure!( + required_arguments == provided_arguments, + "Function expected {} arguments, but received {}", + required_arguments, + provided_arguments, + ); + + let invoke_args = args + .iter() + .zip(func_ty.params().iter()) + .map(|(arg, param_type)| { + parse_value(arg, *param_type) + .with_context(|| format!("Unable to convert {arg:?} to {param_type:?}")) + }) + .collect::, _>>()?; + + let return_values = func.call(store, &invoke_args)?; + + Ok(return_values) +} + +fn parse_value(s: &str, ty: wasmer_types::Type) -> Result { + let value = match ty { + Type::I32 => Value::I32(s.parse()?), + Type::I64 => Value::I64(s.parse()?), + Type::F32 => Value::F32(s.parse()?), + Type::F64 => Value::F64(s.parse()?), + Type::V128 => Value::V128(s.parse()?), + _ => anyhow::bail!("There is no known conversion from {s:?} to {ty:?}"), + }; + Ok(value) +} + fn infer_webc_entrypoint(manifest: &Manifest) -> Result<&str, Error> { if let Some(entrypoint) = manifest.entrypoint.as_deref() { return Ok(entrypoint); diff --git a/tests/integration/cli/tests/run2.rs b/tests/integration/cli/tests/run2.rs index 362813f53..99cee12dc 100644 --- a/tests/integration/cli/tests/run2.rs +++ b/tests/integration/cli/tests/run2.rs @@ -116,7 +116,6 @@ mod wasm_on_disk { } #[test] - #[ignore] fn no_abi() { let assert = wasmer_cli().arg("run2").arg(fixtures::fib()).assert(); @@ -124,7 +123,6 @@ mod wasm_on_disk { } #[test] - #[ignore] fn error_if_no_start_function_found() { let assert = wasmer_cli() .arg("run2")