1 #![no_std]
2 
3 #[macro_use]
4 extern crate alloc;
5 
6 use alloc::string::ToString;
7 use anyhow::Result;
8 use wasmtime::{Engine, Instance, Linker, Module, Store};
9 
10 mod allocator;
11 mod panic;
12 
13 #[cfg(feature = "wasi")]
14 mod wasi;
15 
16 /// Entrypoint of this embedding.
17 ///
18 /// This takes a number of parameters which are the precompiled module AOT
19 /// images that are run for each of the various tests below. The first parameter
20 /// is also where to put an error string, if any, if anything fails.
21 #[unsafe(no_mangle)]
22 pub unsafe extern "C" fn run(
23     error_buf: *mut u8,
24     error_size: usize,
25     smoke_module: *const u8,
26     smoke_size: usize,
27     simple_add_module: *const u8,
28     simple_add_size: usize,
29     simple_host_fn_module: *const u8,
30     simple_host_fn_size: usize,
31 ) -> usize {
32     let buf = core::slice::from_raw_parts_mut(error_buf, error_size);
33     let smoke = core::slice::from_raw_parts(smoke_module, smoke_size);
34     let simple_add = core::slice::from_raw_parts(simple_add_module, simple_add_size);
35     let simple_host_fn = core::slice::from_raw_parts(simple_host_fn_module, simple_host_fn_size);
36     match run_result(smoke, simple_add, simple_host_fn) {
37         Ok(()) => 0,
38         Err(e) => {
39             let msg = format!("{e:?}");
40             let len = buf.len().min(msg.len());
41             buf[..len].copy_from_slice(&msg.as_bytes()[..len]);
42             len
43         }
44     }
45 }
46 
47 fn run_result(
48     smoke_module: &[u8],
49     simple_add_module: &[u8],
50     simple_host_fn_module: &[u8],
51 ) -> Result<()> {
52     smoke(smoke_module)?;
53     simple_add(simple_add_module)?;
54     simple_host_fn(simple_host_fn_module)?;
55     Ok(())
56 }
57 
58 fn smoke(module: &[u8]) -> Result<()> {
59     let engine = Engine::default();
60     let module = match deserialize(&engine, module)? {
61         Some(module) => module,
62         None => return Ok(()),
63     };
64     Instance::new(&mut Store::new(&engine, ()), &module, &[])?;
65     Ok(())
66 }
67 
68 fn simple_add(module: &[u8]) -> Result<()> {
69     let engine = Engine::default();
70     let module = match deserialize(&engine, module)? {
71         Some(module) => module,
72         None => return Ok(()),
73     };
74     let mut store = Store::new(&engine, ());
75     let instance = Linker::new(&engine).instantiate(&mut store, &module)?;
76     let func = instance.get_typed_func::<(u32, u32), u32>(&mut store, "add")?;
77     assert_eq!(func.call(&mut store, (2, 3))?, 5);
78     Ok(())
79 }
80 
81 fn simple_host_fn(module: &[u8]) -> Result<()> {
82     let engine = Engine::default();
83     let module = match deserialize(&engine, module)? {
84         Some(module) => module,
85         None => return Ok(()),
86     };
87     let mut linker = Linker::<()>::new(&engine);
88     linker.func_wrap("host", "multiply", |a: u32, b: u32| a.saturating_mul(b))?;
89     let mut store = Store::new(&engine, ());
90     let instance = linker.instantiate(&mut store, &module)?;
91     let func = instance.get_typed_func::<(u32, u32, u32), u32>(&mut store, "add_and_mul")?;
92     assert_eq!(func.call(&mut store, (2, 3, 4))?, 10);
93     Ok(())
94 }
95 
96 fn deserialize(engine: &Engine, module: &[u8]) -> Result<Option<Module>> {
97     match unsafe { Module::deserialize(engine, module) } {
98         Ok(module) => Ok(Some(module)),
99         Err(e) => {
100             // Currently if custom signals/virtual memory are disabled then this
101             // example is expected to fail to load since loading native code
102             // requires virtual memory. In the future this will go away as when
103             // signals-based-traps is disabled then that means that the
104             // interpreter should be used which should work here.
105             if !cfg!(feature = "custom")
106                 && e.to_string()
107                     .contains("requires virtual memory to be enabled")
108             {
109                 Ok(None)
110             } else {
111                 Err(e)
112             }
113         }
114     }
115 }
116