stuff
This commit is contained in:
parent
828db2bef3
commit
28760e867e
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -626,6 +626,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hex",
|
"hex",
|
||||||
"pit-core",
|
"pit-core",
|
||||||
|
"pit-rust-guest",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quasiquote",
|
"quasiquote",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -970,6 +971,10 @@ dependencies = [
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tpit-rt"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "twox-hash"
|
name = "twox-hash"
|
||||||
version = "1.6.3"
|
version = "1.6.3"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[workspace]
|
[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"
|
resolver="2"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
|
|
@ -67,6 +67,28 @@ const _: () = {
|
||||||
125u8,
|
125u8,
|
||||||
0u8,
|
0u8,
|
||||||
];
|
];
|
||||||
|
fn alloc<T>(m: &mut ::std::collections::BTreeMap<u32, T>, 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<TableCell> = ::std::sync::LazyLock::new(|| TableCell::default());
|
||||||
impl R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5
|
impl R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5
|
||||||
for ::externref::Resource<
|
for ::externref::Resource<
|
||||||
Box<dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5>,
|
Box<dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5>,
|
||||||
|
@ -128,42 +150,23 @@ const _: () = {
|
||||||
}
|
}
|
||||||
#[::externref::externref(crate = ":: externref")]
|
#[::externref::externref(crate = ":: externref")]
|
||||||
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e.drop"]
|
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e.drop"]
|
||||||
extern "C" fn _drop(
|
extern "C" fn _drop(a: u32) {
|
||||||
a: *mut Box<
|
unsafe { (&mut *(TABLE.all.get())).remove(&a) };
|
||||||
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
|
|
||||||
>,
|
|
||||||
) {
|
|
||||||
unsafe { Box::from_raw(a) };
|
|
||||||
}
|
}
|
||||||
#[::externref::externref(crate = ":: externref")]
|
#[::externref::externref(crate = ":: externref")]
|
||||||
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/read8"]
|
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/read8"]
|
||||||
extern "C" fn read8(
|
extern "C" fn read8(id: u32, p0: u32) -> (u32) {
|
||||||
id: *mut Box<
|
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().read8(p0);
|
||||||
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
|
|
||||||
>,
|
|
||||||
p0: u32,
|
|
||||||
) -> (u32) {
|
|
||||||
return unsafe { &mut *id }.read8(p0);
|
|
||||||
}
|
}
|
||||||
#[::externref::externref(crate = ":: externref")]
|
#[::externref::externref(crate = ":: externref")]
|
||||||
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/size"]
|
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/size"]
|
||||||
extern "C" fn size(
|
extern "C" fn size(id: u32) -> (u32) {
|
||||||
id: *mut Box<
|
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().size();
|
||||||
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
|
|
||||||
>,
|
|
||||||
) -> (u32) {
|
|
||||||
return unsafe { &mut *id }.size();
|
|
||||||
}
|
}
|
||||||
#[::externref::externref(crate = ":: externref")]
|
#[::externref::externref(crate = ":: externref")]
|
||||||
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/write8"]
|
#[export_name = "pit/867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5/~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e/write8"]
|
||||||
extern "C" fn write8(
|
extern "C" fn write8(id: u32, p0: u32, p1: u32) -> () {
|
||||||
id: *mut Box<
|
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().write8(p0, p1);
|
||||||
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
|
|
||||||
>,
|
|
||||||
p0: u32,
|
|
||||||
p1: u32,
|
|
||||||
) -> () {
|
|
||||||
return unsafe { &mut *id }.write8(p0, p1);
|
|
||||||
}
|
}
|
||||||
impl From<Box<dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5>>
|
impl From<Box<dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5>>
|
||||||
for ::externref::Resource<
|
for ::externref::Resource<
|
||||||
|
@ -179,16 +182,14 @@ const _: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e"]
|
#[link_name = "~8afbd04c549e07db517e034114e4b8ff8c76ce748f2e2d6e29fcaf48051eaf3e"]
|
||||||
fn _push(
|
fn _push(
|
||||||
a: *mut Box<
|
a: u32,
|
||||||
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
|
|
||||||
>,
|
|
||||||
) -> ::externref::Resource<
|
) -> ::externref::Resource<
|
||||||
Box<
|
Box<
|
||||||
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
|
dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5,
|
||||||
>,
|
>,
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
return unsafe { _push(Box::into_raw(Box::new(a))) };
|
return unsafe { _push(alloc(&mut *(TABLE.all.get()), a)) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -67,6 +67,28 @@ const _: () = {
|
||||||
125u8,
|
125u8,
|
||||||
0u8,
|
0u8,
|
||||||
];
|
];
|
||||||
|
fn alloc<T>(m: &mut ::std::collections::BTreeMap<u32, T>, 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<TableCell> = ::std::sync::LazyLock::new(|| TableCell::default());
|
||||||
impl R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d
|
impl R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d
|
||||||
for ::externref::Resource<
|
for ::externref::Resource<
|
||||||
Box<dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d>,
|
Box<dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d>,
|
||||||
|
@ -128,42 +150,23 @@ const _: () = {
|
||||||
}
|
}
|
||||||
#[::externref::externref(crate = ":: externref")]
|
#[::externref::externref(crate = ":: externref")]
|
||||||
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9.drop"]
|
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9.drop"]
|
||||||
extern "C" fn _drop(
|
extern "C" fn _drop(a: u32) {
|
||||||
a: *mut Box<
|
unsafe { (&mut *(TABLE.all.get())).remove(&a) };
|
||||||
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
|
|
||||||
>,
|
|
||||||
) {
|
|
||||||
unsafe { Box::from_raw(a) };
|
|
||||||
}
|
}
|
||||||
#[::externref::externref(crate = ":: externref")]
|
#[::externref::externref(crate = ":: externref")]
|
||||||
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/read8"]
|
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/read8"]
|
||||||
extern "C" fn read8(
|
extern "C" fn read8(id: u32, p0: u64) -> (u32) {
|
||||||
id: *mut Box<
|
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().read8(p0);
|
||||||
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
|
|
||||||
>,
|
|
||||||
p0: u64,
|
|
||||||
) -> (u32) {
|
|
||||||
return unsafe { &mut *id }.read8(p0);
|
|
||||||
}
|
}
|
||||||
#[::externref::externref(crate = ":: externref")]
|
#[::externref::externref(crate = ":: externref")]
|
||||||
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/size"]
|
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/size"]
|
||||||
extern "C" fn size(
|
extern "C" fn size(id: u32) -> (u64) {
|
||||||
id: *mut Box<
|
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().size();
|
||||||
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
|
|
||||||
>,
|
|
||||||
) -> (u64) {
|
|
||||||
return unsafe { &mut *id }.size();
|
|
||||||
}
|
}
|
||||||
#[::externref::externref(crate = ":: externref")]
|
#[::externref::externref(crate = ":: externref")]
|
||||||
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/write8"]
|
#[export_name = "pit/68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d/~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9/write8"]
|
||||||
extern "C" fn write8(
|
extern "C" fn write8(id: u32, p0: u64, p1: u32) -> () {
|
||||||
id: *mut Box<
|
return unsafe { &mut *(TABLE.all.get()) }.get_mut(&id).unwrap().write8(p0, p1);
|
||||||
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
|
|
||||||
>,
|
|
||||||
p0: u64,
|
|
||||||
p1: u32,
|
|
||||||
) -> () {
|
|
||||||
return unsafe { &mut *id }.write8(p0, p1);
|
|
||||||
}
|
}
|
||||||
impl From<Box<dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d>>
|
impl From<Box<dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d>>
|
||||||
for ::externref::Resource<
|
for ::externref::Resource<
|
||||||
|
@ -179,16 +182,14 @@ const _: () = {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9"]
|
#[link_name = "~b3435bc747738a8874da05bf54d1e6b7c57bbab9ef27b0d40a5db3c3c8b6e5b9"]
|
||||||
fn _push(
|
fn _push(
|
||||||
a: *mut Box<
|
a: u32,
|
||||||
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
|
|
||||||
>,
|
|
||||||
) -> ::externref::Resource<
|
) -> ::externref::Resource<
|
||||||
Box<
|
Box<
|
||||||
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
|
dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d,
|
||||||
>,
|
>,
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
return unsafe { _push(Box::into_raw(Box::new(a))) };
|
return unsafe { _push(alloc(&mut *(TABLE.all.get()), a)) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
use std::collections::BTreeMap;
|
use std::{
|
||||||
|
collections::{BTreeMap, BTreeSet}, iter::once, mem::{replace, take}
|
||||||
use waffle::{
|
|
||||||
util::new_sig, BlockTarget, Func, FunctionBody, Import, ImportKind, Module, Operator,
|
|
||||||
SignatureData, Table, Type,
|
|
||||||
};
|
};
|
||||||
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<Func> {
|
pub fn talloc(m: &mut Module, t: Table) -> anyhow::Result<Func> {
|
||||||
let e = m.tables[t].ty.clone();
|
let e = m.tables[t].ty.clone();
|
||||||
|
@ -189,3 +194,409 @@ pub fn waffle_funcs(m: &mut Module, i: &pit_core::Interface) -> BTreeMap<String,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
|
pub fn shim(
|
||||||
|
retref: bool,
|
||||||
|
f: &mut FunctionBody,
|
||||||
|
mut k: Block,
|
||||||
|
r: &Arg,
|
||||||
|
mut v: Value,
|
||||||
|
talloc: Func,
|
||||||
|
tfree: Func,
|
||||||
|
table: Table,
|
||||||
|
) -> 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::<BTreeSet<_>>();
|
||||||
|
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::<Vec<_>>()
|
||||||
|
.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::<Vec<_>>()
|
||||||
|
.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(())
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ fn main() -> anyhow::Result<()>{
|
||||||
|
|
||||||
},
|
},
|
||||||
salt: std::env::var("PIT_SALT").unwrap_or(format!("")).into_bytes(),
|
salt: std::env::var("PIT_SALT").unwrap_or(format!("")).into_bytes(),
|
||||||
|
tpit: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let v = pit_rust_guest::render(&x, &src);
|
let v = pit_rust_guest::render(&x, &src);
|
||||||
|
|
|
@ -2,48 +2,114 @@ use std::iter::once;
|
||||||
|
|
||||||
use pit_core::{Arg, Interface, ResTy, Sig};
|
use pit_core::{Arg, Interface, ResTy, Sig};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
|
||||||
use quasiquote::quasiquote;
|
use quasiquote::quasiquote;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
use sha3::Digest;
|
use sha3::Digest;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
pub struct Opts{
|
pub struct Opts {
|
||||||
pub root: TokenStream,
|
pub root: TokenStream,
|
||||||
pub salt: Vec<u8>
|
pub salt: Vec<u8>,
|
||||||
|
pub tpit: bool,
|
||||||
}
|
}
|
||||||
pub fn render(opts: &Opts, i: &Interface) -> TokenStream{
|
pub fn render(opts: &Opts, i: &Interface) -> TokenStream {
|
||||||
let root = &opts.root;
|
let root = &opts.root;
|
||||||
let id = i.rid_str();
|
let id = i.rid_str();
|
||||||
let mut ha = sha3::Sha3_256::default();
|
let mut ha = sha3::Sha3_256::default();
|
||||||
write!(ha,"~{}",id);
|
write!(ha, "~{}", id);
|
||||||
ha.write(&opts.salt);
|
ha.write(&opts.salt);
|
||||||
let ha = hex::encode(ha.finalize());
|
let ha = hex::encode(ha.finalize());
|
||||||
let id2 = format_ident!("R{}",i.rid_str());
|
let id2 = format_ident!("R{}", i.rid_str());
|
||||||
let internal = format_ident!("R{id}_utils");
|
let methods = i.methods.iter().map(|(a, b)| {
|
||||||
let methods = i.methods.iter().map(|(a,b)|quasiquote! {
|
quasiquote! {
|
||||||
fn #{format_ident!("{a}")}#{render_sig(root,i,b,"e! {&mut self})};
|
fn #{format_ident!("{a}")}#{render_sig(opts,root,i,b,"e! {&mut self},false)};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
let impl_dyns = i.methods.iter().map(|(a,b)|quasiquote! {
|
let xref = if opts.tpit {
|
||||||
fn #{format_ident!("{a}")}#{render_sig(root,i,b,"e! {&mut self})}{
|
quote! {}
|
||||||
|
} else {
|
||||||
|
quasiquote!(
|
||||||
#[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})]
|
#[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})]
|
||||||
#[link(wasm_import_module = #{format!("pit/{}",i.rid_str())})]
|
)
|
||||||
extern "C"{
|
};
|
||||||
#[link_name = #a]
|
let res = if opts.tpit {
|
||||||
fn go #{render_sig(root, i,b, "e! {this: &mut #root::externref::Resource<Box<dyn #id2>>})};
|
quote! {
|
||||||
}
|
#root::tpit_rt::Tpit
|
||||||
return unsafe{go(self,#{
|
}
|
||||||
let params = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{a}"));
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
#(#params),*
|
#root::externref::Resource
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let rx = if opts.tpit {
|
||||||
|
quote! {
|
||||||
|
u32
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
&mut #res<Box<dyn #id2>>
|
||||||
|
}
|
||||||
|
};
|
||||||
|
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! {
|
let chains2 = i.methods.iter().map(|(a,b)|quasiquote! {
|
||||||
#[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})]
|
#xref
|
||||||
#[export_name = #{format!("pit/{id}/~{ha}/{a}")}]
|
#[export_name = #{format!("{t}pit/{id}/~{ha}/{a}")}]
|
||||||
extern "C" fn #{format_ident!("{a}")}#{render_sig(root,i,b,"e! {id: *mut Box<dyn #id2>})}{
|
extern "C" fn #{format_ident!("{a}")}#{render_sig(opts,root,i,b,"e! {id: u32},true)}{
|
||||||
return unsafe{&mut *id}.#{format_ident!("{a}")}(#{
|
return unsafe{&mut *(TABLE.all.get())}.get_mut(&id).unwrap().#{format_ident!("{a}")}(#{
|
||||||
let params = b.params.iter().enumerate().map(|(a,_)|format_ident!("p{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! {
|
quote! {
|
||||||
#(#params),*
|
#(#params),*
|
||||||
}
|
}
|
||||||
|
@ -51,8 +117,13 @@ pub fn render(opts: &Opts, i: &Interface) -> TokenStream{
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let sb = i.to_string();
|
let sb = i.to_string();
|
||||||
let sc = sb.as_bytes().iter().cloned().chain(once(0u8)).collect::<Vec<_>>();
|
let sc = sb
|
||||||
quasiquote!{
|
.as_bytes()
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.chain(once(0u8))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
quasiquote! {
|
||||||
pub trait #id2{
|
pub trait #id2{
|
||||||
#(#methods)*
|
#(#methods)*
|
||||||
}
|
}
|
||||||
|
@ -63,27 +134,42 @@ pub fn render(opts: &Opts, i: &Interface) -> TokenStream{
|
||||||
[#(#sc),*]
|
[#(#sc),*]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
impl #id2 for #root::externref::Resource<Box<dyn #id2>>{
|
fn alloc<T>(m: &mut ::std::collections::BTreeMap<u32,T>, 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 #id2>>>
|
||||||
|
};
|
||||||
|
unsafe impl Send for TableCell{}
|
||||||
|
unsafe impl Sync for TableCell{}
|
||||||
|
static TABLE: ::std::sync::LazyLock<TableCell> = ::std::sync::LazyLock::new(||TableCell::default());
|
||||||
|
impl #id2 for #res<Box<dyn #id2>>{
|
||||||
#(#impl_dyns)*
|
#(#impl_dyns)*
|
||||||
}
|
}
|
||||||
#[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})]
|
#xref
|
||||||
#[export_name = #{format!("pit/{id}/~{ha}.drop")}]
|
#[export_name = #{format!("{t}pit/{id}/~{ha}.drop")}]
|
||||||
extern "C" fn _drop(a: *mut Box<dyn #id2>){
|
extern "C" fn _drop(a: u32){
|
||||||
unsafe{
|
unsafe{
|
||||||
Box::from_raw(a)
|
(&mut *(TABLE.all.get())).remove(&a)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#(#chains2)*
|
#(#chains2)*
|
||||||
impl From<Box<dyn #id2>> for #root::externref::Resource<Box<dyn #id2>>{
|
impl From<Box<dyn #id2>> for #res<Box<dyn #id2>>{
|
||||||
fn from(a: Box<dyn #id2>) -> Self{
|
fn from(a: Box<dyn #id2>) -> Self{
|
||||||
#[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})]
|
#xref
|
||||||
#[link(wasm_import_module = #{format!("pit/{}",i.rid_str())})]
|
#[link(wasm_import_module = #{format!("pit/{}",i.rid_str())})]
|
||||||
extern "C"{
|
extern "C"{
|
||||||
#[link_name = #{format!("~{ha}")}]
|
#[link_name = #{format!("~{ha}")}]
|
||||||
fn _push(a: *mut Box<dyn #id2>) -> #root::externref::Resource<Box<dyn #id2>>;
|
fn _push(a: u32) -> #res<Box<dyn #id2>>;
|
||||||
}
|
}
|
||||||
return unsafe{
|
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{
|
pub fn render_sig(
|
||||||
let params = s.params.iter().map(|a|render_ty(root,base,a)).enumerate().map(|(a,b)|quasiquote!(#{format_ident!("p{a}")} : #b));
|
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 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! {
|
quote! {
|
||||||
(#(#params),*) -> (#(#rets),*)
|
(#(#params),*) -> (#(#rets),*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn render_ty(root: &TokenStream,base:&Interface, p: &Arg) -> TokenStream{
|
pub fn render_ty(
|
||||||
match p{
|
opts: &Opts,
|
||||||
|
root: &TokenStream,
|
||||||
|
base: &Interface,
|
||||||
|
p: &Arg,
|
||||||
|
ffi: bool,
|
||||||
|
) -> TokenStream {
|
||||||
|
match p {
|
||||||
Arg::I32 => quote! {
|
Arg::I32 => quote! {
|
||||||
u32
|
u32
|
||||||
},
|
},
|
||||||
|
@ -120,30 +224,58 @@ pub fn render_ty(root: &TokenStream,base:&Interface, p: &Arg) -> TokenStream{
|
||||||
Arg::F64 => quote! {
|
Arg::F64 => quote! {
|
||||||
f64
|
f64
|
||||||
},
|
},
|
||||||
Arg::Resource{ty,nullable,take, ann } => {
|
Arg::Resource {
|
||||||
let ty = match ty{
|
ty,
|
||||||
ResTy::Of(a) => quasiquote!{
|
nullable,
|
||||||
#root::externref::Resource<Box<dyn #{format_ident!("R{}",hex::encode(a))}>>
|
take,
|
||||||
},
|
ann,
|
||||||
ResTy::None => quote! {
|
} => {
|
||||||
#root::externref::Resource<()>
|
if !opts.tpit {
|
||||||
},
|
let ty = match ty {
|
||||||
ResTy::This => quasiquote! {
|
ResTy::Of(a) => quasiquote! {
|
||||||
#root::externref::Resource<Box<dyn #{format_ident!("R{}",base.rid_str())}>>
|
#root::externref::Resource<Box<dyn #{format_ident!("R{}",hex::encode(a))}>>
|
||||||
|
},
|
||||||
|
ResTy::None => quote! {
|
||||||
|
#root::externref::Resource<()>
|
||||||
|
},
|
||||||
|
ResTy::This => quasiquote! {
|
||||||
|
#root::externref::Resource<Box<dyn #{format_ident!("R{}",base.rid_str())}>>
|
||||||
|
},
|
||||||
|
};
|
||||||
|
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<Box<dyn #{format_ident!("R{}",hex::encode(a))}>>
|
||||||
|
},
|
||||||
|
ResTy::None => quote! {
|
||||||
|
#root::tpit_rt::Tpit<()>
|
||||||
|
},
|
||||||
|
ResTy::This => quasiquote! {
|
||||||
|
#root::tpit_rt::Tpit<Box<dyn #{format_ident!("R{}",base.rid_str())}>>
|
||||||
|
},
|
||||||
|
};
|
||||||
|
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
|
ty
|
||||||
};
|
}
|
||||||
let ty = if *take{
|
}
|
||||||
ty
|
|
||||||
}else{
|
|
||||||
quote! {&mut #ty}
|
|
||||||
};
|
|
||||||
ty
|
|
||||||
},
|
|
||||||
// Arg::Func(_) => todo!()
|
// Arg::Func(_) => todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,8 +8,7 @@ use std::{
|
||||||
|
|
||||||
use pit_core::{Arg, Interface};
|
use pit_core::{Arg, Interface};
|
||||||
use wasm_runtime_layer::{
|
use wasm_runtime_layer::{
|
||||||
backend::WasmEngine, AsContext, AsContextMut, Extern, ExternRef, Func, FuncType, Imports,
|
backend::WasmEngine, AsContext, AsContextMut, Extern, ExternRef, Func, FuncType, Imports, Instance, Module, Store, StoreContext, StoreContextMut, Value, ValueType
|
||||||
Instance, Module, StoreContext, StoreContextMut, Value, ValueType,
|
|
||||||
};
|
};
|
||||||
pub fn init<U: AsRef<Instance> + 'static, E: WasmEngine>(
|
pub fn init<U: AsRef<Instance> + 'static, E: WasmEngine>(
|
||||||
l: &mut Imports,
|
l: &mut Imports,
|
||||||
|
@ -180,3 +179,26 @@ impl<U: 'static, E: wasm_runtime_layer::backend::WasmEngine> Wrapped<U,E> {
|
||||||
pub type RWrapped<U,E> = ::std::sync::Arc<Wrapped<U,E>>;
|
pub type RWrapped<U,E> = ::std::sync::Arc<Wrapped<U,E>>;
|
||||||
pub extern crate anyhow;
|
pub extern crate anyhow;
|
||||||
pub extern crate wasm_runtime_layer;
|
pub extern crate wasm_runtime_layer;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct W<X,U: 'static,E: WasmEngine>{
|
||||||
|
pub r: X,
|
||||||
|
pub store: Arc<StoreCell<U,E>>
|
||||||
|
}
|
||||||
|
impl<U: 'static,E: WasmEngine,X: Clone> Clone for W<X,U,E>{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self { r: self.r.clone(), store: self.store.clone() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub struct StoreCell<U,E: WasmEngine>{
|
||||||
|
pub wrapped: UnsafeCell<Store<U,E>>
|
||||||
|
}
|
||||||
|
unsafe impl<U: Send,E: Send + wasm_runtime_layer::backend::WasmEngine + wasm_runtime_layer::backend::WasmEngine> Send for StoreCell<U,E>{}
|
||||||
|
unsafe impl<U: Sync,E: Sync + wasm_runtime_layer::backend::WasmEngine + wasm_runtime_layer::backend::WasmEngine> Sync for StoreCell<U,E>{}
|
||||||
|
impl<U,E: WasmEngine> StoreCell<U,E>{
|
||||||
|
pub unsafe fn get(&self) -> StoreContextMut<'_,U,E>{
|
||||||
|
unsafe{
|
||||||
|
&mut *self.wrapped.get()
|
||||||
|
}.as_context_mut()
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
pit-core = { version = "0.1.0", path = "../pit-core" }
|
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"
|
proc-macro2 = "1.0.85"
|
||||||
quasiquote = "0.1.1"
|
quasiquote = "0.1.1"
|
||||||
quote = "1.0.36"
|
quote = "1.0.36"
|
||||||
|
|
|
@ -1,121 +1,247 @@
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
|
|
||||||
use pit_core::{Arg, Interface, Sig};
|
use pit_core::{Arg, Interface, ResTy, Sig};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::{Span, TokenStream};
|
||||||
use quasiquote::quasiquote;
|
use quasiquote::quasiquote;
|
||||||
use quote::{format_ident, quote, ToTokens};
|
use quote::{format_ident, quote, ToTokens};
|
||||||
use syn::{spanned::Spanned, Ident, Index};
|
use syn::{spanned::Spanned, Ident, Index};
|
||||||
pub fn render(root: &TokenStream, i: &Interface) -> TokenStream {
|
pub struct Opts {
|
||||||
let id = format_ident!("R{}", i.rid_str());
|
pub guest: Option<pit_rust_guest::Opts>,
|
||||||
let internal = format_ident!("{id}_utils");
|
}
|
||||||
|
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)| {
|
let methods = i.methods.iter().map(|(a, b)| {
|
||||||
quasiquote! {
|
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 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 = b
|
||||||
let init = once(quote!{#root::wasm_runtime_layer::Value::I32(self.base as i32)}).chain(init);
|
.params
|
||||||
let fini = b.rets.iter().enumerate().map(|(ri,r)|{
|
.iter()
|
||||||
quasiquote!{
|
.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]})}
|
#{render_base_val(root, r, quote! {&rets[#ri]})}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
quasiquote! {
|
quasiquote! {
|
||||||
fn #{format_ident!("{a}")}#{render_sig(root,b,"e! {&self})}{
|
fn #{format_ident!("{a}")}#{render_sig(root,b,"e! {&self},quote!{
|
||||||
let Some(#root::wasm_runtime_layer::Export::Func(f)) = self.instance.get_export(unsafe{
|
ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>
|
||||||
&*::std::cell::UnsafeCell::raw_get(self.ctx)
|
})}{
|
||||||
},#{format_ident!("pit/{}/{}",i.rid_str(),a)}) else{
|
let a = self.all[#{c+1}].clone();
|
||||||
panic!("invalid func")
|
|
||||||
};
|
|
||||||
let args = vec![#(#init),*];
|
let args = vec![#(#init),*];
|
||||||
let mut rets = vec![#root::wasm_runtime_layer::Value::I32(0);#{b.rets.len()}];
|
let mut rets = a(ctx,args);
|
||||||
f.call(unsafe{
|
|
||||||
&mut *::std::cell::UnsafeCell::raw_get(self.ctx)
|
|
||||||
},&args,&mut rets)?;
|
|
||||||
return Ok((#(#fini),*))
|
return Ok((#(#fini),*))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let injects = i.methods.iter().map(|(a,b)|{
|
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)|{
|
let fini = b.rets.iter().enumerate().map(|(ri,r)|{
|
||||||
quasiquote!{
|
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!{
|
quasiquote!{
|
||||||
let f = #root::wasm_runtime_layer::Func::new(ctx,#{render_blit_sig(root, b)},|ctx,args,rets|{
|
let r = a.clone();
|
||||||
#(#init),*
|
Arc::new(ctx,move|ctx,args|{
|
||||||
let #root::wasm_runtime_layer::Value::ExternRef(t) = &args[0] else{
|
let r = r.#{format_ident!("{a}")}(ctx,#(#init),*)
|
||||||
#root::anyhow::bail!("invalid param")
|
Ok(vec![#(#fini),*])
|
||||||
}
|
})
|
||||||
let r = match t.downcast::<'_,'_, ::std::sync::Arc<dyn #id<U,E>>,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>>,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<dyn #id<U,E>> = ::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);
|
|
||||||
}));
|
|
||||||
quasiquote! {
|
quasiquote! {
|
||||||
pub trait #id<U: 'static,E: #root::wasm_runtime_layer::backend::WasmEngine>{
|
pub trait #id<U: 'static,E: #root::wasm_runtime_layer::backend::WasmEngine>{
|
||||||
fn to_any(&self) -> &dyn ::std::any::Any;
|
|
||||||
#(#methods)*
|
#(#methods)*
|
||||||
|
unsafe fn finalize(&self, ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>) -> #root::anyhow::Result<()>;
|
||||||
}
|
}
|
||||||
mod #internal{
|
const _: () = {
|
||||||
use super::#id;
|
|
||||||
impl<U: 'static,E: #root::wasm_runtime_layer::backend::WasmEngine> #id<U,E> for #root::RWrapped<U,E>{
|
impl<U: 'static,E: #root::wasm_runtime_layer::backend::WasmEngine> #id<U,E> for #root::RWrapped<U,E>{
|
||||||
fn to_any(&self) -> &dyn ::std::any::Any{
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
#(#impls)*
|
#(#impls)*
|
||||||
|
unsafe fn finalize(&self, ctx: #root::wasm_runtime_layer::StoreContextMut<'_,U,E>) -> #root::anyhow::Result<()>{
|
||||||
|
self.all[0](ctx,vec![])?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
impl<U: 'static,E: #root::wasm_runtime_layer::backend::WasmEngine> From<Arc<dyn $id<U,E>> for #root::RWrapped<U,E>{
|
||||||
|
fn from(a: Arc<dyn $id<U,E>>) -> 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<U: 'static + AsRef<#root::wasm_runtime_layer::Instance>,E: #root::wasm_runtime_layer::backend::WasmEngine>(ctx: impl #root::wasm_runtime_layer::AsContextMut<UserState = U,Engine = E>, i: &mut #root::wasm_runtime_layer::Imports){
|
quote!{
|
||||||
#(#injects)*
|
#(#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<U,E>::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<U,E>::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<U,E>::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<U,E>::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<T>(::std::cell::UnsafeCell<Option<T>>);
|
||||||
|
impl<U: 'static + Clone,E: #root::wasm_runtime_layer::backend::WasmEngine> #pid for #root::W<#root::RWrapped<U,E>,U,E>{
|
||||||
|
#(#impl_guest)*
|
||||||
|
}
|
||||||
|
impl<U: 'static + Clone,E: #root::wasm_runtime_layer::backend::WasmEngine, X: #pid> #id<U,E> for Compat<X>{
|
||||||
|
#(#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<Box<dyn #pid>> for Arc<dyn #id>{
|
||||||
|
fn from(p: Box<dyn #pid>) -> 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
|
let params = s
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|a| render_ty(root, a))
|
.map(|a| render_ty(root, a))
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(a, b)| quasiquote!(#{format_ident!("p{a}")} : #b));
|
.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));
|
let rets = s.rets.iter().map(|a| render_ty(root, a));
|
||||||
quote! {
|
quote! {
|
||||||
(#(#params),*) -> #root::anyhow::Result<(#(#rets),*)>
|
(#(#params),*) -> #root::anyhow::Result<(#(#rets),*)>
|
||||||
|
@ -168,13 +294,18 @@ pub fn render_ty(root: &TokenStream, p: &Arg) -> TokenStream {
|
||||||
Arg::F64 => quote! {
|
Arg::F64 => quote! {
|
||||||
f64
|
f64
|
||||||
},
|
},
|
||||||
Arg::Resource { ty, nullable } => match ty {
|
Arg::Resource {
|
||||||
None => quote! {
|
ty,
|
||||||
|
nullable,
|
||||||
|
take,
|
||||||
|
ann,
|
||||||
|
} => match ty {
|
||||||
|
ResTy::None => quote! {
|
||||||
#root::wasm_runtime_layer::ExternRef
|
#root::wasm_runtime_layer::ExternRef
|
||||||
},
|
},
|
||||||
Some(a) => {
|
_ => {
|
||||||
let a = quasiquote! {
|
let a = quasiquote! {
|
||||||
::std::sync::Arc<dyn #{format_ident!("R{}",hex::encode(a))}<U,E>>
|
::std::sync::Arc<#root::Wrapped<U,E>>
|
||||||
};
|
};
|
||||||
if *nullable {
|
if *nullable {
|
||||||
quote! {Option<#a>}
|
quote! {Option<#a>}
|
||||||
|
@ -207,21 +338,24 @@ pub fn render_base_val(root: &TokenStream, p: &Arg, x: TokenStream) -> TokenStre
|
||||||
#root::anyhow::bail!("invalid param")
|
#root::anyhow::bail!("invalid param")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Arg::Resource { ty, nullable } => {
|
Arg::Resource {
|
||||||
|
ty,
|
||||||
|
nullable,
|
||||||
|
take,
|
||||||
|
ann,
|
||||||
|
} => {
|
||||||
let mut a = quote! {
|
let mut a = quote! {
|
||||||
let #root::wasm_runtime_layer::Value::ExternRef(t) = #x else{
|
let #root::wasm_runtime_layer::Value::ExternRef(t) = #x else{
|
||||||
#root::anyhow::bail!("invalid param")
|
#root::anyhow::bail!("invalid param")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(r) = ty.as_ref() {
|
if !matches!(ty, ResTy::None) {
|
||||||
quasiquote!{
|
quasiquote!{
|
||||||
let t = match t{None => None,Some(t) => Some(match t.downcast::<'_,'_, ::std::sync::Arc<dyn #{format_ident!("R{}",hex::encode(r))}<U,E>>,U,E>(ctx){
|
let t = match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped<U,E>>,U,E>(ctx){
|
||||||
Ok(t) => t.clone(),
|
|
||||||
Err(_) => match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped<U,E>>,U,E>(ctx){
|
|
||||||
Ok(t) => Arc::new(t.clone()),
|
Ok(t) => Arc::new(t.clone()),
|
||||||
Err(_) => #root::anyhow::bail!("invalid param")
|
Err(_) => #root::anyhow::bail!("invalid param")
|
||||||
}
|
}
|
||||||
})}
|
|
||||||
}.to_tokens(&mut a);
|
}.to_tokens(&mut a);
|
||||||
}
|
}
|
||||||
if !*nullable {
|
if !*nullable {
|
||||||
|
@ -256,33 +390,40 @@ pub fn render_new_val(root: &TokenStream, p: &Arg, t: TokenStream) -> TokenStrea
|
||||||
Arg::F64 => quote! {
|
Arg::F64 => quote! {
|
||||||
#root::wasm_runtime_layer::Value::F64(#t)
|
#root::wasm_runtime_layer::Value::F64(#t)
|
||||||
},
|
},
|
||||||
Arg::Resource { ty, nullable } => {
|
Arg::Resource {
|
||||||
let tq = |t:TokenStream|quasiquote! {
|
ty,
|
||||||
{
|
nullable,
|
||||||
let t = #t;
|
take,
|
||||||
#{match ty{
|
ann,
|
||||||
None => quote! { #root::wasm_runtime_layer::ExternRef::new(ctx,t)},
|
} => {
|
||||||
Some(_) => quote! {
|
let tq = |t: TokenStream| {
|
||||||
match t.to_any().downcast_ref::<::std::sync::Arc<#root::Wrapped<U,E>>>(){
|
quasiquote! {
|
||||||
None => #root::wasm_runtime_layer::ExternRef::new(ctx,t),
|
{
|
||||||
Some(t) => #root::wasm_runtime_layer::ExternRef::new(ctx,t.clone()),
|
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<U,E>>>(){
|
||||||
|
None => #root::wasm_runtime_layer::ExternRef::new(ctx,t),
|
||||||
|
Some(t) => #root::wasm_runtime_layer::ExternRef::new(ctx,t.clone()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if !*nullable {
|
if !*nullable {
|
||||||
quasiquote! {
|
quasiquote! {
|
||||||
#root::wasm_runtime_layer::Value::ExternRef(Some(#{match ty{
|
#root::wasm_runtime_layer::Value::ExternRef(Some(#{match ty{
|
||||||
None => t,
|
ResTy::None => t,
|
||||||
Some(_) => tq(t)
|
_ => tq(t)
|
||||||
}}))
|
}}))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quasiquote! {
|
quasiquote! {
|
||||||
#root::wasm_runtime_layer::Value::ExternRef(#{match ty{
|
#root::wasm_runtime_layer::Value::ExternRef(#{match ty{
|
||||||
None => t,
|
ResTy::None => t,
|
||||||
Some(_) => quasiquote! {#t.map(|t|#{tq(quote! {t})})}
|
_ => quasiquote! {#t.map(|t|#{tq(quote! {t})})}
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
6
tpit-rt/Cargo.toml
Normal file
6
tpit-rt/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "tpit-rt"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
58
tpit-rt/src/lib.rs
Normal file
58
tpit-rt/src/lib.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use std::{
|
||||||
|
marker::PhantomData,
|
||||||
|
mem::forget,
|
||||||
|
num::NonZeroU32,
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicUsize, Ordering},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct Tpit<D> {
|
||||||
|
ptr: Option<NonZeroU32>,
|
||||||
|
phantom: PhantomData<D>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D> Drop for Tpit<D> {
|
||||||
|
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<D> Tpit<D> {
|
||||||
|
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<U>(self) -> Tpit<U> {
|
||||||
|
unsafe { Tpit::<U>::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) }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue