From 28760e867e3347fc7a6afc77bdc5bf82c3c1076d Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Sun, 11 Aug 2024 20:39:53 -0400 Subject: [PATCH] stuff --- Cargo.lock | 5 + Cargo.toml | 2 +- pit-basic/src/buffer/ffi.rs | 63 ++--- pit-basic/src/buffer64/ffi.rs | 63 ++--- pit-patch/src/util.rs | 423 ++++++++++++++++++++++++++++++++- pit-rust-generator/src/main.rs | 1 + pit-rust-guest/src/lib.rs | 262 +++++++++++++++----- pit-rust-host-lib/src/lib.rs | 26 +- pit-rust-host/Cargo.toml | 1 + pit-rust-host/src/lib.rs | 345 +++++++++++++++++++-------- tpit-rt/Cargo.toml | 6 + tpit-rt/src/lib.rs | 58 +++++ 12 files changed, 1017 insertions(+), 238 deletions(-) create mode 100644 tpit-rt/Cargo.toml create mode 100644 tpit-rt/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d4f7a2f..a3af4fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -626,6 +626,7 @@ version = "0.1.0" dependencies = [ "hex", "pit-core", + "pit-rust-guest", "proc-macro2", "quasiquote", "quote", @@ -970,6 +971,10 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "tpit-rt" +version = "0.1.0" + [[package]] name = "twox-hash" version = "1.6.3" diff --git a/Cargo.toml b/Cargo.toml index ab20354..288d40d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members=[ "pit-basic","pit-core", "pit-patch", "pit-rust-externref", "pit-rust-generator", "pit-rust-guest", "pit-rust-host", "pit-rust-host-lib"] +members=[ "pit-basic","pit-core", "pit-patch", "pit-rust-externref", "pit-rust-generator", "pit-rust-guest", "pit-rust-host", "pit-rust-host-lib", "tpit-rt"] resolver="2" [workspace.dependencies] diff --git a/pit-basic/src/buffer/ffi.rs b/pit-basic/src/buffer/ffi.rs index ec941dd..1b0f28f 100644 --- a/pit-basic/src/buffer/ffi.rs +++ b/pit-basic/src/buffer/ffi.rs @@ -67,6 +67,28 @@ const _: () = { 125u8, 0u8, ]; + fn alloc(m: &mut ::std::collections::BTreeMap, x: T) -> u32 { + let mut u = 0; + while m.contains_key(&u) { + u += 1; + } + m.insert(u, x); + return u; + } + #[derive(Default)] + struct TableCell { + all: std::cell::UnsafeCell< + ::std::collections::BTreeMap< + u32, + Box< + dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5, + >, + >, + >, + } + unsafe impl Send for TableCell {} + unsafe impl Sync for TableCell {} + static TABLE: ::std::sync::LazyLock = ::std::sync::LazyLock::new(|| TableCell::default()); impl R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5 for ::externref::Resource< Box, @@ -128,42 +150,23 @@ const _: () = { } #[::externref::externref(crate = ":: externref")] #[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e.drop"] - extern "C" fn _drop( - a: *mut Box< - dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5, - >, - ) { - unsafe { Box::from_raw(a) }; + extern "C" fn _drop(a: u32) { + unsafe { (&mut *(TABLE.all.get())).remove(&a) }; } #[::externref::externref(crate = ":: externref")] #[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/read8"] - extern "C" fn read8( - id: *mut Box< - dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5, - >, - p0: u32, - ) -> (u32) { - return unsafe { &mut *id }.read8(p0); + extern "C" fn read8(id: u32, p0: u32) -> (u32) { + return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().read8(p0); } #[::externref::externref(crate = ":: externref")] #[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/size"] - extern "C" fn size( - id: *mut Box< - dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5, - >, - ) -> (u32) { - return unsafe { &mut *id }.size(); + extern "C" fn size(id: u32) -> (u32) { + return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().size(); } #[::externref::externref(crate = ":: externref")] #[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/write8"] - extern "C" fn write8( - id: *mut Box< - dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5, - >, - p0: u32, - p1: u32, - ) -> () { - return unsafe { &mut *id }.write8(p0, p1); + extern "C" fn write8(id: u32, p0: u32, p1: u32) -> () { + return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().write8(p0, p1); } impl From> for ::externref::Resource< @@ -179,16 +182,14 @@ const _: () = { extern "C" { #[link_name = "~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e"] fn _push( - a: *mut Box< - dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5, - >, + a: u32, ) -> ::externref::Resource< Box< dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5, >, >; } - return unsafe { _push(Box::into_raw(Box::new(a))) }; + return unsafe { _push(alloc(&mut *(TABLE.all.get()), a)) }; } } }; diff --git a/pit-basic/src/buffer64/ffi.rs b/pit-basic/src/buffer64/ffi.rs index f7c790d..2d44b06 100644 --- a/pit-basic/src/buffer64/ffi.rs +++ b/pit-basic/src/buffer64/ffi.rs @@ -67,6 +67,28 @@ const _: () = { 125u8, 0u8, ]; + fn alloc(m: &mut ::std::collections::BTreeMap, x: T) -> u32 { + let mut u = 0; + while m.contains_key(&u) { + u += 1; + } + m.insert(u, x); + return u; + } + #[derive(Default)] + struct TableCell { + all: std::cell::UnsafeCell< + ::std::collections::BTreeMap< + u32, + Box< + dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d, + >, + >, + >, + } + unsafe impl Send for TableCell {} + unsafe impl Sync for TableCell {} + static TABLE: ::std::sync::LazyLock = ::std::sync::LazyLock::new(|| TableCell::default()); impl R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d for ::externref::Resource< Box, @@ -128,42 +150,23 @@ const _: () = { } #[::externref::externref(crate = ":: externref")] #[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9.drop"] - extern "C" fn _drop( - a: *mut Box< - dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d, - >, - ) { - unsafe { Box::from_raw(a) }; + extern "C" fn _drop(a: u32) { + unsafe { (&mut *(TABLE.all.get())).remove(&a) }; } #[::externref::externref(crate = ":: externref")] #[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/read8"] - extern "C" fn read8( - id: *mut Box< - dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d, - >, - p0: u64, - ) -> (u32) { - return unsafe { &mut *id }.read8(p0); + extern "C" fn read8(id: u32, p0: u64) -> (u32) { + return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().read8(p0); } #[::externref::externref(crate = ":: externref")] #[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/size"] - extern "C" fn size( - id: *mut Box< - dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d, - >, - ) -> (u64) { - return unsafe { &mut *id }.size(); + extern "C" fn size(id: u32) -> (u64) { + return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().size(); } #[::externref::externref(crate = ":: externref")] #[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/write8"] - extern "C" fn write8( - id: *mut Box< - dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d, - >, - p0: u64, - p1: u32, - ) -> () { - return unsafe { &mut *id }.write8(p0, p1); + extern "C" fn write8(id: u32, p0: u64, p1: u32) -> () { + return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().write8(p0, p1); } impl From> for ::externref::Resource< @@ -179,16 +182,14 @@ const _: () = { extern "C" { #[link_name = "~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9"] fn _push( - a: *mut Box< - dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d, - >, + a: u32, ) -> ::externref::Resource< Box< dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d, >, >; } - return unsafe { _push(Box::into_raw(Box::new(a))) }; + return unsafe { _push(alloc(&mut *(TABLE.all.get()), a)) }; } } }; diff --git a/pit-patch/src/util.rs b/pit-patch/src/util.rs index 2460dc7..111c1a0 100644 --- a/pit-patch/src/util.rs +++ b/pit-patch/src/util.rs @@ -1,10 +1,15 @@ -use std::collections::BTreeMap; - -use waffle::{ - util::new_sig, BlockTarget, Func, FunctionBody, Import, ImportKind, Module, Operator, - SignatureData, Table, Type, +use std::{ + collections::{BTreeMap, BTreeSet}, iter::once, mem::{replace, take} }; -use waffle_ast::{add_op, Builder, Expr}; + +use anyhow::Context; +use pit_core::{Arg, ResTy}; +use waffle::{ + util::new_sig, Block, BlockTarget, Export, ExportKind, Func, FuncDecl, FunctionBody, Import, ImportKind, Module, Operator, SignatureData, Table, TableData, Type, Value +}; +use waffle_ast::{add_op, results_ref_2, Builder, Expr}; + +use crate::get_interfaces; pub fn talloc(m: &mut Module, t: Table) -> anyhow::Result { let e = m.tables[t].ty.clone(); @@ -189,3 +194,409 @@ pub fn waffle_funcs(m: &mut Module, i: &pit_core::Interface) -> BTreeMap anyhow::Result<(Value, Block)> { + let Arg::Resource { + ty, + nullable, + take, + ann, + } = r + else { + return Ok((v, k)); + }; + let end = f.add_block(); + let ep = f.add_blockparam(end, if retref { Type::ExternRef } else { Type::I32 }); + // if *nullable { + let s = if retref { + let a = add_op(f, &[], &[Type::I32], Operator::I32Const { value: 0 }); + f.append_to_block(k, a); + let a = add_op(f, &[a, v], &[Type::I32], Operator::I32Eq); + f.append_to_block(k, a); + a + } else { + let a = add_op(f, &[v], &[Type::I32], Operator::RefIsNull); + f.append_to_block(k, a); + a + }; + let n = f.add_block(); + if retref { + let a = add_op( + f, + &[], + &[Type::ExternRef], + Operator::RefNull { + ty: Type::ExternRef, + }, + ); + f.append_to_block(n, a); + f.set_terminator( + n, + waffle::Terminator::Br { + target: BlockTarget { + block: end, + args: vec![a], + }, + }, + ) + } else { + let a = add_op(f, &[], &[Type::I32], Operator::I32Const { value: 0 }); + f.append_to_block(n, a); + f.set_terminator( + n, + waffle::Terminator::Br { + target: BlockTarget { + block: end, + args: vec![a], + }, + }, + ) + } + let kk = f.add_block(); + f.set_terminator( + k, + waffle::Terminator::CondBr { + cond: s, + if_true: BlockTarget { + block: n, + args: vec![], + }, + if_false: BlockTarget { + block: kk, + args: vec![], + }, + }, + ); + k = kk; + if retref { + let a = add_op(f, &[], &[Type::I32], Operator::I32Const { value: 1 }); + f.append_to_block(k, a); + let a = add_op(f, &[v, a], &[Type::I32], Operator::I32Sub); + f.append_to_block(k, a); + v = a; + } + // } + + match (take, retref) { + (true, true) => { + v = add_op( + f, + &[v], + &[Type::ExternRef], + Operator::Call { + function_index: tfree, + }, + ); + f.append_to_block(k, v); + } + (_, false) => { + v = add_op( + f, + &[v], + &[Type::I32], + Operator::Call { + function_index: talloc, + }, + ); + f.append_to_block(k, v); + } + (false, true) => { + v = add_op( + f, + &[v], + &[Type::ExternRef], + Operator::TableGet { table_index: table }, + ); + f.append_to_block(k, v); + } + } + if !retref { + let a = add_op(f, &[], &[Type::I32], Operator::I32Const { value: 1 }); + f.append_to_block(k, a); + let a = add_op(f, &[v, a], &[Type::I32], Operator::I32Add); + f.append_to_block(k, a); + v = a; + } + f.set_terminator( + k, + waffle::Terminator::Br { + target: BlockTarget { + block: end, + args: vec![v], + }, + }, + ); + Ok((ep, end)) +} +pub fn wrap(m: &mut Module) -> anyhow::Result<()> { + let t = m.tables.push(TableData{ty: Type::ExternRef, initial: 0, max: None, func_elements: None}); + let talloc = talloc(m, t)?; + let tfree = tfree(m, t)?; + let is = get_interfaces(m)?.into_iter().collect::>(); + for mut import in take(&mut m.imports) { + if import.module == "tpit" && import.name == "void" { + if let ImportKind::Func(f) = &mut import.kind { + let s = m.funcs[*f].sig(); + let o = *f; + let mut b = FunctionBody::new(&m, s); + let e = b.entry; + let arg = b.blocks[b.entry].params[0].1; + let arg = add_op( + &mut b, + &[arg], + &[Type::ExternRef], + Operator::Call { + function_index: tfree, + }, + ); + b.append_to_block(e, arg); + b.set_terminator(e, waffle::Terminator::Return { values: vec![] }); + m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b); + } + continue; + } + if import.module == "tpit" && import.name == "clone" { + if let ImportKind::Func(f) = &mut import.kind { + let s = m.funcs[*f].sig(); + let o = *f; + let mut b = FunctionBody::new(&m, s); + let e = b.entry; + let arg = b.blocks[b.entry].params[0].1; + let arg = add_op( + &mut b, + &[arg], + &[Type::ExternRef], + Operator::TableGet { table_index: t }, + ); + b.append_to_block(e, arg); + b.set_terminator( + e, + waffle::Terminator::ReturnCall { + func: talloc, + args: vec![arg], + }, + ); + m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b); + } + continue; + } + if import.module == "tpit" && import.name == "drop" { + import.module = format!("pit"); + let p = new_sig( + m, + SignatureData { + params: vec![Type::I32], + returns: vec![], + }, + ); + let p = m.funcs.push(waffle::FuncDecl::Import(p, format!("_pit"))); + if let ImportKind::Func(f) = &mut import.kind { + let s = m.funcs[*f].sig(); + let o = replace(f, p); + let mut b = FunctionBody::new(&m, s); + let e = b.entry; + let arg = b.blocks[b.entry].params[0].1; + let arg = add_op( + &mut b, + &[arg], + &[Type::ExternRef], + Operator::Call { + function_index: tfree, + }, + ); + b.append_to_block(e, arg); + b.set_terminator( + e, + waffle::Terminator::ReturnCall { + func: p, + args: vec![arg], + }, + ); + m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b); + } + } + m.imports.push(import); + } + for i in is { + let f = waffle_funcs(m, &i); + for mut import in take(&mut m.imports) { + if import.module == format!("tpit/{}", i.rid_str()) { + match import.name.strip_prefix("~") { + Some(a) => { + let p = new_sig( + m, + SignatureData { + params: vec![Type::I32], + returns: vec![Type::ExternRef], + }, + ); + let p = m.funcs.push(waffle::FuncDecl::Import(p, format!("_pit"))); + if let ImportKind::Func(f) = &mut import.kind { + let s = m.funcs[*f].sig(); + let o = replace(f, p); + let mut b = FunctionBody::new(&m, s); + let e = b.entry; + let arg = b.blocks[b.entry].params[0].1; + let arg = add_op( + &mut b, + &[arg], + &[Type::ExternRef], + Operator::Call { function_index: p }, + ); + b.append_to_block(e, arg); + b.set_terminator( + e, + waffle::Terminator::ReturnCall { + func: talloc, + args: vec![arg], + }, + ); + m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b); + } + } + None => { + let x = i + .methods + .get(&import.name) + .context("in getting the method")?; + let p = to_waffle_sig(m, x); + let p = m.signatures[p].clone(); + let p = new_sig( + m, + SignatureData { + params: vec![Type::I32] + .into_iter() + .chain(p.params.into_iter().map(|a| { + if a == Type::ExternRef { + Type::I32 + } else { + a + } + })) + .collect(), + returns: p + .returns + .into_iter() + .map(|a| if a == Type::ExternRef { Type::I32 } else { a }) + .collect(), + }, + ); + let p = m.funcs.push(waffle::FuncDecl::Import(p, format!("_pit"))); + if let ImportKind::Func(f) = &mut import.kind { + let s = m.funcs[*f].sig(); + let o = replace(f, p); + let mut b = FunctionBody::new(&m, s); + let mut k = b.entry; + let args = b.blocks[b.entry] + .params + .iter() + .map(|a| a.1) + .collect::>() + .into_iter() + .zip(once(Arg::Resource { ty: ResTy::This, nullable: false, take: false, ann: vec![] }).chain(x.params.iter().cloned())); + let mut v2 = vec![]; + for (v, r) in args { + let a; + (a, k) = shim(false, &mut b, k, &r, v, talloc, tfree, t)?; + v2.push(a); + } + let rets = add_op( + &mut b, + &v2, + &m.signatures[m.funcs[p].sig()].returns, + Operator::Call { function_index: p }, + ); + b.append_to_block(k, rets); + let rets = results_ref_2(&mut b, rets); + let mut r2 = vec![]; + for (v, r) in rets.iter().cloned().zip(x.rets.iter()) { + let a; + (a, k) = shim(true, &mut b, k, r, v, talloc, tfree, t)?; + r2.push(a); + } + b.set_terminator(k, waffle::Terminator::Return { values: r2 }); + m.funcs[o] = FuncDecl::Body(s, format!("_pit"), b); + } + } + } + import.module = format!("pit/{}", i.rid_str()); + } + m.imports.push(import) + } + for mut export in take(&mut m.exports) { + if let Some(a) = export.name.strip_prefix(&format!("tpit/{}/~", i.rid_str())) { + let a = a.to_owned(); + export.name = format!("pit/{}/~{a}", i.rid_str()); + match a.split_once("/") { + None => { + let b = a.strip_suffix(".drop").context("in egtting the drop")?; + } + Some((a, b)) => { + let x = i.methods.get(b).context("in getting the method")?; + let p = to_waffle_sig(m, x); + let p = m.signatures[p].clone(); + let p = new_sig( + m, + SignatureData { + params: vec![Type::I32] + .into_iter() + .chain(p.params.into_iter()) + .collect(), + returns: p.returns.into_iter().collect(), + }, + ); + // let p = m.funcs.push(waffle::FuncDecl::Import(p, format!("_pit"))); + if let ExportKind::Func(f) = &mut export.kind { + let s = m.funcs[*f].sig(); + let p = *f; + let mut b = FunctionBody::new(&m, s); + let mut k = b.entry; + let args = b.blocks[b.entry] + .params + .iter() + .map(|a| a.1) + .collect::>() + .into_iter() + .zip(once(Arg::I32).chain(x.params.iter().cloned())); + let mut v2 = vec![]; + for (v, r) in args { + let a; + (a, k) = shim(true, &mut b, k, &r, v, talloc, tfree, t)?; + v2.push(a); + } + let rets = add_op( + &mut b, + &v2, + &m.signatures[m.funcs[p].sig()].returns, + Operator::Call { function_index: p }, + ); + b.append_to_block(k, rets); + let rets = results_ref_2(&mut b, rets); + let mut r2 = vec![]; + for (v, r) in rets.iter().cloned().zip(x.rets.iter()) { + let a; + (a, k) = shim(false, &mut b, k, r, v, talloc, tfree, t)?; + r2.push(a); + } + b.set_terminator(k, waffle::Terminator::Return { values: r2 }); + *f = m.funcs.push(FuncDecl::Body(s, format!("_pit"), b)); + } + } + } + } + m.exports.push(export); + } + } + m.exports.push(Export{name: format!("tpit_alloc"),kind: ExportKind::Func(talloc)}); + m.exports.push(Export{name: format!("tpit_free"),kind: ExportKind::Func(tfree)}); + m.exports.push(Export{name: format!("tpit_table"),kind: ExportKind::Table(t)}); + Ok(()) +} diff --git a/pit-rust-generator/src/main.rs b/pit-rust-generator/src/main.rs index 37aa19b..5c79784 100644 --- a/pit-rust-generator/src/main.rs +++ b/pit-rust-generator/src/main.rs @@ -12,6 +12,7 @@ fn main() -> anyhow::Result<()>{ }, salt: std::env::var("PIT_SALT").unwrap_or(format!("")).into_bytes(), + tpit: false, }; let v = pit_rust_guest::render(&x, &src); diff --git a/pit-rust-guest/src/lib.rs b/pit-rust-guest/src/lib.rs index f04ab9d..74a8957 100644 --- a/pit-rust-guest/src/lib.rs +++ b/pit-rust-guest/src/lib.rs @@ -2,48 +2,114 @@ use std::iter::once; use pit_core::{Arg, Interface, ResTy, Sig}; use proc_macro2::TokenStream; -use quote::{format_ident, quote}; use quasiquote::quasiquote; +use quote::{format_ident, quote}; use sha3::Digest; use std::io::Write; -pub struct Opts{ +pub struct Opts { pub root: TokenStream, - pub salt: Vec + pub salt: Vec, + pub tpit: bool, } -pub fn render(opts: &Opts, i: &Interface) -> TokenStream{ +pub fn render(opts: &Opts, i: &Interface) -> TokenStream { let root = &opts.root; let id = i.rid_str(); let mut ha = sha3::Sha3_256::default(); - write!(ha,"~{}",id); + write!(ha, "~{}", id); ha.write(&opts.salt); let ha = hex::encode(ha.finalize()); - let id2 = format_ident!("R{}",i.rid_str()); - let internal = format_ident!("R{id}_utils"); - let methods = i.methods.iter().map(|(a,b)|quasiquote! { - fn #{format_ident!("{a}")}#{render_sig(root,i,b,"e! {&mut self})}; + let id2 = format_ident!("R{}", i.rid_str()); + let methods = i.methods.iter().map(|(a, b)| { + quasiquote! { + fn #{format_ident!("{a}")}#{render_sig(opts,root,i,b,"e! {&mut self},false)}; + } }); - let impl_dyns = i.methods.iter().map(|(a,b)|quasiquote! { - fn #{format_ident!("{a}")}#{render_sig(root,i,b,"e! {&mut self})}{ + let xref = if opts.tpit { + quote! {} + } else { + quasiquote!( #[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})] - #[link(wasm_import_module = #{format!("pit/{}",i.rid_str())})] - extern "C"{ - #[link_name = #a] - fn go #{render_sig(root, i,b, "e! {this: &mut #root::externref::Resource>})}; - } - return unsafe{go(self,#{ - let params = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}")); - quote! { - #(#params),* + ) + }; + let res = if opts.tpit { + quote! { + #root::tpit_rt::Tpit + } + } else { + quote! { + #root::externref::Resource + } + }; + let rx = if opts.tpit { + quote! { + u32 + } + } else { + quote! { + &mut #res> + } + }; + let t = if opts.tpit { "t" } else { "" }; + let impl_dyns = i.methods.iter().map(|(a, b)| { + quasiquote! { + fn #{format_ident!("{a}")}#{render_sig(opts,root,i,b,"e! {&mut self},false)}{ + #xref + #[link(wasm_import_module = #{format!("{t}pit/{}",i.rid_str())})] + extern "C"{ + #[link_name = #a] + fn go #{render_sig(opts,root, i,b, "e! {this: #rx},true)}; } - })}; + return unsafe{go(#{ + if opts.tpit{ + quote!{self.ptr()} + }else{ + quote!{self} + } + },#{ + let params = b.params.iter().enumerate().map(|(a,b)|{ + let mut c = format_ident!("p{a}"); + let mut c = quote!{ + #c + }; + if let Arg::Resource { ty, nullable, take, ann } = b{ + if opts.tpit{ + if !*take{ + c = quote!{ + #root::tpit_rt::Tpit::summon(&mut #c) + } + } + } + } + c + }); + quote! { + #(#params),* + } + })}; + } } }); let chains2 = i.methods.iter().map(|(a,b)|quasiquote! { - #[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})] - #[export_name = #{format!("pit/{id}/~{ha}/{a}")}] - extern "C" fn #{format_ident!("{a}")}#{render_sig(root,i,b,"e! {id: *mut Box})}{ - return unsafe{&mut *id}.#{format_ident!("{a}")}(#{ - let params = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}")); + #xref + #[export_name = #{format!("{t}pit/{id}/~{ha}/{a}")}] + extern "C" fn #{format_ident!("{a}")}#{render_sig(opts,root,i,b,"e! {id: u32},true)}{ + return unsafe{&mut *(TABLE.all.get())}.get_mut(&id).unwrap().#{format_ident!("{a}")}(#{ + let params = b.params.iter().enumerate().map(|(a,b)|{ + let mut c = format_ident!("p{a}"); + let mut c = quote!{ + #c + }; + if let Arg::Resource { ty, nullable, take, ann } = b{ + if opts.tpit{ + if !*take{ + c = quote!{ + #c.ptr() + } + } + } + } + c + }); quote! { #(#params),* } @@ -51,8 +117,13 @@ pub fn render(opts: &Opts, i: &Interface) -> TokenStream{ } }); let sb = i.to_string(); - let sc = sb.as_bytes().iter().cloned().chain(once(0u8)).collect::>(); - quasiquote!{ + let sc = sb + .as_bytes() + .iter() + .cloned() + .chain(once(0u8)) + .collect::>(); + quasiquote! { pub trait #id2{ #(#methods)* } @@ -63,27 +134,42 @@ pub fn render(opts: &Opts, i: &Interface) -> TokenStream{ [#(#sc),*] } }; - impl #id2 for #root::externref::Resource>{ + fn alloc(m: &mut ::std::collections::BTreeMap, x: T) -> u32{ + let mut u = 0; + while m.contains_key(&u){ + u += 1; + }; + m.insert(u,x); + return u; + } + #[derive(Default)] + struct TableCell{ + all: std::cell::UnsafeCell<::std::collections::BTreeMap>> + }; + unsafe impl Send for TableCell{} + unsafe impl Sync for TableCell{} + static TABLE: ::std::sync::LazyLock = ::std::sync::LazyLock::new(||TableCell::default()); + impl #id2 for #res>{ #(#impl_dyns)* } - #[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})] - #[export_name = #{format!("pit/{id}/~{ha}.drop")}] - extern "C" fn _drop(a: *mut Box){ + #xref + #[export_name = #{format!("{t}pit/{id}/~{ha}.drop")}] + extern "C" fn _drop(a: u32){ unsafe{ - Box::from_raw(a) + (&mut *(TABLE.all.get())).remove(&a) }; } #(#chains2)* - impl From> for #root::externref::Resource>{ + impl From> for #res>{ fn from(a: Box) -> Self{ - #[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})] + #xref #[link(wasm_import_module = #{format!("pit/{}",i.rid_str())})] extern "C"{ #[link_name = #{format!("~{ha}")}] - fn _push(a: *mut Box) -> #root::externref::Resource>; + fn _push(a: u32) -> #res>; } return unsafe{ - _push(Box::into_raw(Box::new(a))) + _push(alloc(&mut *(TABLE.all.get()),a)) } } } @@ -98,16 +184,34 @@ pub fn render(opts: &Opts, i: &Interface) -> TokenStream{ // } } } -pub fn render_sig(root: &TokenStream,base: &Interface, s: &Sig, self_: &TokenStream) -> TokenStream{ - let params = s.params.iter().map(|a|render_ty(root,base,a)).enumerate().map(|(a,b)|quasiquote!(#{format_ident!("p{a}")} : #b)); +pub fn render_sig( + opts: &Opts, + root: &TokenStream, + base: &Interface, + s: &Sig, + self_: &TokenStream, + ffi: bool, +) -> TokenStream { + let params = s + .params + .iter() + .map(|a| render_ty(opts, root, base, a, ffi)) + .enumerate() + .map(|(a, b)| quasiquote!(#{format_ident!("p{a}")} : #b)); let params = once(self_).cloned().chain(params); - let rets = s.rets.iter().map(|a|render_ty(root,base,a)); + let rets = s.rets.iter().map(|a| render_ty(opts, root, base, a, ffi)); quote! { (#(#params),*) -> (#(#rets),*) } } -pub fn render_ty(root: &TokenStream,base:&Interface, p: &Arg) -> TokenStream{ - match p{ +pub fn render_ty( + opts: &Opts, + root: &TokenStream, + base: &Interface, + p: &Arg, + ffi: bool, +) -> TokenStream { + match p { Arg::I32 => quote! { u32 }, @@ -120,30 +224,58 @@ pub fn render_ty(root: &TokenStream,base:&Interface, p: &Arg) -> TokenStream{ Arg::F64 => quote! { f64 }, - Arg::Resource{ty,nullable,take, ann } => { - let ty = match ty{ - ResTy::Of(a) => quasiquote!{ - #root::externref::Resource> - }, - ResTy::None => quote! { - #root::externref::Resource<()> - }, - ResTy::This => quasiquote! { - #root::externref::Resource> + Arg::Resource { + ty, + nullable, + take, + ann, + } => { + if !opts.tpit { + let ty = match ty { + ResTy::Of(a) => quasiquote! { + #root::externref::Resource> + }, + ResTy::None => quote! { + #root::externref::Resource<()> + }, + ResTy::This => quasiquote! { + #root::externref::Resource> + }, + }; + let ty = if *nullable { + quote! {Option<#ty>} + } else { + ty + }; + let ty = if *take { + ty + } else { + quote! {&mut #ty} + }; + ty + } else { + let ty = match ty { + ResTy::Of(a) => quasiquote! { + #root::tpit_rt::Tpit> + }, + ResTy::None => quote! { + #root::tpit_rt::Tpit<()> + }, + ResTy::This => quasiquote! { + #root::tpit_rt::Tpit> + }, + }; + let mut ty = if *take { + ty + } else { + quote! {&mut #ty} + }; + if *take && ffi { + ty = quote! {u32} } - }; - let ty = if *nullable{ - quote! {Option<#ty>} - }else{ ty - }; - let ty = if *take{ - ty - }else{ - quote! {&mut #ty} - }; - ty - }, + } + } // Arg::Func(_) => todo!() } -} \ No newline at end of file +} diff --git a/pit-rust-host-lib/src/lib.rs b/pit-rust-host-lib/src/lib.rs index bc90269..aca8065 100644 --- a/pit-rust-host-lib/src/lib.rs +++ b/pit-rust-host-lib/src/lib.rs @@ -8,8 +8,7 @@ use std::{ use pit_core::{Arg, Interface}; use wasm_runtime_layer::{ - backend::WasmEngine, AsContext, AsContextMut, Extern, ExternRef, Func, FuncType, Imports, - Instance, Module, StoreContext, StoreContextMut, Value, ValueType, + backend::WasmEngine, AsContext, AsContextMut, Extern, ExternRef, Func, FuncType, Imports, Instance, Module, Store, StoreContext, StoreContextMut, Value, ValueType }; pub fn init + 'static, E: WasmEngine>( l: &mut Imports, @@ -180,3 +179,26 @@ impl Wrapped { pub type RWrapped = ::std::sync::Arc>; pub extern crate anyhow; pub extern crate wasm_runtime_layer; + + +pub struct W{ + pub r: X, + pub store: Arc> +} +impl Clone for W{ + fn clone(&self) -> Self { + Self { r: self.r.clone(), store: self.store.clone() } + } +} +pub struct StoreCell{ + pub wrapped: UnsafeCell> +} +unsafe impl Send for StoreCell{} +unsafe impl Sync for StoreCell{} +impl StoreCell{ + pub unsafe fn get(&self) -> StoreContextMut<'_,U,E>{ + unsafe{ + &mut *self.wrapped.get() + }.as_context_mut() + } +} \ No newline at end of file diff --git a/pit-rust-host/Cargo.toml b/pit-rust-host/Cargo.toml index 7affd4e..82ca8d9 100644 --- a/pit-rust-host/Cargo.toml +++ b/pit-rust-host/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] hex = "0.4.3" pit-core = { version = "0.1.0", path = "../pit-core" } +pit-rust-guest = { version = "0.1.0", path = "../pit-rust-guest" } proc-macro2 = "1.0.85" quasiquote = "0.1.1" quote = "1.0.36" diff --git a/pit-rust-host/src/lib.rs b/pit-rust-host/src/lib.rs index 41e506d..c4a62a1 100644 --- a/pit-rust-host/src/lib.rs +++ b/pit-rust-host/src/lib.rs @@ -1,121 +1,247 @@ use std::iter::once; -use pit_core::{Arg, Interface, Sig}; -use proc_macro2::TokenStream; +use pit_core::{Arg, Interface, ResTy, Sig}; +use proc_macro2::{Span, TokenStream}; use quasiquote::quasiquote; use quote::{format_ident, quote, ToTokens}; use syn::{spanned::Spanned, Ident, Index}; -pub fn render(root: &TokenStream, i: &Interface) -> TokenStream { - let id = format_ident!("R{}", i.rid_str()); - let internal = format_ident!("{id}_utils"); +pub struct Opts { + pub guest: Option, +} +pub fn render(root: &TokenStream, i: &Interface, opts: &Opts) -> TokenStream { + let id = format_ident!("B{}", i.rid_str()); + // let internal = format_ident!("{id}_utils"); let methods = i.methods.iter().map(|(a, b)| { quasiquote! { - fn #{format_ident!("{a}")}#{render_sig(root,b,"e! {&self})} + fn #{format_ident!("{a}")}#{render_sig(root,b,"e! {&self},quote!{ + ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E> + })} } }); - let impls = i.methods.iter().map(|(a, b)| { - let init = b.params.iter().enumerate().map(|(pi,a)|render_new_val(root, a, quasiquote!{#{format_ident!("p{pi}")}})); - let init = once(quote!{#root::wasm_runtime_layer::Value::I32(self.base as i32)}).chain(init); - let fini = b.rets.iter().enumerate().map(|(ri,r)|{ - quasiquote!{ + let impls = i.methods.iter().enumerate().map(|(c, (a, b))| { + let init = b + .params + .iter() + .enumerate() + .map(|(pi, a)| render_new_val(root, a, quasiquote! {#{format_ident!("p{pi}")}})); + let init = + once(quote! {#root::wasm_runtime_layer::Value::I32(self.base as i32)}).chain(init); + let fini = b.rets.iter().enumerate().map(|(ri, r)| { + quasiquote! { #{render_base_val(root, r, quote! {&rets[#ri]})} } }); quasiquote! { - fn #{format_ident!("{a}")}#{render_sig(root,b,"e! {&self})}{ - let Some(#root::wasm_runtime_layer::Export::Func(f)) = self.instance.get_export(unsafe{ - &*::std::cell::UnsafeCell::raw_get(self.ctx) - },#{format_ident!("pit/{}/{}",i.rid_str(),a)}) else{ - panic!("invalid func") - }; + fn #{format_ident!("{a}")}#{render_sig(root,b,"e! {&self},quote!{ + ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E> + })}{ + let a = self.all[#{c+1}].clone(); let args = vec![#(#init),*]; - let mut rets = vec![#root::wasm_runtime_layer::Value::I32(0);#{b.rets.len()}]; - f.call(unsafe{ - &mut *::std::cell::UnsafeCell::raw_get(self.ctx) - },&args,&mut rets)?; + let mut rets = a(ctx,args); return Ok((#(#fini),*)) } } }); let injects = i.methods.iter().map(|(a,b)|{ - let init = b.params.iter().enumerate().map(|(pi,a)|quasiquote!{let #{format_ident!("p{pi}")} = #{render_base_val(root, a, quote! {&args[#pi + 1]})}}); + let init = b.params.iter().enumerate().map(|(pi,a)|quasiquote!{#{render_base_val(root, a, quote! {&args[#pi + 1]})}}); let fini = b.rets.iter().enumerate().map(|(ri,r)|{ quasiquote!{ - rets[#ri] = #{render_new_val(root, r, quasiquote! {r . #{Index{index: ri as u32,span: root.span()}}})} + #{render_new_val(root, r, quasiquote! {r . #{Index{index: ri as u32,span: root.span()}}})} } }); quasiquote!{ - let f = #root::wasm_runtime_layer::Func::new(ctx,#{render_blit_sig(root, b)},|ctx,args,rets|{ - #(#init),* - let #root::wasm_runtime_layer::Value::ExternRef(t) = &args[0] else{ - #root::anyhow::bail!("invalid param") - } - let r = match t.downcast::<'_,'_, ::std::sync::Arc>,U,E>(ctx){ - Ok(t) => { - t.#{format_ident!("{a}")}(#{ - let p = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}")); - quote! { - #(#p .clone()),* - } - })? - }, - Err(_) => match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped>,U,E>(ctx)?{ - Ok(t) => { - t.#{format_ident!("{a}")}(#{ - let p = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}")); - quote! { - #(#p .clone()),* - } - })? - }, - Err(_) => #root::anyhow::bail!("invalid externref") - } - }; - #(#fini),* - Ok(()) - }); - i.define(#{format!("pit/{}",i.rid_str())},#a,f); - }}).chain(once( quasiquote!{ - let f = #root::wasm_runtime_layer::Func::new(ctx,#root::wasm_runtime_layer::FuncType::new([#root::wasm_runtime_layer::ValueType::I32],[#root::wasm_runtime_layer::ExternType]),|ctx,args,rets|{ - let #root::wasm_runtime_layer::Value::I32(i) = &args[0] else{ - unreachable!() - }; - let n = ctx.data().as_ref().clone(); - let v = #root::Wrapped::new(*i as u32,#{i.rid_str()},ctx.as_context_mut(),n); - // let v: ::std::sync::Arc> = ::std::sync::Arc::new(v); - rets[0] = #root::wasm_runtime_layer::Value::ExternRef(#root::wasm_runtime_layer::ExternRef::new(ctx,v)); - Ok(()) - }); - i.define(#{format!("pit/{}",i.rid_str())},"~push",f); - })); + let r = a.clone(); + Arc::new(ctx,move|ctx,args|{ + let r = r.#{format_ident!("{a}")}(ctx,#(#init),*) + Ok(vec![#(#fini),*]) + }) + }}); quasiquote! { pub trait #id{ - fn to_any(&self) -> &dyn ::std::any::Any; #(#methods)* + unsafe fn finalize(&self, ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>) -> #root::anyhow::Result<()>; } - mod #internal{ - use super::#id; + const _: () = { impl #id for #root::RWrapped{ - fn to_any(&self) -> &dyn ::std::any::Any{ - return self; - } #(#impls)* + unsafe fn finalize(&self, ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>) -> #root::anyhow::Result<()>{ + self.all[0](ctx,vec![])?; + Ok(()) + } } + impl From> for #root::RWrapped{ + fn from(a: Arc>) -> Self{ + Self{ + rid: Arc::new(#root::pit_core::Interface::parse_interface(#{i.to_string()}).ok().unwrap()), + all: vec![#{ + let all = once(quasiquote!{ + let r = a.clone(); + unsafe{ + Arc::new(move|ctx,args|{r.finalize(ctx);Ok(vec![])}) + } + }).chain(injects); - fn inject,E: #root::wasm_runtime_layer::backend::WasmEngine>(ctx: impl #root::wasm_runtime_layer::AsContextMut, i: &mut #root::wasm_runtime_layer::Imports){ - #(#injects)* + quote!{ + #(#all),* + } + }] + } + } + } + #{match opts.guest.as_ref(){ + None=>quote!{}, + Some(g) => proxy(root,i,opts,g), + }} + } + } +} +pub fn proxy(root: &TokenStream, i: &Interface, opts: &Opts, g: &pit_rust_guest::Opts) -> TokenStream{ + let id = format_ident!("B{}", i.rid_str()); + let pid = format_ident!("R{}", i.rid_str()); + let root2 = &g.root; + let res = if g.tpit { + quote! { + #root2::tpit_rt::Tpit + } + } else { + quote! { + #root2::externref::Resource + } + }; + let impl_guest = i.methods.iter().map(|(a, b)| { + quasiquote! { + fn #{format_ident!("{a}")}#{pit_rust_guest::render_sig(g,root,i,b,"e! {&mut self},false)}{ + let ctx = unsafe{ + self.get() + }; + let r = self.r.#{format_ident!("{a}")}(ctx,#{ + let params = b.params.iter().enumerate().map(|(a,b)|{ + let mut c = format_ident!("p{a}"); + let mut c = quote!{ + #c + }; + if let Arg::Resource { ty, nullable, take, ann } = b{ + c = quote!{Box::new(#root::W{ + r: #root::RWrapped::from(Arc::new(#c)), + store: self.store.clone() + }).into()}; + if !take{ + c = quote!{&mut #c}; + }; + } + c + }); + quote! { + #(#params),* + } + }).unwrap(); + return (#{ + let xs = b.rets.iter().enumerate().map(|(a,b)|{ + let mut c = Index{ + index: a as u32, + span: Span::call_site() + }; + let mut c = quote!{ + r.#c + }; + if let Arg::Resource { ty, nullable, take, ann } = b{ + c = quote!{ + #root::RWrapped::from(Compat(::std::cell::UnsafeCell::new(Some(#c)))) + } + } + c + }); + quote!{ + #(#xs),* + } + }) + }; + + } + }); + let impl_host = i.methods.iter().enumerate().map(|(c, (a, b))| { + let params = b.params.iter().enumerate().map(|(a,b)|{ + let mut c = format_ident!("p{a}"); + let mut c = quote!{ + #c + }; + if let Arg::Resource { ty, nullable, take, ann } = b{ + c = quote!{ + #root::RWrapped::from(Compat(::std::cell::UnsafeCell::new(Some(#c)))) + }; + if !take{ + c = quote!{&mut #c}; + }; + } + c + }); + let rets = b.rets.iter().enumerate().map(|(a,b)|{ + let mut c = Index{ + index: a as u32, + span: Span::call_site() + }; + let mut c = quote!{ + r.#c + }; + if let Arg::Resource { ty, nullable, take, ann } = b{ + c = quote!{Box::new(#root::W{ + r: #root::RWrapped::from(Arc::new(#c)), + store: Arc::new(#root::StoreCell{ + wrapped: ::std::cell::UnsafeCell::new(#root::wasm_runtime_layer::Store::new(ctx.engine(),ctx.data().clone())) + }) + }).into()}; + } + c + }); + quasiquote! { + fn #{format_ident!("{a}")}#{render_sig(root,b,"e! {&self},quote!{ + ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E> + })}{ + let x = unsafe{ + &mut *(self.0.get()) + }.as_mut().unwrap().#{format_ident!("{a}")}(#(#params),*); + + Ok((#(#rets),*)) + } + } + }); + quasiquote!{ + struct Compat(::std::cell::UnsafeCell>); + impl #pid for #root::W<#root::RWrapped,U,E>{ + #(#impl_guest)* + } + impl #id for Compat{ + #(#impl_host)* + unsafe fn finalize(&self, ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>) -> #root::anyhow::Result<()>{ + let x = unsafe{ + &mut *(self.0.get()) + }.take(); + let Some(x) = x else{ + return Err(#root::anyhow::anyhow!("double finalized")) + } + Ok(()) + } + } + impl From> for Arc{ + fn from(p: Box) -> Self{ + return Arc::new(Compat(::std::cell::UnsafeCell::new(Some(#res::from(p))))) } } } } -pub fn render_sig(root: &TokenStream, s: &Sig, self_: &TokenStream) -> TokenStream { +pub fn render_sig( + root: &TokenStream, + s: &Sig, + self_: &TokenStream, + s2: TokenStream, +) -> TokenStream { let params = s .params .iter() .map(|a| render_ty(root, a)) .enumerate() .map(|(a, b)| quasiquote!(#{format_ident!("p{a}")} : #b)); - let params = once(self_).cloned().chain(params); + let params = once(self_).cloned().chain(once(s2)).chain(params); let rets = s.rets.iter().map(|a| render_ty(root, a)); quote! { (#(#params),*) -> #root::anyhow::Result<(#(#rets),*)> @@ -168,13 +294,18 @@ pub fn render_ty(root: &TokenStream, p: &Arg) -> TokenStream { Arg::F64 => quote! { f64 }, - Arg::Resource { ty, nullable } => match ty { - None => quote! { + Arg::Resource { + ty, + nullable, + take, + ann, + } => match ty { + ResTy::None => quote! { #root::wasm_runtime_layer::ExternRef }, - Some(a) => { + _ => { let a = quasiquote! { - ::std::sync::Arc> + ::std::sync::Arc<#root::Wrapped> }; if *nullable { quote! {Option<#a>} @@ -207,21 +338,24 @@ pub fn render_base_val(root: &TokenStream, p: &Arg, x: TokenStream) -> TokenStre #root::anyhow::bail!("invalid param") } }, - Arg::Resource { ty, nullable } => { + Arg::Resource { + ty, + nullable, + take, + ann, + } => { let mut a = quote! { let #root::wasm_runtime_layer::Value::ExternRef(t) = #x else{ #root::anyhow::bail!("invalid param") } }; - if let Some(r) = ty.as_ref() { + if !matches!(ty, ResTy::None) { quasiquote!{ - let t = match t{None => None,Some(t) => Some(match t.downcast::<'_,'_, ::std::sync::Arc>,U,E>(ctx){ - Ok(t) => t.clone(), - Err(_) => match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped>,U,E>(ctx){ + let t = match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped>,U,E>(ctx){ Ok(t) => Arc::new(t.clone()), Err(_) => #root::anyhow::bail!("invalid param") } - })} + }.to_tokens(&mut a); } if !*nullable { @@ -256,33 +390,40 @@ pub fn render_new_val(root: &TokenStream, p: &Arg, t: TokenStream) -> TokenStrea Arg::F64 => quote! { #root::wasm_runtime_layer::Value::F64(#t) }, - Arg::Resource { ty, nullable } => { - let tq = |t:TokenStream|quasiquote! { - { - let t = #t; - #{match ty{ - None => quote! { #root::wasm_runtime_layer::ExternRef::new(ctx,t)}, - Some(_) => quote! { - match t.to_any().downcast_ref::<::std::sync::Arc<#root::Wrapped>>(){ - None => #root::wasm_runtime_layer::ExternRef::new(ctx,t), - Some(t) => #root::wasm_runtime_layer::ExternRef::new(ctx,t.clone()), + Arg::Resource { + ty, + nullable, + take, + ann, + } => { + let tq = |t: TokenStream| { + quasiquote! { + { + let t = #t; + #{match ty{ + ResTy::None => quote! { #root::wasm_runtime_layer::ExternRef::new(ctx,t)}, + _ => quote! { + match t.to_any().downcast_ref::<::std::sync::Arc<#root::Wrapped>>(){ + None => #root::wasm_runtime_layer::ExternRef::new(ctx,t), + Some(t) => #root::wasm_runtime_layer::ExternRef::new(ctx,t.clone()), + } } - } - }} + }} + } } }; if !*nullable { quasiquote! { #root::wasm_runtime_layer::Value::ExternRef(Some(#{match ty{ - None => t, - Some(_) => tq(t) + ResTy::None => t, + _ => tq(t) }})) } } else { quasiquote! { #root::wasm_runtime_layer::Value::ExternRef(#{match ty{ - None => t, - Some(_) => quasiquote! {#t.map(|t|#{tq(quote! {t})})} + ResTy::None => t, + _ => quasiquote! {#t.map(|t|#{tq(quote! {t})})} }}) } } diff --git a/tpit-rt/Cargo.toml b/tpit-rt/Cargo.toml new file mode 100644 index 0000000..18c1ccb --- /dev/null +++ b/tpit-rt/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "tpit-rt" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/tpit-rt/src/lib.rs b/tpit-rt/src/lib.rs new file mode 100644 index 0000000..71fae73 --- /dev/null +++ b/tpit-rt/src/lib.rs @@ -0,0 +1,58 @@ +use std::{ + marker::PhantomData, + mem::forget, + num::NonZeroU32, + sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, + }, +}; +#[repr(transparent)] +pub struct Tpit { + ptr: Option, + phantom: PhantomData, +} + +impl Drop for Tpit { + fn drop(&mut self) { + #[link(wasm_import_module = "tpit")] + extern "C" { + fn drop(a: u32); + fn void(a: u32); + } + + if let Some(p) = self.ptr { + unsafe { + drop(p.into()); + } + } + } +} +impl Tpit { + pub unsafe fn new(ptr: u32) -> Self { + Self { + ptr: NonZeroU32::new(ptr), + phantom: PhantomData, + } + } + pub fn ptr(&self) -> u32 { + match self.ptr { + Some(a) => { + let a: u32 = a.into(); + a + } + None => 0, + } + } + pub unsafe fn cast(self) -> Tpit { + unsafe { Tpit::::new(self.forget_to_ptr()) } + } + pub fn forget_to_ptr(self) -> u32 { + let x = self.ptr(); + forget(self); + return x; + } + pub unsafe fn summon(a: &mut u32) -> &mut Self { + unsafe { std::mem::transmute(a) } + } +}