Skip to content

Commit

Permalink
Merge #2999
Browse files Browse the repository at this point in the history
2999: Support --invoke option for emscripten files without _start function r=epilys a=fschutt

When running emscripten files, the CLI now supports the `--invoke` option to invoke a function by name.

# Review

- [x] Add a short description of the change to the CHANGELOG.md file


Co-authored-by: Felix Schütt <[email protected]>
  • Loading branch information
bors[bot] and fschutt authored Jul 12, 2022
2 parents e32ecdf + 2d4edee commit 7093d61
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 28 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Looking for changes that affect our C API? See the [C API Changelog](lib/c-api/C

### Changed
- [#3003](https://github.com/wasmerio/wasmer/pull/3003) Remove RuntimeError::raise from public API
- [#2999](https://github.com/wasmerio/wasmer/pull/2999) Allow `--invoke` CLI option for Emscripten files without a `main` function
- [#2946](https://github.com/wasmerio/wasmer/pull/2946) Remove dylib,staticlib engines in favor of a single Universal engine
- [#2949](https://github.com/wasmerio/wasmer/pull/2949) Switch back to using custom LLVM builds on CI

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ test-examples:
$(CARGO_BINARY) test $(CARGO_TARGET) --release $(compiler_features) --features wasi --examples

test-integration:
$(CARGO_BINARY) test $(CARGO_TARGET) -p wasmer-integration-tests-cli
$(CARGO_BINARY) test $(CARGO_TARGET) --no-fail-fast -p wasmer-integration-tests-cli

test-integration-ios:
$(CARGO_BINARY) test $(CARGO_TARGET) -p wasmer-integration-tests-ios
Expand Down
5 changes: 1 addition & 4 deletions lib/cli/src/commands/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,6 @@ impl Run {
};
// TODO: refactor this
if is_emscripten_module(&module) {
if self.invoke.is_some() {
bail!("--invoke is not supported with emscripten modules");
}
let mut emscripten_globals = EmscriptenGlobals::new(module.store(), &module)
.map_err(|e| anyhow!("{}", e))?;
let mut em_env = EmEnv::new(&emscripten_globals.data, Default::default());
Expand Down Expand Up @@ -137,7 +134,7 @@ impl Run {
self.path.to_str().unwrap()
},
self.args.iter().map(|arg| arg.as_str()).collect(),
None, //run.em_entrypoint.clone(),
self.invoke.clone(),
)?;
return Ok(());
}
Expand Down
70 changes: 47 additions & 23 deletions lib/emscripten/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ use std::f64;
use std::path::PathBuf;
use std::sync::{Arc, Mutex, RwLock};
use wasmer::{
imports, namespace, Exports, Function, FunctionType, Global, Imports, Instance, LazyInit,
Memory, MemoryType, Module, Pages, RuntimeError, Store, Table, TableType, TypedFunction, Val,
ValType, WasmPtr, WasmerEnv,
imports, namespace, ExportError, Exports, Function, FunctionType, Global, Imports, Instance,
LazyInit, Memory, MemoryType, Module, Pages, RuntimeError, Store, Table, TableType,
TypedFunction, Val, ValType, WasmPtr, WasmerEnv,
};

#[cfg(unix)]
Expand Down Expand Up @@ -313,24 +313,51 @@ pub fn set_up_emscripten(instance: &mut Instance) -> Result<(), RuntimeError> {
Ok(())
}

/// Looks for variations of the main function (usually
/// `["_main", "main"])`, then returns a reference to
/// the name of the first found function. Useful for
/// determining whether a module is executable.
///
/// Returns `ExportError` if none of the `main_func_names`
/// were found.
pub fn emscripten_get_main_func_name<'a>(
instance: &Instance,
main_func_names: &[&'a str],
) -> Result<&'a str, ExportError> {
let mut last_err = None;

for func_name in main_func_names.iter() {
match instance.exports.get::<Function>(func_name) {
Ok(_) => {
return Ok(func_name);
}
Err(e) => {
last_err = Some(e);
}
}
}

match last_err {
None => Err(ExportError::Missing(format!("{main_func_names:?}"))),
Some(e) => Err(e),
}
}

/// Call the main function in emscripten, assumes that the emscripten state is
/// set up.
///
/// If you don't want to set it up yourself, consider using [`run_emscripten_instance`].
pub fn emscripten_call_main(
instance: &mut Instance,
function_name: &str,
env: &EmEnv,
path: &str,
args: &[&str],
) -> Result<(), RuntimeError> {
let (function_name, main_func) = match instance.exports.get::<Function>("_main") {
Ok(func) => Ok(("_main", func)),
Err(_e) => instance
.exports
.get::<Function>("main")
.map(|func| ("main", func)),
}
.map_err(|e| RuntimeError::new(e.to_string()))?;
let main_func = instance
.exports
.get::<Function>(function_name)
.map_err(|e| RuntimeError::new(e.to_string()))?;
let num_params = main_func.ty().params().len();
let _result = match num_params {
2 => {
Expand Down Expand Up @@ -373,19 +400,16 @@ pub fn run_emscripten_instance(
env.set_memory(globals.memory.clone());
set_up_emscripten(instance)?;

// println!("running emscripten instance");

if let Some(ep) = entrypoint {
debug!("Running entry point: {}", &ep);
let arg = unsafe { allocate_cstr_on_stack(env, args[0]).0 };
//let (argc, argv) = store_module_arguments(instance.context_mut(), args);
let func: &Function = instance
.exports
.get(&ep)
.map_err(|e| RuntimeError::new(e.to_string()))?;
func.call(&[Val::I32(arg as i32)])?;
let main_func_names = ["_main", "main"];
if let Some(ep) = entrypoint.as_ref() {
debug!("Running entry point: {}", ep);
emscripten_call_main(instance, ep, env, path, &args)?;
} else if let Ok(name) = emscripten_get_main_func_name(instance, &main_func_names) {
emscripten_call_main(instance, name, env, path, &args)?;
} else {
emscripten_call_main(instance, env, path, &args)?;
return Err(RuntimeError::new(format!(
"No main function found (searched: {main_func_names:?}) and no entrypoint specified"
)));
}

// TODO atexit for emscripten
Expand Down

0 comments on commit 7093d61

Please sign in to comment.