mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-09 06:08:29 +00:00
Migrate wasmer-cli to new Context API
This commit is contained in:
committed by
Manos Pitsidianakis
parent
cf85615e55
commit
bc58b713db
@@ -7,9 +7,11 @@ use crate::warning;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use wasmer::Context as WasmerContext;
|
||||
use wasmer::*;
|
||||
#[cfg(feature = "cache")]
|
||||
use wasmer_cache::{Cache, FileSystemCache, Hash};
|
||||
use wasmer_types::Type as ValueType;
|
||||
|
||||
use structopt::StructOpt;
|
||||
|
||||
@@ -95,6 +97,41 @@ impl Run {
|
||||
})
|
||||
}
|
||||
|
||||
fn inner_run<T>(&self, mut ctx: WasmerContext<T>, instance: Instance) -> Result<()> {
|
||||
let module = self.get_module()?;
|
||||
// If this module exports an _initialize function, run that first.
|
||||
if let Ok(initialize) = instance.exports.get_function("_initialize") {
|
||||
initialize
|
||||
.call(&mut ctx, &[])
|
||||
.with_context(|| "failed to run _initialize function")?;
|
||||
}
|
||||
|
||||
// Do we want to invoke a function?
|
||||
if let Some(ref invoke) = self.invoke {
|
||||
let imports = imports! {};
|
||||
let instance = Instance::new(&mut ctx, &module, &imports)?;
|
||||
let result =
|
||||
self.invoke_function(&mut ctx.as_context_mut(), &instance, &invoke, &self.args)?;
|
||||
println!(
|
||||
"{}",
|
||||
result
|
||||
.iter()
|
||||
.map(|val| val.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(" ")
|
||||
);
|
||||
} else {
|
||||
let start: Function = self.try_find_function(&instance, "_start", &[])?;
|
||||
let result = start.call(&mut ctx, &[]);
|
||||
#[cfg(feature = "wasi")]
|
||||
self.wasi.handle_result(result)?;
|
||||
#[cfg(not(feature = "wasi"))]
|
||||
result?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn inner_execute(&self) -> Result<()> {
|
||||
let module = self.get_module()?;
|
||||
#[cfg(feature = "emscripten")]
|
||||
@@ -105,12 +142,19 @@ impl Run {
|
||||
};
|
||||
// TODO: refactor this
|
||||
if is_emscripten_module(&module) {
|
||||
let mut emscripten_globals = EmscriptenGlobals::new(module.store(), &module)
|
||||
// create an EmEnv with default global
|
||||
let mut ctx = WasmerContext::new(module.store(), EmEnv::new());
|
||||
let mut emscripten_globals = EmscriptenGlobals::new(ctx.as_context_mut(), &module)
|
||||
.map_err(|e| anyhow!("{}", e))?;
|
||||
let mut em_env = EmEnv::new(&emscripten_globals.data, Default::default());
|
||||
ctx.data_mut()
|
||||
.set_data(&emscripten_globals.data, Default::default());
|
||||
let import_object =
|
||||
generate_emscripten_env(module.store(), &mut emscripten_globals, &em_env);
|
||||
let mut instance = match Instance::new(&module, &import_object) {
|
||||
generate_emscripten_env(&mut ctx.as_context_mut(), &mut emscripten_globals);
|
||||
let mut instance = match Instance::new(
|
||||
&mut ctx.as_context_mut(),
|
||||
&module,
|
||||
&import_object,
|
||||
) {
|
||||
Ok(instance) => instance,
|
||||
Err(e) => {
|
||||
let err: Result<(), _> = Err(e);
|
||||
@@ -126,7 +170,7 @@ impl Run {
|
||||
|
||||
run_emscripten_instance(
|
||||
&mut instance,
|
||||
&mut em_env,
|
||||
ctx.as_context_mut(),
|
||||
&mut emscripten_globals,
|
||||
if let Some(cn) = &self.command_name {
|
||||
cn
|
||||
@@ -142,7 +186,7 @@ impl Run {
|
||||
|
||||
// If WASI is enabled, try to execute it with it
|
||||
#[cfg(feature = "wasi")]
|
||||
let instance = {
|
||||
let ret = {
|
||||
use std::collections::BTreeSet;
|
||||
use wasmer_wasi::WasiVersion;
|
||||
|
||||
@@ -175,47 +219,28 @@ impl Run {
|
||||
.map(|f| f.to_string_lossy().to_string())
|
||||
})
|
||||
.unwrap_or_default();
|
||||
self.wasi
|
||||
let (ctx, instance) = self
|
||||
.wasi
|
||||
.instantiate(&module, program_name, self.args.clone())
|
||||
.with_context(|| "failed to instantiate WASI module")?
|
||||
.with_context(|| "failed to instantiate WASI module")?;
|
||||
self.inner_run(ctx, instance)
|
||||
}
|
||||
// not WASI
|
||||
_ => Instance::new(&module, &imports! {})?,
|
||||
_ => {
|
||||
let mut ctx = WasmerContext::new(module.store(), ());
|
||||
let instance = Instance::new(&mut ctx, &module, &imports! {})?;
|
||||
self.inner_run(ctx, instance)
|
||||
}
|
||||
}
|
||||
};
|
||||
#[cfg(not(feature = "wasi"))]
|
||||
let instance = Instance::new(&module, &imports! {})?;
|
||||
let ret = {
|
||||
let mut ctx = WasmerContext::new(module.store(), ());
|
||||
let instance = Instance::new(&mut ctx, &module, &imports! {})?;
|
||||
self.inner_run(ctx, instance)
|
||||
};
|
||||
|
||||
// If this module exports an _initialize function, run that first.
|
||||
if let Ok(initialize) = instance.exports.get_function("_initialize") {
|
||||
initialize
|
||||
.call(&[])
|
||||
.with_context(|| "failed to run _initialize function")?;
|
||||
}
|
||||
|
||||
// Do we want to invoke a function?
|
||||
if let Some(ref invoke) = self.invoke {
|
||||
let imports = imports! {};
|
||||
let instance = Instance::new(&module, &imports)?;
|
||||
let result = self.invoke_function(&instance, invoke, &self.args)?;
|
||||
println!(
|
||||
"{}",
|
||||
result
|
||||
.iter()
|
||||
.map(|val| val.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(" ")
|
||||
);
|
||||
} else {
|
||||
let start: Function = self.try_find_function(&instance, "_start", &[])?;
|
||||
let result = start.call(&[]);
|
||||
#[cfg(feature = "wasi")]
|
||||
self.wasi.handle_result(result)?;
|
||||
#[cfg(not(feature = "wasi"))]
|
||||
result?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
ret
|
||||
}
|
||||
|
||||
fn get_module(&self) -> Result<Module> {
|
||||
@@ -350,12 +375,13 @@ impl Run {
|
||||
|
||||
fn invoke_function(
|
||||
&self,
|
||||
ctx: &mut impl AsContextMut,
|
||||
instance: &Instance,
|
||||
invoke: &str,
|
||||
args: &[String],
|
||||
) -> Result<Box<[Val]>> {
|
||||
let func: Function = self.try_find_function(instance, invoke, args)?;
|
||||
let func_ty = func.ty();
|
||||
) -> Result<Box<[Value]>> {
|
||||
let func: Function = self.try_find_function(&instance, invoke, args)?;
|
||||
let func_ty = func.ty(ctx);
|
||||
let required_arguments = func_ty.params().len();
|
||||
let provided_arguments = args.len();
|
||||
if required_arguments != provided_arguments {
|
||||
@@ -370,23 +396,23 @@ impl Run {
|
||||
.iter()
|
||||
.zip(func_ty.params().iter())
|
||||
.map(|(arg, param_type)| match param_type {
|
||||
ValType::I32 => {
|
||||
Ok(Val::I32(arg.parse().map_err(|_| {
|
||||
ValueType::I32 => {
|
||||
Ok(Value::I32(arg.parse().map_err(|_| {
|
||||
anyhow!("Can't convert `{}` into a i32", arg)
|
||||
})?))
|
||||
}
|
||||
ValType::I64 => {
|
||||
Ok(Val::I64(arg.parse().map_err(|_| {
|
||||
ValueType::I64 => {
|
||||
Ok(Value::I64(arg.parse().map_err(|_| {
|
||||
anyhow!("Can't convert `{}` into a i64", arg)
|
||||
})?))
|
||||
}
|
||||
ValType::F32 => {
|
||||
Ok(Val::F32(arg.parse().map_err(|_| {
|
||||
ValueType::F32 => {
|
||||
Ok(Value::F32(arg.parse().map_err(|_| {
|
||||
anyhow!("Can't convert `{}` into a f32", arg)
|
||||
})?))
|
||||
}
|
||||
ValType::F64 => {
|
||||
Ok(Val::F64(arg.parse().map_err(|_| {
|
||||
ValueType::F64 => {
|
||||
Ok(Value::F64(arg.parse().map_err(|_| {
|
||||
anyhow!("Can't convert `{}` into a f64", arg)
|
||||
})?))
|
||||
}
|
||||
@@ -397,7 +423,7 @@ impl Run {
|
||||
)),
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
Ok(func.call(&invoke_args)?)
|
||||
Ok(func.call(ctx, &invoke_args)?)
|
||||
}
|
||||
|
||||
/// Create Run instance for arguments/env,
|
||||
|
||||
@@ -2,8 +2,11 @@ use crate::utils::{parse_envvar, parse_mapdir};
|
||||
use anyhow::Result;
|
||||
use std::collections::BTreeSet;
|
||||
use std::path::PathBuf;
|
||||
use wasmer::{Instance, Module, RuntimeError, Val};
|
||||
use wasmer_wasi::{get_wasi_versions, is_wasix_module, WasiError, WasiState, WasiVersion};
|
||||
use wasmer::{AsContextMut, Context, Instance, Module, RuntimeError, Value};
|
||||
use wasmer_wasi::{
|
||||
get_wasi_versions, import_object_for_all_wasi_versions, is_wasix_module, WasiEnv, WasiError,
|
||||
WasiState, WasiVersion,
|
||||
};
|
||||
|
||||
use structopt::StructOpt;
|
||||
|
||||
@@ -78,7 +81,7 @@ impl Wasi {
|
||||
module: &Module,
|
||||
program_name: String,
|
||||
args: Vec<String>,
|
||||
) -> Result<Instance> {
|
||||
) -> Result<(Context<WasiEnv>, Instance)> {
|
||||
let args = args.iter().cloned().map(|arg| arg.into_bytes());
|
||||
|
||||
let mut wasi_state_builder = WasiState::new(program_name);
|
||||
@@ -96,19 +99,21 @@ impl Wasi {
|
||||
}
|
||||
}
|
||||
|
||||
let mut wasi_env = wasi_state_builder.finalize()?;
|
||||
let wasi_env = wasi_state_builder.finalize()?;
|
||||
wasi_env.state.fs.is_wasix.store(
|
||||
is_wasix_module(module),
|
||||
std::sync::atomic::Ordering::Release,
|
||||
);
|
||||
|
||||
let import_object = wasi_env.import_object_for_all_wasi_versions(module)?;
|
||||
let instance = Instance::new(module, &import_object)?;
|
||||
Ok(instance)
|
||||
let mut ctx = Context::new(module.store(), wasi_env.clone());
|
||||
let import_object = import_object_for_all_wasi_versions(&mut ctx.as_context_mut());
|
||||
let instance = Instance::new(&mut ctx, &module, &import_object)?;
|
||||
let memory = instance.exports.get_memory("memory")?;
|
||||
ctx.data_mut().set_memory(memory.clone());
|
||||
Ok((ctx, instance))
|
||||
}
|
||||
|
||||
/// Helper function for handling the result of a Wasi _start function.
|
||||
pub fn handle_result(&self, result: Result<Box<[Val]>, RuntimeError>) -> Result<()> {
|
||||
pub fn handle_result(&self, result: Result<Box<[Value]>, RuntimeError>) -> Result<()> {
|
||||
match result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => {
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::store::StoreOptions;
|
||||
use anyhow::{Context, Result};
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
use wasmer::Context as WasmerContext;
|
||||
use wasmer_wast::Wast as WastSpectest;
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
@@ -28,7 +29,8 @@ impl Wast {
|
||||
}
|
||||
fn inner_execute(&self) -> Result<()> {
|
||||
let (store, _compiler_name) = self.store.get_store()?;
|
||||
let mut wast = WastSpectest::new_with_spectest(store);
|
||||
let ctx = WasmerContext::new(&store, ());
|
||||
let mut wast = WastSpectest::new_with_spectest(ctx);
|
||||
wast.fail_fast = self.fail_fast;
|
||||
wast.run_file(&self.path).with_context(|| "tests failed")?;
|
||||
eprintln!("Wast tests succeeded for `{}`.", self.path.display());
|
||||
|
||||
@@ -17,12 +17,12 @@ pub fn exit_with_live_runtime(_ctx: ContextMut<'_, EmEnv>) {
|
||||
|
||||
pub fn setTempRet0(ctx: ContextMut<'_, EmEnv>, val: i32) {
|
||||
trace!("emscripten::setTempRet0: {}", val);
|
||||
get_emscripten_data(&ctx).temp_ret_0 = val;
|
||||
get_emscripten_data(&ctx).as_mut().unwrap().temp_ret_0 = val;
|
||||
}
|
||||
|
||||
pub fn getTempRet0(ctx: ContextMut<'_, EmEnv>) -> i32 {
|
||||
trace!("emscripten::getTempRet0");
|
||||
get_emscripten_data(&ctx).temp_ret_0
|
||||
get_emscripten_data(&ctx).as_ref().unwrap().temp_ret_0
|
||||
}
|
||||
|
||||
pub fn _alarm(_ctx: ContextMut<'_, EmEnv>, _seconds: u32) -> i32 {
|
||||
|
||||
2
lib/emscripten/src/env/mod.rs
vendored
2
lib/emscripten/src/env/mod.rs
vendored
@@ -45,7 +45,7 @@ pub fn call_memset(mut ctx: ContextMut<'_, EmEnv>, pointer: u32, value: u32, siz
|
||||
|
||||
pub(crate) fn get_emscripten_data<'a>(
|
||||
ctx: &'a ContextMut<'_, EmEnv>,
|
||||
) -> MutexGuard<'a, EmscriptenData> {
|
||||
) -> MutexGuard<'a, Option<EmscriptenData>> {
|
||||
ctx.data().data.lock().unwrap()
|
||||
}
|
||||
|
||||
|
||||
@@ -78,15 +78,22 @@ pub use self::utils::{
|
||||
/// The environment provided to the Emscripten imports.
|
||||
pub struct EmEnv {
|
||||
memory: Arc<RwLock<Option<Memory>>>,
|
||||
data: Arc<Mutex<EmscriptenData>>,
|
||||
data: Arc<Mutex<Option<EmscriptenData>>>,
|
||||
funcs: Arc<Mutex<EmscriptenFunctions>>,
|
||||
}
|
||||
|
||||
impl Default for EmEnv {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl EmEnv {
|
||||
pub fn new(data: &EmscriptenGlobalsData, mapped_dirs: HashMap<String, PathBuf>) -> Self {
|
||||
/// Create a new EmEnv, with default value to be set later (set_memory, set_functions and set_data)
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
memory: Arc::new(RwLock::new(None)),
|
||||
data: Arc::new(Mutex::new(EmscriptenData::new(data.clone(), mapped_dirs))),
|
||||
data: Arc::new(Mutex::new(None)),
|
||||
funcs: Arc::new(Mutex::new(EmscriptenFunctions::new())),
|
||||
}
|
||||
}
|
||||
@@ -105,11 +112,14 @@ impl EmEnv {
|
||||
self.funcs = Arc::new(Mutex::new(funcs));
|
||||
}
|
||||
|
||||
// pub fn init_with_instance(&mut self, instance: &Instance) -> Result<(), wasmer::HostEnvInitError> {
|
||||
// let mut ed = self.data.lock().unwrap();
|
||||
// ed.init_with_instance(instance)?;
|
||||
// Ok(())
|
||||
// }
|
||||
pub fn set_data(
|
||||
&mut self,
|
||||
data: &EmscriptenGlobalsData,
|
||||
mapped_dirs: HashMap<String, PathBuf>,
|
||||
) {
|
||||
let mut w = self.data.lock().unwrap();
|
||||
*w = Some(EmscriptenData::new(data.clone(), mapped_dirs));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
||||
@@ -88,7 +88,11 @@ pub fn sbrk(mut ctx: ContextMut<'_, EmEnv>, increment: i32) -> i32 {
|
||||
// let old_dynamic_top = 0;
|
||||
// let new_dynamic_top = 0;
|
||||
let memory = ctx.data().memory(0);
|
||||
let top_ptr = get_emscripten_data(&ctx).globals.dynamictop_ptr;
|
||||
let top_ptr = get_emscripten_data(&ctx)
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.globals
|
||||
.dynamictop_ptr;
|
||||
let dynamictop_ptr = WasmPtr::<i32>::new(top_ptr).deref(&ctx, &memory);
|
||||
let old_dynamic_top = dynamictop_ptr.read().unwrap();
|
||||
let new_dynamic_top: i32 = old_dynamic_top + increment;
|
||||
|
||||
@@ -1059,7 +1059,8 @@ pub fn ___syscall220(ctx: ContextMut<'_, EmEnv>, _which: i32, mut varargs: VarAr
|
||||
|
||||
let dirp = emscripten_memory_pointer!(ctx, ctx.data().memory(0), dirp_addr) as *mut u8;
|
||||
|
||||
let opened_dirs = &mut get_emscripten_data(&ctx).opened_dirs;
|
||||
let data = &mut get_emscripten_data(&ctx);
|
||||
let opened_dirs = &mut data.as_mut().unwrap().opened_dirs;
|
||||
|
||||
// need to persist stream across calls?
|
||||
// let dir: *mut libc::DIR = unsafe { libc::fdopendir(fd) };
|
||||
|
||||
@@ -258,6 +258,8 @@ pub fn get_cstr_path(ctx: ContextMut<'_, EmEnv>, path: *const i8) -> Option<std:
|
||||
for c in components.into_iter() {
|
||||
cumulative_path.push(c);
|
||||
if let Some(val) = data
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.mapped_dirs
|
||||
.get(&cumulative_path.to_string_lossy().to_string())
|
||||
{
|
||||
@@ -276,12 +278,19 @@ pub fn get_cstr_path(ctx: ContextMut<'_, EmEnv>, path: *const i8) -> Option<std:
|
||||
/// gets the current directory
|
||||
/// handles mapdir logic
|
||||
pub fn get_current_directory(ctx: ContextMut<'_, EmEnv>) -> Option<PathBuf> {
|
||||
if let Some(val) = get_emscripten_data(&ctx).mapped_dirs.get(".") {
|
||||
if let Some(val) = get_emscripten_data(&ctx)
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.mapped_dirs
|
||||
.get(".")
|
||||
{
|
||||
return Some(val.clone());
|
||||
}
|
||||
std::env::current_dir()
|
||||
.map(|cwd| {
|
||||
if let Some(val) = get_emscripten_data(&ctx)
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.mapped_dirs
|
||||
.get(&cwd.to_string_lossy().to_string())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user