hermit_wasm/
lib.rs

1#![feature(thread_local)]
2#![feature(maybe_uninit_slice)]
3
4use std::ffi::OsString;
5use std::time::Instant;
6
7use anyhow::{Context, Result};
8#[cfg(target_os = "hermit")]
9use hermit as _;
10use log::debug;
11use wasmtime::*;
12
13#[cfg(target_os = "hermit")]
14mod arch;
15#[cfg(target_os = "hermit")]
16mod capi;
17#[cfg(target_os = "hermit")]
18mod preview1;
19
20pub fn run_preview1(
21	module_bytes: &[u8],
22	config: &wasmtime::Config,
23	#[allow(unused_variables)] module_and_args: &'static [OsString],
24) -> Result<()> {
25	let engine = Engine::new(config)?;
26	debug!("Wasmtime engine is configured as followed: {config:?}");
27
28	// TODO: dirty workaround to get the WebAssembly module into
29	// the VM. Find a way to inject the `.wasm` file into the VM
30	// using another way
31	debug!("Create Module");
32	let now = Instant::now();
33	let module = Module::new(&engine, module_bytes)?;
34	let elapsed = now.elapsed();
35	debug!("Time to create module: {} msec", elapsed.as_millis());
36
37	debug!("Create Linker");
38	#[allow(unused_mut)]
39	let mut linker = Linker::new(&engine);
40
41	#[cfg(target_os = "hermit")]
42	{
43		let mut imports = module.imports();
44		if imports.any(|i| i.module() == "wasi_snapshot_preview1") {
45			preview1::init(&mut linker, module_and_args)?;
46		}
47	}
48
49	// All wasm objects operate within the context of a "store". Each
50	// `Store` has a type parameter to store host-specific data, which in
51	// this case we're using `4` for.
52	let mut store = Store::new(&engine, 4);
53	let instance = linker.instantiate(&mut store, &module)?;
54
55	debug!("Try to find symbol _start");
56	let func = instance.get_func(&mut store, "_start").unwrap();
57
58	let ty = func.ty(&store);
59	if ty.params().len() > 0 {
60		panic!("Currently, _start should not receive arguments");
61	}
62
63	// Invoke the function and then afterwards print all the results that came
64	// out, if there are any.
65	let mut results = vec![Val::null_func_ref(); ty.results().len()];
66	let values = Vec::new();
67	let invoke_res = func
68		.call(&mut store, &values, &mut results)
69		.with_context(|| "failed to invoke command default".to_string());
70
71	debug!("Return value of entry point: {invoke_res:?}");
72
73	invoke_res
74}