more stuff
This commit is contained in:
parent
ad1a16d150
commit
6c87f4f9b8
913
Cargo.lock
generated
913
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members=[ "wars", "wars-macro","wars-rt", "wars-test"]
|
members=[ "waffle-func-reloop", "wars", "wars-component", "wars-macro","wars-rt", "wars-test"]
|
||||||
resolver="2"
|
resolver="2"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
|
10
waffle-func-reloop/Cargo.toml
Normal file
10
waffle-func-reloop/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "waffle-func-reloop"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
portal-pc-waffle.workspace = true
|
||||||
|
relooper = "0.1.0"
|
40
waffle-func-reloop/src/lib.rs
Normal file
40
waffle-func-reloop/src/lib.rs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
use relooper::ShapedBlock;
|
||||||
|
use waffle::{cfg::CFGInfo, Block, FunctionBody};
|
||||||
|
|
||||||
|
pub fn go(b: &FunctionBody) -> Box<ShapedBlock<Block>> {
|
||||||
|
let cfg = CFGInfo::new(b);
|
||||||
|
let reloop = std::panic::catch_unwind(|| {
|
||||||
|
relooper::reloop(
|
||||||
|
b.blocks
|
||||||
|
.entries()
|
||||||
|
.filter(|k| cfg.dominates(b.entry, k.0))
|
||||||
|
.map(|(k, l)| {
|
||||||
|
(
|
||||||
|
k,
|
||||||
|
l.succs
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.chain(b.blocks.iter().filter(|x| cfg.dominates(*x, k)))
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
// .chain(once((Block::invalid(), vec![b.entry])))
|
||||||
|
.collect(),
|
||||||
|
// Block::invalid(),
|
||||||
|
b.entry,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
let reloop = match reloop {
|
||||||
|
Ok(a) => a,
|
||||||
|
Err(e) => {
|
||||||
|
panic!(
|
||||||
|
"reloop failure ({}) in {}",
|
||||||
|
e.downcast_ref::<&str>()
|
||||||
|
.map(|a| *a)
|
||||||
|
.unwrap_or("unknown panic"),
|
||||||
|
b.display("", None)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reloop
|
||||||
|
}
|
14
wars-component/Cargo.toml
Normal file
14
wars-component/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "wars-component"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
golem-wasm-ast = "0.2.2"
|
||||||
|
proc-macro2 = "1.0.85"
|
||||||
|
quasiquote = "0.1.1"
|
||||||
|
quote = "1.0.36"
|
||||||
|
syn = "2.0.66"
|
||||||
|
wars = { version = "0.1.0", path = "../wars" }
|
6
wars-component/src/lib.rs
Normal file
6
wars-component/src/lib.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
pub trait Component{
|
||||||
|
|
||||||
|
}
|
||||||
|
impl Component for Opts<golem_wasm_ast::Component>{
|
||||||
|
|
||||||
|
}
|
|
@ -11,9 +11,9 @@ proc-macro2 = "1.0.85"
|
||||||
quote = "1.0.36"
|
quote = "1.0.36"
|
||||||
syn = "2.0.66"
|
syn = "2.0.66"
|
||||||
wars = { version = "0.1.0", path = "../wars" }
|
wars = { version = "0.1.0", path = "../wars" }
|
||||||
wars-rt = { version = "0.1.0", path = "../wars-rt" }
|
|
||||||
wat = "1.209.1"
|
wat = "1.209.1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
wars-rt = { version = "0.1.0", path = "../wars-rt" }
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
use std::sync::Arc;
|
use std::{collections::BTreeMap, sync::Arc};
|
||||||
|
|
||||||
use expander::{Edition, Expander};
|
use expander::{Edition, Expander};
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{parse::Parse, parse_macro_input, Ident, Path, Token};
|
use syn::{parse::Parse, parse_macro_input, Ident, LitBool, Path, Token};
|
||||||
use wars::Opts;
|
use wars::{Flags, Opts};
|
||||||
|
|
||||||
struct O {
|
struct O {
|
||||||
pub crate_path: syn::Path,
|
pub crate_path: syn::Path,
|
||||||
pub module: Vec<u8>,
|
pub module: Vec<u8>,
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
// pub cfg: Arc<dyn ImportCfg>,
|
pub flags: Flags,
|
||||||
|
pub embed: proc_macro2::TokenStream,
|
||||||
|
pub data: BTreeMap<Ident, proc_macro2::TokenStream>, // pub cfg: Arc<dyn ImportCfg>,
|
||||||
}
|
}
|
||||||
// struct NoopCfg {}
|
// struct NoopCfg {}
|
||||||
// impl ImportCfg for NoopCfg {
|
// impl ImportCfg for NoopCfg {
|
||||||
|
@ -27,6 +29,9 @@ impl Parse for O {
|
||||||
crate_path: syn::parse(quote! {::wars_rt}.into())?,
|
crate_path: syn::parse(quote! {::wars_rt}.into())?,
|
||||||
module: vec![],
|
module: vec![],
|
||||||
name: Ident::new("Wars", Span::call_site()),
|
name: Ident::new("Wars", Span::call_site()),
|
||||||
|
flags: Default::default(),
|
||||||
|
embed: Default::default(),
|
||||||
|
data: BTreeMap::new(),
|
||||||
// cfg: Arc::new(NoopCfg {}),
|
// cfg: Arc::new(NoopCfg {}),
|
||||||
};
|
};
|
||||||
while input.lookahead1().peek(Ident) {
|
while input.lookahead1().peek(Ident) {
|
||||||
|
@ -59,6 +64,22 @@ impl Parse for O {
|
||||||
"name" => {
|
"name" => {
|
||||||
o.name = input.parse()?;
|
o.name = input.parse()?;
|
||||||
}
|
}
|
||||||
|
"r#async" => {
|
||||||
|
let b: LitBool = input.parse()?;
|
||||||
|
if b.value {
|
||||||
|
o.flags |= Flags::ASYNC
|
||||||
|
} else {
|
||||||
|
o.flags &= Flags::ASYNC.complement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"legacy_host" => {
|
||||||
|
let b: LitBool = input.parse()?;
|
||||||
|
if b.value {
|
||||||
|
o.flags |= Flags::LEGACY
|
||||||
|
} else {
|
||||||
|
o.flags &= Flags::LEGACY.complement();
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => return Err(syn::Error::new(i.span(), "unexpected type")),
|
_ => return Err(syn::Error::new(i.span(), "unexpected type")),
|
||||||
};
|
};
|
||||||
let _comma: Token![,] = input.parse()?;
|
let _comma: Token![,] = input.parse()?;
|
||||||
|
@ -73,12 +94,18 @@ impl Parse for O {
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn wars(a: TokenStream) -> TokenStream {
|
pub fn wars(a: TokenStream) -> TokenStream {
|
||||||
let o = parse_macro_input!(a as O);
|
let o = parse_macro_input!(a as O);
|
||||||
let x = wars::go(&Opts {
|
let x = wars::go(
|
||||||
|
&Opts {
|
||||||
crate_path: o.crate_path,
|
crate_path: o.crate_path,
|
||||||
module: o.module,
|
module: o.module,
|
||||||
name: o.name,
|
name: o.name,
|
||||||
|
flags: o.flags,
|
||||||
|
embed: o.embed,
|
||||||
|
data: o.data,
|
||||||
// cfg: o.cfg,
|
// cfg: o.cfg,
|
||||||
});
|
}
|
||||||
|
.to_mod(),
|
||||||
|
);
|
||||||
let expanded = Expander::new("wars")
|
let expanded = Expander::new("wars")
|
||||||
.add_comment("This is generated code!".to_owned())
|
.add_comment("This is generated code!".to_owned())
|
||||||
.fmt(Edition::_2021)
|
.fmt(Edition::_2021)
|
||||||
|
@ -92,3 +119,20 @@ pub fn wars(a: TokenStream) -> TokenStream {
|
||||||
});
|
});
|
||||||
expanded.into()
|
expanded.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[proc_macro]
|
||||||
|
// pub fn wasix(a: TokenStream) -> TokenStream {
|
||||||
|
// let x = wars::wasix::wasix();
|
||||||
|
// let expanded = Expander::new("wars_wasix")
|
||||||
|
// .add_comment("This is generated code!".to_owned())
|
||||||
|
// .fmt(Edition::_2021)
|
||||||
|
// .verbose(true)
|
||||||
|
// // common way of gating this, by making it part of the default feature set
|
||||||
|
// .dry(cfg!(feature = "no-file-expansion"))
|
||||||
|
// .write_to_out_dir(x.clone())
|
||||||
|
// .unwrap_or_else(|e| {
|
||||||
|
// eprintln!("Failed to write to file: {:?}", e);
|
||||||
|
// x
|
||||||
|
// });
|
||||||
|
// expanded.into()
|
||||||
|
// }
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
wars_macro::wars!(
|
wars_macro::wars!(
|
||||||
file = "target/wasm32-unknown-unknown/debug/wars_test.wasm",
|
file = "target/wasm32-unknown-unknown/debug/wars_test.wasm",
|
||||||
|
r#async = true,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn x<A: Wars>(){
|
fn x<A: Wars>(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,3 +12,5 @@ derive_more = "0.99.17"
|
||||||
paste = "1.0.15"
|
paste = "1.0.15"
|
||||||
tramp = "0.3.0"
|
tramp = "0.3.0"
|
||||||
tuple_list = "0.1.3"
|
tuple_list = "0.1.3"
|
||||||
|
wars-macro = { version = "0.1.0", path = "../wars-macro" }
|
||||||
|
wasm_runtime_layer = "0.4.0"
|
||||||
|
|
|
@ -2,6 +2,10 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use tramp::{tramp, BorrowRec, Thunk};
|
use tramp::{tramp, BorrowRec, Thunk};
|
||||||
|
pub mod unsync;
|
||||||
|
pub fn ret<'a,T>(a: T) -> BorrowRec<'a,T>{
|
||||||
|
BorrowRec::Ret(a)
|
||||||
|
}
|
||||||
pub trait CtxSpec: Sized {
|
pub trait CtxSpec: Sized {
|
||||||
type ExternRef: Clone;
|
type ExternRef: Clone;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +20,7 @@ pub enum Value<C: CtxSpec> {
|
||||||
&'a mut C,
|
&'a mut C,
|
||||||
Vec<Value<C>>,
|
Vec<Value<C>>,
|
||||||
) -> tramp::BorrowRec<'a, anyhow::Result<Vec<Value<C>>>>
|
) -> tramp::BorrowRec<'a, anyhow::Result<Vec<Value<C>>>>
|
||||||
+ 'static,
|
+ Send + Sync + 'static,
|
||||||
>,
|
>,
|
||||||
),
|
),
|
||||||
Null,
|
Null,
|
||||||
|
@ -140,13 +144,13 @@ pub fn map_rec<'a, T: 'a, U>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub type Df<A, B, C> =
|
pub type Df<A, B, C> =
|
||||||
Arc<dyn for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + 'static>;
|
Arc<dyn for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + Send + Sync + 'static>;
|
||||||
|
|
||||||
pub fn da<
|
pub fn da<
|
||||||
A,
|
A,
|
||||||
B,
|
B,
|
||||||
C,
|
C,
|
||||||
F: for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + 'static,
|
F: for<'a> Fn(&'a mut C, A) -> tramp::BorrowRec<'a, anyhow::Result<B>> + Send + Sync + 'static,
|
||||||
>(
|
>(
|
||||||
f: F,
|
f: F,
|
||||||
) -> Df<A,B,C> {
|
) -> Df<A,B,C> {
|
||||||
|
|
207
wars-rt/src/func/unsync.rs
Normal file
207
wars-rt/src/func/unsync.rs
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
use std::{future::Future, pin::Pin, sync::Arc};
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
|
// use tramp::{tramp, BorrowRec, Thunk};
|
||||||
|
pub fn ret<'a,T>(a: T) -> AsyncRec<'a,T>{
|
||||||
|
AsyncRec::Ret(a)
|
||||||
|
}
|
||||||
|
pub enum AsyncRec<'a,T>{
|
||||||
|
Ret(T),
|
||||||
|
Async(Pin<Box<dyn Future<Output = AsyncRec<'a,T>> + Send + Sync + 'a>>)
|
||||||
|
}
|
||||||
|
impl<'a,T> AsyncRec<'a,T>{
|
||||||
|
pub async fn go(mut self) -> T{
|
||||||
|
loop{
|
||||||
|
self = match self{
|
||||||
|
AsyncRec::Ret(r) => return r,
|
||||||
|
AsyncRec::Async(a) => a.await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub trait CtxSpec: Sized {
|
||||||
|
type ExternRef: Clone;
|
||||||
|
}
|
||||||
|
pub enum Value<C: CtxSpec> {
|
||||||
|
I32(u32),
|
||||||
|
I64(u64),
|
||||||
|
F32(f32),
|
||||||
|
F64(f64),
|
||||||
|
FunRef(
|
||||||
|
Arc<
|
||||||
|
dyn for<'a> Fn(
|
||||||
|
&'a mut C,
|
||||||
|
Vec<Value<C>>,
|
||||||
|
) -> AsyncRec<'a, anyhow::Result<Vec<Value<C>>>>
|
||||||
|
+ Send + Sync + 'static,
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
Null,
|
||||||
|
ExRef(C::ExternRef),
|
||||||
|
}
|
||||||
|
pub fn call_ref<'a, A: CoeVec<C> + 'static, B: CoeVec<C> + 'static, C: CtxSpec + 'static>(
|
||||||
|
ctx: &'a mut C,
|
||||||
|
go: Df<A,B,C>,
|
||||||
|
a: A,
|
||||||
|
) -> AsyncRec<'a, anyhow::Result<B>> {
|
||||||
|
// let go: Df<A, B, C> = cast(go);
|
||||||
|
go(ctx, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: CtxSpec> Clone for Value<C> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::I32(arg0) => Self::I32(arg0.clone()),
|
||||||
|
Self::I64(arg0) => Self::I64(arg0.clone()),
|
||||||
|
Self::F32(arg0) => Self::F32(arg0.clone()),
|
||||||
|
Self::F64(arg0) => Self::F64(arg0.clone()),
|
||||||
|
Self::FunRef(arg0) => Self::FunRef(arg0.clone()),
|
||||||
|
Self::Null => Self::Null,
|
||||||
|
Self::ExRef(e) => Self::ExRef(e.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub trait Coe<C: CtxSpec>: Sized {
|
||||||
|
fn coe(self) -> Value<C>;
|
||||||
|
fn uncoe(x: Value<C>) -> anyhow::Result<Self>;
|
||||||
|
}
|
||||||
|
pub fn cast<A: Coe<C> + 'static, B: Coe<C> + 'static, C: CtxSpec>(a: A) -> B {
|
||||||
|
let a = match castaway::cast!(a, B) {
|
||||||
|
Ok(b) => return b,
|
||||||
|
Err(a) => a,
|
||||||
|
};
|
||||||
|
B::uncoe(A::coe(a)).unwrap()
|
||||||
|
}
|
||||||
|
impl<C: CtxSpec> Coe<C> for Value<C> {
|
||||||
|
fn coe(self) -> Value<C> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
|
||||||
|
Ok(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<C: CtxSpec, D: Coe<C>> Coe<C> for Option<D> {
|
||||||
|
fn coe(self) -> Value<C> {
|
||||||
|
match self {
|
||||||
|
None => Value::Null,
|
||||||
|
Some(d) => d.coe(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
|
||||||
|
if let Value::Null = x {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
return Ok(Some(D::uncoe(x)?));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
macro_rules! coe_impl_prim {
|
||||||
|
($a:tt in $b:ident) => {
|
||||||
|
impl<C: CtxSpec> Coe<C> for $a {
|
||||||
|
fn coe(self) -> Value<C> {
|
||||||
|
Value::$b(self)
|
||||||
|
}
|
||||||
|
fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
|
||||||
|
match x {
|
||||||
|
Value::$b(a) => Ok(a),
|
||||||
|
_ => anyhow::bail!("invalid type"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
coe_impl_prim!(u32 in I32);
|
||||||
|
coe_impl_prim!(u64 in I64);
|
||||||
|
coe_impl_prim!(f32 in F32);
|
||||||
|
coe_impl_prim!(f64 in F64);
|
||||||
|
pub trait CoeVec<C: CtxSpec>: Sized {
|
||||||
|
fn coe(self) -> Vec<Value<C>>;
|
||||||
|
fn uncoe(a: Vec<Value<C>>) -> anyhow::Result<Self>;
|
||||||
|
}
|
||||||
|
impl<C: CtxSpec> CoeVec<C> for () {
|
||||||
|
fn coe(self) -> Vec<Value<C>> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uncoe(a: Vec<Value<C>>) -> anyhow::Result<Self> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<C: CtxSpec, A: Coe<C>, B: CoeVec<C>> CoeVec<C> for (A, B) {
|
||||||
|
fn coe(self) -> Vec<Value<C>> {
|
||||||
|
let mut a = self.1.coe();
|
||||||
|
a.push(self.0.coe());
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uncoe(mut a: Vec<Value<C>>) -> anyhow::Result<Self> {
|
||||||
|
let Some(x) = a.pop() else {
|
||||||
|
anyhow::bail!("list too small")
|
||||||
|
};
|
||||||
|
let y = A::uncoe(x).context("invalid item (note coe lists are REVERSED)")?;
|
||||||
|
let z = B::uncoe(a)?;
|
||||||
|
Ok((y, z))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn map_rec<'a, T: 'a, U>(
|
||||||
|
r: AsyncRec<'a, T>,
|
||||||
|
go: impl FnOnce(T) -> U + Send + Sync + 'a,
|
||||||
|
) -> AsyncRec<'a, U> {
|
||||||
|
match r {
|
||||||
|
AsyncRec::Ret(x) => AsyncRec::Ret(go(x)),
|
||||||
|
AsyncRec::Async(a) => AsyncRec::Async(Box::pin(async move{
|
||||||
|
let v = a.await;
|
||||||
|
map_rec(v, go)
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub type Df<A, B, C> =
|
||||||
|
Arc<dyn for<'a> Fn(&'a mut C, A) -> AsyncRec<'a, anyhow::Result<B>> + Send + Sync + 'static>;
|
||||||
|
|
||||||
|
pub fn da<
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
F: for<'a> Fn(&'a mut C, A) -> AsyncRec<'a, anyhow::Result<B>> + Send + Sync + 'static,
|
||||||
|
>(
|
||||||
|
f: F,
|
||||||
|
) -> Df<A,B,C> {
|
||||||
|
Arc::new(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: CtxSpec + 'static, A: CoeVec<C> + 'static, B: CoeVec<C> + 'static> Coe<C> for Df<A, B, C> {
|
||||||
|
fn coe(self) -> Value<C> {
|
||||||
|
pub fn x<
|
||||||
|
C: CtxSpec,
|
||||||
|
T: for<'a> Fn(
|
||||||
|
&'a mut C,
|
||||||
|
Vec<Value<C>>,
|
||||||
|
) -> AsyncRec<'a, anyhow::Result<Vec<Value<C>>>>
|
||||||
|
+ 'static,
|
||||||
|
>(
|
||||||
|
a: T,
|
||||||
|
) -> T {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
Value::FunRef(Arc::new(x(move |ctx, x| {
|
||||||
|
let x = match A::uncoe(x) {
|
||||||
|
Ok(x) => x,
|
||||||
|
Err(e) => return AsyncRec::Ret(Err(e)),
|
||||||
|
};
|
||||||
|
let x = self(ctx, x);
|
||||||
|
map_rec(x, |a| a.map(|b| b.coe()))
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn uncoe(x: Value<C>) -> anyhow::Result<Self> {
|
||||||
|
let Value::FunRef(x) = x else {
|
||||||
|
anyhow::bail!("invalid value")
|
||||||
|
};
|
||||||
|
Ok(Arc::new(move |ctx, a| {
|
||||||
|
let v = a.coe();
|
||||||
|
let v = x(ctx, v);
|
||||||
|
map_rec(v, |a| a.and_then(B::uncoe))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,85 @@
|
||||||
pub mod func;
|
pub mod func;
|
||||||
|
pub mod wrl;
|
||||||
|
pub mod wasix;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
// use as_ref::AsSlice;
|
||||||
use func::CtxSpec;
|
use func::CtxSpec;
|
||||||
pub use func::Value;
|
pub use func::Value;
|
||||||
|
pub trait Memory {
|
||||||
|
fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>>;
|
||||||
|
fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()>;
|
||||||
|
fn size(&self) -> anyhow::Result<usize>;
|
||||||
|
fn grow(&mut self, x: usize) -> anyhow::Result<()>;
|
||||||
|
}
|
||||||
|
impl Memory for Vec<u8> {
|
||||||
|
fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>>{
|
||||||
|
Ok(Box::new(&self[a..][..s]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()> {
|
||||||
|
self[a..][..x.len()].copy_from_slice(x);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> anyhow::Result<usize> {
|
||||||
|
Ok(self.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grow(&mut self, x: usize) -> anyhow::Result<()> {
|
||||||
|
self.extend((0..x).map(|a| 0u8));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<T: Memory> Memory for Arc<Mutex<T>>{
|
||||||
|
fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>> {
|
||||||
|
let l = self.lock().unwrap();
|
||||||
|
let r = l.read(a, s)?;
|
||||||
|
return Ok(Box::new(r.as_ref().as_ref().to_vec()));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()> {
|
||||||
|
let mut l = self.lock().unwrap();
|
||||||
|
return l.write(a, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> anyhow::Result<usize> {
|
||||||
|
let l = self.lock().unwrap();
|
||||||
|
return l.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grow(&mut self, x: usize) -> anyhow::Result<()> {
|
||||||
|
let mut l = self.lock().unwrap();
|
||||||
|
return l.grow(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub unsafe fn host_memory() -> impl Memory{
|
||||||
|
struct W{}
|
||||||
|
impl Memory for W{
|
||||||
|
fn read<'a>(&'a self, a: usize, s: usize) -> anyhow::Result<Box<dyn AsRef<[u8]> + 'a>> {
|
||||||
|
return Ok(Box::new(unsafe{
|
||||||
|
std::slice::from_raw_parts(a as *const u8, s)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, a: usize, x: &[u8]) -> anyhow::Result<()> {
|
||||||
|
let n = unsafe{
|
||||||
|
std::slice::from_raw_parts_mut(a as *mut u8, x.len())
|
||||||
|
};
|
||||||
|
n.copy_from_slice(x);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> anyhow::Result<usize> {
|
||||||
|
anyhow::bail!("host memory cannot use size")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grow(&mut self, x: usize) -> anyhow::Result<()> {
|
||||||
|
anyhow::bail!("host memory cannot use grow")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return W{};
|
||||||
|
}
|
||||||
pub mod _rexport {
|
pub mod _rexport {
|
||||||
pub use anyhow;
|
pub use anyhow;
|
||||||
pub use tramp;
|
pub use tramp;
|
||||||
|
@ -135,59 +213,61 @@ macro_rules! int_ty{
|
||||||
Ok(tuple_list::tuple_list!(a.wrapping_sub(b)))
|
Ok(tuple_list::tuple_list!(a.wrapping_sub(b)))
|
||||||
}
|
}
|
||||||
//LOADS and STORES
|
//LOADS and STORES
|
||||||
pub fn [<$p load>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
pub fn [<$p load>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||||
let r = &a[b.try_into()?..][..std::mem::size_of::<$int>()];
|
let r = a.read(b.try_into()?,std::mem::size_of::<$int>())?;
|
||||||
Ok(tuple_list::tuple_list!($int::from_ne_bytes(r.try_into()?)))
|
Ok(tuple_list::tuple_list!($int::from_ne_bytes(r.as_ref().as_ref().try_into()?)))
|
||||||
}
|
}
|
||||||
pub fn [<$p store>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
pub fn [<$p store>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||||
let mut r = &mut a[b.try_into()?..][..std::mem::size_of::<$int>()];
|
// let mut r = &mut a[b.try_into()?..][..std::mem::size_of::<$int>()];
|
||||||
r.copy_from_slice(&c.to_ne_bytes());
|
// r.copy_from_slice(&c.to_ne_bytes());
|
||||||
|
a.write(b.try_into()?,&c.to_ne_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
//8 BIT
|
//8 BIT
|
||||||
pub fn [<$p load8u>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
pub fn [<$p load8u>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||||
let r = a[b.try_into()?..][0];
|
let r = a.read(b.try_into()?,1)?.as_ref().as_ref()[0];
|
||||||
Ok(tuple_list::tuple_list!(r as $int))
|
Ok(tuple_list::tuple_list!(r as $int))
|
||||||
}
|
}
|
||||||
pub fn [<$p load8s>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
pub fn [<$p load8s>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||||
let r = a[b.try_into()?..][0];
|
let r = a.read(b.try_into()?,1)?.as_ref().as_ref()[0];
|
||||||
Ok(tuple_list::tuple_list!(r as i8 as $p as $int))
|
Ok(tuple_list::tuple_list!(r as i8 as $p as $int))
|
||||||
}
|
}
|
||||||
pub fn [<$p store8>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
pub fn [<$p store8>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||||
let mut r = &mut a[b.try_into()?..][..1];
|
// let mut r = &mut a[b.try_into()?..][..1];
|
||||||
r[0] = (c & 0xff) as u8;
|
// r[0] = (c & 0xff) as u8;
|
||||||
|
a.write(b.try_into()?,&[(c & 0xff) as u8])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
//16 BIT
|
//16 BIT
|
||||||
pub fn [<$p load16u>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
pub fn [<$p load16u>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||||
let r = &a[b.try_into()?..][..2];
|
let r = a.read(b.try_into()?,2)?;
|
||||||
let r = u16::from_ne_bytes(r.try_into()?);
|
let r = u16::from_ne_bytes(r.as_ref().as_ref().try_into()?);
|
||||||
Ok(tuple_list::tuple_list!(r as $int))
|
Ok(tuple_list::tuple_list!(r as $int))
|
||||||
}
|
}
|
||||||
pub fn [<$p load16s>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
pub fn [<$p load16s>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||||
let r = &a[b.try_into()?..][..2];
|
let r = a.read(b.try_into()?,2)?;
|
||||||
let r = u16::from_ne_bytes(r.try_into()?);
|
let r = u16::from_ne_bytes(r.as_ref().as_ref().try_into()?);
|
||||||
Ok(tuple_list::tuple_list!(r as i16 as $p as $int))
|
Ok(tuple_list::tuple_list!(r as i16 as $p as $int))
|
||||||
}
|
}
|
||||||
pub fn [<$p store16>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
pub fn [<$p store16>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||||
let mut r = &mut a[b.try_into()?..][..2];
|
// let mut r = &mut a[b.try_into()?..][..2];
|
||||||
r.copy_from_slice(&((c & 0xff) as u16).to_ne_bytes());
|
a.write(b.try_into()?,&((c & 0xffff) as u16).to_ne_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
//32 BIT
|
//32 BIT
|
||||||
pub fn [<$p load32u>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
pub fn [<$p load32u>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||||
let r = &a[b.try_into()?..][..4];
|
let r = a.read(b.try_into()?,4)?;
|
||||||
let r = u32::from_ne_bytes(r.try_into()?);
|
let r = u32::from_ne_bytes(r.as_ref().as_ref().try_into()?);
|
||||||
Ok(tuple_list::tuple_list!(r as $int))
|
Ok(tuple_list::tuple_list!(r as $int))
|
||||||
}
|
}
|
||||||
pub fn [<$p load32s>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
pub fn [<$p load32s>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T) -> anyhow::Result<tuple_list::tuple_list_type!($int)> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||||
let r = &a[b.try_into()?..][..4];
|
let r = a.read(b.try_into()?,4)?;
|
||||||
let r = u32::from_ne_bytes(r.try_into()?);
|
let r = u32::from_ne_bytes(r.as_ref().as_ref().try_into()?);
|
||||||
Ok(tuple_list::tuple_list!(r as i32 as $p as $int))
|
Ok(tuple_list::tuple_list!(r as i32 as $p as $int))
|
||||||
}
|
}
|
||||||
pub fn [<$p store32>]<T: TryInto<usize>>(a: &mut Vec<u8>, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
pub fn [<$p store32>]<T: TryInto<usize>,M: Memory + ?Sized>(a: &mut M, b: T, c: $int) -> anyhow::Result<()> where T::Error: std::error::Error + Send + Sync + 'static{
|
||||||
let mut r = &mut a[b.try_into()?..][..4];
|
// let mut r = &mut a[b.try_into()?..][..4];
|
||||||
r.copy_from_slice(&((c & 0xffffff) as u32).to_ne_bytes());
|
a.write(b.try_into()?,&((c & 0xffffffff) as u32).to_ne_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
0
wars-rt/src/wasix.rs
Normal file
0
wars-rt/src/wasix.rs
Normal file
135
wars-rt/src/wrl.rs
Normal file
135
wars-rt/src/wrl.rs
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use wasm_runtime_layer::{AsContextMut, ExternRef, FuncType};
|
||||||
|
|
||||||
|
use crate::func::CtxSpec;
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum MetaType {
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
F32,
|
||||||
|
F64,
|
||||||
|
ExternRef,
|
||||||
|
FunRef {
|
||||||
|
params: Vec<MetaType>,
|
||||||
|
returns: Vec<MetaType>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
impl MetaType {
|
||||||
|
fn wrl(&self) -> wasm_runtime_layer::ValueType {
|
||||||
|
match self {
|
||||||
|
MetaType::I32 => wasm_runtime_layer::ValueType::I32,
|
||||||
|
MetaType::I64 => wasm_runtime_layer::ValueType::I64,
|
||||||
|
MetaType::F32 => wasm_runtime_layer::ValueType::F32,
|
||||||
|
MetaType::F64 => wasm_runtime_layer::ValueType::F64,
|
||||||
|
MetaType::ExternRef => wasm_runtime_layer::ValueType::ExternRef,
|
||||||
|
MetaType::FunRef { params, returns } => wasm_runtime_layer::ValueType::FuncRef,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn translate_in<C: CtxSpec + AsContextMut<UserState = D> + 'static, D: AsMut<C>>(
|
||||||
|
val: &crate::func::Value<C>,
|
||||||
|
ctx: &mut C,
|
||||||
|
wrl_ty: &MetaType,
|
||||||
|
) -> anyhow::Result<wasm_runtime_layer::Value>
|
||||||
|
where
|
||||||
|
C::ExternRef: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
Ok(match val {
|
||||||
|
crate::Value::I32(a) => wasm_runtime_layer::Value::I32(*a as i32),
|
||||||
|
crate::Value::I64(a) => wasm_runtime_layer::Value::I64(*a as i64),
|
||||||
|
crate::Value::F32(a) => wasm_runtime_layer::Value::F32(*a),
|
||||||
|
crate::Value::F64(a) => wasm_runtime_layer::Value::F64(*a),
|
||||||
|
crate::Value::FunRef(f) => {
|
||||||
|
// let wasm_runtime_layer::ValueType::FuncRef()
|
||||||
|
let MetaType::FunRef { params, returns } = wrl_ty.clone() else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
let ty = FuncType::new(
|
||||||
|
params.iter().map(|a| a.wrl()),
|
||||||
|
returns.iter().map(|a| a.wrl()),
|
||||||
|
);
|
||||||
|
let f = f.clone();
|
||||||
|
wasm_runtime_layer::Value::FuncRef(Some(wasm_runtime_layer::Func::new(
|
||||||
|
ctx,
|
||||||
|
ty,
|
||||||
|
move |mut ctx, args, rets| {
|
||||||
|
let args2 = args
|
||||||
|
.iter()
|
||||||
|
.zip(params.iter())
|
||||||
|
.rev()
|
||||||
|
.map(|(x, y)| translate_out(x, ctx.data_mut().as_mut(), y))
|
||||||
|
.collect::<anyhow::Result<Vec<_>>>()?;
|
||||||
|
let v = tramp::tramp(f(ctx.data_mut().as_mut(), args2))?;
|
||||||
|
for ((w, v), t) in v.iter().rev().zip(rets.iter_mut()).zip(returns.iter()) {
|
||||||
|
*v = translate_in(w, ctx.data_mut().as_mut(), t)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
crate::Value::Null => match wrl_ty{
|
||||||
|
MetaType::ExternRef => wasm_runtime_layer::Value::ExternRef(None),
|
||||||
|
MetaType::FunRef { params, returns } => wasm_runtime_layer::Value::FuncRef(None),
|
||||||
|
_ => anyhow::bail!("invalid null")
|
||||||
|
},
|
||||||
|
crate::Value::ExRef(e) => {
|
||||||
|
wasm_runtime_layer::Value::ExternRef(Some(ExternRef::new(ctx, e.clone())))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn translate_out<C: CtxSpec + AsContextMut<UserState = D> + 'static, D: AsMut<C>>(
|
||||||
|
val: &wasm_runtime_layer::Value,
|
||||||
|
ctx: &mut C,
|
||||||
|
wrl_ty: &MetaType,
|
||||||
|
) -> anyhow::Result<crate::func::Value<C>>
|
||||||
|
where
|
||||||
|
C::ExternRef: Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
Ok(match val {
|
||||||
|
wasm_runtime_layer::Value::I32(i) => crate::Value::I32(*i as u32),
|
||||||
|
wasm_runtime_layer::Value::I64(i) => crate::Value::I64(*i as u64),
|
||||||
|
wasm_runtime_layer::Value::F32(f) => crate::Value::F32(*f),
|
||||||
|
wasm_runtime_layer::Value::F64(f) => crate::Value::F64(*f),
|
||||||
|
wasm_runtime_layer::Value::FuncRef(f) => match f {
|
||||||
|
None => crate::Value::Null,
|
||||||
|
Some(a) => {
|
||||||
|
let a = a.clone();
|
||||||
|
let MetaType::FunRef { params, returns } = wrl_ty.clone() else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
crate::Value::FunRef(Arc::new(move |ctx, args| {
|
||||||
|
let args_in: anyhow::Result<Vec<_>> = args
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.zip(params.iter())
|
||||||
|
.map(|(x, y)| translate_in(x, &mut *ctx, y))
|
||||||
|
.collect();
|
||||||
|
let mut results =
|
||||||
|
vec![wasm_runtime_layer::Value::I32(0); a.ty(&mut *ctx).results().len()];
|
||||||
|
let args_in = match args_in {
|
||||||
|
Ok(a) => a,
|
||||||
|
Err(e) => return tramp::BorrowRec::Ret(Err(e)),
|
||||||
|
};
|
||||||
|
tramp::BorrowRec::Ret(match a.call(&mut *ctx, &args_in, &mut results) {
|
||||||
|
Err(e) => Err(e),
|
||||||
|
Ok(_) => results
|
||||||
|
.iter()
|
||||||
|
.zip(returns.iter())
|
||||||
|
.rev()
|
||||||
|
.map(|(x, y)| translate_out(x, ctx, y))
|
||||||
|
.collect(),
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
wasm_runtime_layer::Value::ExternRef(x) => match x
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|a| a.downcast::<C::ExternRef, _, _>(ctx.as_context()).ok())
|
||||||
|
{
|
||||||
|
None => crate::Value::Null,
|
||||||
|
Some(x) => crate::Value::ExRef(x.clone()),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
|
@ -6,9 +6,13 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bitflags = "2.5.0"
|
||||||
portal-pc-waffle.workspace = true
|
portal-pc-waffle.workspace = true
|
||||||
proc-macro2 = "1.0.85"
|
proc-macro2 = "1.0.85"
|
||||||
|
quasiquote = "0.1.1"
|
||||||
quote = "1.0.36"
|
quote = "1.0.36"
|
||||||
relooper = "0.1.0"
|
relooper = "0.1.0"
|
||||||
syn = "2.0.66"
|
syn = "2.0.66"
|
||||||
|
waffle-func-reloop = { version = "0.1.0", path = "../waffle-func-reloop" }
|
||||||
|
witx = {git="https://github.com/wasix-org/wasix-witx.git",branch="main"}
|
||||||
|
|
||||||
|
|
611
wars/src/lib.rs
611
wars/src/lib.rs
|
@ -1,14 +1,25 @@
|
||||||
use std::{convert::Infallible, iter::once, sync::Arc};
|
use std::{collections::BTreeMap, convert::Infallible, iter::once, sync::Arc};
|
||||||
|
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quasiquote::quasiquote;
|
||||||
|
use quote::{format_ident, quote, ToTokens};
|
||||||
use relooper::{reloop, BranchMode, ShapedBlock};
|
use relooper::{reloop, BranchMode, ShapedBlock};
|
||||||
use syn::{Ident, Lifetime};
|
use syn::{Ident, Lifetime};
|
||||||
use waffle::{
|
use waffle::{
|
||||||
cfg::CFGInfo, entity::EntityRef, Block, BlockTarget, ExportKind, Func, ImportKind, Memory,
|
cfg::CFGInfo, entity::EntityRef, Block, BlockTarget, Export, ExportKind, Func, ImportKind, Memory, Module, Operator, Signature, SignatureData, Type, Value
|
||||||
Module, Operator, Signature, SignatureData, Type, Value,
|
|
||||||
};
|
};
|
||||||
|
bitflags::bitflags! {
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
|
pub struct Flags: u32{
|
||||||
|
const HOST_MEMORY = 0x1;
|
||||||
|
const ASYNC = 0x2;
|
||||||
|
const LEGACY = 0x4;
|
||||||
|
// const WASIX = 0x8;
|
||||||
|
// const UNSANDBOXED = 0x2;
|
||||||
|
}
|
||||||
|
}
|
||||||
pub mod unswitch;
|
pub mod unswitch;
|
||||||
|
// pub mod wasix;
|
||||||
pub fn mangle_value(a: Value, b: usize) -> Ident {
|
pub fn mangle_value(a: Value, b: usize) -> Ident {
|
||||||
if b == 0 {
|
if b == 0 {
|
||||||
format_ident!("{a}")
|
format_ident!("{a}")
|
||||||
|
@ -32,20 +43,123 @@ pub fn bindname(a: &str) -> String {
|
||||||
// }
|
// }
|
||||||
pub const INTRINSIC: &'static str = "wars_intrinsic/";
|
pub const INTRINSIC: &'static str = "wars_intrinsic/";
|
||||||
impl Opts<Module<'static>> {
|
impl Opts<Module<'static>> {
|
||||||
|
pub fn fp(&self) -> TokenStream {
|
||||||
|
let root = self.crate_path.clone();
|
||||||
|
if self.flags.contains(Flags::ASYNC) {
|
||||||
|
quote! {
|
||||||
|
#root::func::unsync
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
#root::func
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn mem(&self, m: Memory) -> TokenStream {
|
||||||
|
if let Some(i) = self
|
||||||
|
.module
|
||||||
|
.imports
|
||||||
|
.iter()
|
||||||
|
.find(|x| x.kind == ImportKind::Memory(m))
|
||||||
|
{
|
||||||
|
if i.module == "!!unsafe" && i.name == "host" && self.flags.contains(Flags::HOST_MEMORY)
|
||||||
|
{
|
||||||
|
return quote! {
|
||||||
|
unsafe{
|
||||||
|
::std::slice::from_raw_parts_mut(::std::ptr::null(),usize::MAX)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let m2 = format_ident!("{m}");
|
||||||
|
quote! {
|
||||||
|
ctx.#m2()
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn import(
|
pub fn import(
|
||||||
&self,
|
&self,
|
||||||
module: &str,
|
module: &str,
|
||||||
name: &str,
|
name: &str,
|
||||||
params: impl Iterator<Item = TokenStream>,
|
mut params: impl Iterator<Item = TokenStream>,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let root = self.crate_path.clone();
|
let root = self.crate_path.clone();
|
||||||
let Some(a) = module.strip_prefix(INTRINSIC) else {
|
// if self.flags.contains(Flags::UNSANDBOXED) {
|
||||||
|
if self.flags.contains(Flags::HOST_MEMORY) {
|
||||||
|
if module == "wars/memory/host" {
|
||||||
|
match name {
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if a == "fs" {
|
||||||
|
// match name {
|
||||||
|
// "open" => {
|
||||||
|
// let p0 = params.next().unwrap();
|
||||||
|
// let l = params.next().unwrap();
|
||||||
|
// return quote! {
|
||||||
|
// #root::_rexport::tramp::BorrowRec::Ret({
|
||||||
|
// let f = #p0;
|
||||||
|
// let l = #l;
|
||||||
|
// let f = ::std::str::from_utf8(&ctx.memory()[(f as usize)..][..(l as usize)]);
|
||||||
|
// let f = match f{
|
||||||
|
// Ok(a) => a,
|
||||||
|
// Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Er(e.into()));
|
||||||
|
// };
|
||||||
|
// let f = ::std::fs::open(f);
|
||||||
|
// let f = match f{
|
||||||
|
// Ok(a) => alloc(&mut ctx.data().files,::std::sync::Arc::new(a)) * 2,
|
||||||
|
// Err(e) => alloc(&mut ctx.data().io_errors,::std::sync::Arc::new(e)) * 2 + 1;
|
||||||
|
// };
|
||||||
|
// f
|
||||||
|
// })
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// "read" => {
|
||||||
|
// let fd = params.next().unwrap();
|
||||||
|
// let p0 = params.next().unwrap();
|
||||||
|
// let l = params.next().unwrap();
|
||||||
|
// return quote! {
|
||||||
|
// {
|
||||||
|
// let f = #p0;
|
||||||
|
// let l = #l;
|
||||||
|
// let fd = #fd;
|
||||||
|
// let fd = ctx.data().files.get(&fd).unwrap().clone();
|
||||||
|
// let f = &mut ctx.memory()[(f as usize)..][..(l as usize)];
|
||||||
|
// let f = ::std::io::Read::read(&mut fd.as_ref(),f);
|
||||||
|
// match f{
|
||||||
|
// Ok(a) => #root::_rexport::tuple_list::tuple_list!(a as u64 * 2),
|
||||||
|
// Err(e) => #root::_rexport::tuple_list::tuple_list!(alloc(&mut ctx.data().io_errors,::std::sync::Arc::new(e)) as u64 * 2 + 1);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// "write" => {
|
||||||
|
// let fd = params.next().unwrap();
|
||||||
|
// let p0 = params.next().unwrap();
|
||||||
|
// let l = params.next().unwrap();
|
||||||
|
// return quote! {
|
||||||
|
// {
|
||||||
|
// let f = #p0;
|
||||||
|
// let l = #l;
|
||||||
|
// let fd = #fd;
|
||||||
|
// let fd = ctx.data().files.get(&fd).unwrap().clone();
|
||||||
|
// let f = &ctx.memory()[(f as usize)..][..(l as usize)];
|
||||||
|
// let f = ::std::io::Write::write(&mut fd.as_ref(),f);
|
||||||
|
// match f{
|
||||||
|
// Ok(a) => #root::_rexport::tuple_list::tuple_list!(a as u64 * 2),
|
||||||
|
// Err(e) => #root::_rexport::tuple_list::tuple_list!(alloc(&mut ctx.data().io_errors,::std::sync::Arc::new(e)) as u64 * 2 + 1);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// _ => {}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
let id = format_ident!("{}_{}", bindname(module), bindname(name));
|
let id = format_ident!("{}_{}", bindname(module), bindname(name));
|
||||||
return quote! {
|
return quote! {
|
||||||
ctx.#id(#(#params),*)
|
ctx.#id(#(#params),*)
|
||||||
};
|
};
|
||||||
};
|
|
||||||
quote! {}
|
|
||||||
}
|
}
|
||||||
pub fn render_ty(&self, ctx: &TokenStream, ty: Type) -> TokenStream {
|
pub fn render_ty(&self, ctx: &TokenStream, ty: Type) -> TokenStream {
|
||||||
let root = self.crate_path.clone();
|
let root = self.crate_path.clone();
|
||||||
|
@ -62,8 +176,14 @@ impl Opts<Module<'static>> {
|
||||||
let data = &self.module.signatures[sig_index];
|
let data = &self.module.signatures[sig_index];
|
||||||
let params = data.params.iter().map(|x| self.render_ty(ctx, *x));
|
let params = data.params.iter().map(|x| self.render_ty(ctx, *x));
|
||||||
let returns = data.returns.iter().map(|x| self.render_ty(ctx, *x));
|
let returns = data.returns.iter().map(|x| self.render_ty(ctx, *x));
|
||||||
let mut x = quote! {
|
let mut x = if self.flags.contains(Flags::ASYNC) {
|
||||||
|
quote! {
|
||||||
|
#root::func::unsync::Df<#root::_rexport::tuple_list::tuple_list_type!(#(#params),*),#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*),#ctx>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
#root::func::Df<#root::_rexport::tuple_list::tuple_list_type!(#(#params),*),#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*),#ctx>
|
#root::func::Df<#root::_rexport::tuple_list::tuple_list_type!(#(#params),*),#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*),#ctx>
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if nullable {
|
if nullable {
|
||||||
x = quote! {
|
x = quote! {
|
||||||
|
@ -72,7 +192,7 @@ impl Opts<Module<'static>> {
|
||||||
}
|
}
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
_ => quote! {#root::func::Value<#ctx>},
|
_ => quasiquote! {#{self.fp()}::Value<#ctx>},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn render_generics(&self, ctx: &TokenStream, data: &SignatureData) -> TokenStream {
|
pub fn render_generics(&self, ctx: &TokenStream, data: &SignatureData) -> TokenStream {
|
||||||
|
@ -100,23 +220,28 @@ impl Opts<Module<'static>> {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(a, _)| format_ident!("p{a}"));
|
.map(|(a, _)| format_ident!("p{a}"));
|
||||||
let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x));
|
let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x));
|
||||||
|
if self.flags.contains(Flags::ASYNC) {
|
||||||
|
quote! {
|
||||||
|
fn #name<'a,C: #base + 'static>(ctx: &'a mut C, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::func::unsync::AsyncRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
fn #name<'a,C: #base + 'static>(ctx: &'a mut C, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>
|
fn #name<'a,C: #base + 'static>(ctx: &'a mut C, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pub fn render_fun_ref(&self, ctx: &TokenStream, x: Func) -> TokenStream {
|
pub fn render_fun_ref(&self, ctx: &TokenStream, x: Func) -> TokenStream {
|
||||||
let root = self.crate_path.clone();
|
let root = self.crate_path.clone();
|
||||||
if x.is_invalid() {
|
if x.is_invalid() {
|
||||||
return quote! {
|
return quasiquote! {
|
||||||
#root::func::da::<(),(),C,_>(|ctx,arg|panic!("invalid func"))
|
#{self.fp()}::da::<(),(),C,_>(|ctx,arg|panic!("invalid func"))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let generics =
|
let generics =
|
||||||
self.render_generics(ctx, &self.module.signatures[self.module.funcs[x].sig()]);
|
self.render_generics(ctx, &self.module.signatures[self.module.funcs[x].sig()]);
|
||||||
let x = format_ident!("{x}");
|
let x = format_ident!("{x}");
|
||||||
quote! {
|
quasiquote! {
|
||||||
#root::func::da::<#generics,C,_>(|ctx,arg|#x(ctx,arg))
|
#{self.fp()}::da::<#generics,C,_>(|ctx,arg|#x(ctx,arg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn render_self_sig(
|
pub fn render_self_sig(
|
||||||
|
@ -138,13 +263,20 @@ impl Opts<Module<'static>> {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x));
|
let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x));
|
||||||
|
if self.flags.contains(Flags::ASYNC) {
|
||||||
|
quote! {
|
||||||
|
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::func::unsync::AsyncRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> where Self: 'static{
|
||||||
|
return #wrapped(self,#root::_rexport::tuple_list::tuple_list!(#(#param_ids),*));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> where Self: 'static{
|
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>> where Self: 'static{
|
||||||
return #wrapped(self,#root::_rexport::tuple_list::tuple_list!(#(#param_ids),*));
|
return #wrapped(self,#root::_rexport::tuple_list::tuple_list!(#(#param_ids),*));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pub fn render_self_sig_import(&self, name: Ident, data: &SignatureData) -> TokenStream {
|
pub fn render_self_sig_import(&self, name: Ident, data: &SignatureData) -> TokenStream {
|
||||||
let root = self.crate_path.clone();
|
let root = self.crate_path.clone();
|
||||||
let base = self.name.clone();
|
let base = self.name.clone();
|
||||||
|
@ -159,11 +291,16 @@ impl Opts<Module<'static>> {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x));
|
let returns = data.returns.iter().map(|x| self.render_ty(&ctx, *x));
|
||||||
|
if self.flags.contains(Flags::ASYNC) {
|
||||||
|
quote! {
|
||||||
|
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::func::unsync::AsyncRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>;
|
fn #name<'a>(self: &'a mut Self, #root::_rexport::tuple_list::tuple_list!(#(#param_ids),*): #root::_rexport::tuple_list::tuple_list_type!(#(#params),*)) -> #root::_rexport::tramp::BorrowRec<'a,#root::_rexport::anyhow::Result<#root::_rexport::tuple_list::tuple_list_type!(#(#returns),*)>>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pub fn render_relooped_block(&self, f: Func, x: &ShapedBlock<Block>) -> TokenStream {
|
pub fn render_relooped_block(&self, f: Func, x: &ShapedBlock<Block>) -> TokenStream {
|
||||||
let root = self.crate_path.clone();
|
let root = self.crate_path.clone();
|
||||||
let b = self.module.funcs[f].body().unwrap();
|
let b = self.module.funcs[f].body().unwrap();
|
||||||
|
@ -228,6 +365,7 @@ impl Opts<Module<'static>> {
|
||||||
#next;
|
#next;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
let fp = self.fp();
|
||||||
let stmts = b.blocks[stmts].params.iter().map(|a|&a.1).chain(b.blocks[stmts].insts.iter()).map(|a|{
|
let stmts = b.blocks[stmts].params.iter().map(|a|&a.1).chain(b.blocks[stmts].insts.iter()).map(|a|{
|
||||||
let av = b.values[*a].tys(&b.type_pool).iter().enumerate().map(|b|mangle_value(*a,b.0));
|
let av = b.values[*a].tys(&b.type_pool).iter().enumerate().map(|b|mangle_value(*a,b.0));
|
||||||
let b = match &b.values[*a]{
|
let b = match &b.values[*a]{
|
||||||
|
@ -251,10 +389,21 @@ impl Opts<Module<'static>> {
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
let func = format_ident!("{function_index}");
|
let func = format_ident!("{function_index}");
|
||||||
let vals = vals.iter().map(|a|format_ident!("{a}"));
|
let vals = vals.iter().map(|a|format_ident!("{a}"));
|
||||||
quote! {
|
quasiquote! {
|
||||||
match #root::_rexport::tramp::tramp(#func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))){
|
{
|
||||||
|
let x = #func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#fp::cast::<_,_,C>(#vals .clone())),*));
|
||||||
|
match #{if self.flags.contains(Flags::ASYNC){
|
||||||
|
quote!{
|
||||||
|
x.go().await
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
quote!{
|
||||||
|
#root::_rexport::tramp::tramp(x)
|
||||||
|
}
|
||||||
|
}}{
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -270,10 +419,18 @@ impl Opts<Module<'static>> {
|
||||||
i.name.as_str(),
|
i.name.as_str(),
|
||||||
vals.iter().map(|a|format_ident!("{a}")).map(|a| quote! {#a}),
|
vals.iter().map(|a|format_ident!("{a}")).map(|a| quote! {#a}),
|
||||||
);
|
);
|
||||||
|
quasiquote!{
|
||||||
|
match #{if self.flags.contains(Flags::ASYNC){
|
||||||
quote!{
|
quote!{
|
||||||
match #root::_rexport::tramp::tramp(x){
|
#x.go().await
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
quote!{
|
||||||
|
#root::_rexport::tramp::tramp(#x)
|
||||||
|
}
|
||||||
|
}}{
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,10 +443,21 @@ impl Opts<Module<'static>> {
|
||||||
let vals = vals.iter().map(|a|format_ident!("{a}"));
|
let vals = vals.iter().map(|a|format_ident!("{a}"));
|
||||||
let r = format_ident!("{r}");
|
let r = format_ident!("{r}");
|
||||||
let g = self.render_generics("e! {c}, &self.module.signatures[*sig_index]);
|
let g = self.render_generics("e! {c}, &self.module.signatures[*sig_index]);
|
||||||
quote! {
|
quasiquote! {
|
||||||
match #root::_rexport::tramp::tramp(#root::func::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))){
|
{
|
||||||
|
let x = #{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#fp::cast::<_,_,C>(#vals .clone())),*));
|
||||||
|
match #{if self.flags.contains(Flags::ASYNC){
|
||||||
|
quote!{
|
||||||
|
x.go().await
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
quote!{
|
||||||
|
#root::_rexport::tramp::tramp(x)
|
||||||
|
}
|
||||||
|
}}{
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -304,12 +472,21 @@ impl Opts<Module<'static>> {
|
||||||
ctx.#t()[#r as usize]
|
ctx.#t()[#r as usize]
|
||||||
};
|
};
|
||||||
let g = self.render_generics("e! {c}, &self.module.signatures[*sig_index]);
|
let g = self.render_generics("e! {c}, &self.module.signatures[*sig_index]);
|
||||||
quote! {
|
quasiquote! {
|
||||||
{
|
{
|
||||||
let r = #r.clone();
|
let r = #r.clone();
|
||||||
match #root::_rexport::tramp::tramp(#root::func::call_ref::<#g,C>(ctx,#root::func::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))){
|
let x = #{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#fp::cast::<_,_,C>(#vals .clone())),*));
|
||||||
|
match #{if self.flags.contains(Flags::ASYNC){
|
||||||
|
quote!{
|
||||||
|
x.go().await
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
quote!{
|
||||||
|
#root::_rexport::tramp::tramp(x)
|
||||||
|
}
|
||||||
|
}}{
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,8 +501,11 @@ impl Opts<Module<'static>> {
|
||||||
quote! {u32}
|
quote! {u32}
|
||||||
};
|
};
|
||||||
let m = Ident::new(&mem.to_string(), Span::call_site());
|
let m = Ident::new(&mem.to_string(), Span::call_site());
|
||||||
quote! {
|
quasiquote! {
|
||||||
#root::_rexport::tuple_list::tuple_list!((ctx.#m().len() / 65536) as #rt)
|
#root::_rexport::tuple_list::tuple_list!(((match #root::Memory::size(ctx.#m()){
|
||||||
|
Ok(a) => a,
|
||||||
|
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||||
|
}) / 65536) as #rt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
waffle::Operator::MemoryGrow { mem } => {
|
waffle::Operator::MemoryGrow { mem } => {
|
||||||
|
@ -337,25 +517,30 @@ impl Opts<Module<'static>> {
|
||||||
}else{
|
}else{
|
||||||
quote! {u32}
|
quote! {u32}
|
||||||
};
|
};
|
||||||
quote! {
|
quasiquote! {
|
||||||
{
|
{
|
||||||
let vn = ctx.#m().len() / 65536;
|
let vn = (match #root::Memory::size(ctx.#m()){
|
||||||
let l = ctx.#m().len();
|
Ok(a) => a,
|
||||||
ctx.#m().resize(l + (#a .clone() as usize) * 65536,0);
|
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||||
|
}) / 65536;
|
||||||
|
match #root::Memory::grow(ctx.#m(),(#a .clone() as usize) * 65536){
|
||||||
|
Ok(a) => a,
|
||||||
|
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||||
|
};
|
||||||
#root::_rexport::tuple_list::tuple_list!(vn as #rt)
|
#root::_rexport::tuple_list::tuple_list!(vn as #rt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
waffle::Operator::MemoryCopy { dst_mem, src_mem } => {
|
waffle::Operator::MemoryCopy { dst_mem, src_mem } => {
|
||||||
let dst = format_ident!("{dst_mem}");
|
let dst = self.mem(*dst_mem);
|
||||||
let src = format_ident!("{src_mem}");
|
let src = self.mem(*src_mem);
|
||||||
let dst_ptr = format_ident!("{}",vals[0].to_string());
|
let dst_ptr = format_ident!("{}",vals[0].to_string());
|
||||||
let src_ptr = format_ident!("{}",vals[1].to_string());
|
let src_ptr = format_ident!("{}",vals[1].to_string());
|
||||||
let len = format_ident!("{}",vals[2].to_string());
|
let len = format_ident!("{}",vals[2].to_string());
|
||||||
quote!{
|
quote!{
|
||||||
{
|
{
|
||||||
let m = ctx.#src()[(#src_ptr as usize)..][..(#len as usize)].to_owned();
|
let m = #src[(#src_ptr as usize)..][..(#len as usize)].to_owned();
|
||||||
ctx.#dst()[(#dst_ptr as usize)..][..(#len as usize)].copy_from_slice(&m);
|
#dst[(#dst_ptr as usize)..][..(#len as usize)].copy_from_slice(&m);
|
||||||
()
|
()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,6 +562,55 @@ impl Opts<Module<'static>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Operator::TableGet { table_index } => {
|
||||||
|
let table = format_ident!("{table_index}");
|
||||||
|
let [i,..] = vals else{
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
let i = format_ident!("{i}");
|
||||||
|
// let j = format_ident!("{j}");
|
||||||
|
quasiquote!{
|
||||||
|
{
|
||||||
|
(ctx.#table()[#i as usize].clone(),())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Operator::TableSet { table_index } => {
|
||||||
|
let table = format_ident!("{table_index}");
|
||||||
|
let [i,j,..] = vals else{
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
let i = format_ident!("{i}");
|
||||||
|
let j = format_ident!("{j}");
|
||||||
|
quasiquote!{
|
||||||
|
{
|
||||||
|
ctx.#table()[#i as usize] = #{self.fp()}::cast::<_,_,C>(#j.clone());
|
||||||
|
()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Operator::TableSize { table_index } => {
|
||||||
|
let table = format_ident!("{table_index}");
|
||||||
|
quote!{
|
||||||
|
(ctx.#table().len() as u32,())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Operator::TableGrow { table_index } => {
|
||||||
|
let table = format_ident!("{table_index}");
|
||||||
|
let [i,j,..] = vals else{
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
let i = format_ident!("{i}");
|
||||||
|
let j = format_ident!("{j}");
|
||||||
|
quasiquote!{
|
||||||
|
{
|
||||||
|
for _ in 0..#i{
|
||||||
|
ctx.#table().push(#{self.fp()}::cast::<_,_,C>(#j.clone()));
|
||||||
|
}
|
||||||
|
()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
_ if waffle::op_traits::mem_count(o) == 1 => {
|
_ if waffle::op_traits::mem_count(o) == 1 => {
|
||||||
let mut mem = Memory::invalid();
|
let mut mem = Memory::invalid();
|
||||||
waffle::op_traits::rewrite_mem(&mut o.clone(), &mut [();4], |m,_|{
|
waffle::op_traits::rewrite_mem(&mut o.clone(), &mut [();4], |m,_|{
|
||||||
|
@ -386,7 +620,7 @@ impl Opts<Module<'static>> {
|
||||||
// let clean = o.to_string();
|
// let clean = o.to_string();
|
||||||
let clean = format_ident!("{}",o.to_string().split_once("<").unwrap().0);
|
let clean = format_ident!("{}",o.to_string().split_once("<").unwrap().0);
|
||||||
let m2 = mem;
|
let m2 = mem;
|
||||||
let mem = format_ident!("{mem}");
|
let mem = self.mem(m2);
|
||||||
let mut vals = vals.iter().map(|a|format_ident!("{a}"));
|
let mut vals = vals.iter().map(|a|format_ident!("{a}"));
|
||||||
let rt = if self.module.memories[m2].memory64{
|
let rt = if self.module.memories[m2].memory64{
|
||||||
quote! {u64}
|
quote! {u64}
|
||||||
|
@ -402,10 +636,10 @@ impl Opts<Module<'static>> {
|
||||||
};
|
};
|
||||||
let val = vals.next().unwrap();
|
let val = vals.next().unwrap();
|
||||||
let vals = once(quote! {(#val.clone() + #offset)}).chain(vals.map(|w|quote!{#w}));
|
let vals = once(quote! {(#val.clone() + #offset)}).chain(vals.map(|w|quote!{#w}));
|
||||||
quote! {
|
quasiquote! {
|
||||||
match #root::#clean::<#rt>(ctx.#mem(),#(#root::func::cast::<_,_,C>(#vals .clone())),*){
|
match #root::#clean::<#rt,_>(#mem,#(#fp::cast::<_,_,C>(#vals .clone())),*){
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -426,10 +660,10 @@ impl Opts<Module<'static>> {
|
||||||
// let clean = o.to_string();
|
// let clean = o.to_string();
|
||||||
let clean = format_ident!("{o}");
|
let clean = format_ident!("{o}");
|
||||||
let vals = vals.iter().map(|a|format_ident!("{a}"));
|
let vals = vals.iter().map(|a|format_ident!("{a}"));
|
||||||
quote! {
|
quasiquote! {
|
||||||
match #root::#clean(#(#root::func::cast::<_,_,C>(#vals .clone())),*){
|
match #root::#clean(#(#fp::cast::<_,_,C>(#vals .clone())),*){
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => return #root::_rexport::tramp::BorrowRec::Ret(Err(e))
|
Err(e) => return #{self.fp()}::ret(Err(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,8 +693,8 @@ impl Opts<Module<'static>> {
|
||||||
let vars = k.args.iter().enumerate().map(|(i, a)| {
|
let vars = k.args.iter().enumerate().map(|(i, a)| {
|
||||||
let a = format_ident!("{a}");
|
let a = format_ident!("{a}");
|
||||||
let i = format_ident!("{}param{i}", k.block.to_string());
|
let i = format_ident!("{}param{i}", k.block.to_string());
|
||||||
quote! {
|
quasiquote! {
|
||||||
#i = #a;
|
#i = #{self.fp()}::cast::<_,_,C>(#a);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let br = term(
|
let br = term(
|
||||||
|
@ -523,8 +757,8 @@ impl Opts<Module<'static>> {
|
||||||
let values = b.rets.iter().enumerate().map(|(a, _)| match values.get(a) {
|
let values = b.rets.iter().enumerate().map(|(a, _)| match values.get(a) {
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
let v = format_ident!("{v}");
|
let v = format_ident!("{v}");
|
||||||
quote! {
|
quasiquote! {
|
||||||
#v
|
#{self.fp()}::cast::<_,_,C>(#v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -533,21 +767,31 @@ impl Opts<Module<'static>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
quote! {
|
quasiquote! {
|
||||||
return #root::_rexport::tramp::BorrowRec::Ret(Ok(#root::_rexport::tuple_list::tuple_list!(#(#values),*)))
|
return #{self.fp()}::ret(Ok(#root::_rexport::tuple_list::tuple_list!(#(#values),*)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
waffle::Terminator::ReturnCall { func, args } => {
|
waffle::Terminator::ReturnCall { func, args } => {
|
||||||
match self.module.funcs[*func].body() {
|
match self.module.funcs[*func].body() {
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
let values = args.iter().map(|v| format_ident!("{v}"));
|
let values = args.iter().map(|v| format_ident!("{v}")).map(|a| {
|
||||||
|
quasiquote! {
|
||||||
|
#{self.fp()}::cast::<_,_,C>(#a)
|
||||||
|
}
|
||||||
|
});
|
||||||
let func = format_ident!("{func}");
|
let func = format_ident!("{func}");
|
||||||
|
if self.flags.contains(Flags::ASYNC) {
|
||||||
|
quote! {
|
||||||
|
#func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#values),*))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
||||||
#func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#values),*))
|
#func(ctx,#root::_rexport::tuple_list::tuple_list!(#(#values),*))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
None => {
|
None => {
|
||||||
let i = self
|
let i = self
|
||||||
.module
|
.module
|
||||||
|
@ -562,43 +806,67 @@ impl Opts<Module<'static>> {
|
||||||
.map(|a| format_ident!("{a}"))
|
.map(|a| format_ident!("{a}"))
|
||||||
.map(|a| quote! {#a}),
|
.map(|a| quote! {#a}),
|
||||||
);
|
);
|
||||||
|
if self.flags.contains(Flags::ASYNC) {
|
||||||
|
x
|
||||||
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{#x}))
|
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{#x}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
waffle::Terminator::ReturnCallIndirect { sig, table, args } => {
|
waffle::Terminator::ReturnCallIndirect { sig, table, args } => {
|
||||||
let t = format_ident!("{table}");
|
let t = format_ident!("{table}");
|
||||||
let mut vals = args.to_owned();
|
let mut vals = args.to_owned();
|
||||||
let r = vals.pop().unwrap();
|
let r = vals.pop().unwrap();
|
||||||
// let func = format_ident!("{function_index}");
|
// let func = format_ident!("{function_index}");
|
||||||
let vals = vals.iter().map(|a| format_ident!("{a}"));
|
let vals = vals.iter().map(|a| format_ident!("{a}")).map(|a| {
|
||||||
|
quasiquote! {
|
||||||
|
#{self.fp()}::cast::<_,_,C>(#a)
|
||||||
|
}
|
||||||
|
});
|
||||||
let r = format_ident!("{r}");
|
let r = format_ident!("{r}");
|
||||||
let r = quote! {
|
let r = quote! {
|
||||||
ctx.#t()[#r as usize]
|
ctx.#t()[#r as usize]
|
||||||
};
|
};
|
||||||
let g = self.render_generics("e! {c}, &self.module.signatures[*sig]);
|
let g = self.render_generics("e! {c}, &self.module.signatures[*sig]);
|
||||||
quote! {
|
if self.flags.contains(Flags::ASYNC) {
|
||||||
|
quasiquote! {
|
||||||
|
return #{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#{self.fp()}::cast::<_,_,C>(#vals .clone())),*))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quasiquote! {
|
||||||
let r = #r.clone();
|
let r = #r.clone();
|
||||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
||||||
#root::func::call_ref::<#g,C>(ctx,#root::func::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))
|
#{self.fp()}::call_ref::<#g,C>(ctx,#{self.fp()}::cast(r),#root::_rexport::tuple_list::tuple_list!(#(#{self.fp()}::cast::<_,_,C>(#vals .clone())),*))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
waffle::Terminator::ReturnCallRef { sig, args } => {
|
waffle::Terminator::ReturnCallRef { sig, args } => {
|
||||||
let mut vals = args.clone();
|
let mut vals = args.clone();
|
||||||
let r = vals.pop().unwrap();
|
let r = vals.pop().unwrap();
|
||||||
// let func = format_ident!("{function_index}");
|
// let func = format_ident!("{function_index}");
|
||||||
let vals = vals.iter().map(|a| format_ident!("{a}"));
|
let vals = vals.iter().map(|a| format_ident!("{a}")).map(|a| {
|
||||||
|
quasiquote! {
|
||||||
|
#{self.fp()}::cast::<_,_,C>(#a)
|
||||||
|
}
|
||||||
|
});
|
||||||
let r = format_ident!("{r}");
|
let r = format_ident!("{r}");
|
||||||
let g = self.render_generics("e! {c}, &self.module.signatures[*sig]);
|
let g = self.render_generics("e! {c}, &self.module.signatures[*sig]);
|
||||||
quote! {
|
if self.flags.contains(Flags::ASYNC) {
|
||||||
|
quasiquote! {
|
||||||
|
return #{self.fp()}::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quasiquote! {
|
||||||
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
return #root::_rexport::tramp::BorrowRec::Call(#root::_rexport::tramp::Thunk::new(move||{
|
||||||
#root::func::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))
|
#{self.fp()}::call_ref::<#g,C>(ctx,#root::func::cast(#r.clone()),#root::_rexport::tuple_list::tuple_list!(#(#root::func::cast::<_,_,C>(#vals .clone())),*))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
waffle::Terminator::Unreachable => quote! {
|
waffle::Terminator::Unreachable => quote! {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
},
|
},
|
||||||
|
@ -753,45 +1021,56 @@ impl Opts<Module<'static>> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
let reloop = std::panic::catch_unwind(|| {
|
let reloop = waffle_func_reloop::go(b);
|
||||||
reloop(
|
// let reloop = std::panic::catch_unwind(|| {
|
||||||
b.blocks
|
// reloop(
|
||||||
.entries()
|
// b.blocks
|
||||||
.filter(|k| cfg.dominates(b.entry, k.0))
|
// .entries()
|
||||||
.map(|(k, l)| {
|
// .filter(|k| cfg.dominates(b.entry, k.0))
|
||||||
(
|
// .map(|(k, l)| {
|
||||||
k,
|
// (
|
||||||
l.succs
|
// k,
|
||||||
.iter()
|
// l.succs
|
||||||
.cloned()
|
// .iter()
|
||||||
.chain(b.blocks.iter().filter(|x| cfg.dominates(*x, k)))
|
// .cloned()
|
||||||
.collect(),
|
// .chain(b.blocks.iter().filter(|x| cfg.dominates(*x, k)))
|
||||||
)
|
// .collect(),
|
||||||
})
|
// )
|
||||||
.chain(once((Block::invalid(), vec![b.entry])))
|
// })
|
||||||
.collect(),
|
// .chain(once((Block::invalid(), vec![b.entry])))
|
||||||
Block::invalid(),
|
// .collect(),
|
||||||
)
|
// Block::invalid(),
|
||||||
});
|
// )
|
||||||
let reloop = match reloop {
|
// });
|
||||||
Ok(a) => a,
|
// let reloop = match reloop {
|
||||||
Err(e) => {
|
// Ok(a) => a,
|
||||||
panic!(
|
// Err(e) => {
|
||||||
"reloop failure ({}) in {}",
|
// panic!(
|
||||||
e.downcast_ref::<&str>()
|
// "reloop failure ({}) in {}",
|
||||||
.map(|a| *a)
|
// e.downcast_ref::<&str>()
|
||||||
.unwrap_or("unknown panic"),
|
// .map(|a| *a)
|
||||||
b.display("", None)
|
// .unwrap_or("unknown panic"),
|
||||||
);
|
// b.display("", None)
|
||||||
}
|
// );
|
||||||
};
|
// }
|
||||||
|
// };
|
||||||
let x = self.render_relooped_block(f, reloop.as_ref());
|
let x = self.render_relooped_block(f, reloop.as_ref());
|
||||||
quote! {
|
let mut b = quote! {
|
||||||
#sig {
|
|
||||||
let mut cff: usize = 0;
|
let mut cff: usize = 0;
|
||||||
#(let mut #bpvalues);*;
|
#(let mut #bpvalues);*;
|
||||||
#x;
|
#x;
|
||||||
panic!("should have returned");
|
panic!("should have returned");
|
||||||
|
};
|
||||||
|
if self.flags.contains(Flags::ASYNC) {
|
||||||
|
b = quasiquote! {
|
||||||
|
return #{self.fp()}::AsyncRec::Async(Box::pin(async move{
|
||||||
|
#b
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
quote! {
|
||||||
|
#sig {
|
||||||
|
#b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -800,10 +1079,16 @@ pub struct Opts<B> {
|
||||||
pub crate_path: syn::Path,
|
pub crate_path: syn::Path,
|
||||||
pub module: B,
|
pub module: B,
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
|
pub flags: Flags,
|
||||||
|
pub embed: TokenStream,
|
||||||
|
pub data: BTreeMap<Ident, TokenStream>,
|
||||||
// pub cfg: Arc<dyn ImportCfg>,
|
// pub cfg: Arc<dyn ImportCfg>,
|
||||||
}
|
}
|
||||||
pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
impl<X: AsRef<[u8]>> Opts<X> {
|
||||||
let mut module = waffle::Module::from_wasm_bytes(&opts.module, &Default::default()).unwrap();
|
pub fn to_mod(&self) -> Opts<Module<'static>> {
|
||||||
|
let opts = self;
|
||||||
|
let mut module =
|
||||||
|
waffle::Module::from_wasm_bytes(opts.module.as_ref(), &Default::default()).unwrap();
|
||||||
module.expand_all_funcs().unwrap();
|
module.expand_all_funcs().unwrap();
|
||||||
let mut module = module.without_orig_bytes();
|
let mut module = module.without_orig_bytes();
|
||||||
// module.per_func_body(|b|unswitch::go(b)); //TODO: reloop better and make it not needed
|
// module.per_func_body(|b|unswitch::go(b)); //TODO: reloop better and make it not needed
|
||||||
|
@ -816,29 +1101,70 @@ pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
||||||
crate_path: opts.crate_path.clone(),
|
crate_path: opts.crate_path.clone(),
|
||||||
module,
|
module,
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
|
flags: opts.flags,
|
||||||
|
embed: opts.embed.clone(),
|
||||||
|
data: opts.data.clone(),
|
||||||
// cfg: opts.cfg.clone(),
|
// cfg: opts.cfg.clone(),
|
||||||
};
|
};
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl ToTokens for Opts<Module<'static>> {
|
||||||
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
go(self).to_tokens(tokens)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn go(opts: &Opts<Module<'static>>) -> proc_macro2::TokenStream {
|
||||||
|
// let mut module = waffle::Module::from_wasm_bytes(&opts.module, &Default::default()).unwrap();
|
||||||
|
// module.expand_all_funcs().unwrap();
|
||||||
|
// let mut module = module.without_orig_bytes();
|
||||||
|
// // module.per_func_body(|b|unswitch::go(b)); //TODO: reloop better and make it not needed
|
||||||
|
// // eprintln!("{}",module.display());
|
||||||
|
// module.per_func_body(|f| f.convert_to_max_ssa(None));
|
||||||
|
let internal_path = format_ident!("_{}_internal", opts.name);
|
||||||
|
let data = format_ident!("{}Data", opts.name);
|
||||||
|
let name = opts.name.clone();
|
||||||
|
// let opts = Opts {
|
||||||
|
// crate_path: opts.crate_path.clone(),
|
||||||
|
// module,
|
||||||
|
// name: name.clone(),
|
||||||
|
// flags: opts.flags,
|
||||||
|
// // cfg: opts.cfg.clone(),
|
||||||
|
// };
|
||||||
let root = opts.crate_path.clone();
|
let root = opts.crate_path.clone();
|
||||||
let funcs = opts.module.funcs.iter().map(|a| opts.render_fn(a));
|
let funcs = opts.module.funcs.iter().map(|a| opts.render_fn(a));
|
||||||
let mut z = vec![];
|
let mut z = vec![];
|
||||||
let mut fields = vec![];
|
let mut fields = vec![];
|
||||||
let mut fs = vec![];
|
let mut fs = vec![];
|
||||||
|
fs.push(opts.embed.clone());
|
||||||
|
for (k, v) in opts.data.iter() {
|
||||||
|
fields.push(k.clone());
|
||||||
|
z.push(quote! {
|
||||||
|
#k : #v
|
||||||
|
});
|
||||||
|
}
|
||||||
let mut init = vec![];
|
let mut init = vec![];
|
||||||
for (t, d) in opts.module.tables.entries() {
|
for (t, d) in opts.module.tables.entries() {
|
||||||
// let dty = opts.render_ty("e! {Target}, d.ty.clone());
|
// let dty = opts.render_ty("e! {Target}, d.ty.clone());
|
||||||
let n = Ident::new(&t.to_string(), Span::call_site());
|
let n = Ident::new(&t.to_string(), Span::call_site());
|
||||||
z.push(quote! {
|
z.push(quasiquote! {
|
||||||
#n: Vec<#root::func::Value<Target>>
|
#n: Vec<#{opts.fp()}::Value<Target>>
|
||||||
});
|
});
|
||||||
fields.push(n.clone());
|
fields.push(n.clone());
|
||||||
if let Some(e) = d.func_elements.as_ref() {
|
if let Some(e) = d.func_elements.as_ref() {
|
||||||
let e = e.iter().map(|x| opts.render_fun_ref("e! {C}, *x));
|
let e = e.iter().map(|x| opts.render_fun_ref("e! {C}, *x));
|
||||||
init.push(quote! {
|
init.push(if opts.flags.contains(Flags::ASYNC) {
|
||||||
|
quote! {
|
||||||
|
#(ctx.data().#n.push(#root::func::unsync::Coe::coe(#e)));*;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
#(ctx.data().#n.push(#root::func::Coe::coe(#e)));*;
|
#(ctx.data().#n.push(#root::func::Coe::coe(#e)));*;
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fs.push(quote! {
|
fs.push(quasiquote! {
|
||||||
fn #n(&mut self) -> &mut Vec<#root::func::Value<Self>>{
|
fn #n(&mut self) -> &mut Vec<#{opts.fp()}::Value<Self>>{
|
||||||
&mut self.data().#n
|
&mut self.data().#n
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -893,17 +1219,27 @@ pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Some((a, b)) => {
|
Some((a, b)) => {
|
||||||
|
if a == "!!unsafe" && b == "host" && opts.flags.contains(Flags::HOST_MEMORY) {
|
||||||
|
} else {
|
||||||
// let a = bindname(&a);
|
// let a = bindname(&a);
|
||||||
// let b = bindname(&b);
|
// let b = bindname(&b);
|
||||||
let m = Ident::new(&format!("{a}_{b}"), Span::call_site());
|
let m = Ident::new(&format!("{a}_{b}"), Span::call_site());
|
||||||
|
let p = if opts.flags.contains(Flags::LEGACY) {
|
||||||
|
quote! {dyn #root::Memory}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
impl #root::Memory
|
||||||
|
}
|
||||||
|
};
|
||||||
fs.push(quote! {
|
fs.push(quote! {
|
||||||
fn #m<'a>(&'a mut self) -> &'a mut Vec<u8>;
|
fn #m<'a>(&'a mut self) -> &'a mut #p;
|
||||||
fn #n<'a>(&'a mut self) -> &'a mut Vec<u8>{
|
fn #n<'a>(&'a mut self) -> &'a mut #p{
|
||||||
return self.#m();
|
return self.#m();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let pk = d.initial_pages * 65536;
|
let pk = d.initial_pages * 65536;
|
||||||
init.push(quote! {
|
init.push(quote! {
|
||||||
let l = #pk.max(ctx.#n().len());
|
let l = #pk.max(ctx.#n().len());
|
||||||
|
@ -930,6 +1266,10 @@ pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for xp in opts.module.exports.iter() {
|
for xp in opts.module.exports.iter() {
|
||||||
|
let xp = Export{
|
||||||
|
name: bindname(&xp.name),
|
||||||
|
kind: xp.kind.clone()
|
||||||
|
};
|
||||||
match &xp.kind {
|
match &xp.kind {
|
||||||
ExportKind::Func(f) => {
|
ExportKind::Func(f) => {
|
||||||
let f = *f;
|
let f = *f;
|
||||||
|
@ -969,8 +1309,14 @@ pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
||||||
ExportKind::Memory(m) => {
|
ExportKind::Memory(m) => {
|
||||||
let x = Ident::new(&m.to_string(), Span::call_site());
|
let x = Ident::new(&m.to_string(), Span::call_site());
|
||||||
let mn = Ident::new(&xp.name, Span::call_site());
|
let mn = Ident::new(&xp.name, Span::call_site());
|
||||||
let i = quote! {
|
let i = quasiquote! {
|
||||||
fn #mn(&mut self) -> &mut Vec<u8>{
|
fn #mn(&mut self) -> &mut #{if opts.flags.contains(Flags::LEGACY) {
|
||||||
|
quote! {dyn #root::Memory}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
impl #root::Memory
|
||||||
|
}
|
||||||
|
}}{
|
||||||
return self.#x()
|
return self.#x()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -990,13 +1336,56 @@ pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// if opts.flags.contains(Flags::UNSANDBOXED) {
|
||||||
|
// for (x, y) in [
|
||||||
|
// (
|
||||||
|
// format_ident!("files"),
|
||||||
|
// quote! {
|
||||||
|
// ::std::collections::BTreeMap<u32,::std::sync::Arc<::std::fs::File>>
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// (
|
||||||
|
// format_ident!("io_errors"),
|
||||||
|
// quote! {
|
||||||
|
// ::std::collections::BTreeMap<u32,::std::sync::Arc<::std::io::Error>>
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// ] {
|
||||||
|
// fields.push(x.clone());
|
||||||
|
// z.push(quote! {
|
||||||
|
// #x: #y
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
let defaults = fields.iter().map(|a| {
|
||||||
quote! {
|
quote! {
|
||||||
|
#a: Default::default()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let clones = fields.iter().map(|a| {
|
||||||
|
quote! {
|
||||||
|
#a: self.#a.clone()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
quasiquote! {
|
||||||
mod #internal_path{
|
mod #internal_path{
|
||||||
#(#funcs)*
|
#(#funcs)*
|
||||||
|
pub 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;
|
||||||
|
}
|
||||||
pub struct #data<Target: #name + ?Sized>{
|
pub struct #data<Target: #name + ?Sized>{
|
||||||
#(#z),*
|
#(#z),*
|
||||||
}
|
}
|
||||||
pub trait #name: #root::func::CtxSpec{
|
pub trait #name: #{opts.fp()}::CtxSpec #{if opts.flags.contains(Flags::ASYNC){
|
||||||
|
quote! {+ Send + Sync}
|
||||||
|
}else{
|
||||||
|
quote! {}
|
||||||
|
}}{
|
||||||
fn data(&mut self) -> &mut #data<Self>;
|
fn data(&mut self) -> &mut #data<Self>;
|
||||||
#(#fs)*
|
#(#fs)*
|
||||||
|
|
||||||
|
@ -1005,6 +1394,20 @@ pub fn go(opts: &Opts<Vec<u8>>) -> proc_macro2::TokenStream {
|
||||||
#(#init);*;
|
#(#init);*;
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
|
impl<Target: #name + ?Sized> Default for #data<Target>{
|
||||||
|
fn default() -> Self{
|
||||||
|
Self{
|
||||||
|
#(#defaults),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Target: #name + ?Sized> Clone for #data<Target>{
|
||||||
|
fn clone(&self) -> Self{
|
||||||
|
Self{
|
||||||
|
#(#clones),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
use #internal_path::{#name,#data};
|
use #internal_path::{#name,#data};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue