1#![no_std]
2#[doc(hidden)]
3pub extern crate alloc;
4use alloc::borrow::ToOwned;
5use alloc::string::String;
6use alloc::sync::Arc;
7use alloc::vec;
8use alloc::format;
9use alloc::vec::Vec;
10use core::{
11 cell::UnsafeCell,
12 iter::{empty, once},
13};
14
15use pit_core::{Arg, Interface};
16use wasm_runtime_layer::{
17 backend::WasmEngine, AsContext, AsContextMut, Extern, ExternRef, Func, FuncType, Imports,
18 Instance, Module, Store, StoreContext, StoreContextMut, Value, ValueType,
19};
20pub fn init<U: AsRef<Instance> + 'static, E: WasmEngine>(
21 l: &mut Imports,
22 ctx: &mut impl AsContextMut<UserState = U, Engine = E>,
23) {
24 l.define(
25 "pit",
26 "drop",
27 Extern::Func(Func::new(
28 &mut *ctx,
29 FuncType::new(once(ValueType::ExternRef), empty()),
30 move |mut ctx, args, rets| {
31 let Value::ExternRef(Some(a)) = args[0].clone() else {
32 anyhow::bail!("invalid type")
33 };
34 let Ok(x): Result<&Wrapped<U, E>, anyhow::Error> =
35 a.downcast::<'_, '_, Wrapped<U, E>, U, E>(ctx.as_context())
36 else {
37 return Ok(());
38 };
39 let f = x.all[0].clone();
40 f(ctx.as_context_mut(), vec![])?;
41 Ok(())
42 },
43 )),
44 );
45}
46pub fn emit_ty(a: &Arg) -> ValueType {
47 match a {
48 Arg::I32 => ValueType::I32,
49 Arg::I64 => ValueType::I64,
50 Arg::F32 => ValueType::F32,
51 Arg::F64 => ValueType::F64,
52 Arg::Resource {
53 ty,
54 nullable,
55 take,
56 ann,
57 } => ValueType::ExternRef,
58 _ => todo!(), }
60}
61pub fn emit<U: AsRef<Instance> + 'static, E: WasmEngine>(
62 l: &mut Imports,
63 rid: Arc<Interface>,
64 m: &Module,
65 ctx: &mut impl AsContextMut<UserState = U, Engine = E>,
66) {
67 let n = format!("pit/{}", rid.rid_str());
68 for (j, (i, m)) in rid.methods.iter().enumerate() {
69 l.define(
70 &n,
71 i.as_str(),
72 Extern::Func(Func::new(
73 &mut *ctx,
74 FuncType::new(
75 once(ValueType::ExternRef).chain(m.params.iter().map(emit_ty)),
76 m.rets.iter().map(emit_ty),
77 ),
78 move |mut ctx, args, rets| {
79 let Value::ExternRef(Some(a)) = args[0].clone() else {
80 anyhow::bail!("invalid type")
81 };
82 let x: &Wrapped<U, E> = a.downcast(ctx.as_context())?;
83 let t = x.all[j + 1].clone();
84 let rets2 = t(ctx.as_context_mut(), args[1..].iter().cloned().collect())?;
85 for (r, s) in rets2.into_iter().zip(rets.iter_mut()) {
86 *s = r;
87 }
88 Ok(())
89 },
90 )),
91 )
92 }
93 let i = m
94 .imports(ctx.as_context().engine())
95 .map(|a| (a.module.to_owned(), a.name.to_owned()))
96 .collect::<Vec<_>>();
97 for i in i {
98 if i.0 == n {
99 if let Some(t) = i.1.strip_prefix("~") {
100 let t = t.to_owned();
101 let rid = rid.clone();
102 l.define(
103 &n,
104 &i.1,
105 Extern::Func(Func::new(
106 &mut *ctx,
107 FuncType::new(once(ValueType::I32), once(ValueType::ExternRef)),
108 move |mut ctx, args, rets| {
109 let i = ctx.data().as_ref().clone();
110 let object = Wrapped::new(
111 args.to_owned(),
112 rid.clone(),
113 t.to_owned(),
114 i,
115 ctx.as_context_mut(),
116 );
117 rets[0] = Value::ExternRef(Some(ExternRef::new(ctx, object)));
118 Ok(())
119 },
120 )),
121 )
122 };
123 };
124 }
125}
126pub struct Wrapped<U: 'static, E: wasm_runtime_layer::backend::WasmEngine> {
127 pub rid: Arc<Interface>,
128 pub all: Vec<
129 Arc<
130 dyn Fn(StoreContextMut<'_, U, E>, Vec<Value>) -> anyhow::Result<Vec<Value>>
131 + Send
132 + Sync,
133 >,
134 >,
135 }
137impl<U: 'static, E: wasm_runtime_layer::backend::WasmEngine> Wrapped<U, E> {
138 pub fn new(
139 base: Vec<wasm_runtime_layer::Value>,
140 rid: Arc<Interface>,
141 rs: String,
142 instance: ::wasm_runtime_layer::Instance,
143 store: ::wasm_runtime_layer::StoreContextMut<'_, U, E>,
144 ) -> Self {
145 let rid2 = rid.clone();
150 let instance2 = instance.clone();
151 let rs2 = rs.clone();
153 let base2 = base.clone();
154 return Self {
155 rid: rid.clone(),
156 all: once(Arc::new(
157 move |mut ctx: StoreContextMut<'_, U, E>,
158 vals: Vec<Value>|
159 -> anyhow::Result<Vec<Value>> {
160 let vals: Vec<_> = base.clone().into_iter().chain(vals.into_iter()).collect();
163 let mut rets = vec![];
164 let f = instance2.get_export(
165 ctx.as_context_mut(),
166 &format!("pit/{}/~{rs2}.drop", rid2.rid_str()),
167 );
168 let Some(Extern::Func(f)) = f else {
169 anyhow::bail!("invalid func")
170 };
171 f.call(ctx.as_context_mut(), &vals, &mut rets)?;
172 Ok(rets)
173 },
174 )
175 as Arc<
176 dyn Fn(StoreContextMut<'_, U, E>, Vec<Value>) -> anyhow::Result<Vec<Value>>
177 + Send
178 + Sync,
179 >)
180 .chain(rid.methods.iter().map(|(a, b)| {
181 let rid = rid.clone();
182 let a = a.clone();
183 let instance = instance.clone();
184 let b = Arc::new(b.clone());
185 let rs = rs.clone();
187 let base = base2.clone();
188 (Arc::new(
189 move |mut ctx: StoreContextMut<'_, U, E>,
190 vals: Vec<Value>|
191 -> anyhow::Result<Vec<Value>> {
192 let vals: Vec<_> =
195 base.clone().into_iter().chain(vals.into_iter()).collect();
196 let mut rets = vec![Value::I32(0); b.rets.len()];
197 let f = instance.get_export(
198 ctx.as_context_mut(),
199 &format!("pit/{}/~{rs}/{a}", rid.rid_str()),
200 );
201 let Some(Extern::Func(f)) = f else {
202 anyhow::bail!("invalid func")
203 };
204 f.call(ctx.as_context_mut(), &vals, &mut rets)?;
205 Ok(rets)
206 },
207 )
208 as Arc<
209 dyn Fn(StoreContextMut<'_, U, E>, Vec<Value>) -> anyhow::Result<Vec<Value>>
210 + Send
211 + Sync,
212 >)
213 }))
214 .collect(),
215 };
216 }
217}
218pub type RWrapped<U, E> = ::alloc::sync::Arc<Wrapped<U, E>>;
224pub extern crate anyhow;
225pub extern crate wasm_runtime_layer;
226
227pub struct W<X, U: 'static, E: WasmEngine> {
228 pub r: X,
229 pub store: Arc<StoreCell<U, E>>,
230}
231impl<U: 'static, E: WasmEngine, X: Clone> Clone for W<X, U, E> {
232 fn clone(&self) -> Self {
233 Self {
234 r: self.r.clone(),
235 store: self.store.clone(),
236 }
237 }
238}
239pub struct StoreCell<U, E: WasmEngine> {
240 pub wrapped: UnsafeCell<Store<U, E>>,
241}
242unsafe impl<
243 U: Send,
244 E: Send + wasm_runtime_layer::backend::WasmEngine + wasm_runtime_layer::backend::WasmEngine,
245 > Send for StoreCell<U, E>
246{
247}
248unsafe impl<
249 U: Sync,
250 E: Sync + wasm_runtime_layer::backend::WasmEngine + wasm_runtime_layer::backend::WasmEngine,
251 > Sync for StoreCell<U, E>
252{
253}
254impl<U, E: WasmEngine> StoreCell<U, E> {
255 pub unsafe fn get(&self) -> StoreContextMut<'_, U, E> {
256 unsafe { &mut *self.wrapped.get() }.as_context_mut()
257 }
258}