1 #![no_std]
2 
3 #[macro_use]
4 extern crate alloc;
5 
6 use anyhow::Result;
7 use wasmtime::{Engine, Instance, Linker, Module, Store};
8 
9 mod allocator;
10 mod panic;
11 
12 /// Entrypoint of this embedding.
13 ///
14 /// This takes a number of parameters which are the precompiled module AOT
15 /// images that are run for each of the various tests below. The first parameter
16 /// is also where to put an error string, if any, if anything fails.
17 #[no_mangle]
18 pub unsafe extern "C" fn run(
19     error_buf: *mut u8,
20     error_size: usize,
21     smoke_module: *const u8,
22     smoke_size: usize,
23     simple_add_module: *const u8,
24     simple_add_size: usize,
25     simple_host_fn_module: *const u8,
26     simple_host_fn_size: usize,
27 ) -> usize {
28     let buf = core::slice::from_raw_parts_mut(error_buf, error_size);
29     let smoke = core::slice::from_raw_parts(smoke_module, smoke_size);
30     let simple_add = core::slice::from_raw_parts(simple_add_module, simple_add_size);
31     let simple_host_fn = core::slice::from_raw_parts(simple_host_fn_module, simple_host_fn_size);
32     match run_result(smoke, simple_add, simple_host_fn) {
33         Ok(()) => 0,
34         Err(e) => {
35             let msg = format!("{e:?}");
36             let len = buf.len().min(msg.len());
37             buf[..len].copy_from_slice(&msg.as_bytes()[..len]);
38             len
39         }
40     }
41 }
42 
43 fn run_result(
44     smoke_module: &[u8],
45     simple_add_module: &[u8],
46     simple_host_fn_module: &[u8],
47 ) -> Result<()> {
48     smoke(smoke_module)?;
49     simple_add(simple_add_module)?;
50     simple_host_fn(simple_host_fn_module)?;
51     Ok(())
52 }
53 
54 fn smoke(module: &[u8]) -> Result<()> {
55     let engine = Engine::default();
56     let module = unsafe { Module::deserialize(&engine, module)? };
57     Instance::new(&mut Store::new(&engine, ()), &module, &[])?;
58     Ok(())
59 }
60 
61 fn simple_add(module: &[u8]) -> Result<()> {
62     let engine = Engine::default();
63     let module = unsafe { Module::deserialize(&engine, module)? };
64     let mut store = Store::new(&engine, ());
65     let instance = Linker::new(&engine).instantiate(&mut store, &module)?;
66     let func = instance.get_typed_func::<(u32, u32), u32>(&mut store, "add")?;
67     assert_eq!(func.call(&mut store, (2, 3))?, 5);
68     Ok(())
69 }
70 
71 fn simple_host_fn(module: &[u8]) -> Result<()> {
72     let engine = Engine::default();
73     let module = unsafe { Module::deserialize(&engine, module)? };
74     let mut linker = Linker::<()>::new(&engine);
75     linker.func_wrap("host", "multiply", |a: u32, b: u32| a.saturating_mul(b))?;
76     let mut store = Store::new(&engine, ());
77     let instance = linker.instantiate(&mut store, &module)?;
78     let func = instance.get_typed_func::<(u32, u32, u32), u32>(&mut store, "add_and_mul")?;
79     assert_eq!(func.call(&mut store, (2, 3, 4))?, 10);
80     Ok(())
81 }
82