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 = [
|
||||
"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"
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -67,6 +67,28 @@ const _: () = {
|
|||
125u8,
|
||||
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
|
||||
for ::externref::Resource<
|
||||
Box<dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5>,
|
||||
|
@ -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<Box<dyn R867207405fe87fda620c2d7a5485e8e5e274636a898a166fb674448b4391ffc5>>
|
||||
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)) };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -67,6 +67,28 @@ const _: () = {
|
|||
125u8,
|
||||
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
|
||||
for ::externref::Resource<
|
||||
Box<dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d>,
|
||||
|
@ -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<Box<dyn R68da167712ddf1601aed7908c99972e62a41bdea1e28b241306a6b58d29e532d>>
|
||||
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)) };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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<Func> {
|
||||
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();
|
||||
}
|
||||
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(),
|
||||
tpit: false,
|
||||
};
|
||||
|
||||
let v = pit_rust_guest::render(&x, &src);
|
||||
|
|
|
@ -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<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 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<Box<dyn #id2>>})};
|
||||
}
|
||||
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<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! {
|
||||
#[#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<dyn #id2>})}{
|
||||
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::<Vec<_>>();
|
||||
quasiquote!{
|
||||
let sc = sb
|
||||
.as_bytes()
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(once(0u8))
|
||||
.collect::<Vec<_>>();
|
||||
quasiquote! {
|
||||
pub trait #id2{
|
||||
#(#methods)*
|
||||
}
|
||||
|
@ -63,27 +134,42 @@ pub fn render(opts: &Opts, i: &Interface) -> TokenStream{
|
|||
[#(#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)*
|
||||
}
|
||||
#[#root::externref::externref(crate = #{quote! {#root::externref}.to_string()})]
|
||||
#[export_name = #{format!("pit/{id}/~{ha}.drop")}]
|
||||
extern "C" fn _drop(a: *mut Box<dyn #id2>){
|
||||
#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<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{
|
||||
#[#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<dyn #id2>) -> #root::externref::Resource<Box<dyn #id2>>;
|
||||
fn _push(a: u32) -> #res<Box<dyn #id2>>;
|
||||
}
|
||||
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<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())}>>
|
||||
Arg::Resource {
|
||||
ty,
|
||||
nullable,
|
||||
take,
|
||||
ann,
|
||||
} => {
|
||||
if !opts.tpit {
|
||||
let ty = match ty {
|
||||
ResTy::Of(a) => quasiquote! {
|
||||
#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
|
||||
};
|
||||
let ty = if *take{
|
||||
ty
|
||||
}else{
|
||||
quote! {&mut #ty}
|
||||
};
|
||||
ty
|
||||
},
|
||||
}
|
||||
}
|
||||
// Arg::Func(_) => todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<U: AsRef<Instance> + 'static, E: WasmEngine>(
|
||||
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 extern crate anyhow;
|
||||
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]
|
||||
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"
|
||||
|
|
|
@ -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<pit_rust_guest::Opts>,
|
||||
}
|
||||
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<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);
|
||||
}));
|
||||
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<U: 'static,E: #root::wasm_runtime_layer::backend::WasmEngine>{
|
||||
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<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)*
|
||||
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){
|
||||
#(#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<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
|
||||
.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<dyn #{format_ident!("R{}",hex::encode(a))}<U,E>>
|
||||
::std::sync::Arc<#root::Wrapped<U,E>>
|
||||
};
|
||||
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<dyn #{format_ident!("R{}",hex::encode(r))}<U,E>>,U,E>(ctx){
|
||||
Ok(t) => t.clone(),
|
||||
Err(_) => match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped<U,E>>,U,E>(ctx){
|
||||
let t = match t.downcast::<'_,'_, ::std::sync::Arc<#root::Wrapped<U,E>>,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<U,E>>>(){
|
||||
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<U,E>>>(){
|
||||
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})})}
|
||||
}})
|
||||
}
|
||||
}
|
||||
|
|
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